1993-08-04 23:30:29 +04:00
|
|
|
|
/* chat.c
|
|
|
|
|
Chat routine for the UUCP package.
|
|
|
|
|
|
1994-10-25 01:15:56 +03:00
|
|
|
|
Copyright (C) 1991, 1992, 1993 Ian Lance Taylor
|
1993-08-04 23:30:29 +04:00
|
|
|
|
|
|
|
|
|
This file is part of the Taylor UUCP package.
|
|
|
|
|
|
|
|
|
|
This program is free software; you can redistribute it and/or
|
|
|
|
|
modify it under the terms of the GNU General Public License as
|
|
|
|
|
published by the Free Software Foundation; either version 2 of the
|
|
|
|
|
License, or (at your option) any later version.
|
|
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful, but
|
|
|
|
|
WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
General Public License for more details.
|
|
|
|
|
|
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
|
along with this program; if not, write to the Free Software
|
|
|
|
|
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
|
|
|
|
|
|
|
|
|
The author of the program may be contacted at ian@airs.com or
|
1994-10-25 01:15:56 +03:00
|
|
|
|
c/o Cygnus Support, Building 200, 1 Kendall Square, Cambridge, MA 02139.
|
1993-08-04 23:30:29 +04:00
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "uucp.h"
|
|
|
|
|
|
|
|
|
|
#if USE_RCS_ID
|
1994-10-25 01:15:56 +03:00
|
|
|
|
const char chat_rcsid[] = "$Id: chat.c,v 1.2 1994/10/24 22:17:03 jtc Exp $";
|
1993-08-04 23:30:29 +04:00
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
|
|
#include "uudefs.h"
|
|
|
|
|
#include "uuconf.h"
|
|
|
|
|
#include "conn.h"
|
|
|
|
|
#include "prot.h"
|
|
|
|
|
#include "system.h"
|
|
|
|
|
|
|
|
|
|
/* Local functions. */
|
|
|
|
|
|
|
|
|
|
static int icexpect P((struct sconnection *qconn, int cstrings,
|
|
|
|
|
char **azstrings, size_t *aclens,
|
|
|
|
|
int ctimeout, boolean fstrip));
|
|
|
|
|
static boolean fcsend P((struct sconnection *qconn, pointer puuconf,
|
|
|
|
|
const char *zsend,
|
|
|
|
|
const struct uuconf_system *qsys,
|
|
|
|
|
const struct uuconf_dialer *qdial,
|
|
|
|
|
const char *zphone,
|
|
|
|
|
boolean ftranslate, boolean fstrip));
|
|
|
|
|
static boolean fcecho_send_strip P((struct sconnection *qconn,
|
|
|
|
|
const char *z, size_t clen));
|
|
|
|
|
static boolean fcecho_send_nostrip P((struct sconnection *qconn,
|
|
|
|
|
const char *z, size_t clen));
|
|
|
|
|
static boolean fcecho_send P((struct sconnection *qconn, const char *z,
|
|
|
|
|
size_t clen, boolean fstrip));
|
|
|
|
|
static boolean fcphone P((struct sconnection *qconn,
|
|
|
|
|
pointer puuconf,
|
|
|
|
|
const struct uuconf_dialer *qdial,
|
|
|
|
|
const char *zphone,
|
|
|
|
|
boolean (*pfwrite) P((struct sconnection *qc,
|
|
|
|
|
const char *zwrite,
|
|
|
|
|
size_t cwrite)),
|
|
|
|
|
boolean ftranslate, boolean *pfquote));
|
|
|
|
|
static boolean fctranslate P((pointer puuconf, const char *zphone,
|
|
|
|
|
const char **pzprefix,
|
|
|
|
|
const char **pzsuffix));
|
|
|
|
|
static boolean fcprogram P((struct sconnection *qconn, pointer puuconf,
|
|
|
|
|
char **pzprogram,
|
|
|
|
|
const struct uuconf_system *qsys,
|
|
|
|
|
const struct uuconf_dialer *qdial,
|
|
|
|
|
const char *zphone, const char *zport,
|
|
|
|
|
long ibaud));
|
|
|
|
|
|
|
|
|
|
/* Run a chat script with the other system. The chat script is a
|
|
|
|
|
series of expect send pairs. We wait for the expect string to show
|
|
|
|
|
up, and then we send the send string. The chat string for a system
|
|
|
|
|
holds the expect and send strings separated by a single space. */
|
|
|
|
|
|
|
|
|
|
boolean
|
|
|
|
|
fchat (qconn, puuconf, qchat, qsys, qdial, zphone, ftranslate, zport, ibaud)
|
|
|
|
|
struct sconnection *qconn;
|
|
|
|
|
pointer puuconf;
|
|
|
|
|
const struct uuconf_chat *qchat;
|
|
|
|
|
const struct uuconf_system *qsys;
|
|
|
|
|
const struct uuconf_dialer *qdial;
|
|
|
|
|
const char *zphone;
|
|
|
|
|
boolean ftranslate;
|
|
|
|
|
const char *zport;
|
|
|
|
|
long ibaud;
|
|
|
|
|
{
|
|
|
|
|
int cstrings;
|
|
|
|
|
char **azstrings;
|
|
|
|
|
size_t *aclens;
|
|
|
|
|
char **pzchat;
|
|
|
|
|
char *zbuf;
|
|
|
|
|
size_t cbuflen;
|
|
|
|
|
boolean fret;
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
/* First run the program, if any. */
|
|
|
|
|
if (qchat->uuconf_pzprogram != NULL)
|
|
|
|
|
{
|
|
|
|
|
if (! fcprogram (qconn, puuconf, qchat->uuconf_pzprogram, qsys, qdial,
|
|
|
|
|
zphone, zport, ibaud))
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If there's no chat script, we're done. */
|
|
|
|
|
if (qchat->uuconf_pzchat == NULL)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
if (qchat->uuconf_pzfail == NULL)
|
|
|
|
|
{
|
|
|
|
|
cstrings = 1;
|
|
|
|
|
azstrings = (char **) xmalloc (sizeof (char *));
|
|
|
|
|
aclens = (size_t *) xmalloc (sizeof (size_t));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
char **pz;
|
|
|
|
|
|
|
|
|
|
/* We leave string number 0 for the chat script. */
|
|
|
|
|
cstrings = 1;
|
|
|
|
|
for (pz = qchat->uuconf_pzfail; *pz != NULL; pz++)
|
|
|
|
|
++cstrings;
|
|
|
|
|
|
|
|
|
|
azstrings = (char **) xmalloc (cstrings * sizeof (char *));
|
|
|
|
|
aclens = (size_t *) xmalloc (cstrings * sizeof (size_t));
|
|
|
|
|
|
|
|
|
|
/* Get the strings into the array, and handle all the escape
|
|
|
|
|
characters. */
|
|
|
|
|
for (cstrings = 1, pz = qchat->uuconf_pzfail;
|
|
|
|
|
*pz != NULL;
|
|
|
|
|
cstrings++, pz++)
|
|
|
|
|
{
|
|
|
|
|
azstrings[cstrings] = zbufcpy (*pz);
|
|
|
|
|
aclens[cstrings] = cescape (azstrings[cstrings]);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
cbuflen = 0;
|
|
|
|
|
zbuf = NULL;
|
|
|
|
|
fret = TRUE;
|
|
|
|
|
|
|
|
|
|
pzchat = qchat->uuconf_pzchat;
|
|
|
|
|
|
|
|
|
|
while (*pzchat != NULL)
|
|
|
|
|
{
|
|
|
|
|
size_t clen;
|
|
|
|
|
|
|
|
|
|
/* Loop over subexpects and subsends. */
|
|
|
|
|
while (TRUE)
|
|
|
|
|
{
|
1994-10-25 01:15:56 +03:00
|
|
|
|
char *ztimeout;
|
|
|
|
|
int ctimeout;
|
|
|
|
|
|
1993-08-04 23:30:29 +04:00
|
|
|
|
/* Copy the expect string into the buffer so that we can
|
|
|
|
|
modify it in cescape. */
|
|
|
|
|
clen = strlen (*pzchat);
|
|
|
|
|
if (clen >= cbuflen)
|
|
|
|
|
{
|
|
|
|
|
ubuffree (zbuf);
|
|
|
|
|
zbuf = zbufalc (clen + 1);
|
|
|
|
|
cbuflen = clen;
|
|
|
|
|
}
|
|
|
|
|
memcpy (zbuf, *pzchat, clen + 1);
|
|
|
|
|
|
|
|
|
|
azstrings[0] = zbuf;
|
|
|
|
|
if (azstrings[0][0] == '-')
|
|
|
|
|
++azstrings[0];
|
1994-10-25 01:15:56 +03:00
|
|
|
|
|
|
|
|
|
/* \Wnum at the end of the string is a timeout. */
|
|
|
|
|
ctimeout = qchat->uuconf_ctimeout;
|
|
|
|
|
ztimeout = strrchr (azstrings[0], '\\');
|
|
|
|
|
if (ztimeout != NULL && ztimeout[1] == 'W')
|
|
|
|
|
{
|
|
|
|
|
char *zend;
|
|
|
|
|
int cval;
|
|
|
|
|
|
|
|
|
|
cval = (int) strtol (ztimeout + 2, &zend, 10);
|
|
|
|
|
if (zend != ztimeout + 2 && *zend == '\0')
|
|
|
|
|
{
|
|
|
|
|
ctimeout = cval;
|
|
|
|
|
*ztimeout = '\0';
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
1993-08-04 23:30:29 +04:00
|
|
|
|
aclens[0] = cescape (azstrings[0]);
|
|
|
|
|
|
|
|
|
|
if (aclens[0] == 0
|
|
|
|
|
|| (aclens[0] == 2
|
|
|
|
|
&& strcmp (azstrings[0], "\"\"") == 0))
|
|
|
|
|
{
|
|
|
|
|
/* There is no subexpect sequence. If there is a
|
|
|
|
|
subsend sequence we move on to it. Otherwise we let
|
|
|
|
|
this expect succeed. This is somewhat inconsistent,
|
|
|
|
|
but it seems to be the traditional approach. */
|
|
|
|
|
if (pzchat[1] == NULL || pzchat[1][0] != '-')
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int istr;
|
|
|
|
|
|
|
|
|
|
istr = icexpect (qconn, cstrings, azstrings, aclens,
|
1994-10-25 01:15:56 +03:00
|
|
|
|
ctimeout, qchat->uuconf_fstrip);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
|
|
|
|
|
/* If we found the string, break out of the
|
|
|
|
|
subexpect/subsend loop. */
|
|
|
|
|
if (istr == 0)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* If we got an error, return FALSE. */
|
|
|
|
|
if (istr < -1)
|
|
|
|
|
{
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If we found a failure string, log it and get out. */
|
|
|
|
|
if (istr > 0)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "Chat script failed: Got \"%s\"",
|
|
|
|
|
qchat->uuconf_pzfail[istr - 1]);
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* We timed out; look for a send subsequence. If none,
|
|
|
|
|
the chat script has failed. */
|
|
|
|
|
if (pzchat[1] == NULL || pzchat[1][0] != '-')
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "Timed out in chat script");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Send the send subsequence without the leading '-'. A
|
|
|
|
|
\"\" will send nothing. An empty string will send a
|
|
|
|
|
carriage return. */
|
|
|
|
|
++pzchat;
|
|
|
|
|
if (! fcsend (qconn, puuconf, *pzchat + 1, qsys, qdial, zphone,
|
|
|
|
|
ftranslate, qchat->uuconf_fstrip))
|
|
|
|
|
{
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* If there is no expect subsequence, we are done. */
|
|
|
|
|
if (pzchat[1] == NULL || pzchat[1][0] != '-')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Move on to next expect subsequence. */
|
|
|
|
|
++pzchat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! fret)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* Move on to the send string. If there is none, we have
|
|
|
|
|
succeeded. */
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
++pzchat;
|
|
|
|
|
}
|
|
|
|
|
while (*pzchat != NULL && (*pzchat)[0] == '-');
|
|
|
|
|
|
|
|
|
|
if (*pzchat == NULL)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (**pzchat != '\0')
|
|
|
|
|
{
|
|
|
|
|
if (! fcsend (qconn, puuconf, *pzchat, qsys, qdial, zphone,
|
|
|
|
|
ftranslate, qchat->uuconf_fstrip))
|
|
|
|
|
{
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++pzchat;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ubuffree (zbuf);
|
|
|
|
|
for (i = 1; i < cstrings; i++)
|
|
|
|
|
ubuffree (azstrings[i]);
|
|
|
|
|
xfree ((pointer) azstrings);
|
|
|
|
|
xfree ((pointer) aclens);
|
|
|
|
|
|
|
|
|
|
return fret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Read characters and wait for one of a set of memory strings to come
|
|
|
|
|
in. This returns the index into the array of the string that
|
|
|
|
|
arrives, or -1 on timeout, or -2 on error. */
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
icexpect (qconn, cstrings, azstrings, aclens, ctimeout, fstrip)
|
|
|
|
|
struct sconnection *qconn;
|
|
|
|
|
int cstrings;
|
|
|
|
|
char **azstrings;
|
|
|
|
|
size_t *aclens;
|
|
|
|
|
int ctimeout;
|
|
|
|
|
boolean fstrip;
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
size_t cmax;
|
|
|
|
|
char *zhave;
|
|
|
|
|
size_t chave;
|
|
|
|
|
long iendtime;
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
int cchars;
|
|
|
|
|
int iolddebug;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
cmax = aclens[0];
|
|
|
|
|
for (i = 1; i < cstrings; i++)
|
|
|
|
|
if (cmax < aclens[i])
|
|
|
|
|
cmax = aclens[i];
|
|
|
|
|
|
|
|
|
|
zhave = zbufalc (cmax);
|
|
|
|
|
chave = 0;
|
|
|
|
|
|
|
|
|
|
iendtime = ixsysdep_time ((long *) NULL) + ctimeout;
|
|
|
|
|
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
cchars = 0;
|
|
|
|
|
iolddebug = iDebug;
|
|
|
|
|
if (FDEBUGGING (DEBUG_CHAT))
|
|
|
|
|
{
|
|
|
|
|
udebug_buffer ("icexpect: Looking for", azstrings[0],
|
|
|
|
|
aclens[0]);
|
|
|
|
|
ulog (LOG_DEBUG_START, "icexpect: Got \"");
|
|
|
|
|
iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
while (TRUE)
|
|
|
|
|
{
|
|
|
|
|
int bchar;
|
|
|
|
|
|
|
|
|
|
/* If we have no more time, get out. */
|
|
|
|
|
if (ctimeout <= 0)
|
|
|
|
|
{
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
if (FDEBUGGING (DEBUG_CHAT))
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_DEBUG_END, "\" (timed out)");
|
|
|
|
|
iDebug = iolddebug;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
ubuffree (zhave);
|
|
|
|
|
return -1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Read one character at a time. We could use a more complex
|
|
|
|
|
algorithm to read in larger batches, but it's probably not
|
|
|
|
|
worth it. If the buffer is full, shift it left; we already
|
|
|
|
|
know that no string matches, and the buffer holds the largest
|
|
|
|
|
string, so this can't lose a match. */
|
|
|
|
|
if (chave >= cmax)
|
|
|
|
|
{
|
|
|
|
|
size_t imove;
|
|
|
|
|
|
|
|
|
|
for (imove = 0; imove < cmax - 1; imove++)
|
|
|
|
|
zhave[imove] = zhave[imove + 1];
|
|
|
|
|
--chave;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* The timeout/error return values from breceive_char are the
|
|
|
|
|
same as for this function. */
|
|
|
|
|
bchar = breceive_char (qconn, ctimeout, TRUE);
|
|
|
|
|
if (bchar < 0)
|
|
|
|
|
{
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
if (FDEBUGGING (DEBUG_CHAT))
|
|
|
|
|
{
|
|
|
|
|
/* If there was an error, it will probably be logged in
|
|
|
|
|
the middle of our string, but this is only debugging
|
|
|
|
|
so it's not a big deal. */
|
|
|
|
|
ulog (LOG_DEBUG_END, "\" (%s)",
|
|
|
|
|
bchar == -1 ? "timed out" : "error");
|
|
|
|
|
iDebug = iolddebug;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
ubuffree (zhave);
|
|
|
|
|
return bchar;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Strip the parity bit if desired. */
|
|
|
|
|
if (fstrip)
|
|
|
|
|
bchar &= 0x7f;
|
|
|
|
|
|
|
|
|
|
zhave[chave] = (char) bchar;
|
|
|
|
|
++chave;
|
|
|
|
|
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
if (FDEBUGGING (DEBUG_CHAT))
|
|
|
|
|
{
|
|
|
|
|
char ab[5];
|
|
|
|
|
|
|
|
|
|
++cchars;
|
|
|
|
|
if (cchars > 60)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_DEBUG_END, "\"");
|
|
|
|
|
ulog (LOG_DEBUG_START, "icexpect: Got \"");
|
|
|
|
|
cchars = 0;
|
|
|
|
|
}
|
|
|
|
|
(void) cdebug_char (ab, bchar);
|
|
|
|
|
ulog (LOG_DEBUG_CONTINUE, "%s", ab);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
/* See if any of the strings can be found in the buffer. Since
|
|
|
|
|
we read one character at a time, the string can only be found
|
|
|
|
|
at the end of the buffer. */
|
|
|
|
|
for (i = 0; i < cstrings; i++)
|
|
|
|
|
{
|
|
|
|
|
if (aclens[i] <= chave
|
|
|
|
|
&& memcmp (zhave + chave - aclens[i], azstrings[i],
|
|
|
|
|
aclens[i]) == 0)
|
|
|
|
|
{
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
if (FDEBUGGING (DEBUG_CHAT))
|
|
|
|
|
{
|
|
|
|
|
if (i == 0)
|
|
|
|
|
ulog (LOG_DEBUG_END, "\" (found it)");
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_DEBUG_END, "\"");
|
|
|
|
|
udebug_buffer ("icexpect: Found", azstrings[i],
|
|
|
|
|
aclens[i]);
|
|
|
|
|
}
|
|
|
|
|
iDebug = iolddebug;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
ubuffree (zhave);
|
|
|
|
|
return i;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ctimeout = (int) (iendtime - ixsysdep_time ((long *) NULL));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
|
|
|
|
|
/* Debugging function for fcsend. This takes the fquote variable, the
|
|
|
|
|
length of the string (0 if this an informational string which can
|
|
|
|
|
be printed directly) and the string itself. It returns the new
|
|
|
|
|
value for fquote. The fquote variable is TRUE if the debugging
|
|
|
|
|
output is in the middle of a quoted string. */
|
|
|
|
|
|
|
|
|
|
static size_t cCsend_chars;
|
|
|
|
|
static int iColddebug;
|
|
|
|
|
|
|
|
|
|
static boolean fcsend_debug P((boolean, size_t, const char *));
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
fcsend_debug (fquote, clen, zbuf)
|
|
|
|
|
boolean fquote;
|
|
|
|
|
size_t clen;
|
|
|
|
|
const char *zbuf;
|
|
|
|
|
{
|
|
|
|
|
size_t cwas;
|
|
|
|
|
|
|
|
|
|
if (! FDEBUGGING (DEBUG_CHAT))
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
cwas = cCsend_chars;
|
|
|
|
|
if (clen > 0)
|
|
|
|
|
cCsend_chars += clen;
|
|
|
|
|
else
|
|
|
|
|
cCsend_chars += strlen (zbuf);
|
|
|
|
|
if (cCsend_chars > 60 && cwas > 10)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_DEBUG_END, "%s", fquote ? "\"" : "");
|
|
|
|
|
fquote = FALSE;
|
|
|
|
|
ulog (LOG_DEBUG_START, "fcsend: Writing");
|
|
|
|
|
cCsend_chars = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (clen == 0)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_DEBUG_CONTINUE, "%s %s", fquote ? "\"" : "", zbuf);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (! fquote)
|
|
|
|
|
ulog (LOG_DEBUG_CONTINUE, " \"");
|
|
|
|
|
for (i = 0; i < clen; i++)
|
|
|
|
|
{
|
|
|
|
|
char ab[5];
|
|
|
|
|
|
|
|
|
|
(void) cdebug_char (ab, zbuf[i]);
|
|
|
|
|
ulog (LOG_DEBUG_CONTINUE, "%s", ab);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Finish up the debugging information for fcsend. */
|
|
|
|
|
|
|
|
|
|
static void ucsend_debug_end P((boolean, boolean));
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
ucsend_debug_end (fquote, ferr)
|
|
|
|
|
boolean fquote;
|
|
|
|
|
boolean ferr;
|
|
|
|
|
{
|
|
|
|
|
if (! FDEBUGGING (DEBUG_CHAT))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (fquote)
|
|
|
|
|
ulog (LOG_DEBUG_CONTINUE, "\"");
|
|
|
|
|
|
|
|
|
|
if (ferr)
|
|
|
|
|
ulog (LOG_DEBUG_CONTINUE, " (error)");
|
|
|
|
|
|
|
|
|
|
ulog (LOG_DEBUG_END, "%s", "");
|
|
|
|
|
|
|
|
|
|
iDebug = iColddebug;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#else /* DEBUG <= 1 */
|
|
|
|
|
|
|
|
|
|
/* Use macro definitions to make fcsend look neater. */
|
|
|
|
|
|
|
|
|
|
#define fcsend_debug(fquote, clen, zbuf) TRUE
|
|
|
|
|
|
|
|
|
|
#define ucsend_debug_end(fquote, ferror)
|
|
|
|
|
|
|
|
|
|
#endif /* DEBUG <= 1 */
|
|
|
|
|
|
|
|
|
|
/* Send a string out. This has to parse escape sequences as it goes.
|
|
|
|
|
Note that it handles the dialer escape sequences (\e, \E, \D, \T)
|
|
|
|
|
although they make no sense for chatting with a system. */
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
fcsend (qconn, puuconf, z, qsys, qdial, zphone, ftranslate, fstrip)
|
|
|
|
|
struct sconnection *qconn;
|
|
|
|
|
pointer puuconf;
|
|
|
|
|
const char *z;
|
|
|
|
|
const struct uuconf_system *qsys;
|
|
|
|
|
const struct uuconf_dialer *qdial;
|
|
|
|
|
const char *zphone;
|
|
|
|
|
boolean ftranslate;
|
|
|
|
|
boolean fstrip;
|
|
|
|
|
{
|
|
|
|
|
boolean fnocr;
|
|
|
|
|
boolean (*pfwrite) P((struct sconnection *, const char *, size_t));
|
|
|
|
|
char *zcallout_login;
|
|
|
|
|
char *zcallout_pass;
|
|
|
|
|
boolean fquote;
|
|
|
|
|
|
|
|
|
|
if (strcmp (z, "\"\"") == 0)
|
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
|
|
fnocr = FALSE;
|
|
|
|
|
pfwrite = fconn_write;
|
|
|
|
|
zcallout_login = NULL;
|
|
|
|
|
zcallout_pass = NULL;
|
|
|
|
|
|
|
|
|
|
#if DEBUG > 1
|
|
|
|
|
if (FDEBUGGING (DEBUG_CHAT))
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_DEBUG_START, "fcsend: Writing");
|
|
|
|
|
fquote = FALSE;
|
|
|
|
|
cCsend_chars = 0;
|
|
|
|
|
iColddebug = iDebug;
|
|
|
|
|
iDebug &=~ (DEBUG_OUTGOING | DEBUG_PORT);
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
while (*z != '\0')
|
|
|
|
|
{
|
|
|
|
|
const char *zlook;
|
|
|
|
|
boolean fsend;
|
|
|
|
|
char bsend;
|
|
|
|
|
|
|
|
|
|
zlook = z + strcspn ((char *) z, "\\BE");
|
|
|
|
|
|
|
|
|
|
if (zlook > z)
|
|
|
|
|
{
|
|
|
|
|
size_t c;
|
|
|
|
|
|
|
|
|
|
c = zlook - z;
|
|
|
|
|
fquote = fcsend_debug (fquote, c, z);
|
|
|
|
|
if (! (*pfwrite) (qconn, z, c))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*zlook == '\0')
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
z = zlook;
|
|
|
|
|
|
|
|
|
|
fsend = FALSE;
|
|
|
|
|
switch (*z)
|
|
|
|
|
{
|
|
|
|
|
case 'B':
|
|
|
|
|
if (strncmp (z, "BREAK", 5) == 0)
|
|
|
|
|
{
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "break");
|
|
|
|
|
if (! fconn_break (qconn))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
fnocr = TRUE;
|
|
|
|
|
z += 5;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = 'B';
|
|
|
|
|
++z;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'E':
|
|
|
|
|
if (strncmp (z, "EOT", 3) == 0)
|
|
|
|
|
{
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = '\004';
|
|
|
|
|
fnocr = TRUE;
|
|
|
|
|
z += 3;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = 'E';
|
|
|
|
|
++z;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case '\\':
|
|
|
|
|
++z;
|
|
|
|
|
switch (*z)
|
|
|
|
|
{
|
|
|
|
|
case '-':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = '-';
|
|
|
|
|
break;
|
|
|
|
|
case 'b':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = '\b';
|
|
|
|
|
break;
|
|
|
|
|
case 'c':
|
|
|
|
|
fnocr = TRUE;
|
|
|
|
|
break;
|
|
|
|
|
case 'd':
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "sleep");
|
1994-10-25 01:15:56 +03:00
|
|
|
|
usysdep_sleep (1);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
break;
|
|
|
|
|
case 'e':
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "echo-check-off");
|
|
|
|
|
pfwrite = fconn_write;
|
|
|
|
|
break;
|
|
|
|
|
case 'E':
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "echo-check-on");
|
|
|
|
|
if (fstrip)
|
|
|
|
|
pfwrite = fcecho_send_strip;
|
|
|
|
|
else
|
|
|
|
|
pfwrite = fcecho_send_nostrip;
|
|
|
|
|
break;
|
|
|
|
|
case 'K':
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "break");
|
|
|
|
|
if (! fconn_break (qconn))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'n':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = '\n';
|
|
|
|
|
break;
|
|
|
|
|
case 'N':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = '\0';
|
|
|
|
|
break;
|
|
|
|
|
case 'p':
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "pause");
|
|
|
|
|
usysdep_pause ();
|
|
|
|
|
break;
|
|
|
|
|
case 'r':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = '\r';
|
|
|
|
|
break;
|
|
|
|
|
case 's':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = ' ';
|
|
|
|
|
break;
|
|
|
|
|
case 't':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = '\t';
|
|
|
|
|
break;
|
|
|
|
|
case '\0':
|
|
|
|
|
--z;
|
|
|
|
|
/* Fall through. */
|
|
|
|
|
case '\\':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = '\\';
|
|
|
|
|
break;
|
|
|
|
|
case '0': case '1': case '2': case '3': case '4':
|
|
|
|
|
case '5': case '6': case '7': case '8': case '9':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = *z - '0';
|
|
|
|
|
if (z[1] >= '0' && z[1] <= '7')
|
|
|
|
|
bsend = (char) (8 * bsend + *++z - '0');
|
|
|
|
|
if (z[1] >= '0' && z[1] <= '7')
|
|
|
|
|
bsend = (char) (8 * bsend + *++z - '0');
|
|
|
|
|
break;
|
|
|
|
|
case 'x':
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = 0;
|
|
|
|
|
while (isxdigit (BUCHAR (z[1])))
|
|
|
|
|
{
|
|
|
|
|
if (isdigit (BUCHAR (z[1])))
|
|
|
|
|
bsend = (char) (16 * bsend + *++z - '0');
|
|
|
|
|
else if (isupper (BUCHAR (z[1])))
|
|
|
|
|
bsend = (char) (16 * bsend + *++z - 'A');
|
|
|
|
|
else
|
|
|
|
|
bsend = (char) (16 * bsend + *++z - 'a');
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'L':
|
|
|
|
|
{
|
|
|
|
|
const char *zlog;
|
1994-10-25 01:15:56 +03:00
|
|
|
|
char *zcopy;
|
|
|
|
|
size_t clen;
|
1993-08-04 23:30:29 +04:00
|
|
|
|
|
|
|
|
|
if (qsys == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "Illegal use of \\L");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
zlog = qsys->uuconf_zcall_login;
|
|
|
|
|
if (zlog == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "No login defined");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (zlog[0] == '*' && zlog[1] == '\0')
|
|
|
|
|
{
|
|
|
|
|
if (zcallout_login == NULL)
|
|
|
|
|
{
|
|
|
|
|
int iuuconf;
|
|
|
|
|
|
|
|
|
|
iuuconf = uuconf_callout (puuconf, qsys,
|
|
|
|
|
&zcallout_login,
|
|
|
|
|
&zcallout_pass);
|
|
|
|
|
if (iuuconf == UUCONF_NOT_FOUND
|
|
|
|
|
|| zcallout_login == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "No login defined");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
zlog = zcallout_login;
|
|
|
|
|
}
|
1994-10-25 01:15:56 +03:00
|
|
|
|
zcopy = zbufcpy (zlog);
|
|
|
|
|
clen = cescape (zcopy);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "login");
|
1994-10-25 01:15:56 +03:00
|
|
|
|
fquote = fcsend_debug (fquote, clen, zcopy);
|
|
|
|
|
if (! (*pfwrite) (qconn, zcopy, clen))
|
1993-08-04 23:30:29 +04:00
|
|
|
|
{
|
1994-10-25 01:15:56 +03:00
|
|
|
|
ubuffree (zcopy);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
1994-10-25 01:15:56 +03:00
|
|
|
|
ubuffree (zcopy);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'P':
|
|
|
|
|
{
|
|
|
|
|
const char *zpass;
|
1994-10-25 01:15:56 +03:00
|
|
|
|
char *zcopy;
|
|
|
|
|
size_t clen;
|
1993-08-04 23:30:29 +04:00
|
|
|
|
|
|
|
|
|
if (qsys == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "Illegal use of \\P");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
zpass = qsys->uuconf_zcall_password;
|
|
|
|
|
if (zpass == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "No password defined");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (zpass[0] == '*' && zpass[1] == '\0')
|
|
|
|
|
{
|
|
|
|
|
if (zcallout_pass == NULL)
|
|
|
|
|
{
|
|
|
|
|
int iuuconf;
|
|
|
|
|
|
|
|
|
|
iuuconf = uuconf_callout (puuconf, qsys,
|
|
|
|
|
&zcallout_login,
|
|
|
|
|
&zcallout_pass);
|
|
|
|
|
if (iuuconf == UUCONF_NOT_FOUND
|
|
|
|
|
|| zcallout_pass == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "No password defined");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
zpass = zcallout_pass;
|
|
|
|
|
}
|
1994-10-25 01:15:56 +03:00
|
|
|
|
zcopy = zbufcpy (zpass);
|
|
|
|
|
clen = cescape (zcopy);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "password");
|
1994-10-25 01:15:56 +03:00
|
|
|
|
fquote = fcsend_debug (fquote, clen, zcopy);
|
|
|
|
|
if (! (*pfwrite) (qconn, zcopy, clen))
|
1993-08-04 23:30:29 +04:00
|
|
|
|
{
|
1994-10-25 01:15:56 +03:00
|
|
|
|
ubuffree (zcopy);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
1994-10-25 01:15:56 +03:00
|
|
|
|
ubuffree (zcopy);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'D':
|
|
|
|
|
if (qdial == NULL || zphone == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "Illegal use of \\D");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "\\D");
|
|
|
|
|
if (! fcphone (qconn, puuconf, qdial, zphone, pfwrite,
|
|
|
|
|
ftranslate, &fquote))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'T':
|
|
|
|
|
if (qdial == NULL || zphone == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "Illegal use of \\T");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "\\T");
|
|
|
|
|
if (! fcphone (qconn, puuconf, qdial, zphone, pfwrite, TRUE,
|
|
|
|
|
&fquote))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'M':
|
|
|
|
|
if (qdial == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "Illegal use of \\M");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "ignore-carrier");
|
|
|
|
|
if (! fconn_carrier (qconn, FALSE))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'm':
|
|
|
|
|
if (qdial == NULL)
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
ulog (LOG_ERROR, "Illegal use of \\m");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (qdial->uuconf_fcarrier)
|
|
|
|
|
{
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 0, "need-carrier");
|
|
|
|
|
if (! fconn_carrier (qconn, TRUE))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
/* This error message will screw up any debugging
|
|
|
|
|
information, but it's easily avoidable. */
|
|
|
|
|
ulog (LOG_ERROR,
|
|
|
|
|
"Unrecognized escape sequence \\%c in send string",
|
|
|
|
|
*z);
|
|
|
|
|
fsend = TRUE;
|
|
|
|
|
bsend = *z;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
++z;
|
|
|
|
|
break;
|
|
|
|
|
#if DEBUG > 0
|
|
|
|
|
default:
|
|
|
|
|
ulog (LOG_FATAL, "fcsend: Can't happen");
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (fsend)
|
|
|
|
|
{
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 1, &bsend);
|
|
|
|
|
if (! (*pfwrite) (qconn, &bsend, (size_t) 1))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
xfree ((pointer) zcallout_login);
|
|
|
|
|
xfree ((pointer) zcallout_pass);
|
|
|
|
|
|
|
|
|
|
/* Output a final carriage return, unless there was a \c. Don't
|
|
|
|
|
bother to check for an echo. */
|
|
|
|
|
if (! fnocr)
|
|
|
|
|
{
|
|
|
|
|
char b;
|
|
|
|
|
|
|
|
|
|
b = '\r';
|
|
|
|
|
fquote = fcsend_debug (fquote, (size_t) 1, &b);
|
|
|
|
|
if (! fconn_write (qconn, &b, (size_t) 1))
|
|
|
|
|
{
|
|
|
|
|
ucsend_debug_end (fquote, TRUE);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ucsend_debug_end (fquote, FALSE);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write out a phone number with optional dialcode translation. The
|
|
|
|
|
pfquote argument is only used for debugging. */
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
fcphone (qconn, puuconf, qdial, zphone, pfwrite, ftranslate, pfquote)
|
|
|
|
|
struct sconnection *qconn;
|
|
|
|
|
pointer puuconf;
|
|
|
|
|
const struct uuconf_dialer *qdial;
|
|
|
|
|
const char *zphone;
|
|
|
|
|
boolean (*pfwrite) P((struct sconnection *qc, const char *zwrite,
|
|
|
|
|
size_t cwrite));
|
|
|
|
|
boolean ftranslate;
|
|
|
|
|
boolean *pfquote;
|
|
|
|
|
{
|
|
|
|
|
const char *zprefix, *zsuffix;
|
|
|
|
|
|
|
|
|
|
if (ftranslate)
|
|
|
|
|
{
|
|
|
|
|
if (! fctranslate (puuconf, zphone, &zprefix, &zsuffix))
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
zprefix = zphone;
|
|
|
|
|
zsuffix = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while (zprefix != NULL)
|
|
|
|
|
{
|
|
|
|
|
while (TRUE)
|
|
|
|
|
{
|
|
|
|
|
const char *z;
|
|
|
|
|
const char *zstr;
|
|
|
|
|
|
|
|
|
|
z = zprefix + strcspn ((char *) zprefix, "=-");
|
|
|
|
|
if (z > zprefix)
|
|
|
|
|
{
|
|
|
|
|
size_t clen;
|
|
|
|
|
|
|
|
|
|
clen = z - zprefix;
|
|
|
|
|
*pfquote = fcsend_debug (*pfquote, clen, zprefix);
|
|
|
|
|
if (! (*pfwrite) (qconn, zprefix, clen))
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (*z == '=')
|
|
|
|
|
zstr = qdial->uuconf_zdialtone;
|
|
|
|
|
else if (*z == '-')
|
|
|
|
|
zstr = qdial->uuconf_zpause;
|
|
|
|
|
else /* *z == '\0' */
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
if (zstr != NULL)
|
|
|
|
|
{
|
|
|
|
|
*pfquote = fcsend_debug (*pfquote, strlen (zstr), zstr);
|
|
|
|
|
if (! (*pfwrite) (qconn, zstr, strlen (zstr)))
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zprefix = z + 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
zprefix = zsuffix;
|
|
|
|
|
zsuffix = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Given a phone number, run it through dial code translation
|
|
|
|
|
returning two strings. */
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
fctranslate (puuconf, zphone, pzprefix, pzsuffix)
|
|
|
|
|
pointer puuconf;
|
|
|
|
|
const char *zphone;
|
|
|
|
|
const char **pzprefix;
|
|
|
|
|
const char **pzsuffix;
|
|
|
|
|
{
|
|
|
|
|
int iuuconf;
|
|
|
|
|
char *zdialcode, *zto;
|
|
|
|
|
const char *zfrom;
|
|
|
|
|
char *ztrans;
|
|
|
|
|
|
|
|
|
|
*pzprefix = zphone;
|
|
|
|
|
*pzsuffix = NULL;
|
|
|
|
|
|
|
|
|
|
zdialcode = zbufalc (strlen (zphone) + 1);
|
|
|
|
|
zfrom = zphone;
|
|
|
|
|
zto = zdialcode;
|
|
|
|
|
while (*zfrom != '\0' && isalpha (BUCHAR (*zfrom)))
|
|
|
|
|
*zto++ = *zfrom++;
|
|
|
|
|
*zto = '\0';
|
|
|
|
|
|
|
|
|
|
if (*zdialcode == '\0')
|
|
|
|
|
{
|
|
|
|
|
ubuffree (zdialcode);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
iuuconf = uuconf_dialcode (puuconf, zdialcode, &ztrans);
|
|
|
|
|
|
|
|
|
|
ubuffree (zdialcode);
|
|
|
|
|
|
|
|
|
|
if (iuuconf == UUCONF_NOT_FOUND)
|
|
|
|
|
return TRUE;
|
|
|
|
|
else if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
/* We really should figure out a way to free up ztrans here. */
|
|
|
|
|
*pzprefix = ztrans;
|
|
|
|
|
*pzsuffix = zfrom;
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Write out a string making sure the each character is echoed back.
|
|
|
|
|
There are two versions of this function, one which strips the
|
|
|
|
|
parity bit from the characters and one which does not. This is so
|
|
|
|
|
that I can use a single function pointer in fcsend, and to avoid
|
|
|
|
|
using any static variables so that I can put chat scripts in a
|
|
|
|
|
library some day. */
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
fcecho_send_strip (qconn, zwrite, cwrite)
|
|
|
|
|
struct sconnection *qconn;
|
|
|
|
|
const char *zwrite;
|
|
|
|
|
size_t cwrite;
|
|
|
|
|
{
|
|
|
|
|
return fcecho_send (qconn, zwrite, cwrite, TRUE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
fcecho_send_nostrip (qconn, zwrite, cwrite)
|
|
|
|
|
struct sconnection *qconn;
|
|
|
|
|
const char *zwrite;
|
|
|
|
|
size_t cwrite;
|
|
|
|
|
{
|
|
|
|
|
return fcecho_send (qconn, zwrite, cwrite, FALSE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
fcecho_send (qconn, zwrite, cwrite, fstrip)
|
|
|
|
|
struct sconnection *qconn;
|
|
|
|
|
const char *zwrite;
|
|
|
|
|
size_t cwrite;
|
|
|
|
|
boolean fstrip;
|
|
|
|
|
{
|
|
|
|
|
const char *zend;
|
|
|
|
|
|
|
|
|
|
zend = zwrite + cwrite;
|
|
|
|
|
|
|
|
|
|
for (; zwrite < zend; zwrite++)
|
|
|
|
|
{
|
|
|
|
|
int b;
|
|
|
|
|
char bwrite;
|
|
|
|
|
|
|
|
|
|
bwrite = *zwrite;
|
|
|
|
|
if (! fconn_write (qconn, &bwrite, (size_t) 1))
|
|
|
|
|
return FALSE;
|
|
|
|
|
if (fstrip)
|
|
|
|
|
bwrite &= 0x7f;
|
|
|
|
|
do
|
|
|
|
|
{
|
|
|
|
|
/* We arbitrarily wait five seconds for the echo. */
|
|
|
|
|
b = breceive_char (qconn, 5, TRUE);
|
|
|
|
|
/* Now b == -1 on timeout, -2 on error. */
|
|
|
|
|
if (b < 0)
|
|
|
|
|
{
|
|
|
|
|
if (b == -1)
|
|
|
|
|
ulog (LOG_ERROR, "Character not echoed");
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
if (fstrip)
|
|
|
|
|
b &= 0x7f;
|
|
|
|
|
}
|
|
|
|
|
while (b != BUCHAR (bwrite));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Run a chat program. Expand any escape sequences and call a system
|
|
|
|
|
dependent program to run it. */
|
|
|
|
|
|
|
|
|
|
static boolean
|
|
|
|
|
fcprogram (qconn, puuconf, pzprogram, qsys, qdial, zphone, zport, ibaud)
|
|
|
|
|
struct sconnection *qconn;
|
|
|
|
|
pointer puuconf;
|
|
|
|
|
char **pzprogram;
|
|
|
|
|
const struct uuconf_system *qsys;
|
|
|
|
|
const struct uuconf_dialer *qdial;
|
|
|
|
|
const char *zphone;
|
|
|
|
|
const char *zport;
|
|
|
|
|
long ibaud;
|
|
|
|
|
{
|
|
|
|
|
size_t cargs;
|
|
|
|
|
char **pzpass, **pzarg;
|
|
|
|
|
char **pz;
|
|
|
|
|
char *zcallout_login;
|
|
|
|
|
char *zcallout_pass;
|
|
|
|
|
boolean fret;
|
|
|
|
|
|
|
|
|
|
cargs = 1;
|
|
|
|
|
for (pz = pzprogram; *pz != NULL; pz++)
|
|
|
|
|
++cargs;
|
|
|
|
|
|
|
|
|
|
pzpass = (char **) xmalloc (cargs * sizeof (char *));
|
|
|
|
|
|
|
|
|
|
zcallout_login = NULL;
|
|
|
|
|
zcallout_pass = NULL;
|
|
|
|
|
fret = TRUE;
|
|
|
|
|
|
|
|
|
|
/* Copy the string into memory expanding escape sequences. */
|
|
|
|
|
for (pz = pzprogram, pzarg = pzpass; *pz != NULL; pz++, pzarg++)
|
|
|
|
|
{
|
|
|
|
|
const char *zfrom;
|
|
|
|
|
size_t calc, clen;
|
|
|
|
|
char *zto;
|
|
|
|
|
|
|
|
|
|
if (strchr (*pz, '\\') == NULL)
|
|
|
|
|
{
|
|
|
|
|
*pzarg = zbufcpy (*pz);
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*pzarg = NULL;
|
|
|
|
|
zto = NULL;
|
|
|
|
|
calc = 0;
|
|
|
|
|
clen = 0;
|
|
|
|
|
|
|
|
|
|
for (zfrom = *pz; *zfrom != '\0'; zfrom++)
|
|
|
|
|
{
|
|
|
|
|
const char *zadd = NULL;
|
1994-10-25 01:15:56 +03:00
|
|
|
|
char *zfree = NULL;
|
1993-08-04 23:30:29 +04:00
|
|
|
|
size_t cadd;
|
|
|
|
|
char abadd[15];
|
|
|
|
|
|
|
|
|
|
if (*zfrom != '\\')
|
|
|
|
|
{
|
|
|
|
|
if (clen + 2 > calc)
|
|
|
|
|
{
|
|
|
|
|
char *znew;
|
|
|
|
|
|
|
|
|
|
calc = clen + 50;
|
|
|
|
|
znew = zbufalc (calc);
|
|
|
|
|
memcpy (znew, *pzarg, clen);
|
|
|
|
|
ubuffree (*pzarg);
|
|
|
|
|
*pzarg = znew;
|
|
|
|
|
zto = znew + clen;
|
|
|
|
|
}
|
|
|
|
|
*zto++ = *zfrom;
|
|
|
|
|
++clen;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
++zfrom;
|
|
|
|
|
switch (*zfrom)
|
|
|
|
|
{
|
|
|
|
|
case '\0':
|
|
|
|
|
--zfrom;
|
|
|
|
|
/* Fall through. */
|
|
|
|
|
case '\\':
|
|
|
|
|
zadd = "\\";
|
|
|
|
|
break;
|
|
|
|
|
case 'L':
|
|
|
|
|
{
|
|
|
|
|
const char *zlog;
|
|
|
|
|
|
|
|
|
|
if (qsys == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: Illegal use of \\L");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
zlog = qsys->uuconf_zcall_login;
|
|
|
|
|
if (zlog == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: No login defined");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (zlog[0] == '*' && zlog[1] == '\0')
|
|
|
|
|
{
|
|
|
|
|
if (zcallout_login == NULL)
|
|
|
|
|
{
|
|
|
|
|
int iuuconf;
|
|
|
|
|
|
|
|
|
|
iuuconf = uuconf_callout (puuconf, qsys,
|
|
|
|
|
&zcallout_login,
|
|
|
|
|
&zcallout_pass);
|
|
|
|
|
if (iuuconf == UUCONF_NOT_FOUND
|
|
|
|
|
|| zcallout_login == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR,
|
|
|
|
|
"chat-program: No login defined");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
zlog = zcallout_login;
|
|
|
|
|
}
|
1994-10-25 01:15:56 +03:00
|
|
|
|
zfree = zbufcpy (zlog);
|
|
|
|
|
(void) cescape (zfree);
|
|
|
|
|
zadd = zfree;
|
1993-08-04 23:30:29 +04:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'P':
|
|
|
|
|
{
|
|
|
|
|
const char *zpass;
|
|
|
|
|
|
|
|
|
|
if (qsys == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: Illegal use of \\P");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
zpass = qsys->uuconf_zcall_password;
|
|
|
|
|
if (zpass == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: No password defined");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (zpass[0] == '*' && zpass[1] == '\0')
|
|
|
|
|
{
|
|
|
|
|
if (zcallout_pass == NULL)
|
|
|
|
|
{
|
|
|
|
|
int iuuconf;
|
|
|
|
|
|
|
|
|
|
iuuconf = uuconf_callout (puuconf, qsys,
|
|
|
|
|
&zcallout_login,
|
|
|
|
|
&zcallout_pass);
|
|
|
|
|
if (iuuconf == UUCONF_NOT_FOUND
|
|
|
|
|
|| zcallout_pass == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR,
|
|
|
|
|
"chat-program: No password defined");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
else if (iuuconf != UUCONF_SUCCESS)
|
|
|
|
|
{
|
|
|
|
|
ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
zpass = zcallout_pass;
|
|
|
|
|
}
|
1994-10-25 01:15:56 +03:00
|
|
|
|
zfree = zbufcpy (zpass);
|
|
|
|
|
(void) cescape (zfree);
|
|
|
|
|
zadd = zfree;
|
1993-08-04 23:30:29 +04:00
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'D':
|
|
|
|
|
if (qdial == NULL || zphone == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: Illegal use of \\D");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
zadd = zphone;
|
|
|
|
|
break;
|
|
|
|
|
case 'T':
|
|
|
|
|
{
|
|
|
|
|
const char *zprefix, *zsuffix;
|
|
|
|
|
|
|
|
|
|
if (qdial == NULL || zphone == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: Illegal use of \\T");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! fctranslate (puuconf, zphone, &zprefix, &zsuffix))
|
|
|
|
|
{
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (zsuffix == NULL)
|
|
|
|
|
zadd = zprefix;
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
size_t cprefix;
|
|
|
|
|
|
|
|
|
|
cprefix = strlen (zprefix);
|
|
|
|
|
if (clen + cprefix + 1 > calc)
|
|
|
|
|
{
|
|
|
|
|
char *znew;
|
|
|
|
|
|
|
|
|
|
calc = clen + cprefix + 20;
|
|
|
|
|
znew = zbufalc (calc);
|
|
|
|
|
memcpy (znew, *pzarg, clen);
|
|
|
|
|
ubuffree (*pzarg);
|
|
|
|
|
*pzarg = znew;
|
|
|
|
|
zto = znew + clen;
|
|
|
|
|
}
|
|
|
|
|
memcpy (zto, zprefix, cprefix);
|
|
|
|
|
zto += cprefix;
|
|
|
|
|
clen += cprefix;
|
|
|
|
|
zadd = zsuffix;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case 'Y':
|
|
|
|
|
if (zLdevice == NULL && zport == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: Illegal use of \\Y");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* zLdevice will generally make more sense than zport, but
|
|
|
|
|
it might not be set yet. */
|
|
|
|
|
zadd = zLdevice;
|
|
|
|
|
if (zadd == NULL)
|
|
|
|
|
zadd = zport;
|
|
|
|
|
break;
|
|
|
|
|
case 'Z':
|
|
|
|
|
if (qsys == NULL)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: Illegal use of \\Z");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
zadd = qsys->uuconf_zname;
|
|
|
|
|
break;
|
|
|
|
|
case 'S':
|
|
|
|
|
{
|
|
|
|
|
if (ibaud == 0)
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR, "chat-program: Illegal use of \\S");
|
|
|
|
|
fret = FALSE;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
sprintf (abadd, "%ld", ibaud);
|
|
|
|
|
zadd = abadd;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
{
|
|
|
|
|
ulog (LOG_ERROR,
|
|
|
|
|
"chat-program: Unrecognized escape sequence \\%c",
|
|
|
|
|
*zfrom);
|
|
|
|
|
abadd[0] = *zfrom;
|
|
|
|
|
abadd[1] = '\0';
|
|
|
|
|
zadd = abadd;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! fret)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
cadd = strlen (zadd);
|
|
|
|
|
if (clen + cadd + 1 > calc)
|
|
|
|
|
{
|
|
|
|
|
char *znew;
|
|
|
|
|
|
|
|
|
|
calc = clen + cadd + 20;
|
|
|
|
|
znew = zbufalc (calc);
|
|
|
|
|
memcpy (znew, *pzarg, clen);
|
|
|
|
|
ubuffree (*pzarg);
|
|
|
|
|
*pzarg = znew;
|
|
|
|
|
zto = znew + clen;
|
|
|
|
|
}
|
|
|
|
|
memcpy (zto, zadd, cadd + 1);
|
|
|
|
|
zto += cadd;
|
|
|
|
|
clen += cadd;
|
1994-10-25 01:15:56 +03:00
|
|
|
|
ubuffree (zfree);
|
1993-08-04 23:30:29 +04:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (! fret)
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
*zto++ = '\0';
|
|
|
|
|
++clen;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
*pzarg = NULL;
|
|
|
|
|
|
|
|
|
|
if (fret)
|
|
|
|
|
fret = fconn_run_chat (qconn, pzpass);
|
|
|
|
|
|
|
|
|
|
for (pz = pzpass; *pz != NULL; pz++)
|
|
|
|
|
ubuffree (*pz);
|
|
|
|
|
xfree ((pointer) pzpass);
|
|
|
|
|
xfree ((pointer) zcallout_login);
|
|
|
|
|
xfree ((pointer) zcallout_pass);
|
|
|
|
|
|
|
|
|
|
return fret;
|
|
|
|
|
}
|