|
|
1.1 ! root 1: /* uucico.c ! 2: This is the main UUCP communication program. ! 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 uucico_rcsid[] = "$Id: uucico.c,v 1.1 93/07/30 07:54:34 bin Exp Locker: bin $"; ! 30: #endif ! 31: ! 32: #include <ctype.h> ! 33: ! 34: #if HAVE_LIMITS_H ! 35: #include <limits.h> ! 36: #else ! 37: #define LONG_MAX 2147483647L ! 38: #endif ! 39: ! 40: #include "getopt.h" ! 41: ! 42: #include "uudefs.h" ! 43: #include "uuconf.h" ! 44: #include "conn.h" ! 45: #include "prot.h" ! 46: #include "trans.h" ! 47: #include "system.h" ! 48: ! 49: /* The program name. */ ! 50: char abProgram[] = "uucico"; ! 51: ! 52: /* Define the known protocols. */ ! 53: ! 54: #define TCP_PROTO \ ! 55: (UUCONF_RELIABLE_ENDTOEND \ ! 56: | UUCONF_RELIABLE_RELIABLE \ ! 57: | UUCONF_RELIABLE_EIGHT) ! 58: ! 59: static const struct sprotocol asProtocols[] = ! 60: { ! 61: { 't', TCP_PROTO, 1, ! 62: asTproto_params, ftstart, ftshutdown, ftsendcmd, ztgetspace, ! 63: ftsenddata, ftwait, ftfile }, ! 64: { 'e', TCP_PROTO, 1, ! 65: asEproto_params, festart, feshutdown, fesendcmd, zegetspace, ! 66: fesenddata, fewait, fefile }, ! 67: { 'i', UUCONF_RELIABLE_EIGHT, 7, ! 68: asIproto_params, fistart, fishutdown, fisendcmd, zigetspace, ! 69: fisenddata, fiwait, NULL }, ! 70: { 'a', UUCONF_RELIABLE_EIGHT, 1, ! 71: asZproto_params, fzstart, fzshutdown, fzsendcmd, zzgetspace, ! 72: fzsenddata, fzwait, fzfile }, ! 73: { 'g', UUCONF_RELIABLE_EIGHT, 1, ! 74: asGproto_params, fgstart, fgshutdown, fgsendcmd, zggetspace, ! 75: fgsenddata, fgwait, NULL }, ! 76: { 'G', UUCONF_RELIABLE_EIGHT, 1, ! 77: asGproto_params, fbiggstart, fgshutdown, fgsendcmd, zggetspace, ! 78: fgsenddata, fgwait, NULL }, ! 79: { 'j', UUCONF_RELIABLE_EIGHT, 7, ! 80: asIproto_params, fjstart, fjshutdown, fisendcmd, zigetspace, ! 81: fisenddata, fiwait, NULL }, ! 82: { 'f', UUCONF_RELIABLE_RELIABLE, 1, ! 83: asFproto_params, ffstart, ffshutdown, ffsendcmd, zfgetspace, ! 84: ffsenddata, ffwait, fffile }, ! 85: }; ! 86: ! 87: #define CPROTOCOLS (sizeof asProtocols / sizeof asProtocols[0]) ! 88: ! 89: /* Locked system. */ ! 90: static boolean fLocked_system; ! 91: static struct uuconf_system sLocked_system; ! 92: ! 93: /* Daemon structure holding information about the remote system (must ! 94: be global so the error handler can see it. */ ! 95: static struct sdaemon sDaemon; ! 96: ! 97: /* Open connection. */ ! 98: static struct sconnection *qConn; ! 99: ! 100: /* uuconf global pointer; need to close the connection after a fatal ! 101: error. */ ! 102: static pointer pUuconf; ! 103: ! 104: /* This structure is passed to iuport_lock via uuconf_find_port. */ ! 105: struct spass ! 106: { ! 107: boolean fmatched; ! 108: boolean flocked; ! 109: struct sconnection *qconn; ! 110: }; ! 111: ! 112: /* Local functions. */ ! 113: ! 114: static void uusage P((void)); ! 115: static void uabort P((void)); ! 116: static boolean fcall P((pointer puuconf, ! 117: const struct uuconf_system *qsys, ! 118: struct uuconf_port *qport, boolean fifwork, ! 119: boolean fforce, boolean fdetach, ! 120: boolean ftimewarn)); ! 121: static boolean fconn_call P((struct sdaemon *qdaemon, ! 122: struct uuconf_port *qport, ! 123: struct sstatus *qstat, int cretry, ! 124: boolean *pfcalled)); ! 125: static boolean fdo_call P((struct sdaemon *qdaemon, ! 126: struct sstatus *qstat, ! 127: const struct uuconf_dialer *qdialer, ! 128: boolean *pfcalled, enum tstatus_type *pterr)); ! 129: static int iuport_lock P((struct uuconf_port *qport, pointer pinfo)); ! 130: static boolean flogin_prompt P((pointer puuconf, ! 131: struct sconnection *qconn)); ! 132: static boolean faccept_call P((pointer puuconf, const char *zlogin, ! 133: struct sconnection *qconn, ! 134: const char **pzsystem)); ! 135: static void uapply_proto_params P((pointer puuconf, int bproto, ! 136: struct uuconf_cmdtab *qcmds, ! 137: struct uuconf_proto_param *pas)); ! 138: static boolean fsend_uucp_cmd P((struct sconnection *qconn, ! 139: const char *z)); ! 140: static char *zget_uucp_cmd P((struct sconnection *qconn, ! 141: boolean frequired)); ! 142: static char *zget_typed_line P((struct sconnection *qconn)); ! 143: ! 144: /* Long getopt options. */ ! 145: static const struct option asLongopts[] = { { NULL, 0, NULL, 0 } }; ! 146: ! 147: int ! 148: main (argc, argv) ! 149: int argc; ! 150: char **argv; ! 151: { ! 152: /* -c: Whether to warn if a call is attempted at a bad time. */ ! 153: boolean ftimewarn = TRUE; ! 154: /* -D: don't detach from controlling terminal. */ ! 155: boolean fdetach = TRUE; ! 156: /* -e: Whether to do an endless loop of accepting calls. */ ! 157: boolean fendless = FALSE; ! 158: /* -f: Whether to force a call despite status of previous call. */ ! 159: boolean fforce = FALSE; ! 160: /* -I file: configuration file name. */ ! 161: const char *zconfig = NULL; ! 162: /* -l: Whether to give a single login prompt. */ ! 163: boolean flogin = FALSE; ! 164: /* -P port: port to use; in master mode, call out on this port. In ! 165: slave mode, accept logins on this port. If port not specified, ! 166: then in master mode figure it out for each system, and in slave ! 167: mode use stdin and stdout. */ ! 168: const char *zport = NULL; ! 169: /* -q: Whether to start uuxqt when done. */ ! 170: boolean fuuxqt = TRUE; ! 171: /* -r1: Whether we are the master. */ ! 172: boolean fmaster = FALSE; ! 173: /* -s,-S system: system to call. */ ! 174: const char *zsystem = NULL; ! 175: /* -w: Whether to wait for a call after doing one. */ ! 176: boolean fwait = FALSE; ! 177: int iopt; ! 178: struct uuconf_port *qport; ! 179: struct uuconf_port sport; ! 180: boolean fret = TRUE; ! 181: pointer puuconf; ! 182: int iuuconf; ! 183: #if defined(__COHERENT__) ! 184: boolean checkfirst = FALSE; ! 185: #endif /* COHERENT */ ! 186: ! 187: #if DEBUG > 1 ! 188: int iholddebug; ! 189: #endif ! 190: ! 191: /* For COHERENT, '-c system' means call the system only if there is ! 192: * work pending. This is to maintain backward compatibility with earlier ! 193: * versions of Coherent 4.x uucp. ! 194: */ ! 195: ! 196: #if defined(__COHERENT__) ! 197: while ((iopt = getopt_long (argc, argv, ! 198: "c:DefI:lp:qr:s:S:u:x:X:w", ! 199: asLongopts, (int *) NULL)) != EOF) ! 200: #else ! 201: while ((iopt = getopt_long (argc, argv, ! 202: "cDefI:lp:qr:s:S:u:x:X:w", ! 203: asLongopts, (int *) NULL)) != EOF) ! 204: #endif ! 205: { ! 206: switch (iopt) ! 207: { ! 208: #if defined(__COHERENT__) ! 209: case 'c': ! 210: /* for COHERENT backward compatibility, -c and -s are ! 211: * almost synonomous. ! 212: */ ! 213: checkfirst = TRUE; ! 214: zsystem = optarg; ! 215: fmaster = TRUE; ! 216: break; ! 217: #else ! 218: case 'c': ! 219: /* Don't warn if a call is attempted at a bad time. */ ! 220: ftimewarn = FALSE; ! 221: break; ! 222: #endif ! 223: case 'D': ! 224: /* Don't detach from controlling terminal. */ ! 225: fdetach = FALSE; ! 226: break; ! 227: ! 228: case 'e': ! 229: /* Do an endless loop of accepting calls. */ ! 230: fendless = TRUE; ! 231: break; ! 232: ! 233: case 'f': ! 234: /* Force a call even if it hasn't been long enough since the last ! 235: failed call. */ ! 236: fforce = TRUE; ! 237: break; ! 238: ! 239: case 'I': ! 240: /* Set configuration file name (default is in sysdep.h). */ ! 241: if (fsysdep_other_config (optarg)) ! 242: zconfig = optarg; ! 243: break; ! 244: ! 245: case 'l': ! 246: /* Prompt for login name and password. */ ! 247: flogin = TRUE; ! 248: break; ! 249: ! 250: case 'p': ! 251: /* Port to use */ ! 252: zport = optarg; ! 253: break; ! 254: ! 255: case 'q': ! 256: /* Don't start uuxqt. */ ! 257: fuuxqt = FALSE; ! 258: break; ! 259: ! 260: case 'r': ! 261: /* Set mode: -r1 for master, -r0 for slave (default) */ ! 262: if (strcmp (optarg, "1") == 0) ! 263: fmaster = TRUE; ! 264: else if (strcmp (optarg, "0") == 0) ! 265: fmaster = FALSE; ! 266: else ! 267: uusage (); ! 268: break; ! 269: ! 270: case 's': ! 271: /* Set system name */ ! 272: zsystem = optarg; ! 273: fmaster = TRUE; ! 274: break; ! 275: ! 276: case 'S': ! 277: /* Set system name and force call like -f */ ! 278: zsystem = optarg; ! 279: fforce = TRUE; ! 280: fmaster = TRUE; ! 281: break; ! 282: ! 283: case 'u': ! 284: /* Some versions of uucpd invoke uucico with a -u argument ! 285: specifying the login name. I'm told it is safe to ignore ! 286: this value, although perhaps we should use it rather than ! 287: zsysdep_login_name (). */ ! 288: break; ! 289: ! 290: case 'x': ! 291: case 'X': ! 292: #if DEBUG > 1 ! 293: /* Set debugging level */ ! 294: iDebug |= idebug_parse (optarg); ! 295: #endif ! 296: break; ! 297: ! 298: case 'w': ! 299: /* Call out and then wait for a call in */ ! 300: fwait = TRUE; ! 301: break; ! 302: ! 303: case 0: ! 304: /* Long option found, and flag value set. */ ! 305: break; ! 306: ! 307: default: ! 308: uusage (); ! 309: break; ! 310: } ! 311: } ! 312: ! 313: if (optind != argc) ! 314: uusage (); ! 315: ! 316: if (fwait && zport == NULL) ! 317: { ! 318: ulog (LOG_ERROR, "-w requires -e"); ! 319: uusage (); ! 320: } ! 321: ! 322: iuuconf = uuconf_init (&puuconf, (const char *) NULL, zconfig); ! 323: if (iuuconf != UUCONF_SUCCESS) ! 324: ulog_uuconf (LOG_FATAL, puuconf, iuuconf); ! 325: pUuconf = puuconf; ! 326: ! 327: #if DEBUG > 1 ! 328: { ! 329: const char *zdebug; ! 330: ! 331: iuuconf = uuconf_debuglevel (puuconf, &zdebug); ! 332: if (iuuconf != UUCONF_SUCCESS) ! 333: ulog_uuconf (LOG_FATAL, puuconf, iuuconf); ! 334: if (zdebug != NULL) ! 335: iDebug |= idebug_parse (zdebug); ! 336: } ! 337: #endif ! 338: ! 339: /* If a port was named, get its information. */ ! 340: if (zport == NULL) ! 341: qport = NULL; ! 342: else ! 343: { ! 344: iuuconf = uuconf_find_port (puuconf, zport, (long) 0, (long) 0, ! 345: (int (*) P((struct uuconf_port *, ! 346: pointer))) NULL, ! 347: (pointer) NULL, &sport); ! 348: if (iuuconf == UUCONF_NOT_FOUND) ! 349: ulog (LOG_FATAL, "%s: Port not found", zport); ! 350: else if (iuuconf != UUCONF_SUCCESS) ! 351: ulog_uuconf (LOG_FATAL, puuconf, iuuconf); ! 352: qport = &sport; ! 353: } ! 354: ! 355: #ifdef SIGINT ! 356: usysdep_signal (SIGINT); ! 357: #endif ! 358: #ifdef SIGHUP ! 359: usysdep_signal (SIGHUP); ! 360: #endif ! 361: #ifdef SIGQUIT ! 362: usysdep_signal (SIGQUIT); ! 363: #endif ! 364: #ifdef SIGTERM ! 365: usysdep_signal (SIGTERM); ! 366: #endif ! 367: #ifdef SIGPIPE ! 368: usysdep_signal (SIGPIPE); ! 369: #endif ! 370: ! 371: usysdep_initialize (puuconf, INIT_SUID); ! 372: ! 373: ulog_to_file (puuconf, TRUE); ! 374: ulog_fatal_fn (uabort); ! 375: ! 376: if (fmaster) ! 377: { ! 378: if (zsystem != NULL) ! 379: { ! 380: /* A system was named. Call it. */ ! 381: iuuconf = uuconf_system_info (puuconf, zsystem, ! 382: &sLocked_system); ! 383: if (iuuconf == UUCONF_NOT_FOUND) ! 384: ulog (LOG_FATAL, "%s: System not found", zsystem); ! 385: else if (iuuconf != UUCONF_SUCCESS) ! 386: ulog_uuconf (LOG_FATAL, puuconf, iuuconf); ! 387: ! 388: /* Detach from the controlling terminal for the call. This ! 389: probably makes sense only on Unix. We want the modem ! 390: line to become the controlling terminal. */ ! 391: if (fdetach && ! 392: (qport == NULL ! 393: || qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN)) ! 394: usysdep_detach (); ! 395: ! 396: ulog_system (sLocked_system.uuconf_zname); ! 397: ! 398: #if DEBUG > 1 ! 399: iholddebug = iDebug; ! 400: if (sLocked_system.uuconf_zdebug != NULL) ! 401: iDebug |= idebug_parse (sLocked_system.uuconf_zdebug); ! 402: #endif ! 403: ! 404: #if defined(__COHERENT__) /* backward compatibility with older COH -c option */ ! 405: if((checkfirst && fsysdep_has_work(&sLocked_system)) || (!checkfirst)){ ! 406: #endif /* COHERENT */ ! 407: ! 408: if (! fsysdep_lock_system (&sLocked_system)) ! 409: { ! 410: ulog (LOG_ERROR, "System already locked"); ! 411: fret = FALSE; ! 412: } ! 413: else ! 414: { ! 415: fLocked_system = TRUE; ! 416: fret = fcall (puuconf, &sLocked_system, qport, FALSE, ! 417: fforce, fdetach, ftimewarn); ! 418: if (fLocked_system) ! 419: { ! 420: (void) fsysdep_unlock_system (&sLocked_system); ! 421: fLocked_system = FALSE; ! 422: } ! 423: } ! 424: ! 425: #if defined(__COHERENT__) /* backward compat. with older COH -c option */ ! 426: } ! 427: #endif /* COHERENT */ ! 428: ! 429: #if DEBUG > 1 ! 430: iDebug = iholddebug; ! 431: #endif ! 432: ulog_system ((const char *) NULL); ! 433: (void) uuconf_system_free (puuconf, &sLocked_system); ! 434: } ! 435: else ! 436: { ! 437: char **pznames, **pz; ! 438: int c, i; ! 439: boolean fdidone; ! 440: ! 441: /* Call all systems which have work to do. */ ! 442: fret = TRUE; ! 443: fdidone = FALSE; ! 444: ! 445: iuuconf = uuconf_system_names (puuconf, &pznames, 0); ! 446: if (iuuconf != UUCONF_SUCCESS) ! 447: ulog_uuconf (LOG_FATAL, puuconf, iuuconf); ! 448: ! 449: /* Randomize the order in which we call the systems. */ ! 450: c = 0; ! 451: for (pz = pznames; *pz != NULL; pz++) ! 452: c++; ! 453: ! 454: srand ((unsigned int) ixsysdep_time ((long *) NULL)); ! 455: for (i = c - 1; i > 0; i--) ! 456: { ! 457: int iuse; ! 458: char *zhold; ! 459: ! 460: iuse = rand () % (i + 1); ! 461: zhold = pznames[i]; ! 462: pznames[i] = pznames[iuse]; ! 463: pznames[iuse] = zhold; ! 464: } ! 465: ! 466: for (pz = pznames; *pz != NULL && ! FGOT_SIGNAL (); pz++) ! 467: { ! 468: iuuconf = uuconf_system_info (puuconf, *pz, ! 469: &sLocked_system); ! 470: if (iuuconf != UUCONF_SUCCESS) ! 471: { ! 472: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 473: xfree ((pointer) *pz); ! 474: continue; ! 475: } ! 476: ! 477: if (fsysdep_has_work (&sLocked_system)) ! 478: { ! 479: fdidone = TRUE; ! 480: ! 481: /* Detach from the controlling terminal. On Unix ! 482: this means that we will wind up forking a new ! 483: process for each system we call. */ ! 484: if (fdetach ! 485: && (qport == NULL ! 486: || qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN)) ! 487: usysdep_detach (); ! 488: ! 489: ulog_system (sLocked_system.uuconf_zname); ! 490: ! 491: #if DEBUG > 1 ! 492: iholddebug = iDebug; ! 493: if (sLocked_system.uuconf_zdebug != NULL) ! 494: iDebug |= idebug_parse (sLocked_system.uuconf_zdebug); ! 495: #endif ! 496: ! 497: if (! fsysdep_lock_system (&sLocked_system)) ! 498: { ! 499: ulog (LOG_ERROR, "System already locked"); ! 500: fret = FALSE; ! 501: } ! 502: else ! 503: { ! 504: fLocked_system = TRUE; ! 505: if (! fcall (puuconf, &sLocked_system, qport, TRUE, ! 506: fforce, fdetach, ftimewarn)) ! 507: fret = FALSE; ! 508: ! 509: /* Now ignore any SIGHUP that we got. */ ! 510: afSignal[INDEXSIG_SIGHUP] = FALSE; ! 511: ! 512: if (fLocked_system) ! 513: { ! 514: (void) fsysdep_unlock_system (&sLocked_system); ! 515: fLocked_system = FALSE; ! 516: } ! 517: } ! 518: #if DEBUG > 1 ! 519: iDebug = iholddebug; ! 520: #endif ! 521: ulog_system ((const char *) NULL); ! 522: } ! 523: ! 524: (void) uuconf_system_free (puuconf, &sLocked_system); ! 525: xfree ((pointer) *pz); ! 526: } ! 527: ! 528: xfree ((pointer) pznames); ! 529: ! 530: if (! fdidone) ! 531: ulog (LOG_NORMAL, "No work"); ! 532: } ! 533: ! 534: /* If requested, wait for calls after dialing out. */ ! 535: if (fwait) ! 536: { ! 537: fendless = TRUE; ! 538: fmaster = FALSE; ! 539: } ! 540: } ! 541: ! 542: if (! fmaster) ! 543: { ! 544: struct sconnection sconn; ! 545: boolean flocked; ! 546: ! 547: /* If a port was specified by name, we go into endless loop ! 548: mode. In this mode, we wait for calls and prompt them with ! 549: "login:" and "Password:", so that they think we are a regular ! 550: UNIX system. If we aren't in endless loop mode, we have been ! 551: called by some other system. If flogin is TRUE, we prompt ! 552: with "login:" and "Password:" a single time. */ ! 553: ! 554: fret = TRUE; ! 555: zsystem = NULL; ! 556: ! 557: if (! fconn_init (qport, &sconn)) ! 558: fret = FALSE; ! 559: ! 560: if (qport != NULL) ! 561: { ! 562: /* We are not using standard input. Detach from the ! 563: controlling terminal, so that the port we are about to ! 564: use becomes our controlling terminal. */ ! 565: if (fdetach ! 566: && qport->uuconf_ttype != UUCONF_PORTTYPE_STDIN) ! 567: usysdep_detach (); ! 568: ! 569: /* If a port was given, we loop forever. */ ! 570: fendless = TRUE; ! 571: } ! 572: ! 573: if (fconn_lock (&sconn, TRUE)) ! 574: flocked = TRUE; ! 575: else ! 576: { ! 577: flocked = FALSE; ! 578: ulog (LOG_ERROR, "%s: Port already locked", ! 579: qport->uuconf_zname); ! 580: fret = FALSE; ! 581: } ! 582: ! 583: if (fret) ! 584: { ! 585: if (! fconn_open (&sconn, (long) 0, (long) 0, TRUE)) ! 586: fret = FALSE; ! 587: qConn = &sconn; ! 588: } ! 589: ! 590: if (fret) ! 591: { ! 592: if (fendless) ! 593: { ! 594: while (! FGOT_SIGNAL () ! 595: && flogin_prompt (puuconf, &sconn)) ! 596: { ! 597: /* Now ignore any SIGHUP that we got. */ ! 598: afSignal[INDEXSIG_SIGHUP] = FALSE; ! 599: ! 600: if (fLocked_system) ! 601: { ! 602: (void) fsysdep_unlock_system (&sLocked_system); ! 603: fLocked_system = FALSE; ! 604: } ! 605: if (! fconn_reset (&sconn)) ! 606: break; ! 607: } ! 608: fret = FALSE; ! 609: } ! 610: else ! 611: { ! 612: if (flogin) ! 613: fret = flogin_prompt (puuconf, &sconn); ! 614: else ! 615: { ! 616: #if DEBUG > 1 ! 617: iholddebug = iDebug; ! 618: #endif ! 619: fret = faccept_call (puuconf, zsysdep_login_name (), ! 620: &sconn, &zsystem); ! 621: #if DEBUG > 1 ! 622: iDebug = iholddebug; ! 623: #endif ! 624: } ! 625: } ! 626: } ! 627: ! 628: if (qConn != NULL) ! 629: { ! 630: if (! fconn_close (&sconn, puuconf, (struct uuconf_dialer *) NULL, ! 631: fret)) ! 632: fret = FALSE; ! 633: qConn = NULL; ! 634: } ! 635: ! 636: if (flocked) ! 637: (void) fconn_unlock (&sconn); ! 638: ! 639: if (fLocked_system) ! 640: { ! 641: (void) fsysdep_unlock_system (&sLocked_system); ! 642: fLocked_system = FALSE; ! 643: } ! 644: ! 645: uconn_free (&sconn); ! 646: } ! 647: ! 648: ulog_close (); ! 649: ustats_close (); ! 650: ! 651: /* If we got a SIGTERM, perhaps because the system is going down, ! 652: don't run uuxqt. We go ahead and run it for any other signal, ! 653: since I think they indicate more temporary conditions. */ ! 654: if (afSignal[INDEXSIG_SIGTERM]) ! 655: fuuxqt = FALSE; ! 656: ! 657: if (fuuxqt) ! 658: { ! 659: /* Detach from the controlling terminal before starting up uuxqt, ! 660: so that it runs as a true daemon. */ ! 661: if (fdetach) ! 662: usysdep_detach (); ! 663: if (zsystem == NULL) ! 664: { ! 665: if (! fsysdep_run ("uuxqt", (const char *) NULL, ! 666: (const char *) NULL)) ! 667: fret = FALSE; ! 668: } ! 669: else ! 670: { ! 671: if (! fsysdep_run ("uuxqt", "-s", zsystem)) ! 672: fret = FALSE; ! 673: } ! 674: } ! 675: ! 676: usysdep_exit (fret); ! 677: ! 678: /* Avoid complaints about not returning. */ ! 679: return 0; ! 680: } ! 681: ! 682: /* Print out a usage message. */ ! 683: ! 684: static void ! 685: uusage () ! 686: { ! 687: fprintf (stderr, ! 688: "Taylor UUCP version %s, copyright (C) 1991, 1992 Ian Lance Taylor\n", ! 689: VERSION); ! 690: fprintf (stderr, ! 691: "Usage: uucico [options]\n"); ! 692: fprintf (stderr, ! 693: " -s,-S system: Call system (-S implies -f)\n"); ! 694: fprintf (stderr, ! 695: " -f: Force call despite system status\n"); ! 696: fprintf (stderr, ! 697: " -r state: 1 for master, 0 for slave (default)\n"); ! 698: fprintf (stderr, ! 699: " -p port: Specify port (implies -e)\n"); ! 700: fprintf (stderr, ! 701: " -l: prompt for login name and password\n"); ! 702: fprintf (stderr, ! 703: " -e: Endless loop of login prompts and daemon execution\n"); ! 704: fprintf (stderr, ! 705: " -w: After calling out, wait for incoming calls\n"); ! 706: fprintf (stderr, ! 707: " -q: Don't start uuxqt when done\n"); ! 708: fprintf (stderr, ! 709: " -x,-X debug: Set debugging level\n"); ! 710: #if HAVE_TAYLOR_CONFIG ! 711: fprintf (stderr, ! 712: " -I file: Set configuration file to use\n"); ! 713: #endif /* HAVE_TAYLOR_CONFIG */ ! 714: ! 715: exit (EXIT_FAILURE); ! 716: } ! 717: ! 718: /* This function is called when a LOG_FATAL error occurs. */ ! 719: ! 720: static void ! 721: uabort () ! 722: { ! 723: if (fLocked_system) ! 724: ufailed (&sDaemon); ! 725: ! 726: ulog_user ((const char *) NULL); ! 727: ! 728: if (qConn != NULL) ! 729: { ! 730: (void) fconn_close (qConn, pUuconf, (struct uuconf_dialer *) NULL, ! 731: FALSE); ! 732: (void) fconn_unlock (qConn); ! 733: uconn_free (qConn); ! 734: } ! 735: ! 736: if (fLocked_system) ! 737: { ! 738: (void) fsysdep_unlock_system (&sLocked_system); ! 739: fLocked_system = FALSE; ! 740: } ! 741: ! 742: ulog_system ((const char *) NULL); ! 743: ! 744: ulog_close (); ! 745: ustats_close (); ! 746: ! 747: usysdep_exit (FALSE); ! 748: } ! 749: ! 750: /* Call another system, trying all the possible sets of calling ! 751: instructions. The qsys argument is the system to call. The qport ! 752: argument is the port to use, and may be NULL. If the fifwork ! 753: argument is TRUE, the call is only placed if there is work to be ! 754: done. If the fforce argument is TRUE, a call is forced even if not ! 755: enough time has passed since the last failed call. If the ! 756: ftimewarn argument is TRUE (the normal case), then a warning is ! 757: given if calls are not permitted at this time. */ ! 758: ! 759: static boolean ! 760: fcall (puuconf, qorigsys, qport, fifwork, fforce, fdetach, ftimewarn) ! 761: pointer puuconf; ! 762: const struct uuconf_system *qorigsys; ! 763: struct uuconf_port *qport; ! 764: boolean fifwork; ! 765: boolean fforce; ! 766: boolean fdetach; ! 767: boolean ftimewarn; ! 768: { ! 769: struct sstatus sstat; ! 770: long inow; ! 771: boolean fbadtime, fnevertime; ! 772: const struct uuconf_system *qsys; ! 773: ! 774: if (! fsysdep_get_status (qorigsys, &sstat, (boolean *) NULL)) ! 775: return FALSE; ! 776: ! 777: /* Make sure it's been long enough since the last failed call, and ! 778: that we haven't exceeded the maximum number of retries. Even if ! 779: we are over the limit on retries, we permit a call to be made if ! 780: 24 hours have passed. This 24 hour limit is still controlled by ! 781: the retry time. */ ! 782: inow = ixsysdep_time ((long *) NULL); ! 783: if (! fforce) ! 784: { ! 785: if (qorigsys->uuconf_cmax_retries > 0 ! 786: && sstat.cretries >= qorigsys->uuconf_cmax_retries ! 787: && sstat.ilast + 24 * 60 * 60 < inow) ! 788: { ! 789: ulog (LOG_ERROR, "Too many retries"); ! 790: return FALSE; ! 791: } ! 792: ! 793: if (sstat.ttype == STATUS_COMPLETE ! 794: ? sstat.ilast + qorigsys->uuconf_csuccess_wait > inow ! 795: : sstat.ilast + sstat.cwait > inow) ! 796: { ! 797: ulog (LOG_NORMAL, "Retry time not reached"); ! 798: return FALSE; ! 799: } ! 800: } ! 801: ! 802: sDaemon.puuconf = puuconf; ! 803: sDaemon.qsys = NULL; ! 804: sDaemon.zlocalname = NULL; ! 805: sDaemon.qconn = NULL; ! 806: sDaemon.qproto = NULL; ! 807: sDaemon.clocal_size = -1; ! 808: sDaemon.cremote_size = -1; ! 809: sDaemon.cmax_ever = -2; ! 810: sDaemon.cmax_receive = -1; ! 811: sDaemon.ifeatures = 0; ! 812: sDaemon.frequest_hangup = FALSE; ! 813: sDaemon.fhangup_requested = FALSE; ! 814: sDaemon.fhangup = FALSE; ! 815: sDaemon.fmaster = TRUE; ! 816: sDaemon.fcaller = TRUE; ! 817: sDaemon.ireliable = 0; ! 818: sDaemon.bgrade = '\0'; ! 819: ! 820: fbadtime = TRUE; ! 821: fnevertime = TRUE; ! 822: ! 823: for (qsys = qorigsys; qsys != NULL; qsys = qsys->uuconf_qalternate) ! 824: { ! 825: int cretry; ! 826: boolean fany, fret, fcalled; ! 827: ! 828: if (FGOT_SIGNAL ()) ! 829: return FALSE; ! 830: ! 831: if (! qsys->uuconf_fcall || qsys->uuconf_qtimegrade == NULL) ! 832: continue; ! 833: ! 834: fnevertime = FALSE; ! 835: ! 836: /* Make sure this is a legal time to call. */ ! 837: if (! ftimespan_match (qsys->uuconf_qtimegrade, (long *) NULL, ! 838: &cretry)) ! 839: continue; ! 840: ! 841: sDaemon.qsys = qsys; ! 842: ! 843: /* Queue up any work there is to do. */ ! 844: if (! fqueue (&sDaemon, &fany)) ! 845: return FALSE; ! 846: ! 847: /* If we are only supposed to call if there is work, and there ! 848: isn't any work, check the next alternates. We can't give up ! 849: at this point because there might be some other alternates ! 850: with fewer restrictions on grade or file transfer size. */ ! 851: if (fifwork && ! fany) ! 852: { ! 853: uclear_queue (&sDaemon); ! 854: continue; ! 855: } ! 856: ! 857: fbadtime = FALSE; ! 858: ! 859: fret = fconn_call (&sDaemon, qport, &sstat, cretry, &fcalled); ! 860: ! 861: uclear_queue (&sDaemon); ! 862: ! 863: if (fret) ! 864: return TRUE; ! 865: if (fcalled) ! 866: return FALSE; ! 867: ! 868: /* Now we have to dump that port so that we can aquire a new ! 869: one. On Unix this means that we will fork and get a new ! 870: process ID, so we must unlock and relock the system. */ ! 871: if (fdetach) ! 872: { ! 873: (void) fsysdep_unlock_system (&sLocked_system); ! 874: fLocked_system = FALSE; ! 875: usysdep_detach (); ! 876: if (! fsysdep_lock_system (&sLocked_system)) ! 877: return FALSE; ! 878: fLocked_system = TRUE; ! 879: } ! 880: } ! 881: ! 882: if (fbadtime && ftimewarn) ! 883: { ! 884: ulog (LOG_NORMAL, "Wrong time to call"); ! 885: ! 886: /* Update the status, unless the system can never be called. If ! 887: the system can never be called, there is little point to ! 888: putting in a ``wrong time to call'' message. We don't change ! 889: the number of retries, although we do set the wait until the ! 890: next retry to 0. */ ! 891: if (! fnevertime) ! 892: { ! 893: sstat.ttype = STATUS_WRONG_TIME; ! 894: sstat.ilast = inow; ! 895: sstat.cwait = 0; ! 896: (void) fsysdep_set_status (qorigsys, &sstat); ! 897: } ! 898: } ! 899: ! 900: return FALSE; ! 901: } ! 902: ! 903: /* Find a port to use when calling a system, open a connection, and ! 904: dial the system. The actual call is done in fdo_call. This ! 905: routine is responsible for opening and closing the connection. */ ! 906: ! 907: static boolean ! 908: fconn_call (qdaemon, qport, qstat, cretry, pfcalled) ! 909: struct sdaemon *qdaemon; ! 910: struct uuconf_port *qport; ! 911: struct sstatus *qstat; ! 912: int cretry; ! 913: boolean *pfcalled; ! 914: { ! 915: pointer puuconf; ! 916: const struct uuconf_system *qsys; ! 917: struct uuconf_port sport; ! 918: struct sconnection sconn; ! 919: enum tstatus_type terr; ! 920: boolean fret; ! 921: ! 922: puuconf = qdaemon->puuconf; ! 923: qsys = qdaemon->qsys; ! 924: ! 925: *pfcalled = FALSE; ! 926: ! 927: /* Ignore any SIGHUP signal we may have received up to this point. ! 928: This is needed on Unix because we may have gotten one from the ! 929: shell before we detached from the controlling terminal. */ ! 930: afSignal[INDEXSIG_SIGHUP] = FALSE; ! 931: ! 932: /* If no port was specified on the command line, use any port ! 933: defined for the system. To select the system port: 1) see if ! 934: port information was specified directly; 2) see if a port was ! 935: named; 3) get an available port given the baud rate. We don't ! 936: change the system status if a port is unavailable; i.e. we don't ! 937: force the system to wait for the retry time. */ ! 938: if (qport == NULL) ! 939: qport = qsys->uuconf_qport; ! 940: if (qport != NULL) ! 941: { ! 942: if (! fconn_init (qport, &sconn)) ! 943: return FALSE; ! 944: if (! fconn_lock (&sconn, FALSE)) ! 945: { ! 946: ulog (LOG_ERROR, "%s: Port already locked", ! 947: qport->uuconf_zname); ! 948: return FALSE; ! 949: } ! 950: } ! 951: else ! 952: { ! 953: struct spass s; ! 954: int iuuconf; ! 955: ! 956: s.fmatched = FALSE; ! 957: s.flocked = FALSE; ! 958: s.qconn = &sconn; ! 959: iuuconf = uuconf_find_port (puuconf, qsys->uuconf_zport, ! 960: qsys->uuconf_ibaud, ! 961: qsys->uuconf_ihighbaud, ! 962: iuport_lock, (pointer) &s, ! 963: &sport); ! 964: if (iuuconf == UUCONF_NOT_FOUND) ! 965: { ! 966: if (s.fmatched) ! 967: ulog (LOG_ERROR, "All matching ports in use"); ! 968: else ! 969: ulog (LOG_ERROR, "No matching ports"); ! 970: return FALSE; ! 971: } ! 972: else if (iuuconf != UUCONF_SUCCESS) ! 973: { ! 974: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 975: if (s.flocked) ! 976: { ! 977: (void) fconn_unlock (&sconn); ! 978: uconn_free (&sconn); ! 979: } ! 980: return FALSE; ! 981: } ! 982: } ! 983: ! 984: if (! fconn_open (&sconn, qsys->uuconf_ibaud, qsys->uuconf_ihighbaud, ! 985: FALSE)) ! 986: { ! 987: terr = STATUS_PORT_FAILED; ! 988: fret = FALSE; ! 989: } ! 990: else ! 991: { ! 992: struct uuconf_dialer *qdialer; ! 993: struct uuconf_dialer sdialer; ! 994: enum tdialerfound tdialer; ! 995: ! 996: if (qsys->uuconf_zalternate == NULL) ! 997: ulog (LOG_NORMAL, "Calling system %s (port %s)", qsys->uuconf_zname, ! 998: zLdevice == NULL ? (char *) "unknown" : zLdevice); ! 999: else ! 1000: ulog (LOG_NORMAL, "Calling system %s (alternate %s, port %s)", ! 1001: qsys->uuconf_zname, qsys->uuconf_zalternate, ! 1002: zLdevice == NULL ? (char *) "unknown" : zLdevice); ! 1003: ! 1004: qdialer = NULL; ! 1005: ! 1006: if (! fconn_dial (&sconn, puuconf, qsys, qsys->uuconf_zphone, ! 1007: &sdialer, &tdialer)) ! 1008: { ! 1009: terr = STATUS_DIAL_FAILED; ! 1010: fret = FALSE; ! 1011: } ! 1012: else ! 1013: { ! 1014: qdaemon->qconn = &sconn; ! 1015: if (tdialer == DIALERFOUND_FALSE) ! 1016: qdialer = NULL; ! 1017: else ! 1018: qdialer = &sdialer; ! 1019: fret = fdo_call (qdaemon, qstat, qdialer, pfcalled, &terr); ! 1020: } ! 1021: ! 1022: (void) fconn_close (&sconn, puuconf, qdialer, fret); ! 1023: ! 1024: if (tdialer == DIALERFOUND_FREE) ! 1025: (void) uuconf_dialer_free (puuconf, &sdialer); ! 1026: } ! 1027: ! 1028: if (! fret) ! 1029: { ! 1030: DEBUG_MESSAGE2 (DEBUG_HANDSHAKE, "Call failed: %d (%s)", ! 1031: (int) terr, azStatus[(int) terr]); ! 1032: qstat->ttype = terr; ! 1033: qstat->cretries++; ! 1034: qstat->ilast = ixsysdep_time ((long *) NULL); ! 1035: if (cretry == 0) ! 1036: qstat->cwait = CRETRY_WAIT (qstat->cretries); ! 1037: else ! 1038: qstat->cwait = cretry * 60; ! 1039: (void) fsysdep_set_status (qsys, qstat); ! 1040: } ! 1041: ! 1042: (void) fconn_unlock (&sconn); ! 1043: uconn_free (&sconn); ! 1044: ! 1045: if (qport == NULL) ! 1046: (void) uuconf_port_free (puuconf, &sport); ! 1047: ! 1048: return fret; ! 1049: } ! 1050: ! 1051: /* Do the actual work of calling another system. The qsys argument is ! 1052: the system to call, the qconn argument is the connection to use, ! 1053: the qstat argument holds the current status of the ssystem, and the ! 1054: qdialer argument holds the dialer being used (it may be NULL). If ! 1055: we log in successfully, set *pfcalled to TRUE; this is used to ! 1056: distinguish a failed dial from a failure during the call. If an ! 1057: error occurs *pterr is set to the status type to record. */ ! 1058: ! 1059: static boolean ! 1060: fdo_call (qdaemon, qstat, qdialer, pfcalled, pterr) ! 1061: struct sdaemon *qdaemon; ! 1062: struct sstatus *qstat; ! 1063: const struct uuconf_dialer *qdialer; ! 1064: boolean *pfcalled; ! 1065: enum tstatus_type *pterr; ! 1066: { ! 1067: pointer puuconf; ! 1068: const struct uuconf_system *qsys; ! 1069: struct sconnection *qconn; ! 1070: const char *zport; ! 1071: int iuuconf; ! 1072: char *zstr; ! 1073: long istart_time; ! 1074: char *zlog; ! 1075: ! 1076: puuconf = qdaemon->puuconf; ! 1077: qsys = qdaemon->qsys; ! 1078: qconn = qdaemon->qconn; ! 1079: ! 1080: *pterr = STATUS_LOGIN_FAILED; ! 1081: ! 1082: if (qconn->qport == NULL) ! 1083: zport = "unknown"; ! 1084: else ! 1085: zport = qconn->qport->uuconf_zname; ! 1086: if (! fchat (qconn, puuconf, &qsys->uuconf_schat, qsys, ! 1087: (const struct uuconf_dialer *) NULL, ! 1088: (const char *) NULL, FALSE, zport, ! 1089: iconn_baud (qconn))) ! 1090: return FALSE; ! 1091: ! 1092: *pfcalled = TRUE; ! 1093: istart_time = ixsysdep_time ((long *) NULL); ! 1094: ! 1095: *pterr = STATUS_HANDSHAKE_FAILED; ! 1096: ! 1097: /* We should now see "Shere" from the other system. Newer systems ! 1098: send "Shere=foo" where foo is the remote name. */ ! 1099: zstr = zget_uucp_cmd (qconn, TRUE); ! 1100: if (zstr == NULL) ! 1101: return FALSE; ! 1102: ! 1103: if (strncmp (zstr, "Shere", 5) != 0) ! 1104: { ! 1105: ulog (LOG_ERROR, "Bad initialization string"); ! 1106: ubuffree (zstr); ! 1107: return FALSE; ! 1108: } ! 1109: ! 1110: ulog (LOG_NORMAL, "Login successful"); ! 1111: ! 1112: qstat->ttype = STATUS_TALKING; ! 1113: qstat->ilast = ixsysdep_time ((long *) NULL); ! 1114: qstat->cretries = 0; ! 1115: qstat->cwait = 0; ! 1116: if (! fsysdep_set_status (qsys, qstat)) ! 1117: return FALSE; ! 1118: ! 1119: if (zstr[5] == '=') ! 1120: { ! 1121: const char *zheresys; ! 1122: size_t clen; ! 1123: int icmp; ! 1124: ! 1125: /* Some UUCP packages only provide seven characters in the Shere ! 1126: machine name. Others only provide fourteen. */ ! 1127: zheresys = zstr + 6; ! 1128: clen = strlen (zheresys); ! 1129: if (clen == 7 || clen == 14) ! 1130: icmp = strncmp (zheresys, qsys->uuconf_zname, clen); ! 1131: else ! 1132: icmp = strcmp (zheresys, qsys->uuconf_zname); ! 1133: if (icmp != 0) ! 1134: { ! 1135: if (qsys->uuconf_pzalias != NULL) ! 1136: { ! 1137: char **pz; ! 1138: ! 1139: for (pz = qsys->uuconf_pzalias; *pz != NULL; pz++) ! 1140: { ! 1141: if (clen == 7 || clen == 14) ! 1142: icmp = strncmp (zheresys, *pz, clen); ! 1143: else ! 1144: icmp = strcmp (zheresys, *pz); ! 1145: if (icmp == 0) ! 1146: break; ! 1147: } ! 1148: } ! 1149: if (icmp != 0) ! 1150: { ! 1151: ulog (LOG_ERROR, "Called wrong system (%s)", zheresys); ! 1152: ubuffree (zstr); ! 1153: return FALSE; ! 1154: } ! 1155: } ! 1156: } ! 1157: #if DEBUG > 1 ! 1158: else if (zstr[5] != '\0') ! 1159: DEBUG_MESSAGE1 (DEBUG_HANDSHAKE, ! 1160: "fdo_call: Strange Shere: %s", zstr); ! 1161: #endif ! 1162: ! 1163: ubuffree (zstr); ! 1164: ! 1165: /* We now send "S" name switches, where name is our UUCP name. If ! 1166: we are using sequence numbers with this system, we send a -Q ! 1167: argument with the sequence number. If the call-timegrade command ! 1168: was used, we send a -p argument and a -vgrade= argument with the ! 1169: grade to send us (we send both argument to make it more likely ! 1170: that one is recognized). We always send a -N (for new) switch ! 1171: indicating what new features we support. */ ! 1172: { ! 1173: long ival; ! 1174: char bgrade; ! 1175: char *zsend; ! 1176: boolean fret; ! 1177: ! 1178: /* Determine the grade we should request of the other system. A ! 1179: '\0' means that no restrictions have been made. */ ! 1180: if (! ftimespan_match (qsys->uuconf_qcalltimegrade, &ival, ! 1181: (int *) NULL)) ! 1182: bgrade = '\0'; ! 1183: else ! 1184: bgrade = (char) ival; ! 1185: ! 1186: /* Determine the name we will call ourselves. */ ! 1187: if (qsys->uuconf_zlocalname != NULL) ! 1188: qdaemon->zlocalname = qsys->uuconf_zlocalname; ! 1189: else ! 1190: { ! 1191: iuuconf = uuconf_localname (puuconf, &qdaemon->zlocalname); ! 1192: if (iuuconf == UUCONF_NOT_FOUND) ! 1193: { ! 1194: qdaemon->zlocalname = zsysdep_localname (); ! 1195: if (qdaemon->zlocalname == NULL) ! 1196: return FALSE; ! 1197: } ! 1198: else if (iuuconf != UUCONF_SUCCESS) ! 1199: { ! 1200: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 1201: return FALSE; ! 1202: } ! 1203: } ! 1204: ! 1205: zsend = zbufalc (strlen (qdaemon->zlocalname) + 70); ! 1206: if (! qsys->uuconf_fsequence) ! 1207: { ! 1208: if (bgrade == '\0') ! 1209: sprintf (zsend, "S%s -R -N0%o", qdaemon->zlocalname, ! 1210: (unsigned int) (FEATURE_SIZES ! 1211: | FEATURE_EXEC ! 1212: | FEATURE_RESTART)); ! 1213: else ! 1214: sprintf (zsend, "S%s -p%c -vgrade=%c -R -N0%o", ! 1215: qdaemon->zlocalname, bgrade, bgrade, ! 1216: (unsigned int) (FEATURE_SIZES ! 1217: | FEATURE_EXEC ! 1218: | FEATURE_RESTART)); ! 1219: } ! 1220: else ! 1221: { ! 1222: long iseq; ! 1223: ! 1224: iseq = ixsysdep_get_sequence (qsys); ! 1225: if (iseq < 0) ! 1226: return FALSE; ! 1227: if (bgrade == '\0') ! 1228: sprintf (zsend, "S%s -Q%ld -R -N0%o", qdaemon->zlocalname, iseq, ! 1229: (unsigned int) (FEATURE_SIZES ! 1230: | FEATURE_EXEC ! 1231: | FEATURE_RESTART)); ! 1232: else ! 1233: sprintf (zsend, "S%s -Q%ld -p%c -vgrade=%c -R -N0%o", ! 1234: qdaemon->zlocalname, iseq, bgrade, bgrade, ! 1235: (unsigned int) (FEATURE_SIZES ! 1236: | FEATURE_EXEC ! 1237: | FEATURE_RESTART)); ! 1238: } ! 1239: ! 1240: fret = fsend_uucp_cmd (qconn, zsend); ! 1241: ubuffree (zsend); ! 1242: if (! fret) ! 1243: return FALSE; ! 1244: } ! 1245: ! 1246: /* Now we should see ROK or Rreason where reason gives a cryptic ! 1247: reason for failure. If we are talking to a counterpart, we will ! 1248: get back ROKN, possibly with a feature bitfield attached. */ ! 1249: zstr = zget_uucp_cmd (qconn, TRUE); ! 1250: if (zstr == NULL) ! 1251: return FALSE; ! 1252: ! 1253: if (zstr[0] != 'R') ! 1254: { ! 1255: ulog (LOG_ERROR, "Bad reponse to handshake string (%s)", ! 1256: zstr); ! 1257: ubuffree (zstr); ! 1258: return FALSE; ! 1259: } ! 1260: ! 1261: if (strncmp (zstr + 1, "OKN", sizeof "OKN" - 1) == 0) ! 1262: { ! 1263: if (zstr[sizeof "ROKN" - 1] == '\0') ! 1264: qdaemon->ifeatures |= FEATURE_SIZES | FEATURE_V103; ! 1265: else ! 1266: qdaemon->ifeatures |= (int) strtol (zstr + sizeof "ROKN" - 1, ! 1267: (char **) NULL, 0); ! 1268: } ! 1269: else if (strncmp (zstr + 1, "OK", sizeof "OK" - 1) == 0) ! 1270: { ! 1271: if (zstr[sizeof "ROK" - 1] != '\0') ! 1272: { ! 1273: char *zopt; ! 1274: ! 1275: /* SVR4 UUCP returns options following the ROK string. */ ! 1276: zopt = zstr + sizeof "ROK" - 1; ! 1277: while (*zopt != '\0') ! 1278: { ! 1279: char b; ! 1280: long c; ! 1281: char *zend; ! 1282: ! 1283: b = *zopt++; ! 1284: if (isspace (b) || b != '-') ! 1285: continue; ! 1286: switch (*zopt) ! 1287: { ! 1288: case 'R': ! 1289: qdaemon->ifeatures |= (FEATURE_RESTART ! 1290: | FEATURE_SVR4 ! 1291: | FEATURE_SIZES); ! 1292: break; ! 1293: case 'U': ! 1294: c = strtol (zopt, &zend, 0); ! 1295: if (c > 0 && c <= LONG_MAX / (long) 512) ! 1296: qdaemon->cmax_receive = c * (long) 512; ! 1297: zopt = zend; ! 1298: break; ! 1299: } ! 1300: while (*zopt != '\0' && ! isspace (*zopt)) ! 1301: ++zopt; ! 1302: } ! 1303: } ! 1304: } ! 1305: else if (strcmp (zstr + 1, "CB") == 0) ! 1306: { ! 1307: ulog (LOG_NORMAL, "Remote system will call back"); ! 1308: qstat->ttype = STATUS_COMPLETE; ! 1309: (void) fsysdep_set_status (qsys, qstat); ! 1310: ubuffree (zstr); ! 1311: return TRUE; ! 1312: } ! 1313: else ! 1314: { ! 1315: ulog (LOG_ERROR, "Handshake failed (%s)", zstr + 1); ! 1316: ubuffree (zstr); ! 1317: return FALSE; ! 1318: } ! 1319: ! 1320: ubuffree (zstr); ! 1321: ! 1322: /* The slave should now send \020Pprotos\0 where protos is a list of ! 1323: supported protocols. Each protocol is a single character. */ ! 1324: zstr = zget_uucp_cmd (qconn, TRUE); ! 1325: if (zstr == NULL) ! 1326: return FALSE; ! 1327: ! 1328: if (zstr[0] != 'P') ! 1329: { ! 1330: ulog (LOG_ERROR, "Bad protocol handshake (%s)", zstr); ! 1331: ubuffree (zstr); ! 1332: return FALSE; ! 1333: } ! 1334: ! 1335: /* Determine the reliability characteristics of the connection by ! 1336: combining information for the port and the dialer. If we have no ! 1337: information, default to a reliable eight-bit full-duplex ! 1338: connection. */ ! 1339: if (qconn->qport != NULL ! 1340: && (qconn->qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0) ! 1341: qdaemon->ireliable = qconn->qport->uuconf_ireliable; ! 1342: if (qdialer != NULL ! 1343: && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0) ! 1344: { ! 1345: if (qdaemon->ireliable != 0) ! 1346: qdaemon->ireliable &= qdialer->uuconf_ireliable; ! 1347: else ! 1348: qdaemon->ireliable = qdialer->uuconf_ireliable; ! 1349: } ! 1350: if (qdaemon->ireliable == 0) ! 1351: qdaemon->ireliable = (UUCONF_RELIABLE_RELIABLE ! 1352: | UUCONF_RELIABLE_EIGHT ! 1353: | UUCONF_RELIABLE_FULLDUPLEX ! 1354: | UUCONF_RELIABLE_SPECIFIED); ! 1355: ! 1356: /* Now decide which protocol to use. The system and the port may ! 1357: have their own list of protocols. */ ! 1358: { ! 1359: int i; ! 1360: char ab[5]; ! 1361: ! 1362: i = CPROTOCOLS; ! 1363: if (qsys->uuconf_zprotocols != NULL ! 1364: || (qconn->qport != NULL ! 1365: && qconn->qport->uuconf_zprotocols != NULL)) ! 1366: { ! 1367: const char *zproto; ! 1368: ! 1369: if (qsys->uuconf_zprotocols != NULL) ! 1370: zproto = qsys->uuconf_zprotocols; ! 1371: else ! 1372: zproto = qconn->qport->uuconf_zprotocols; ! 1373: for (; *zproto != '\0'; zproto++) ! 1374: { ! 1375: if (strchr (zstr + 1, *zproto) != NULL) ! 1376: { ! 1377: for (i = 0; i < CPROTOCOLS; i++) ! 1378: if (asProtocols[i].bname == *zproto) ! 1379: break; ! 1380: if (i < CPROTOCOLS) ! 1381: break; ! 1382: } ! 1383: } ! 1384: } ! 1385: else ! 1386: { ! 1387: /* If neither the system nor the port specified a list of ! 1388: protocols, we want only protocols that match the known ! 1389: reliability of the dialer and the port. */ ! 1390: for (i = 0; i < CPROTOCOLS; i++) ! 1391: { ! 1392: int ipr; ! 1393: ! 1394: ipr = asProtocols[i].ireliable; ! 1395: if ((ipr & qdaemon->ireliable) != ipr) ! 1396: continue; ! 1397: if (strchr (zstr + 1, asProtocols[i].bname) != NULL) ! 1398: break; ! 1399: } ! 1400: } ! 1401: ! 1402: ubuffree (zstr); ! 1403: ! 1404: if (i >= CPROTOCOLS) ! 1405: { ! 1406: (void) fsend_uucp_cmd (qconn, "UN"); ! 1407: ulog (LOG_ERROR, "No mutually supported protocols"); ! 1408: return FALSE; ! 1409: } ! 1410: ! 1411: qdaemon->qproto = &asProtocols[i]; ! 1412: ! 1413: sprintf (ab, "U%c", qdaemon->qproto->bname); ! 1414: if (! fsend_uucp_cmd (qconn, ab)) ! 1415: return FALSE; ! 1416: } ! 1417: ! 1418: /* Run any protocol parameter commands. */ ! 1419: if (qdaemon->qproto->qcmds != NULL) ! 1420: { ! 1421: if (qsys->uuconf_qproto_params != NULL) ! 1422: uapply_proto_params (puuconf, qdaemon->qproto->bname, ! 1423: qdaemon->qproto->qcmds, ! 1424: qsys->uuconf_qproto_params); ! 1425: if (qconn->qport != NULL ! 1426: && qconn->qport->uuconf_qproto_params != NULL) ! 1427: uapply_proto_params (puuconf, qdaemon->qproto->bname, ! 1428: qdaemon->qproto->qcmds, ! 1429: qconn->qport->uuconf_qproto_params); ! 1430: if (qdialer != NULL ! 1431: && qdialer->uuconf_qproto_params != NULL) ! 1432: uapply_proto_params (puuconf, qdaemon->qproto->bname, ! 1433: qdaemon->qproto->qcmds, ! 1434: qdialer->uuconf_qproto_params); ! 1435: } ! 1436: ! 1437: /* Turn on the selected protocol. */ ! 1438: if (! (*qdaemon->qproto->pfstart) (qdaemon, &zlog)) ! 1439: return FALSE; ! 1440: if (zlog == NULL) ! 1441: { ! 1442: zlog = zbufalc (sizeof "protocol ''" + 1); ! 1443: sprintf (zlog, "protocol '%c'", qdaemon->qproto->bname); ! 1444: } ! 1445: ulog (LOG_NORMAL, "Handshake successful (%s)", zlog); ! 1446: ubuffree (zlog); ! 1447: ! 1448: *pterr = STATUS_FAILED; ! 1449: ! 1450: { ! 1451: boolean fret; ! 1452: long iend_time; ! 1453: ! 1454: fret = floop (qdaemon); ! 1455: ! 1456: /* Now send the hangup message. As the caller, we send six O's ! 1457: and expect to receive seven O's. We send the six O's twice to ! 1458: help the other side. We don't worry about errors here. */ ! 1459: if (fsend_uucp_cmd (qconn, "OOOOOO") ! 1460: && fsend_uucp_cmd (qconn, "OOOOOO")) ! 1461: { ! 1462: int i, fdone; ! 1463: ! 1464: /* We look for the remote hangup string to ensure that the ! 1465: modem has sent out our hangup string. This is only ! 1466: necessary because some versions of UUCP complain if they ! 1467: don't get the hangup string. The remote site should send 7 ! 1468: O's, but some versions of UUCP only send 6. We look for ! 1469: the string several times because supposedly some ! 1470: implementations send some garbage after the last packet but ! 1471: before the hangup string. */ ! 1472: for (i = 0; i < 25; i++) ! 1473: { ! 1474: zstr = zget_uucp_cmd (qconn, FALSE); ! 1475: if (zstr == NULL) ! 1476: break; ! 1477: fdone = strstr (zstr, "OOOOOO") != NULL; ! 1478: ubuffree (zstr); ! 1479: if (fdone) ! 1480: break; ! 1481: } ! 1482: } ! 1483: ! 1484: iend_time = ixsysdep_time ((long *) NULL); ! 1485: ! 1486: ulog (LOG_NORMAL, "Call complete (%ld seconds)", ! 1487: iend_time - istart_time); ! 1488: ! 1489: if (fret) ! 1490: { ! 1491: qstat->ttype = STATUS_COMPLETE; ! 1492: qstat->ilast = iend_time; ! 1493: (void) fsysdep_set_status (qsys, qstat); ! 1494: } ! 1495: ! 1496: return fret; ! 1497: } ! 1498: } ! 1499: ! 1500: /* This routine is called via uuconf_find_port when a matching port is ! 1501: found. It tries to lock the port. If it fails, it returns ! 1502: UUCONF_NOT_FOUND to force uuconf_find_port to continue searching ! 1503: for the next matching port. */ ! 1504: ! 1505: static int ! 1506: iuport_lock (qport, pinfo) ! 1507: struct uuconf_port *qport; ! 1508: pointer pinfo; ! 1509: { ! 1510: struct spass *q = (struct spass *) pinfo; ! 1511: ! 1512: q->fmatched = TRUE; ! 1513: ! 1514: if (! fconn_init (qport, q->qconn)) ! 1515: return UUCONF_NOT_FOUND; ! 1516: else if (! fconn_lock (q->qconn, FALSE)) ! 1517: { ! 1518: uconn_free (q->qconn); ! 1519: return UUCONF_NOT_FOUND; ! 1520: } ! 1521: else ! 1522: { ! 1523: q->flocked = TRUE; ! 1524: return UUCONF_SUCCESS; ! 1525: } ! 1526: } ! 1527: ! 1528: /* Prompt for a login name and a password, and run as the slave. */ ! 1529: ! 1530: static boolean ! 1531: flogin_prompt (puuconf, qconn) ! 1532: pointer puuconf; ! 1533: struct sconnection *qconn; ! 1534: { ! 1535: char *zuser, *zpass; ! 1536: boolean fret; ! 1537: int iuuconf; ! 1538: ! 1539: DEBUG_MESSAGE0 (DEBUG_HANDSHAKE, "flogin_prompt: Waiting for login"); ! 1540: ! 1541: zuser = NULL; ! 1542: do ! 1543: { ! 1544: ubuffree (zuser); ! 1545: if (! fconn_write (qconn, "login: ", sizeof "login: " - 1)) ! 1546: return FALSE; ! 1547: zuser = zget_typed_line (qconn); ! 1548: } ! 1549: while (zuser != NULL && *zuser == '\0'); ! 1550: ! 1551: if (zuser == NULL) ! 1552: return TRUE; ! 1553: ! 1554: if (! fconn_write (qconn, "Password:", sizeof "Password:" - 1)) ! 1555: { ! 1556: ubuffree (zuser); ! 1557: return FALSE; ! 1558: } ! 1559: ! 1560: zpass = zget_typed_line (qconn); ! 1561: if (zpass == NULL) ! 1562: { ! 1563: ubuffree (zuser); ! 1564: return TRUE; ! 1565: } ! 1566: ! 1567: fret = TRUE; ! 1568: ! 1569: iuuconf = uuconf_callin (puuconf, zuser, zpass); ! 1570: ubuffree (zpass); ! 1571: if (iuuconf == UUCONF_NOT_FOUND) ! 1572: ulog (LOG_ERROR, "Bad login"); ! 1573: else if (iuuconf != UUCONF_SUCCESS) ! 1574: { ! 1575: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 1576: fret = FALSE; ! 1577: } ! 1578: else ! 1579: { ! 1580: #if DEBUG > 1 ! 1581: int iholddebug; ! 1582: #endif ! 1583: ! 1584: /* We ignore the return value of faccept_call because we really ! 1585: don't care whether the call succeeded or not. We are going ! 1586: to reset the port anyhow. */ ! 1587: #if DEBUG > 1 ! 1588: iholddebug = iDebug; ! 1589: #endif ! 1590: (void) faccept_call (puuconf, zuser, qconn, (const char **) NULL); ! 1591: #if DEBUG > 1 ! 1592: iDebug = iholddebug; ! 1593: #endif ! 1594: } ! 1595: ! 1596: ubuffree (zuser); ! 1597: ! 1598: return fret; ! 1599: } ! 1600: ! 1601: /* Accept a call from a remote system. If pqsys is not NULL, *pqsys ! 1602: will be set to the system that called in if known. */ ! 1603: ! 1604: static boolean ! 1605: faccept_call (puuconf, zlogin, qconn, pzsystem) ! 1606: pointer puuconf; ! 1607: const char *zlogin; ! 1608: struct sconnection *qconn; ! 1609: const char **pzsystem; ! 1610: { ! 1611: long istart_time; ! 1612: const char *zport; ! 1613: struct uuconf_port *qport; ! 1614: struct uuconf_port sport; ! 1615: int iuuconf; ! 1616: struct uuconf_dialer *qdialer; ! 1617: struct uuconf_dialer sdialer; ! 1618: boolean ftcp_port; ! 1619: char *zsend, *zspace; ! 1620: boolean fret; ! 1621: char *zstr; ! 1622: struct uuconf_system ssys; ! 1623: const struct uuconf_system *qsys; ! 1624: const struct uuconf_system *qany; ! 1625: char *zloc; ! 1626: struct sstatus sstat; ! 1627: boolean fgotseq, fgotn; ! 1628: int i; ! 1629: char *zlog; ! 1630: char *zgrade; ! 1631: ! 1632: if (pzsystem != NULL) ! 1633: *pzsystem = NULL; ! 1634: ! 1635: ulog (LOG_NORMAL, "Incoming call (login %s port %s)", zlogin, ! 1636: zLdevice == NULL ? (char *) "unknown" : zLdevice); ! 1637: ! 1638: istart_time = ixsysdep_time ((long *) NULL); ! 1639: ! 1640: /* Figure out protocol parameters determined by the port. If no ! 1641: port was specified we're reading standard input, so try to get ! 1642: the port name and read information from the port file. We only ! 1643: use the port information to get protocol parameters; we don't ! 1644: want to start treating the port as though it were a modem, for ! 1645: example. */ ! 1646: if (qconn->qport != NULL) ! 1647: { ! 1648: qport = qconn->qport; ! 1649: zport = qport->uuconf_zname; ! 1650: ftcp_port = FALSE; ! 1651: } ! 1652: else ! 1653: { ! 1654: zport = zsysdep_port_name (&ftcp_port); ! 1655: if (zport == NULL) ! 1656: { ! 1657: qport = NULL; ! 1658: zport = "unknown"; ! 1659: } ! 1660: else ! 1661: { ! 1662: iuuconf = uuconf_find_port (puuconf, zport, (long) 0, (long) 0, ! 1663: (int (*) P((struct uuconf_port *, ! 1664: pointer pinfo))) NULL, ! 1665: (pointer) NULL, ! 1666: &sport); ! 1667: if (iuuconf == UUCONF_NOT_FOUND) ! 1668: qport = NULL; ! 1669: else if (iuuconf != UUCONF_SUCCESS) ! 1670: { ! 1671: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 1672: return FALSE; ! 1673: } ! 1674: else ! 1675: qport = &sport; ! 1676: } ! 1677: } ! 1678: ! 1679: /* If we've managed to figure out that this is a modem port, now try ! 1680: to get protocol parameters from the dialer. */ ! 1681: qdialer = NULL; ! 1682: if (qport != NULL) ! 1683: { ! 1684: if (qport->uuconf_ttype == UUCONF_PORTTYPE_MODEM) ! 1685: { ! 1686: if (qport->uuconf_u.uuconf_smodem.uuconf_pzdialer != NULL) ! 1687: { ! 1688: const char *zdialer; ! 1689: ! 1690: zdialer = qport->uuconf_u.uuconf_smodem.uuconf_pzdialer[0]; ! 1691: iuuconf = uuconf_dialer_info (puuconf, zdialer, &sdialer); ! 1692: if (iuuconf == UUCONF_SUCCESS) ! 1693: qdialer = &sdialer; ! 1694: } ! 1695: else ! 1696: qdialer = qport->uuconf_u.uuconf_smodem.uuconf_qdialer; ! 1697: } ! 1698: else if (qport->uuconf_ttype == UUCONF_PORTTYPE_TCP ! 1699: || (qport->uuconf_ttype == UUCONF_PORTTYPE_TLI ! 1700: && (qport->uuconf_ireliable ! 1701: & UUCONF_RELIABLE_SPECIFIED) == 0)) ! 1702: ftcp_port = TRUE; ! 1703: } ! 1704: ! 1705: sDaemon.puuconf = puuconf; ! 1706: sDaemon.qsys = NULL; ! 1707: sDaemon.zlocalname = NULL; ! 1708: sDaemon.qconn = qconn; ! 1709: sDaemon.qproto = NULL; ! 1710: sDaemon.clocal_size = -1; ! 1711: sDaemon.cremote_size = -1; ! 1712: sDaemon.cmax_ever = -2; ! 1713: sDaemon.cmax_receive = -1; ! 1714: sDaemon.ifeatures = 0; ! 1715: sDaemon.frequest_hangup = FALSE; ! 1716: sDaemon.fhangup_requested = FALSE; ! 1717: sDaemon.fhangup = FALSE; ! 1718: sDaemon.fmaster = FALSE; ! 1719: sDaemon.fcaller = FALSE; ! 1720: sDaemon.ireliable = 0; ! 1721: sDaemon.bgrade = UUCONF_GRADE_LOW; ! 1722: ! 1723: /* Get the local name to use. If uuconf_login_localname returns a ! 1724: value, it is not always freed up, although it should be. */ ! 1725: iuuconf = uuconf_login_localname (puuconf, zlogin, &zloc); ! 1726: if (iuuconf == UUCONF_SUCCESS) ! 1727: sDaemon.zlocalname = zloc; ! 1728: else if (iuuconf == UUCONF_NOT_FOUND) ! 1729: { ! 1730: sDaemon.zlocalname = zsysdep_localname (); ! 1731: if (sDaemon.zlocalname == NULL) ! 1732: return FALSE; ! 1733: } ! 1734: else ! 1735: { ! 1736: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 1737: return FALSE; ! 1738: } ! 1739: ! 1740: /* Tell the remote system who we are. */ ! 1741: zsend = zbufalc (strlen (sDaemon.zlocalname) + sizeof "Shere="); ! 1742: sprintf (zsend, "Shere=%s", sDaemon.zlocalname); ! 1743: fret = fsend_uucp_cmd (qconn, zsend); ! 1744: ubuffree (zsend); ! 1745: if (! fret) ! 1746: return FALSE; ! 1747: ! 1748: zstr = zget_uucp_cmd (qconn, TRUE); ! 1749: if (zstr == NULL) ! 1750: return FALSE; ! 1751: ! 1752: if (zstr[0] != 'S') ! 1753: { ! 1754: ulog (LOG_ERROR, "Bad introduction string"); ! 1755: ubuffree (zstr); ! 1756: return FALSE; ! 1757: } ! 1758: ! 1759: zspace = strchr (zstr, ' '); ! 1760: if (zspace != NULL) ! 1761: *zspace = '\0'; ! 1762: ! 1763: iuuconf = uuconf_system_info (puuconf, zstr + 1, &ssys); ! 1764: if (iuuconf == UUCONF_NOT_FOUND) ! 1765: { ! 1766: char *zscript; ! 1767: ! 1768: /* Run the remote.unknown script, if appropriate. */ ! 1769: iuuconf = uuconf_remote_unknown (puuconf, &zscript); ! 1770: if (iuuconf == UUCONF_SUCCESS) ! 1771: { ! 1772: if (! fsysdep_unknown_caller (zscript, zstr + 1)) ! 1773: { ! 1774: xfree ((pointer) zscript); ! 1775: (void) fsend_uucp_cmd (qconn, "RYou are unknown to me"); ! 1776: ubuffree (zstr); ! 1777: return FALSE; ! 1778: } ! 1779: xfree ((pointer) zscript); ! 1780: } ! 1781: else if (iuuconf != UUCONF_NOT_FOUND) ! 1782: { ! 1783: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 1784: ubuffree (zstr); ! 1785: return FALSE; ! 1786: } ! 1787: ! 1788: if (! funknown_system (puuconf, zstr + 1, &ssys)) ! 1789: { ! 1790: (void) fsend_uucp_cmd (qconn, "RYou are unknown to me"); ! 1791: ulog (LOG_ERROR, "Call from unknown system %s", zstr + 1); ! 1792: ubuffree (zstr); ! 1793: return FALSE; ! 1794: } ! 1795: } ! 1796: else if (iuuconf != UUCONF_SUCCESS) ! 1797: { ! 1798: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 1799: ubuffree (zstr); ! 1800: return FALSE; ! 1801: } ! 1802: ! 1803: qany = NULL; ! 1804: for (qsys = &ssys; qsys != NULL; qsys = qsys->uuconf_qalternate) ! 1805: { ! 1806: if (! qsys->uuconf_fcalled) ! 1807: continue; ! 1808: ! 1809: if (qsys->uuconf_zcalled_login == NULL ! 1810: || strcmp (qsys->uuconf_zcalled_login, "ANY") == 0) ! 1811: { ! 1812: if (qany == NULL) ! 1813: qany = qsys; ! 1814: } ! 1815: else if (strcmp (qsys->uuconf_zcalled_login, zlogin) == 0) ! 1816: break; ! 1817: } ! 1818: ! 1819: if (qsys == NULL && qany != NULL) ! 1820: { ! 1821: iuuconf = uuconf_validate (puuconf, qany, zlogin); ! 1822: if (iuuconf == UUCONF_SUCCESS) ! 1823: qsys = qany; ! 1824: else if (iuuconf != UUCONF_NOT_FOUND) ! 1825: { ! 1826: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 1827: ubuffree (zstr); ! 1828: return FALSE; ! 1829: } ! 1830: } ! 1831: ! 1832: if (qsys == NULL) ! 1833: { ! 1834: (void) fsend_uucp_cmd (qconn, "RLOGIN"); ! 1835: ulog (LOG_ERROR, "System %s used wrong login name %s", ! 1836: zstr + 1, zlogin); ! 1837: ubuffree (zstr); ! 1838: return FALSE; ! 1839: } ! 1840: ! 1841: sDaemon.qsys = qsys; ! 1842: ! 1843: if (pzsystem != NULL) ! 1844: *pzsystem = zbufcpy (qsys->uuconf_zname); ! 1845: ! 1846: ulog_system (qsys->uuconf_zname); ! 1847: ! 1848: #if DEBUG > 1 ! 1849: if (qsys->uuconf_zdebug != NULL) ! 1850: iDebug |= idebug_parse (qsys->uuconf_zdebug); ! 1851: #endif ! 1852: ! 1853: /* See if we are supposed to call the system back. This will queue ! 1854: up an empty command. It would be better to actually call back ! 1855: directly at this point as well. */ ! 1856: if (qsys->uuconf_fcallback) ! 1857: { ! 1858: (void) fsend_uucp_cmd (qconn, "RCB"); ! 1859: ulog (LOG_NORMAL, "Will call back"); ! 1860: ! 1861: /* Clear any existing status. */ ! 1862: sstat.ttype = STATUS_COMPLETE; ! 1863: sstat.cretries = 0; ! 1864: sstat.ilast = ixsysdep_time ((long *) NULL); ! 1865: sstat.cwait = 0; ! 1866: (void) fsysdep_set_status (qsys, &sstat); ! 1867: ! 1868: ubuffree (zsysdep_spool_commands (qsys, UUCONF_GRADE_HIGH, 0, ! 1869: (const struct scmd *) NULL)); ! 1870: ubuffree (zstr); ! 1871: return TRUE; ! 1872: } ! 1873: ! 1874: /* We only permit one call at a time from a remote system. Lock it. */ ! 1875: if (! fsysdep_lock_system (qsys)) ! 1876: { ! 1877: (void) fsend_uucp_cmd (qconn, "RLCK"); ! 1878: ulog (LOG_ERROR, "System already locked"); ! 1879: ubuffree (zstr); ! 1880: return FALSE; ! 1881: } ! 1882: sLocked_system = *qsys; ! 1883: fLocked_system = TRUE; ! 1884: ! 1885: /* Set the system status. We don't care what the status was before. ! 1886: We also don't want to kill the conversation just because we can't ! 1887: output the .Status file, so we ignore any errors. */ ! 1888: sstat.ttype = STATUS_TALKING; ! 1889: sstat.cretries = 0; ! 1890: sstat.ilast = ixsysdep_time ((long *) NULL); ! 1891: sstat.cwait = 0; ! 1892: (void) fsysdep_set_status (qsys, &sstat); ! 1893: ! 1894: /* Check the arguments of the remote system, if any. */ ! 1895: fgotseq = FALSE; ! 1896: fgotn = FALSE; ! 1897: if (zspace != NULL) ! 1898: { ! 1899: char **paz; ! 1900: char **pzset; ! 1901: ! 1902: ++zspace; ! 1903: ! 1904: /* Break the introduction line up into arguments. */ ! 1905: paz = (char **) xmalloc ((strlen (zspace) / 2 + 2) * sizeof (char *)); ! 1906: pzset = paz; ! 1907: *pzset++ = NULL; ! 1908: while (TRUE) ! 1909: { ! 1910: while (*zspace != '\0' && isspace (BUCHAR (*zspace))) ! 1911: ++zspace; ! 1912: if (*zspace == '\0') ! 1913: break; ! 1914: *pzset++ = zspace; ! 1915: ++zspace; ! 1916: while (*zspace != '\0' && ! isspace (BUCHAR (*zspace))) ! 1917: ++zspace; ! 1918: if (*zspace == '\0') ! 1919: break; ! 1920: *zspace++ = '\0'; ! 1921: } ! 1922: ! 1923: if (pzset != paz + 1) ! 1924: { ! 1925: int iopt; ! 1926: ! 1927: *pzset = NULL; ! 1928: ! 1929: /* We are going to use getopt to parse the arguments. We ! 1930: must clear optind to force getopt to reinitialize, and ! 1931: clear opterr to prevent getopt from printing an error ! 1932: message. This approach assumes we are using the GNU ! 1933: getopt, which is distributed with the program anyhow. */ ! 1934: optind = 0; ! 1935: opterr = 0; ! 1936: ! 1937: while ((iopt = getopt (pzset - paz, paz, ! 1938: "N::p:Q:RU:v:x:")) != EOF) ! 1939: { ! 1940: long iseq; ! 1941: long c; ! 1942: char b; ! 1943: int iwant; ! 1944: ! 1945: switch (iopt) ! 1946: { ! 1947: case 'N': ! 1948: /* This is used to indicate support for Taylor UUCP ! 1949: extensions. An plain -N mean support for size ! 1950: negotiation. If -N is followed by a number (with ! 1951: no intervening space), the number is a bit field ! 1952: of feature flags as defined in trans.h. Note ! 1953: that the argument may start with 0x for hex or 0 ! 1954: for octal. */ ! 1955: fgotn = TRUE; ! 1956: if (optarg == NULL) ! 1957: sDaemon.ifeatures |= FEATURE_SIZES | FEATURE_V103; ! 1958: else ! 1959: sDaemon.ifeatures |= (int) strtol (optarg, ! 1960: (char **) NULL, ! 1961: 0); ! 1962: break; ! 1963: ! 1964: case 'p': ! 1965: /* The argument is the lowest grade of work the ! 1966: local system should send. */ ! 1967: if (UUCONF_GRADE_LEGAL (optarg[0])) ! 1968: sDaemon.bgrade = optarg[0]; ! 1969: break; ! 1970: ! 1971: case 'Q': ! 1972: /* The conversation sequence number. */ ! 1973: iseq = strtol (optarg, (char **) NULL, 10); ! 1974: if (qsys->uuconf_fsequence ! 1975: && iseq != ixsysdep_get_sequence (qsys)) ! 1976: { ! 1977: (void) fsend_uucp_cmd (qconn, "RBADSEQ"); ! 1978: ulog (LOG_ERROR, "Out of sequence call rejected"); ! 1979: sstat.ttype = STATUS_FAILED; ! 1980: (void) fsysdep_set_status (qsys, &sstat); ! 1981: xfree ((pointer) paz); ! 1982: ubuffree (zstr); ! 1983: return FALSE; ! 1984: } ! 1985: fgotseq = TRUE; ! 1986: break; ! 1987: ! 1988: case 'R': ! 1989: /* The remote system supports file restart. */ ! 1990: sDaemon.ifeatures |= FEATURE_RESTART; ! 1991: break; ! 1992: ! 1993: case 'U': ! 1994: /* The maximum file size the remote system is ! 1995: prepared to received, in blocks where each block ! 1996: is 512 bytes. */ ! 1997: c = strtol (optarg, (char **) NULL, 0); ! 1998: if (c > 0 && c < LONG_MAX / (long) 512) ! 1999: sDaemon.cmax_receive = c * (long) 512; ! 2000: break; ! 2001: ! 2002: case 'v': ! 2003: /* -vgrade=X can be used to set the lowest grade of ! 2004: work the local system should send. */ ! 2005: if (strncmp (optarg, "grade=", sizeof "grade=" - 1) == 0) ! 2006: { ! 2007: b = optarg[sizeof "grade=" - 1]; ! 2008: if (UUCONF_GRADE_LEGAL (b)) ! 2009: sDaemon.bgrade = b; ! 2010: } ! 2011: break; ! 2012: ! 2013: case 'x': ! 2014: iwant = (int) strtol (optarg, (char **) NULL, 10); ! 2015: #if DEBUG > 1 ! 2016: if (iwant <= 9) ! 2017: iwant = (1 << iwant) - 1; ! 2018: if (qsys->uuconf_zmax_remote_debug != NULL) ! 2019: iwant &= idebug_parse (qsys->uuconf_zmax_remote_debug); ! 2020: if ((iDebug | iwant) != iDebug) ! 2021: { ! 2022: iDebug |= iwant; ! 2023: ulog (LOG_NORMAL, "Setting debugging mode to 0%o", ! 2024: iDebug); ! 2025: } ! 2026: #endif ! 2027: break; ! 2028: ! 2029: default: ! 2030: break; ! 2031: } ! 2032: } ! 2033: } ! 2034: ! 2035: xfree ((pointer) paz); ! 2036: } ! 2037: ! 2038: ubuffree (zstr); ! 2039: ! 2040: if (qsys->uuconf_fsequence && ! fgotseq) ! 2041: { ! 2042: (void) fsend_uucp_cmd (qconn, "RBADSEQ"); ! 2043: ulog (LOG_ERROR, "No sequence number (call rejected)"); ! 2044: sstat.ttype = STATUS_FAILED; ! 2045: (void) fsysdep_set_status (qsys, &sstat); ! 2046: return FALSE; ! 2047: } ! 2048: ! 2049: /* We recognized the system, and the sequence number (if any) was ! 2050: OK. Send an ROK, and send a list of protocols. If we got the -N ! 2051: switch, send ROKN to confirm it; if the -N switch was followed by ! 2052: a feature bitfield, return our own feature bitfield. */ ! 2053: { ! 2054: char ab[20]; ! 2055: const char *zreply; ! 2056: ! 2057: if (! fgotn) ! 2058: { ! 2059: if ((sDaemon.ifeatures & FEATURE_RESTART) == 0) ! 2060: zreply = "ROK"; ! 2061: else ! 2062: { ! 2063: /* We got -R without -N, so assume that this is SVR4 UUCP. ! 2064: SVR4 UUCP expects ROK -R to signal support for file ! 2065: restart. */ ! 2066: sDaemon.ifeatures |= FEATURE_SVR4 | FEATURE_SIZES; ! 2067: zreply = "ROK -R"; ! 2068: } ! 2069: } ! 2070: else if ((sDaemon.ifeatures & FEATURE_V103) != 0) ! 2071: zreply = "ROKN"; ! 2072: else ! 2073: { ! 2074: sprintf (ab, "ROKN0%o", ! 2075: (unsigned int) (FEATURE_SIZES ! 2076: | FEATURE_EXEC ! 2077: | FEATURE_RESTART)); ! 2078: zreply = ab; ! 2079: } ! 2080: if (! fsend_uucp_cmd (qconn, zreply)) ! 2081: { ! 2082: sstat.ttype = STATUS_FAILED; ! 2083: (void) fsysdep_set_status (qsys, &sstat); ! 2084: return FALSE; ! 2085: } ! 2086: } ! 2087: ! 2088: /* Determine the reliability of the connection based on the ! 2089: reliability of the port and the dialer. If we have no ! 2090: information, default to a reliable eight-bit full-duplex ! 2091: connection. */ ! 2092: if (ftcp_port) ! 2093: sDaemon.ireliable = (UUCONF_RELIABLE_SPECIFIED ! 2094: | UUCONF_RELIABLE_ENDTOEND ! 2095: | UUCONF_RELIABLE_RELIABLE ! 2096: | UUCONF_RELIABLE_EIGHT ! 2097: | UUCONF_RELIABLE_FULLDUPLEX); ! 2098: else ! 2099: { ! 2100: if (qport != NULL ! 2101: && (qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0) ! 2102: sDaemon.ireliable = qport->uuconf_ireliable; ! 2103: if (qdialer != NULL ! 2104: && (qdialer->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0) ! 2105: { ! 2106: if (sDaemon.ireliable != 0) ! 2107: sDaemon.ireliable &= qdialer->uuconf_ireliable; ! 2108: else ! 2109: sDaemon.ireliable = qdialer->uuconf_ireliable; ! 2110: } ! 2111: if (sDaemon.ireliable == 0) ! 2112: sDaemon.ireliable = (UUCONF_RELIABLE_RELIABLE ! 2113: | UUCONF_RELIABLE_EIGHT ! 2114: | UUCONF_RELIABLE_FULLDUPLEX ! 2115: | UUCONF_RELIABLE_SPECIFIED); ! 2116: } ! 2117: ! 2118: if (qsys->uuconf_zprotocols != NULL || ! 2119: (qport != NULL && qport->uuconf_zprotocols != NULL)) ! 2120: { ! 2121: const char *zprotos; ! 2122: ! 2123: if (qsys->uuconf_zprotocols != NULL) ! 2124: zprotos = qsys->uuconf_zprotocols; ! 2125: else ! 2126: zprotos = qport->uuconf_zprotocols; ! 2127: zsend = zbufalc (strlen (zprotos) + 2); ! 2128: sprintf (zsend, "P%s", zprotos); ! 2129: } ! 2130: else ! 2131: { ! 2132: char *zset; ! 2133: ! 2134: zsend = zbufalc (CPROTOCOLS + 2); ! 2135: zset = zsend; ! 2136: *zset++ = 'P'; ! 2137: ! 2138: /* If the system did not specify a list of protocols, we want ! 2139: only protocols that match the known reliability of the dialer ! 2140: and the port. */ ! 2141: for (i = 0; i < CPROTOCOLS; i++) ! 2142: { ! 2143: int ipr; ! 2144: ! 2145: ipr = asProtocols[i].ireliable; ! 2146: if ((ipr & sDaemon.ireliable) != ipr) ! 2147: continue; ! 2148: *zset++ = asProtocols[i].bname; ! 2149: } ! 2150: *zset = '\0'; ! 2151: } ! 2152: ! 2153: fret = fsend_uucp_cmd (qconn, zsend); ! 2154: ubuffree (zsend); ! 2155: if (! fret) ! 2156: { ! 2157: sstat.ttype = STATUS_FAILED; ! 2158: (void) fsysdep_set_status (qsys, &sstat); ! 2159: return FALSE; ! 2160: } ! 2161: ! 2162: /* The master will now send back the selected protocol. */ ! 2163: zstr = zget_uucp_cmd (qconn, TRUE); ! 2164: if (zstr == NULL) ! 2165: { ! 2166: sstat.ttype = STATUS_FAILED; ! 2167: (void) fsysdep_set_status (qsys, &sstat); ! 2168: return FALSE; ! 2169: } ! 2170: ! 2171: if (zstr[0] != 'U' || zstr[2] != '\0') ! 2172: { ! 2173: ulog (LOG_ERROR, "Bad protocol response string"); ! 2174: sstat.ttype = STATUS_FAILED; ! 2175: (void) fsysdep_set_status (qsys, &sstat); ! 2176: ubuffree (zstr); ! 2177: return FALSE; ! 2178: } ! 2179: ! 2180: if (zstr[1] == 'N') ! 2181: { ! 2182: ulog (LOG_ERROR, "No supported protocol"); ! 2183: sstat.ttype = STATUS_FAILED; ! 2184: (void) fsysdep_set_status (qsys, &sstat); ! 2185: ubuffree (zstr); ! 2186: return FALSE; ! 2187: } ! 2188: ! 2189: for (i = 0; i < CPROTOCOLS; i++) ! 2190: if (asProtocols[i].bname == zstr[1]) ! 2191: break; ! 2192: ! 2193: ubuffree (zstr); ! 2194: ! 2195: if (i >= CPROTOCOLS) ! 2196: { ! 2197: ulog (LOG_ERROR, "No supported protocol"); ! 2198: sstat.ttype = STATUS_FAILED; ! 2199: (void) fsysdep_set_status (qsys, &sstat); ! 2200: return FALSE; ! 2201: } ! 2202: ! 2203: sDaemon.qproto = &asProtocols[i]; ! 2204: ! 2205: /* Run the chat script for when a call is received. */ ! 2206: if (! fchat (qconn, puuconf, &qsys->uuconf_scalled_chat, qsys, ! 2207: (const struct uuconf_dialer *) NULL, (const char *) NULL, ! 2208: FALSE, zport, iconn_baud (qconn))) ! 2209: { ! 2210: sstat.ttype = STATUS_FAILED; ! 2211: sstat.ilast = ixsysdep_time ((long *) NULL); ! 2212: (void) fsysdep_set_status (qsys, &sstat); ! 2213: return FALSE; ! 2214: } ! 2215: ! 2216: /* Run any protocol parameter commands. */ ! 2217: if (sDaemon.qproto->qcmds != NULL) ! 2218: { ! 2219: if (qsys->uuconf_qproto_params != NULL) ! 2220: uapply_proto_params (puuconf, sDaemon.qproto->bname, ! 2221: sDaemon.qproto->qcmds, ! 2222: qsys->uuconf_qproto_params); ! 2223: if (qport != NULL ! 2224: && qport->uuconf_qproto_params != NULL) ! 2225: uapply_proto_params (puuconf, sDaemon.qproto->bname, ! 2226: sDaemon.qproto->qcmds, ! 2227: qport->uuconf_qproto_params); ! 2228: if (qdialer != NULL ! 2229: && qdialer->uuconf_qproto_params != NULL) ! 2230: uapply_proto_params (puuconf, sDaemon.qproto->bname, ! 2231: sDaemon.qproto->qcmds, ! 2232: qdialer->uuconf_qproto_params); ! 2233: } ! 2234: ! 2235: /* We don't need the dialer information any more. */ ! 2236: if (qdialer == &sdialer) ! 2237: (void) uuconf_dialer_free (puuconf, &sdialer); ! 2238: ! 2239: /* Get any jobs queued for the system, and turn on the selected ! 2240: protocol. */ ! 2241: if (! fqueue (&sDaemon, (boolean *) NULL) ! 2242: || ! (*sDaemon.qproto->pfstart) (&sDaemon, &zlog)) ! 2243: { ! 2244: uclear_queue (&sDaemon); ! 2245: sstat.ttype = STATUS_FAILED; ! 2246: sstat.ilast = ixsysdep_time ((long *) NULL); ! 2247: (void) fsysdep_set_status (qsys, &sstat); ! 2248: return FALSE; ! 2249: } ! 2250: ! 2251: if (zlog == NULL) ! 2252: { ! 2253: zlog = zbufalc (sizeof "protocol ''" + 1); ! 2254: sprintf (zlog, "protocol '%c'", sDaemon.qproto->bname); ! 2255: } ! 2256: ! 2257: zgrade = zbufalc (sizeof "grade " + 1); ! 2258: if (sDaemon.bgrade == UUCONF_GRADE_LOW) ! 2259: *zgrade = '\0'; ! 2260: else ! 2261: sprintf (zgrade, "grade %c ", sDaemon.bgrade); ! 2262: ! 2263: /* If we are using HAVE_HDB_LOGGING, then the previous ``incoming ! 2264: call'' message went to the general log, since we didn't know the ! 2265: system name at that point. In that case, we repeat the port and ! 2266: login names. */ ! 2267: #if HAVE_HDB_LOGGING ! 2268: ulog (LOG_NORMAL, "Handshake successful (login %s port %s %s%s)", ! 2269: zlogin, ! 2270: zLdevice == NULL ? "unknown" : zLdevice, ! 2271: zgrade, zlog); ! 2272: #else /* ! HAVE_HDB_LOGGING */ ! 2273: ulog (LOG_NORMAL, "Handshake successful (%s%s)", zgrade, zlog); ! 2274: #endif /* ! HAVE_HDB_LOGGING */ ! 2275: ! 2276: ubuffree (zlog); ! 2277: ubuffree (zgrade); ! 2278: ! 2279: { ! 2280: long iend_time; ! 2281: ! 2282: fret = floop (&sDaemon); ! 2283: ! 2284: /* Hangup. As the answerer, we send seven O's and expect to ! 2285: receive six O's. We send the seven O's twice to help the other ! 2286: side. We don't worry about errors here. */ ! 2287: if (fsend_uucp_cmd (qconn, "OOOOOOO") ! 2288: && fsend_uucp_cmd (qconn, "OOOOOOO")) ! 2289: { ! 2290: int fdone; ! 2291: ! 2292: /* We look for the remote hangup string to ensure that the ! 2293: modem has sent out our hangup string. This is only ! 2294: necessary because some versions of UUCP complain if they ! 2295: don't get the hangup string. We look for the string ! 2296: several times because supposedly some implementations send ! 2297: some garbage after the last packet but before the hangup ! 2298: string. */ ! 2299: for (i = 0; i < 25; i++) ! 2300: { ! 2301: zstr = zget_uucp_cmd (qconn, FALSE); ! 2302: if (zstr == NULL) ! 2303: break; ! 2304: fdone = strstr (zstr, "OOOOOO") != NULL; ! 2305: ubuffree (zstr); ! 2306: if (fdone) ! 2307: break; ! 2308: } ! 2309: } ! 2310: ! 2311: iend_time = ixsysdep_time ((long *) NULL); ! 2312: ! 2313: ulog (LOG_NORMAL, "Call complete (%ld seconds)", ! 2314: iend_time - istart_time); ! 2315: ! 2316: uclear_queue (&sDaemon); ! 2317: ! 2318: if (fret) ! 2319: sstat.ttype = STATUS_COMPLETE; ! 2320: else ! 2321: sstat.ttype = STATUS_FAILED; ! 2322: sstat.ilast = iend_time; ! 2323: (void) fsysdep_set_status (qsys, &sstat); ! 2324: ! 2325: (void) uuconf_system_free (puuconf, &ssys); ! 2326: if (qport == &sport) ! 2327: (void) uuconf_port_free (puuconf, &sport); ! 2328: xfree ((pointer) zloc); ! 2329: ! 2330: return fret; ! 2331: } ! 2332: } ! 2333: ! 2334: /* Apply protocol parameters, once we know the protocol. */ ! 2335: ! 2336: static void ! 2337: uapply_proto_params (puuconf, bproto, qcmds, pas) ! 2338: pointer puuconf; ! 2339: int bproto; ! 2340: struct uuconf_cmdtab *qcmds; ! 2341: struct uuconf_proto_param *pas; ! 2342: { ! 2343: struct uuconf_proto_param *qp; ! 2344: ! 2345: for (qp = pas; qp->uuconf_bproto != '\0'; qp++) ! 2346: { ! 2347: if (qp->uuconf_bproto == bproto) ! 2348: { ! 2349: struct uuconf_proto_param_entry *qe; ! 2350: ! 2351: for (qe = qp->uuconf_qentries; qe->uuconf_cargs > 0; qe++) ! 2352: { ! 2353: int iuuconf; ! 2354: ! 2355: iuuconf = uuconf_cmd_args (puuconf, qe->uuconf_cargs, ! 2356: qe->uuconf_pzargs, qcmds, ! 2357: (pointer) NULL, ! 2358: (uuconf_cmdtabfn) NULL, 0, ! 2359: (pointer) NULL); ! 2360: if (UUCONF_ERROR_VALUE (iuuconf) != UUCONF_SUCCESS) ! 2361: { ! 2362: ulog (LOG_ERROR, "Error in %c protocol parameters", ! 2363: bproto); ! 2364: ulog_uuconf (LOG_ERROR, puuconf, iuuconf); ! 2365: } ! 2366: } ! 2367: ! 2368: break; ! 2369: } ! 2370: } ! 2371: } ! 2372: ! 2373: /* Send a string to the other system beginning with a DLE ! 2374: character and terminated with a null byte. This is only ! 2375: used when no protocol is in force. */ ! 2376: ! 2377: static boolean ! 2378: fsend_uucp_cmd (qconn, z) ! 2379: struct sconnection *qconn; ! 2380: const char *z; ! 2381: { ! 2382: size_t cwrite; ! 2383: char *zalc; ! 2384: boolean fret; ! 2385: ! 2386: DEBUG_MESSAGE1 (DEBUG_HANDSHAKE, "fsend_uucp_cmd: Sending \"%s\"", z); ! 2387: ! 2388: cwrite = strlen (z) + 2; ! 2389: ! 2390: zalc = zbufalc (cwrite); ! 2391: zalc[0] = '\020'; ! 2392: memcpy (zalc + 1, z, cwrite - 1); ! 2393: ! 2394: fret = fconn_write (qconn, zalc, cwrite); ! 2395: ubuffree (zalc); ! 2396: return fret; ! 2397: } ! 2398: ! 2399: /* Get a UUCP command beginning with a DLE character and ending with a ! 2400: null byte. This is only used when no protocol is in force. This ! 2401: implementation has the potential of being seriously slow. It also ! 2402: doesn't have any real error recovery. The frequired argument is ! 2403: passed as TRUE if we need the string; we don't care that much if ! 2404: we're closing down the connection anyhow. */ ! 2405: ! 2406: #define CTIMEOUT (120) ! 2407: #define CSHORTTIMEOUT (10) ! 2408: #define CINCREMENT (100) ! 2409: ! 2410: static char * ! 2411: zget_uucp_cmd (qconn, frequired) ! 2412: struct sconnection *qconn; ! 2413: boolean frequired; ! 2414: { ! 2415: char *zalc; ! 2416: size_t calc; ! 2417: size_t cgot; ! 2418: boolean fintro; ! 2419: long iendtime; ! 2420: int ctimeout; ! 2421: #if DEBUG > 1 ! 2422: int cchars; ! 2423: int iolddebug; ! 2424: #endif ! 2425: ! 2426: iendtime = ixsysdep_time ((long *) NULL); ! 2427: if (frequired) ! 2428: iendtime += CTIMEOUT; ! 2429: else ! 2430: iendtime += CSHORTTIMEOUT; ! 2431: ! 2432: #if DEBUG > 1 ! 2433: cchars = 0; ! 2434: iolddebug = iDebug; ! 2435: if (FDEBUGGING (DEBUG_HANDSHAKE)) ! 2436: { ! 2437: ulog (LOG_DEBUG_START, "zget_uucp_cmd: Got \""); ! 2438: iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT); ! 2439: } ! 2440: #endif ! 2441: ! 2442: zalc = NULL; ! 2443: calc = 0; ! 2444: cgot = 0; ! 2445: fintro = FALSE; ! 2446: while ((ctimeout = (int) (iendtime - ixsysdep_time ((long *) NULL))) > 0) ! 2447: { ! 2448: int b; ! 2449: ! 2450: b = breceive_char (qconn, ctimeout, frequired); ! 2451: /* Now b == -1 on timeout, -2 on error. */ ! 2452: if (b < 0) ! 2453: { ! 2454: #if DEBUG > 1 ! 2455: if (FDEBUGGING (DEBUG_HANDSHAKE)) ! 2456: { ! 2457: ulog (LOG_DEBUG_END, "\" (%s)", ! 2458: b == -1 ? "timeout" : "error"); ! 2459: iDebug = iolddebug; ! 2460: } ! 2461: #endif ! 2462: if (b == -1 && frequired) ! 2463: ulog (LOG_ERROR, "Timeout"); ! 2464: ubuffree (zalc); ! 2465: return NULL; ! 2466: } ! 2467: ! 2468: /* Apparently some systems use parity on these strings, so we ! 2469: strip the parity bit. This may need to be configurable at ! 2470: some point, although only if system names can have eight bit ! 2471: characters. */ ! 2472: if (! isprint (BUCHAR (b))) ! 2473: b &= 0x7f; ! 2474: ! 2475: #if DEBUG > 1 ! 2476: if (FDEBUGGING (DEBUG_HANDSHAKE)) ! 2477: { ! 2478: char ab[5]; ! 2479: ! 2480: ++cchars; ! 2481: if (cchars > 60) ! 2482: { ! 2483: ulog (LOG_DEBUG_END, "\""); ! 2484: ulog (LOG_DEBUG_START, "zget_uucp_cmd: Got \""); ! 2485: cchars = 0; ! 2486: } ! 2487: (void) cdebug_char (ab, b); ! 2488: ulog (LOG_DEBUG_CONTINUE, "%s", ab); ! 2489: } ! 2490: #endif ! 2491: ! 2492: if (! fintro) ! 2493: { ! 2494: if (b == '\020') ! 2495: fintro = TRUE; ! 2496: continue; ! 2497: } ! 2498: ! 2499: /* If we see another DLE, something has gone wrong; continue ! 2500: as though this were the first one we saw. */ ! 2501: if (b == '\020') ! 2502: { ! 2503: cgot = 0; ! 2504: continue; ! 2505: } ! 2506: ! 2507: /* Some systems send a trailing \n on the Shere line. As far as ! 2508: I can tell this line can never contain a \n, so this ! 2509: modification should be safe enough. */ ! 2510: if (b == '\r' || b == '\n') ! 2511: b = '\0'; ! 2512: ! 2513: if (cgot >= calc) ! 2514: { ! 2515: char *znew; ! 2516: ! 2517: calc += CINCREMENT; ! 2518: znew = zbufalc (calc); ! 2519: memcpy (znew, zalc, cgot); ! 2520: ubuffree (zalc); ! 2521: zalc = znew; ! 2522: } ! 2523: ! 2524: zalc[cgot] = (char) b; ! 2525: ++cgot; ! 2526: ! 2527: if (b == '\0') ! 2528: { ! 2529: #if DEBUG > 1 ! 2530: if (FDEBUGGING (DEBUG_HANDSHAKE)) ! 2531: { ! 2532: ulog (LOG_DEBUG_END, "\""); ! 2533: iDebug = iolddebug; ! 2534: } ! 2535: #endif ! 2536: return zalc; ! 2537: } ! 2538: } ! 2539: ! 2540: #if DEBUG > 1 ! 2541: if (FDEBUGGING (DEBUG_HANDSHAKE)) ! 2542: { ! 2543: ulog (LOG_DEBUG_END, "\" (timeout)"); ! 2544: iDebug = iolddebug; ! 2545: } ! 2546: #endif ! 2547: ! 2548: ubuffree (zalc); ! 2549: ! 2550: if (frequired) ! 2551: ulog (LOG_ERROR, "Timeout"); ! 2552: return NULL; ! 2553: } ! 2554: ! 2555: /* Read a sequence of characters up to a newline or carriage return, and ! 2556: return the line without the line terminating character. */ ! 2557: ! 2558: static char * ! 2559: zget_typed_line (qconn) ! 2560: struct sconnection *qconn; ! 2561: { ! 2562: char *zalc; ! 2563: size_t calc; ! 2564: size_t cgot; ! 2565: ! 2566: #if DEBUG > 1 ! 2567: int cchars; ! 2568: int iolddebug; ! 2569: ! 2570: cchars = 0; ! 2571: iolddebug = iDebug; ! 2572: if (FDEBUGGING (DEBUG_CHAT)) ! 2573: { ! 2574: ulog (LOG_DEBUG_START, "zget_typed_line: Got \""); ! 2575: iDebug &=~ (DEBUG_INCOMING | DEBUG_PORT); ! 2576: } ! 2577: #endif ! 2578: ! 2579: zalc = NULL; ! 2580: calc = 0; ! 2581: cgot = 0; ! 2582: while (TRUE) ! 2583: { ! 2584: int b; ! 2585: ! 2586: b = breceive_char (qconn, CTIMEOUT, FALSE); ! 2587: ! 2588: /* Now b == -1 on timeout, -2 on error. */ ! 2589: ! 2590: if (b == -2 || FGOT_SIGNAL ()) ! 2591: { ! 2592: #if DEBUG > 1 ! 2593: if (FDEBUGGING (DEBUG_CHAT)) ! 2594: { ! 2595: ulog (LOG_DEBUG_END, "\" (error)"); ! 2596: iDebug = iolddebug; ! 2597: } ! 2598: #endif ! 2599: ubuffree (zalc); ! 2600: return NULL; ! 2601: } ! 2602: ! 2603: if (b == -1) ! 2604: continue; ! 2605: ! 2606: #if DEBUG > 1 ! 2607: if (FDEBUGGING (DEBUG_CHAT)) ! 2608: { ! 2609: char ab[5]; ! 2610: ! 2611: ++cchars; ! 2612: if (cchars > 60) ! 2613: { ! 2614: ulog (LOG_DEBUG_END, "\""); ! 2615: ulog (LOG_DEBUG_START, "zget_typed_line: Got \""); ! 2616: cchars = 0; ! 2617: } ! 2618: (void) cdebug_char (ab, b); ! 2619: ulog (LOG_DEBUG_CONTINUE, "%s", ab); ! 2620: } ! 2621: #endif ! 2622: ! 2623: if (cgot >= calc) ! 2624: { ! 2625: char *znew; ! 2626: ! 2627: calc += CINCREMENT; ! 2628: znew = zbufalc (calc); ! 2629: memcpy (znew, zalc, cgot); ! 2630: ubuffree (zalc); ! 2631: zalc = znew; ! 2632: } ! 2633: ! 2634: if (b == '\r' || b == '\n') ! 2635: b = '\0'; ! 2636: ! 2637: zalc[cgot] = (char) b; ! 2638: ++cgot; ! 2639: ! 2640: if (b == '\0') ! 2641: { ! 2642: #if DEBUG > 1 ! 2643: if (FDEBUGGING (DEBUG_CHAT)) ! 2644: { ! 2645: ulog (LOG_DEBUG_END, "\""); ! 2646: iDebug = iolddebug; ! 2647: } ! 2648: #endif ! 2649: return zalc; ! 2650: } ! 2651: } ! 2652: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.