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