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