|
|
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.