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