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