Annotation of coherent/g/usr/lib/uucp/tay104/chat.c, revision 1.1.1.1

1.1       root        1: /* chat.c
                      2:    Chat routine for the UUCP package.
                      3: 
                      4:    Copyright (C) 1991, 1992 Ian Lance Taylor
                      5: 
                      6:    This file is part of the Taylor UUCP package.
                      7: 
                      8:    This program is free software; you can redistribute it and/or
                      9:    modify it under the terms of the GNU General Public License as
                     10:    published by the Free Software Foundation; either version 2 of the
                     11:    License, or (at your option) any later version.
                     12: 
                     13:    This program is distributed in the hope that it will be useful, but
                     14:    WITHOUT ANY WARRANTY; without even the implied warranty of
                     15:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     16:    General Public License for more details.
                     17: 
                     18:    You should have received a copy of the GNU General Public License
                     19:    along with this program; if not, write to the Free Software
                     20:    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
                     21: 
                     22:    The author of the program may be contacted at [email protected] or
                     23:    c/o Infinity Development Systems, P.O. Box 520, Waltham, MA 02254.
                     24:    */
                     25: 
                     26: #include "uucp.h"
                     27: 
                     28: #if USE_RCS_ID
                     29: const char chat_rcsid[] = "$Id: chat.c,v 1.1 93/07/30 07:52:38 bin Exp Locker: bin $";
                     30: #endif
                     31: 
                     32: #include <ctype.h>
                     33: #include <errno.h>
                     34: 
                     35: #include "uudefs.h"
                     36: #include "uuconf.h"
                     37: #include "conn.h"
                     38: #include "prot.h"
                     39: #include "system.h"
                     40: 
                     41: /* Local functions.  */
                     42: 
                     43: static int icexpect P((struct sconnection *qconn, int cstrings,
                     44:                       char **azstrings, size_t *aclens,
                     45:                       int ctimeout, boolean fstrip));
                     46: static boolean fcsend P((struct sconnection *qconn, pointer puuconf,
                     47:                         const char *zsend,
                     48:                         const struct uuconf_system *qsys,
                     49:                         const struct uuconf_dialer *qdial,
                     50:                         const char *zphone,
                     51:                         boolean ftranslate, boolean fstrip));
                     52: static boolean fcecho_send_strip P((struct sconnection *qconn,
                     53:                                    const char *z, size_t clen));
                     54: static boolean fcecho_send_nostrip P((struct sconnection  *qconn,
                     55:                                      const char *z, size_t clen));
                     56: static boolean fcecho_send P((struct sconnection *qconn, const char *z,
                     57:                              size_t clen, boolean fstrip));
                     58: static boolean fcphone P((struct sconnection *qconn,
                     59:                          pointer puuconf,
                     60:                          const struct uuconf_dialer *qdial,
                     61:                          const char *zphone,
                     62:                          boolean (*pfwrite) P((struct sconnection *qc,
                     63:                                                const char *zwrite,
                     64:                                                size_t cwrite)),
                     65:                          boolean ftranslate, boolean *pfquote));
                     66: static boolean fctranslate P((pointer puuconf, const char *zphone,
                     67:                              const char **pzprefix,
                     68:                              const char **pzsuffix));
                     69: static boolean fcprogram P((struct sconnection *qconn, pointer puuconf,
                     70:                            char **pzprogram,
                     71:                            const struct uuconf_system *qsys,
                     72:                            const struct uuconf_dialer *qdial,
                     73:                            const char *zphone, const char *zport,
                     74:                            long ibaud));
                     75: 
                     76: /* Run a chat script with the other system.  The chat script is a
                     77:    series of expect send pairs.  We wait for the expect string to show
                     78:    up, and then we send the send string.  The chat string for a system
                     79:    holds the expect and send strings separated by a single space.  */
                     80: 
                     81: boolean
                     82: fchat (qconn, puuconf, qchat, qsys, qdial, zphone, ftranslate, zport, ibaud)
                     83:      struct sconnection *qconn;
                     84:      pointer puuconf;
                     85:      const struct uuconf_chat *qchat;
                     86:      const struct uuconf_system *qsys;
                     87:      const struct uuconf_dialer *qdial;
                     88:      const char *zphone;
                     89:      boolean ftranslate;
                     90:      const char *zport;
                     91:      long ibaud;
                     92: {
                     93:   int cstrings;
                     94:   char **azstrings;
                     95:   size_t *aclens;
                     96:   char **pzchat;
                     97:   char *zbuf;
                     98:   size_t cbuflen;
                     99:   boolean fret;
                    100:   int i;
                    101: 
                    102:   /* First run the program, if any.  */
                    103:   if (qchat->uuconf_pzprogram != NULL)
                    104:     {
                    105:       if (! fcprogram (qconn, puuconf, qchat->uuconf_pzprogram, qsys, qdial,
                    106:                       zphone, zport, ibaud))
                    107:        return FALSE;
                    108:     }
                    109: 
                    110:   /* If there's no chat script, we're done.  */
                    111:   if (qchat->uuconf_pzchat == NULL)
                    112:     return TRUE;
                    113: 
                    114:   if (qchat->uuconf_pzfail == NULL)
                    115:     {
                    116:       cstrings = 1;
                    117:       azstrings = (char **) xmalloc (sizeof (char *));
                    118:       aclens = (size_t *) xmalloc (sizeof (size_t));
                    119:     }
                    120:   else
                    121:     {
                    122:       char **pz;
                    123: 
                    124:       /* We leave string number 0 for the chat script.  */
                    125:       cstrings = 1;
                    126:       for (pz = qchat->uuconf_pzfail; *pz != NULL; pz++)
                    127:        ++cstrings;
                    128: 
                    129:       azstrings = (char **) xmalloc (cstrings * sizeof (char *));
                    130:       aclens = (size_t *) xmalloc (cstrings * sizeof (size_t));
                    131: 
                    132:       /* Get the strings into the array, and handle all the escape
                    133:         characters.  */
                    134:       for (cstrings = 1, pz = qchat->uuconf_pzfail;
                    135:           *pz != NULL;
                    136:           cstrings++, pz++)
                    137:        {
                    138:          azstrings[cstrings] = zbufcpy (*pz);
                    139:          aclens[cstrings] = cescape (azstrings[cstrings]);
                    140:        }
                    141:     }
                    142: 
                    143:   cbuflen = 0;
                    144:   zbuf = NULL;
                    145:   fret = TRUE;
                    146: 
                    147:   pzchat = qchat->uuconf_pzchat;
                    148: 
                    149:   while (*pzchat != NULL)
                    150:     {
                    151:       size_t clen;
                    152: 
                    153:       /* Loop over subexpects and subsends.  */
                    154:       while (TRUE)
                    155:        {
                    156:          /* Copy the expect string into the buffer so that we can
                    157:             modify it in cescape.  */
                    158:          clen = strlen (*pzchat);
                    159:          if (clen >= cbuflen)
                    160:            {
                    161:              ubuffree (zbuf);
                    162:              zbuf = zbufalc (clen + 1);
                    163:              cbuflen = clen;
                    164:            }
                    165:          memcpy (zbuf, *pzchat, clen + 1);
                    166: 
                    167:          azstrings[0] = zbuf;
                    168:          if (azstrings[0][0] == '-')
                    169:            ++azstrings[0];
                    170:          aclens[0] = cescape (azstrings[0]);
                    171: 
                    172:          if (aclens[0] == 0
                    173:              || (aclens[0] == 2
                    174:                  && strcmp (azstrings[0], "\"\"") == 0))
                    175:            {
                    176:              /* There is no subexpect sequence.  If there is a
                    177:                 subsend sequence we move on to it.  Otherwise we let
                    178:                 this expect succeed.  This is somewhat inconsistent,
                    179:                 but it seems to be the traditional approach.  */
                    180:              if (pzchat[1] == NULL || pzchat[1][0] != '-')
                    181:                break;
                    182:            }
                    183:          else
                    184:            {
                    185:              int istr;
                    186: 
                    187:              istr = icexpect (qconn, cstrings, azstrings, aclens,
                    188:                               qchat->uuconf_ctimeout,
                    189:                               qchat->uuconf_fstrip);
                    190: 
                    191:              /* If we found the string, break out of the
                    192:                 subexpect/subsend loop.  */
                    193:              if (istr == 0)
                    194:                break;
                    195: 
                    196:              /* If we got an error, return FALSE.  */
                    197:              if (istr < -1)
                    198:                {
                    199:                  fret = FALSE;
                    200:                  break;
                    201:                }
                    202: 
                    203:              /* If we found a failure string, log it and get out.  */
                    204:              if (istr > 0)
                    205:                {
                    206:                  ulog (LOG_ERROR, "Chat script failed: Got \"%s\"",
                    207:                        qchat->uuconf_pzfail[istr - 1]);
                    208:                  fret = FALSE;
                    209:                  break;
                    210:                }
                    211: 
                    212:              /* We timed out; look for a send subsequence.  If none,
                    213:                 the chat script has failed.  */
                    214:              if (pzchat[1] == NULL || pzchat[1][0] != '-')
                    215:                {
                    216:                  ulog (LOG_ERROR, "Timed out in chat script");
                    217:                  fret = FALSE;
                    218:                  break;
                    219:                }
                    220:            }
                    221: 
                    222:          /* Send the send subsequence without the leading '-'.  A
                    223:             \"\" will send nothing.  An empty string will send a
                    224:             carriage return.  */
                    225:          ++pzchat;
                    226:          if (! fcsend (qconn, puuconf, *pzchat + 1, qsys, qdial, zphone,
                    227:                        ftranslate, qchat->uuconf_fstrip))
                    228:            {
                    229:              fret = FALSE;
                    230:              break;
                    231:            }
                    232: 
                    233:          /* If there is no expect subsequence, we are done.  */
                    234:          if (pzchat[1] == NULL || pzchat[1][0] != '-')
                    235:            break;
                    236: 
                    237:          /* Move on to next expect subsequence.  */
                    238:          ++pzchat;
                    239:        }
                    240: 
                    241:       if (! fret)
                    242:        break;
                    243: 
                    244:       /* Move on to the send string.  If there is none, we have
                    245:         succeeded.  */
                    246:       do
                    247:        {
                    248:          ++pzchat;
                    249:        }
                    250:       while (*pzchat != NULL && (*pzchat)[0] == '-');
                    251: 
                    252:       if (*pzchat == NULL)
                    253:        break;
                    254: 
                    255:       if (**pzchat != '\0')
                    256:        {
                    257:          if (! fcsend (qconn, puuconf, *pzchat, qsys, qdial, zphone,
                    258:                        ftranslate, qchat->uuconf_fstrip))
                    259:            {
                    260:              fret = FALSE;
                    261:              break;
                    262:            }
                    263:        }
                    264: 
                    265:       ++pzchat;
                    266:     }
                    267: 
                    268:   ubuffree (zbuf);
                    269:   for (i = 1; i < cstrings; i++)
                    270:     ubuffree (azstrings[i]);
                    271:   xfree ((pointer) azstrings);
                    272:   xfree ((pointer) aclens);
                    273: 
                    274:   return fret;
                    275: }
                    276: 
                    277: /* Read characters and wait for one of a set of memory strings to come
                    278:    in.  This returns the index into the array of the string that
                    279:    arrives, or -1 on timeout, or -2 on error.  */
                    280: 
                    281: static int
                    282: icexpect (qconn, cstrings, azstrings, aclens, ctimeout, fstrip)
                    283:      struct sconnection *qconn;
                    284:      int cstrings;
                    285:      char **azstrings;
                    286:      size_t *aclens;
                    287:      int ctimeout;
                    288:      boolean fstrip;
                    289: {
                    290:   int i;
                    291:   size_t cmax;
                    292:   char *zhave;
                    293:   size_t chave;
                    294:   long iendtime;
                    295: #if DEBUG > 1
                    296:   int cchars;
                    297:   int iolddebug;
                    298: #endif
                    299: 
                    300:   cmax = aclens[0];
                    301:   for (i = 1; i < cstrings; i++)
                    302:     if (cmax < aclens[i])
                    303:       cmax = aclens[i];
                    304: 
                    305:   zhave = zbufalc (cmax);
                    306:   chave = 0;
                    307: 
                    308:   iendtime = ixsysdep_time ((long *) NULL) + ctimeout;
                    309: 
                    310: #if DEBUG > 1
                    311:   cchars = 0;
                    312:   iolddebug = iDebug;
                    313:   if (FDEBUGGING (DEBUG_CHAT))
                    314:     {
                    315:       udebug_buffer ("icexpect: Looking for", azstrings[0],
                    316:                     aclens[0]);
                    317:       ulog (LOG_DEBUG_START, "icexpect: Got \"");
                    318:       iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT);
                    319:     }
                    320: #endif
                    321: 
                    322:   while (TRUE)
                    323:     {
                    324:       int bchar;
                    325: 
                    326:       /* If we have no more time, get out.  */
                    327:       if (ctimeout <= 0)
                    328:        {
                    329: #if DEBUG > 1
                    330:          if (FDEBUGGING (DEBUG_CHAT))
                    331:            {
                    332:              ulog (LOG_DEBUG_END, "\" (timed out)");
                    333:              iDebug = iolddebug;
                    334:            }
                    335: #endif
                    336:          ubuffree (zhave);
                    337:          return -1;
                    338:        }
                    339: 
                    340:       /* Read one character at a time.  We could use a more complex
                    341:         algorithm to read in larger batches, but it's probably not
                    342:         worth it.  If the buffer is full, shift it left; we already
                    343:         know that no string matches, and the buffer holds the largest
                    344:         string, so this can't lose a match.  */
                    345:       if (chave >= cmax)
                    346:        {
                    347:          size_t imove;
                    348: 
                    349:          for (imove = 0; imove < cmax - 1; imove++)
                    350:            zhave[imove] = zhave[imove + 1];
                    351:          --chave;
                    352:        }
                    353: 
                    354:       /* The timeout/error return values from breceive_char are the
                    355:         same as for this function.  */
                    356:       bchar = breceive_char (qconn, ctimeout, TRUE);
                    357:       if (bchar < 0)
                    358:        {
                    359: #if DEBUG > 1
                    360:          if (FDEBUGGING (DEBUG_CHAT))
                    361:            {
                    362:              /* If there was an error, it will probably be logged in
                    363:                 the middle of our string, but this is only debugging
                    364:                 so it's not a big deal.  */
                    365:              ulog (LOG_DEBUG_END, "\" (%s)",
                    366:                    bchar == -1 ? "timed out" : "error");
                    367:              iDebug = iolddebug;
                    368:            }
                    369: #endif
                    370:          ubuffree (zhave);
                    371:          return bchar;
                    372:        }
                    373: 
                    374:       /* Strip the parity bit if desired.  */
                    375:       if (fstrip)
                    376:        bchar &= 0x7f;
                    377: 
                    378:       zhave[chave] = (char) bchar;
                    379:       ++chave;
                    380: 
                    381: #if DEBUG > 1
                    382:       if (FDEBUGGING (DEBUG_CHAT))
                    383:        {
                    384:          char ab[5];
                    385: 
                    386:          ++cchars;
                    387:          if (cchars > 60)
                    388:            {
                    389:              ulog (LOG_DEBUG_END, "\"");
                    390:              ulog (LOG_DEBUG_START, "icexpect: Got \"");
                    391:              cchars = 0;
                    392:            }
                    393:          (void) cdebug_char (ab, bchar);
                    394:          ulog (LOG_DEBUG_CONTINUE, "%s", ab);
                    395:        }
                    396: #endif
                    397: 
                    398:       /* See if any of the strings can be found in the buffer.  Since
                    399:         we read one character at a time, the string can only be found
                    400:         at the end of the buffer.  */
                    401:       for (i = 0; i < cstrings; i++)
                    402:        {
                    403:          if (aclens[i] <= chave
                    404:              && memcmp (zhave + chave - aclens[i], azstrings[i],
                    405:                         aclens[i]) == 0)
                    406:            {
                    407: #if DEBUG > 1
                    408:              if (FDEBUGGING (DEBUG_CHAT))
                    409:                {
                    410:                  if (i == 0)
                    411:                    ulog (LOG_DEBUG_END, "\" (found it)");
                    412:                  else
                    413:                    {
                    414:                      ulog (LOG_DEBUG_END, "\"");
                    415:                      udebug_buffer ("icexpect: Found", azstrings[i],
                    416:                                     aclens[i]);
                    417:                    }
                    418:                  iDebug = iolddebug;
                    419:                }
                    420: #endif
                    421:              ubuffree (zhave);
                    422:              return i;
                    423:            }
                    424:        }
                    425: 
                    426:       ctimeout = (int) (iendtime - ixsysdep_time ((long *) NULL));
                    427:     }
                    428: }
                    429: 
                    430: #if DEBUG > 1
                    431: 
                    432: /* Debugging function for fcsend.  This takes the fquote variable, the
                    433:    length of the string (0 if this an informational string which can
                    434:    be printed directly) and the string itself.  It returns the new
                    435:    value for fquote.  The fquote variable is TRUE if the debugging
                    436:    output is in the middle of a quoted string.  */
                    437: 
                    438: static size_t cCsend_chars;
                    439: static int iColddebug;
                    440: 
                    441: static boolean fcsend_debug P((boolean, size_t, const char *));
                    442: 
                    443: static boolean
                    444: fcsend_debug (fquote, clen, zbuf)
                    445:      boolean fquote;
                    446:      size_t clen;
                    447:      const char *zbuf;
                    448: {
                    449:   size_t cwas;
                    450: 
                    451:   if (! FDEBUGGING (DEBUG_CHAT))
                    452:     return TRUE;
                    453: 
                    454:   cwas = cCsend_chars;
                    455:   if (clen > 0)
                    456:     cCsend_chars += clen;
                    457:   else
                    458:     cCsend_chars += strlen (zbuf);
                    459:   if (cCsend_chars > 60 && cwas > 10)
                    460:     {
                    461:       ulog (LOG_DEBUG_END, "%s", fquote ? "\"" : "");
                    462:       fquote = FALSE;
                    463:       ulog (LOG_DEBUG_START, "fcsend: Writing");
                    464:       cCsend_chars = 0;
                    465:     }
                    466: 
                    467:   if (clen == 0)
                    468:     {
                    469:       ulog (LOG_DEBUG_CONTINUE, "%s %s", fquote ? "\"" : "", zbuf);
                    470:       return FALSE;
                    471:     }
                    472:   else
                    473:     {
                    474:       int i;
                    475: 
                    476:       if (! fquote)
                    477:        ulog (LOG_DEBUG_CONTINUE, " \"");
                    478:       for (i = 0; i < clen; i++)
                    479:        {
                    480:          char ab[5];
                    481: 
                    482:          (void) cdebug_char (ab, zbuf[i]);
                    483:          ulog (LOG_DEBUG_CONTINUE, "%s", ab);
                    484:        }
                    485: 
                    486:       return TRUE;
                    487:     }
                    488: }
                    489: 
                    490: /* Finish up the debugging information for fcsend.  */
                    491: 
                    492: static void ucsend_debug_end P((boolean, boolean));
                    493: 
                    494: static void
                    495: ucsend_debug_end (fquote, ferr)
                    496:      boolean fquote;
                    497:      boolean ferr;
                    498: {
                    499:   if (! FDEBUGGING (DEBUG_CHAT))
                    500:     return;
                    501: 
                    502:   if (fquote)
                    503:     ulog (LOG_DEBUG_CONTINUE, "\"");
                    504: 
                    505:   if (ferr)
                    506:     ulog (LOG_DEBUG_CONTINUE, " (error)");
                    507: 
                    508:   ulog (LOG_DEBUG_END, "%s", "");
                    509: 
                    510:   iDebug = iColddebug;
                    511: }
                    512: 
                    513: #else /* DEBUG <= 1 */
                    514: 
                    515: /* Use macro definitions to make fcsend look neater.  */
                    516: 
                    517: #define fcsend_debug(fquote, clen, zbuf) TRUE
                    518: 
                    519: #define ucsend_debug_end(fquote, ferror)
                    520: 
                    521: #endif /* DEBUG <= 1 */
                    522: 
                    523: /* Send a string out.  This has to parse escape sequences as it goes.
                    524:    Note that it handles the dialer escape sequences (\e, \E, \D, \T)
                    525:    although they make no sense for chatting with a system.  */
                    526: 
                    527: static boolean
                    528: fcsend (qconn, puuconf, z, qsys, qdial, zphone, ftranslate, fstrip)
                    529:      struct sconnection *qconn;
                    530:      pointer puuconf;
                    531:      const char *z;
                    532:      const struct uuconf_system *qsys;
                    533:      const struct uuconf_dialer *qdial;
                    534:      const char *zphone;
                    535:      boolean ftranslate;
                    536:      boolean fstrip;
                    537: {
                    538:   boolean fnocr;
                    539:   boolean (*pfwrite) P((struct sconnection *, const char *, size_t));
                    540:   char *zcallout_login;
                    541:   char *zcallout_pass;
                    542:   boolean fquote;
                    543: 
                    544:   if (strcmp (z, "\"\"") == 0)
                    545:     return TRUE;
                    546: 
                    547:   fnocr = FALSE;
                    548:   pfwrite = fconn_write;
                    549:   zcallout_login = NULL;
                    550:   zcallout_pass = NULL;
                    551: 
                    552: #if DEBUG > 1
                    553:   if (FDEBUGGING (DEBUG_CHAT))
                    554:     {
                    555:       ulog (LOG_DEBUG_START, "fcsend: Writing");
                    556:       fquote = FALSE;
                    557:       cCsend_chars = 0;
                    558:       iColddebug = iDebug;
                    559:       iDebug &=~ (DEBUG_OUTGOING | DEBUG_PORT);
                    560:     }
                    561: #endif
                    562: 
                    563:   while (*z != '\0')
                    564:     {
                    565:       const char *zlook;
                    566:       boolean fsend;
                    567:       char bsend;
                    568: 
                    569:       zlook = z + strcspn ((char *) z, "\\BE");
                    570: 
                    571:       if (zlook > z)
                    572:        {
                    573:          size_t c;
                    574: 
                    575:          c = zlook - z;
                    576:          fquote = fcsend_debug (fquote, c, z);
                    577:          if (! (*pfwrite) (qconn, z, c))
                    578:            {
                    579:              ucsend_debug_end (fquote, TRUE);
                    580:              return FALSE;
                    581:            }
                    582:        }
                    583: 
                    584:       if (*zlook == '\0')
                    585:        break;
                    586: 
                    587:       z = zlook;
                    588: 
                    589:       fsend = FALSE;
                    590:       switch (*z)
                    591:        {
                    592:        case 'B':
                    593:          if (strncmp (z, "BREAK", 5) == 0)
                    594:            {
                    595:              fquote = fcsend_debug (fquote, (size_t) 0, "break");
                    596:              if (! fconn_break (qconn))
                    597:                {
                    598:                  ucsend_debug_end (fquote, TRUE);
                    599:                  return FALSE;
                    600:                }
                    601:              fnocr = TRUE;
                    602:              z += 5;
                    603:            }
                    604:          else
                    605:            {
                    606:              fsend = TRUE;
                    607:              bsend = 'B';
                    608:              ++z;
                    609:            }
                    610:          break;
                    611:        case 'E':
                    612:          if (strncmp (z, "EOT", 3) == 0)
                    613:            {
                    614:              fsend = TRUE;
                    615:              bsend = '\004';
                    616:              fnocr = TRUE;
                    617:              z += 3;
                    618:            }
                    619:          else
                    620:            {
                    621:              fsend = TRUE;
                    622:              bsend = 'E';
                    623:              ++z;
                    624:            }
                    625:          break;
                    626:        case '\\':
                    627:          ++z;
                    628:          switch (*z)
                    629:            {
                    630:            case '-':
                    631:              fsend = TRUE;
                    632:              bsend = '-';
                    633:              break;
                    634:            case 'b':
                    635:              fsend = TRUE;
                    636:              bsend = '\b';
                    637:              break;
                    638:            case 'c':
                    639:              fnocr = TRUE;
                    640:              break;
                    641:            case 'd':
                    642:              fquote = fcsend_debug (fquote, (size_t) 0, "sleep");
                    643:              usysdep_sleep (2);
                    644:              break;
                    645:            case 'e':
                    646:              fquote = fcsend_debug (fquote, (size_t) 0, "echo-check-off");
                    647:              pfwrite = fconn_write;
                    648:              break;
                    649:            case 'E':
                    650:              fquote = fcsend_debug (fquote, (size_t) 0, "echo-check-on");
                    651:              if (fstrip)
                    652:                pfwrite = fcecho_send_strip;
                    653:              else
                    654:                pfwrite = fcecho_send_nostrip;
                    655:              break;
                    656:            case 'K':
                    657:              fquote = fcsend_debug (fquote, (size_t) 0, "break");
                    658:              if (! fconn_break (qconn))
                    659:                {
                    660:                  ucsend_debug_end (fquote, TRUE);
                    661:                  return FALSE;
                    662:                }
                    663:              break;
                    664:            case 'n':
                    665:              fsend = TRUE;
                    666:              bsend = '\n';
                    667:              break;
                    668:            case 'N':
                    669:              fsend = TRUE;
                    670:              bsend = '\0';
                    671:              break;
                    672:            case 'p':
                    673:              fquote = fcsend_debug (fquote, (size_t) 0, "pause");
                    674:              usysdep_pause ();
                    675:              break;
                    676:            case 'r':
                    677:              fsend = TRUE;
                    678:              bsend = '\r';
                    679:              break;
                    680:            case 's':
                    681:              fsend = TRUE;
                    682:              bsend = ' ';
                    683:              break;
                    684:            case 't':
                    685:              fsend = TRUE;
                    686:              bsend = '\t';
                    687:              break;
                    688:            case '\0':
                    689:              --z;
                    690:              /* Fall through.  */
                    691:            case '\\':
                    692:              fsend = TRUE;
                    693:              bsend = '\\';
                    694:              break;
                    695:            case '0': case '1': case '2': case '3': case '4':
                    696:            case '5': case '6': case '7': case '8': case '9':
                    697:              fsend = TRUE;
                    698:              bsend = *z - '0';
                    699:              if (z[1] >= '0' && z[1] <= '7')
                    700:                bsend = (char) (8 * bsend + *++z - '0');
                    701:              if (z[1] >= '0' && z[1] <= '7')
                    702:                bsend = (char) (8 * bsend + *++z - '0');
                    703:              break;
                    704:            case 'x':
                    705:              fsend = TRUE;
                    706:              bsend = 0;
                    707:              while (isxdigit (BUCHAR (z[1])))
                    708:                {
                    709:                  if (isdigit (BUCHAR (z[1])))
                    710:                    bsend = (char) (16 * bsend + *++z - '0');
                    711:                  else if (isupper (BUCHAR (z[1])))
                    712:                    bsend = (char) (16 * bsend + *++z - 'A');
                    713:                  else
                    714:                    bsend = (char) (16 * bsend + *++z - 'a');
                    715:                }
                    716:              break;
                    717:            case 'L':
                    718:              {
                    719:                const char *zlog;
                    720: 
                    721:                if (qsys == NULL)
                    722:                  {
                    723:                    ucsend_debug_end (fquote, TRUE);
                    724:                    ulog (LOG_ERROR, "Illegal use of \\L");
                    725:                    return FALSE;
                    726:                  }
                    727:                zlog = qsys->uuconf_zcall_login;
                    728:                if (zlog == NULL)
                    729:                  {
                    730:                    ucsend_debug_end (fquote, TRUE);
                    731:                    ulog (LOG_ERROR, "No login defined");
                    732:                    return FALSE;
                    733:                  }
                    734:                if (zlog[0] == '*' && zlog[1] == '\0')
                    735:                  {
                    736:                    if (zcallout_login == NULL)
                    737:                      {
                    738:                        int iuuconf;
                    739: 
                    740:                        iuuconf = uuconf_callout (puuconf, qsys,
                    741:                                                  &zcallout_login,
                    742:                                                  &zcallout_pass);
                    743:                        if (iuuconf == UUCONF_NOT_FOUND
                    744:                            || zcallout_login == NULL)
                    745:                          {
                    746:                            ucsend_debug_end (fquote, TRUE);
                    747:                            ulog (LOG_ERROR, "No login defined");
                    748:                            return FALSE;
                    749:                          }
                    750:                        else if (iuuconf != UUCONF_SUCCESS)
                    751:                          {
                    752:                            ucsend_debug_end (fquote, TRUE);
                    753:                            ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                    754:                            return FALSE;
                    755:                          }
                    756:                      }
                    757:                    zlog = zcallout_login;
                    758:                  }
                    759:                fquote = fcsend_debug (fquote, (size_t) 0, "login");
                    760:                fquote = fcsend_debug (fquote, strlen (zlog), zlog);
                    761:                if (! (*pfwrite) (qconn, zlog, strlen (zlog)))
                    762:                  {
                    763:                    ucsend_debug_end (fquote, TRUE);
                    764:                    return FALSE;
                    765:                  }
                    766:              }
                    767:              break;
                    768:            case 'P':
                    769:              {
                    770:                const char *zpass;
                    771: 
                    772:                if (qsys == NULL)
                    773:                  {
                    774:                    ucsend_debug_end (fquote, TRUE);
                    775:                    ulog (LOG_ERROR, "Illegal use of \\P");
                    776:                    return FALSE;
                    777:                  }
                    778:                zpass = qsys->uuconf_zcall_password;
                    779:                if (zpass == NULL)
                    780:                  {
                    781:                    ucsend_debug_end (fquote, TRUE);
                    782:                    ulog (LOG_ERROR, "No password defined");
                    783:                    return FALSE;
                    784:                  }
                    785:                if (zpass[0] == '*' && zpass[1] == '\0')
                    786:                  {
                    787:                    if (zcallout_pass == NULL)
                    788:                      {
                    789:                        int iuuconf;
                    790: 
                    791:                        iuuconf = uuconf_callout (puuconf, qsys,
                    792:                                                  &zcallout_login,
                    793:                                                  &zcallout_pass);
                    794:                        if (iuuconf == UUCONF_NOT_FOUND
                    795:                            || zcallout_pass == NULL)
                    796:                          {
                    797:                            ucsend_debug_end (fquote, TRUE);
                    798:                            ulog (LOG_ERROR, "No password defined");
                    799:                            return FALSE;
                    800:                          }
                    801:                        else if (iuuconf != UUCONF_SUCCESS)
                    802:                          {
                    803:                            ucsend_debug_end (fquote, TRUE);
                    804:                            ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                    805:                            return FALSE;
                    806:                          }
                    807:                      }
                    808:                    zpass = zcallout_pass;
                    809:                  }
                    810:                fquote = fcsend_debug (fquote, (size_t) 0, "password");
                    811:                fquote = fcsend_debug (fquote, strlen (zpass), zpass);
                    812:                if (! (*pfwrite) (qconn, zpass, strlen (zpass)))
                    813:                  {
                    814:                    ucsend_debug_end (fquote, TRUE);
                    815:                    return FALSE;
                    816:                  }
                    817:              }
                    818:              break;
                    819:            case 'D':
                    820:              if (qdial == NULL || zphone == NULL)
                    821:                {
                    822:                  ucsend_debug_end (fquote, TRUE);
                    823:                  ulog (LOG_ERROR, "Illegal use of \\D");
                    824:                  return FALSE;
                    825:                }
                    826:              fquote = fcsend_debug (fquote, (size_t) 0, "\\D");
                    827:              if (! fcphone (qconn, puuconf, qdial, zphone, pfwrite,
                    828:                             ftranslate, &fquote))
                    829:                {
                    830:                  ucsend_debug_end (fquote, TRUE);
                    831:                  return FALSE;
                    832:                }
                    833:              break;
                    834:            case 'T':
                    835:              if (qdial == NULL || zphone == NULL)
                    836:                {
                    837:                  ucsend_debug_end (fquote, TRUE);
                    838:                  ulog (LOG_ERROR, "Illegal use of \\T");
                    839:                  return FALSE;
                    840:                }
                    841:              fquote = fcsend_debug (fquote, (size_t) 0, "\\T");
                    842:              if (! fcphone (qconn, puuconf, qdial, zphone, pfwrite, TRUE,
                    843:                             &fquote))
                    844:                {
                    845:                  ucsend_debug_end (fquote, TRUE);
                    846:                  return FALSE;
                    847:                }
                    848:              break;
                    849:            case 'M':
                    850:              if (qdial == NULL)
                    851:                {
                    852:                  ucsend_debug_end (fquote, TRUE);
                    853:                  ulog (LOG_ERROR, "Illegal use of \\M");
                    854:                  return FALSE;
                    855:                }
                    856:              fquote = fcsend_debug (fquote, (size_t) 0, "ignore-carrier");
                    857:              if (! fconn_carrier (qconn, FALSE))
                    858:                {
                    859:                  ucsend_debug_end (fquote, TRUE);
                    860:                  return FALSE;
                    861:                }
                    862:              break;
                    863:            case 'm':
                    864:              if (qdial == NULL)
                    865:                {
                    866:                  ucsend_debug_end (fquote, TRUE);
                    867:                  ulog (LOG_ERROR, "Illegal use of \\m");
                    868:                  return FALSE;
                    869:                }
                    870:              if (qdial->uuconf_fcarrier)
                    871:                {
                    872:                  fquote = fcsend_debug (fquote, (size_t) 0, "need-carrier");
                    873:                  if (! fconn_carrier (qconn, TRUE))
                    874:                    {
                    875:                      ucsend_debug_end (fquote, TRUE);
                    876:                      return FALSE;
                    877:                    }
                    878:                }
                    879:              break;
                    880:            default:
                    881:              /* This error message will screw up any debugging
                    882:                 information, but it's easily avoidable.  */
                    883:              ulog (LOG_ERROR,
                    884:                    "Unrecognized escape sequence \\%c in send string",
                    885:                    *z);
                    886:              fsend = TRUE;
                    887:              bsend = *z;
                    888:              break;
                    889:            }
                    890:          ++z;
                    891:          break;
                    892: #if DEBUG > 0
                    893:        default:
                    894:          ulog (LOG_FATAL, "fcsend: Can't happen");
                    895:          break;
                    896: #endif
                    897:        }
                    898:       
                    899:       if (fsend)
                    900:        {
                    901:          fquote = fcsend_debug (fquote, (size_t) 1, &bsend);
                    902:          if (! (*pfwrite) (qconn, &bsend, (size_t) 1))
                    903:            {
                    904:              ucsend_debug_end (fquote, TRUE);
                    905:              return FALSE;
                    906:            }
                    907:        }
                    908:     }
                    909: 
                    910:   xfree ((pointer) zcallout_login);
                    911:   xfree ((pointer) zcallout_pass);
                    912: 
                    913:   /* Output a final carriage return, unless there was a \c.  Don't
                    914:      bother to check for an echo.  */
                    915:   if (! fnocr)
                    916:     {
                    917:       char b;
                    918: 
                    919:       b = '\r';
                    920:       fquote = fcsend_debug (fquote, (size_t) 1, &b);
                    921:       if (! fconn_write (qconn, &b, (size_t) 1))
                    922:        {
                    923:          ucsend_debug_end (fquote, TRUE);
                    924:          return FALSE;
                    925:        }
                    926:     }
                    927: 
                    928:   ucsend_debug_end (fquote, FALSE);
                    929: 
                    930:   return TRUE;
                    931: }
                    932: 
                    933: /* Write out a phone number with optional dialcode translation.  The
                    934:    pfquote argument is only used for debugging.  */
                    935: 
                    936: static boolean
                    937: fcphone (qconn, puuconf, qdial, zphone, pfwrite, ftranslate, pfquote)
                    938:      struct sconnection *qconn;
                    939:      pointer puuconf;
                    940:      const struct uuconf_dialer *qdial;
                    941:      const char *zphone;
                    942:      boolean (*pfwrite) P((struct sconnection *qc, const char *zwrite,
                    943:                           size_t cwrite));
                    944:      boolean ftranslate;
                    945:      boolean *pfquote;
                    946: {
                    947:   const char *zprefix, *zsuffix;
                    948: 
                    949:   if (ftranslate)
                    950:     {
                    951:       if (! fctranslate (puuconf, zphone, &zprefix, &zsuffix))
                    952:        return FALSE;
                    953:     }
                    954:   else
                    955:     {
                    956:       zprefix = zphone;
                    957:       zsuffix = NULL;
                    958:     }
                    959: 
                    960:   while (zprefix != NULL)
                    961:     {
                    962:       while (TRUE)
                    963:        {
                    964:          const char *z;
                    965:          const char *zstr;
                    966: 
                    967:          z = zprefix + strcspn ((char *) zprefix, "=-");
                    968:          if (z > zprefix)
                    969:            {
                    970:              size_t clen;
                    971: 
                    972:              clen = z - zprefix;
                    973:              *pfquote = fcsend_debug (*pfquote, clen, zprefix);
                    974:              if (! (*pfwrite) (qconn, zprefix, clen))
                    975:                return FALSE;
                    976:            }
                    977: 
                    978:          if (*z == '=')
                    979:            zstr = qdial->uuconf_zdialtone;
                    980:          else if (*z == '-')
                    981:            zstr = qdial->uuconf_zpause;
                    982:          else                  /* *z == '\0' */
                    983:            break;
                    984: 
                    985:          if (zstr != NULL)
                    986:            {
                    987:              *pfquote = fcsend_debug (*pfquote, strlen (zstr), zstr);
                    988:              if (! (*pfwrite) (qconn, zstr, strlen (zstr)))
                    989:                return FALSE;
                    990:            }
                    991: 
                    992:          zprefix = z + 1;
                    993:        }
                    994: 
                    995:       zprefix = zsuffix;
                    996:       zsuffix = NULL;
                    997:     }
                    998: 
                    999:   return TRUE;
                   1000: }
                   1001: 
                   1002: /* Given a phone number, run it through dial code translation
                   1003:    returning two strings.  */
                   1004: 
                   1005: static boolean
                   1006: fctranslate (puuconf, zphone, pzprefix, pzsuffix)
                   1007:      pointer puuconf;
                   1008:      const char *zphone;
                   1009:      const char **pzprefix;
                   1010:      const char **pzsuffix;
                   1011: {
                   1012:   int iuuconf;
                   1013:   char *zdialcode, *zto;
                   1014:   const char *zfrom;
                   1015:   char *ztrans;
                   1016: 
                   1017:   *pzprefix = zphone;
                   1018:   *pzsuffix = NULL;
                   1019: 
                   1020:   zdialcode = zbufalc (strlen (zphone) + 1);
                   1021:   zfrom = zphone;
                   1022:   zto = zdialcode;
                   1023:   while (*zfrom != '\0' && isalpha (BUCHAR (*zfrom)))
                   1024:     *zto++ = *zfrom++;
                   1025:   *zto = '\0';
                   1026: 
                   1027:   if (*zdialcode == '\0')
                   1028:     {
                   1029:       ubuffree (zdialcode);
                   1030:       return TRUE;
                   1031:     }
                   1032: 
                   1033:   iuuconf = uuconf_dialcode (puuconf, zdialcode, &ztrans);
                   1034: 
                   1035:   ubuffree (zdialcode);
                   1036: 
                   1037:   if (iuuconf == UUCONF_NOT_FOUND)
                   1038:     return TRUE;
                   1039:   else if (iuuconf != UUCONF_SUCCESS)
                   1040:     {
                   1041:       ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                   1042:       return FALSE;
                   1043:     }
                   1044:   else
                   1045:     {
                   1046:       /* We really should figure out a way to free up ztrans here.  */
                   1047:       *pzprefix = ztrans;
                   1048:       *pzsuffix = zfrom;
                   1049:       return TRUE;
                   1050:     }
                   1051: }
                   1052: 
                   1053: /* Write out a string making sure the each character is echoed back.
                   1054:    There are two versions of this function, one which strips the
                   1055:    parity bit from the characters and one which does not.  This is so
                   1056:    that I can use a single function pointer in fcsend, and to avoid
                   1057:    using any static variables so that I can put chat scripts in a
                   1058:    library some day.  */
                   1059: 
                   1060: static boolean
                   1061: fcecho_send_strip (qconn, zwrite, cwrite)
                   1062:      struct sconnection *qconn;
                   1063:      const char *zwrite;
                   1064:      size_t cwrite;
                   1065: {
                   1066:   return fcecho_send (qconn, zwrite, cwrite, TRUE);
                   1067: }
                   1068: 
                   1069: static boolean
                   1070: fcecho_send_nostrip (qconn, zwrite, cwrite)
                   1071:      struct sconnection *qconn;
                   1072:      const char *zwrite;
                   1073:      size_t cwrite;
                   1074: {
                   1075:   return fcecho_send (qconn, zwrite, cwrite, FALSE);
                   1076: }
                   1077: 
                   1078: static boolean
                   1079: fcecho_send (qconn, zwrite, cwrite, fstrip)
                   1080:      struct sconnection *qconn;
                   1081:      const char *zwrite;
                   1082:      size_t cwrite;
                   1083:      boolean fstrip;
                   1084: {
                   1085:   const char *zend;
                   1086: 
                   1087:   zend = zwrite + cwrite;
                   1088: 
                   1089:   for (; zwrite < zend; zwrite++)
                   1090:     {
                   1091:       int b;
                   1092:       char bwrite;
                   1093: 
                   1094:       bwrite = *zwrite;
                   1095:       if (! fconn_write (qconn, &bwrite, (size_t) 1))
                   1096:        return FALSE;
                   1097:       if (fstrip)
                   1098:        bwrite &= 0x7f;
                   1099:       do
                   1100:        {
                   1101:          /* We arbitrarily wait five seconds for the echo.  */
                   1102:          b = breceive_char (qconn, 5, TRUE);
                   1103:          /* Now b == -1 on timeout, -2 on error.  */
                   1104:          if (b < 0)
                   1105:            {
                   1106:              if (b == -1)
                   1107:                ulog (LOG_ERROR, "Character not echoed");
                   1108:              return FALSE;
                   1109:            }
                   1110:          if (fstrip)
                   1111:            b &= 0x7f;
                   1112:        }
                   1113:       while (b != BUCHAR (bwrite));
                   1114:     }
                   1115: 
                   1116:   return TRUE;
                   1117: }
                   1118: 
                   1119: /* Run a chat program.  Expand any escape sequences and call a system
                   1120:    dependent program to run it.  */
                   1121: 
                   1122: static boolean
                   1123: fcprogram (qconn, puuconf, pzprogram, qsys, qdial, zphone, zport, ibaud)
                   1124:      struct sconnection *qconn;
                   1125:      pointer puuconf;
                   1126:      char **pzprogram;
                   1127:      const struct uuconf_system *qsys;
                   1128:      const struct uuconf_dialer *qdial;
                   1129:      const char *zphone;
                   1130:      const char *zport;
                   1131:      long ibaud;
                   1132: {
                   1133:   size_t cargs;
                   1134:   char **pzpass, **pzarg;
                   1135:   char **pz;
                   1136:   char *zcallout_login;
                   1137:   char *zcallout_pass;
                   1138:   boolean fret;
                   1139: 
                   1140:   cargs = 1;
                   1141:   for (pz = pzprogram; *pz != NULL; pz++)
                   1142:     ++cargs;
                   1143: 
                   1144:   pzpass = (char **) xmalloc (cargs * sizeof (char *));
                   1145: 
                   1146:   zcallout_login = NULL;
                   1147:   zcallout_pass = NULL;
                   1148:   fret = TRUE;
                   1149: 
                   1150:   /* Copy the string into memory expanding escape sequences.  */
                   1151:   for (pz = pzprogram, pzarg = pzpass; *pz != NULL; pz++, pzarg++)
                   1152:     {
                   1153:       const char *zfrom;
                   1154:       size_t calc, clen;
                   1155:       char *zto;
                   1156: 
                   1157:       if (strchr (*pz, '\\') == NULL)
                   1158:        {
                   1159:          *pzarg = zbufcpy (*pz);
                   1160:          continue;
                   1161:        }
                   1162:       
                   1163:       *pzarg = NULL;
                   1164:       zto = NULL;
                   1165:       calc = 0;
                   1166:       clen = 0;
                   1167: 
                   1168:       for (zfrom = *pz; *zfrom != '\0'; zfrom++)
                   1169:        {
                   1170:          const char *zadd = NULL;
                   1171:          size_t cadd;
                   1172:          char abadd[15];
                   1173: 
                   1174:          if (*zfrom != '\\')
                   1175:            {
                   1176:              if (clen + 2 > calc)
                   1177:                {
                   1178:                  char *znew;
                   1179: 
                   1180:                  calc = clen + 50;
                   1181:                  znew = zbufalc (calc);
                   1182:                  memcpy (znew, *pzarg, clen);
                   1183:                  ubuffree (*pzarg);
                   1184:                  *pzarg = znew;
                   1185:                  zto = znew + clen;
                   1186:                }
                   1187:              *zto++ = *zfrom;
                   1188:              ++clen;
                   1189:              continue;
                   1190:            }
                   1191: 
                   1192:          ++zfrom;
                   1193:          switch (*zfrom)
                   1194:            {
                   1195:            case '\0':
                   1196:              --zfrom;
                   1197:              /* Fall through.  */
                   1198:            case '\\':
                   1199:              zadd = "\\";
                   1200:              break;
                   1201:            case 'L':
                   1202:              {
                   1203:                const char *zlog;
                   1204: 
                   1205:                if (qsys == NULL)
                   1206:                  {
                   1207:                    ulog (LOG_ERROR, "chat-program: Illegal use of \\L");
                   1208:                    fret = FALSE;
                   1209:                    break;
                   1210:                  }
                   1211:                zlog = qsys->uuconf_zcall_login;
                   1212:                if (zlog == NULL)
                   1213:                  {
                   1214:                    ulog (LOG_ERROR, "chat-program: No login defined");
                   1215:                    fret = FALSE;
                   1216:                    break;
                   1217:                  }
                   1218:                if (zlog[0] == '*' && zlog[1] == '\0')
                   1219:                  {
                   1220:                    if (zcallout_login == NULL)
                   1221:                      {
                   1222:                        int iuuconf;
                   1223: 
                   1224:                        iuuconf = uuconf_callout (puuconf, qsys,
                   1225:                                                  &zcallout_login,
                   1226:                                                  &zcallout_pass);
                   1227:                        if (iuuconf == UUCONF_NOT_FOUND
                   1228:                            || zcallout_login == NULL)
                   1229:                          {
                   1230:                            ulog (LOG_ERROR,
                   1231:                                  "chat-program: No login defined");
                   1232:                            fret = FALSE;
                   1233:                            break;
                   1234:                          }
                   1235:                        else if (iuuconf != UUCONF_SUCCESS)
                   1236:                          {
                   1237:                            ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                   1238:                            fret = FALSE;
                   1239:                            break;
                   1240:                          }
                   1241:                      }
                   1242:                    zlog = zcallout_login;
                   1243:                  }
                   1244:                zadd = zlog;
                   1245:              }
                   1246:              break;
                   1247:            case 'P':
                   1248:              {
                   1249:                const char *zpass;
                   1250: 
                   1251:                if (qsys == NULL)
                   1252:                  {
                   1253:                    ulog (LOG_ERROR, "chat-program: Illegal use of \\P");
                   1254:                    fret = FALSE;
                   1255:                    break;
                   1256:                  }
                   1257:                zpass = qsys->uuconf_zcall_password;
                   1258:                if (zpass == NULL)
                   1259:                  {
                   1260:                    ulog (LOG_ERROR, "chat-program: No password defined");
                   1261:                    fret = FALSE;
                   1262:                    break;
                   1263:                  }
                   1264:                if (zpass[0] == '*' && zpass[1] == '\0')
                   1265:                  {
                   1266:                    if (zcallout_pass == NULL)
                   1267:                      {
                   1268:                        int iuuconf;
                   1269: 
                   1270:                        iuuconf = uuconf_callout (puuconf, qsys,
                   1271:                                                  &zcallout_login,
                   1272:                                                  &zcallout_pass);
                   1273:                        if (iuuconf == UUCONF_NOT_FOUND
                   1274:                            || zcallout_pass == NULL)
                   1275:                          {
                   1276:                            ulog (LOG_ERROR,
                   1277:                                  "chat-program: No password defined");
                   1278:                            fret = FALSE;
                   1279:                            break;
                   1280:                          }
                   1281:                        else if (iuuconf != UUCONF_SUCCESS)
                   1282:                          {
                   1283:                            ulog_uuconf (LOG_ERROR, puuconf, iuuconf);
                   1284:                            fret = FALSE;
                   1285:                            break;
                   1286:                          }
                   1287:                      }
                   1288:                    zpass = zcallout_pass;
                   1289:                  }
                   1290:                zadd = zpass;
                   1291:              }
                   1292:              break;
                   1293:            case 'D':
                   1294:              if (qdial == NULL || zphone == NULL)
                   1295:                {
                   1296:                  ulog (LOG_ERROR, "chat-program: Illegal use of \\D");
                   1297:                  fret = FALSE;
                   1298:                  break;
                   1299:                }
                   1300:              zadd = zphone;
                   1301:              break;
                   1302:            case 'T':
                   1303:              {
                   1304:                const char *zprefix, *zsuffix;
                   1305: 
                   1306:                if (qdial == NULL || zphone == NULL)
                   1307:                  {
                   1308:                    ulog (LOG_ERROR, "chat-program: Illegal use of \\T");
                   1309:                    fret = FALSE;
                   1310:                    break;
                   1311:                  }
                   1312: 
                   1313:                if (! fctranslate (puuconf, zphone, &zprefix, &zsuffix))
                   1314:                  {
                   1315:                    fret = FALSE;
                   1316:                    break;
                   1317:                  }
                   1318: 
                   1319:                if (zsuffix == NULL)
                   1320:                  zadd = zprefix;
                   1321:                else
                   1322:                  {
                   1323:                    size_t cprefix;
                   1324: 
                   1325:                    cprefix = strlen (zprefix);
                   1326:                    if (clen + cprefix + 1 > calc)
                   1327:                      {
                   1328:                        char *znew;
                   1329: 
                   1330:                        calc = clen + cprefix + 20;
                   1331:                        znew = zbufalc (calc);
                   1332:                        memcpy (znew, *pzarg, clen);
                   1333:                        ubuffree (*pzarg);
                   1334:                        *pzarg = znew;
                   1335:                        zto = znew + clen;
                   1336:                      }
                   1337:                    memcpy (zto, zprefix, cprefix);
                   1338:                    zto += cprefix;
                   1339:                    clen += cprefix;
                   1340:                    zadd = zsuffix;
                   1341:                  }
                   1342:              }
                   1343:              break;
                   1344:            case 'Y':
                   1345:              if (zLdevice == NULL && zport == NULL)
                   1346:                {
                   1347:                  ulog (LOG_ERROR, "chat-program: Illegal use of \\Y");
                   1348:                  fret = FALSE;
                   1349:                  break;
                   1350:                }
                   1351:              /* zLdevice will generally make more sense than zport, but
                   1352:                 it might not be set yet.  */
                   1353:              zadd = zLdevice;
                   1354:              if (zadd == NULL)
                   1355:                zadd = zport;
                   1356:              break;
                   1357:            case 'Z':
                   1358:              if (qsys == NULL)
                   1359:                {
                   1360:                  ulog (LOG_ERROR, "chat-program: Illegal use of \\Z");
                   1361:                  fret = FALSE;
                   1362:                  break;
                   1363:                }
                   1364:              zadd = qsys->uuconf_zname;
                   1365:              break;
                   1366:            case 'S':
                   1367:              {
                   1368:                if (ibaud == 0)
                   1369:                  {
                   1370:                    ulog (LOG_ERROR, "chat-program: Illegal use of \\S");
                   1371:                    fret = FALSE;
                   1372:                    break;
                   1373:                  }
                   1374:                sprintf (abadd, "%ld", ibaud);
                   1375:                zadd = abadd;
                   1376:              }
                   1377:              break;
                   1378:            default:
                   1379:              {
                   1380:                ulog (LOG_ERROR,
                   1381:                      "chat-program: Unrecognized escape sequence \\%c",
                   1382:                      *zfrom);
                   1383:                abadd[0] = *zfrom;
                   1384:                abadd[1] = '\0';
                   1385:                zadd = abadd;
                   1386:              }
                   1387:              break;
                   1388:            }
                   1389: 
                   1390:          if (! fret)
                   1391:            break;
                   1392: 
                   1393:          cadd = strlen (zadd);
                   1394:          if (clen + cadd + 1 > calc)
                   1395:            {
                   1396:              char *znew;
                   1397: 
                   1398:              calc = clen + cadd + 20;
                   1399:              znew = zbufalc (calc);
                   1400:              memcpy (znew, *pzarg, clen);
                   1401:              ubuffree (*pzarg);
                   1402:              *pzarg = znew;
                   1403:              zto = znew + clen;
                   1404:            }
                   1405:          memcpy (zto, zadd, cadd + 1);
                   1406:          zto += cadd;
                   1407:          clen += cadd;
                   1408:        }
                   1409: 
                   1410:       if (! fret)
                   1411:        break;
                   1412: 
                   1413:       *zto++ = '\0';
                   1414:       ++clen;
                   1415:     }
                   1416: 
                   1417:   *pzarg = NULL;
                   1418: 
                   1419:   if (fret)
                   1420:     fret = fconn_run_chat (qconn, pzpass);
                   1421: 
                   1422:   for (pz = pzpass; *pz != NULL; pz++)
                   1423:     ubuffree (*pz);
                   1424:   xfree ((pointer) pzpass);
                   1425:   xfree ((pointer) zcallout_login);
                   1426:   xfree ((pointer) zcallout_pass);
                   1427: 
                   1428:   return fret;
                   1429: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.