1/* uuchk.c
2   Display what we think the permissions of systems are.
3
4   Copyright (C) 1991, 1992, 1993, 1994, 1995, 2002 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 uuchk_rcsid[] = "$Id: uuchk.c,v 1.71 2002/03/05 19:10:42 ian Rel $";
29#endif
30
31#include "getopt.h"
32
33#include "uuconf.h"
34
35/* Local functions.  */
36
37static void ukusage P((void));
38static void ukhelp P((void));
39static void ukshow_names P((const char *zheader, const char * const *pznames));
40static void ukshow P((const struct uuconf_system *qsys,
41		      pointer puuconf));
42static int ikshow_port P((struct uuconf_port *qport, pointer pinfo));
43static void ukshow_dialer P((struct uuconf_dialer *qdial));
44static void ukshow_chat P((const struct uuconf_chat *qchat,
45			   const char *zhdr));
46static void ukshow_size P((struct uuconf_timespan *q, boolean fcall,
47			   boolean flocal));
48static void ukshow_reliable P ((int i, const char *zhdr));
49static void ukshow_proto_params P((struct uuconf_proto_param *pas,
50				   int cindent));
51static void ukshow_time P((const struct uuconf_timespan *));
52static struct uuconf_timespan *qcompress_span P((struct uuconf_timespan *));
53static void ukuuconf_error P((pointer puuconf, int iret));
54
55/* Structure used to pass uuconf pointer into ikshow_port and also let
56   it record whether any ports were found.  */
57struct sinfo
58{
59  /* The uuconf global pointer.  */
60  pointer puuconf;
61  /* The system.  */
62  const struct uuconf_system *qsys;
63  /* Whether any ports were seen.  */
64  boolean fgot;
65};
66
67/* Program name.  */
68static const char *zKprogram;
69
70/* Long getopt options.  */
71static const struct option asKlongopts[] =
72{
73  { "system", required_argument, NULL,'s' },
74  { "config", required_argument, NULL, 'I' },
75  { "debug", required_argument, NULL, 'x' },
76  { "version", no_argument, NULL, 'v' },
77  { "help", no_argument, NULL, 1 },
78  { NULL, 0, NULL, 0 }
79};
80
81int
82main (argc, argv)
83     int argc;
84     char **argv;
85{
86  int iopt;
87  const char *zsystem = NULL;
88  const char *zconfig = NULL;
89  int iret;
90  pointer puuconf;
91
92  if (argc < 1)
93  {
94      zKprogram = "uuchk";
95      ukusage ();
96  }
97
98  zKprogram = argv[0];
99
100  while ((iopt = getopt_long (argc, argv, "I:s:vx:", asKlongopts,
101			      (int *) NULL)) != EOF)
102    {
103      switch (iopt)
104	{
105	case 's':
106	  /* Examine specific system.  */
107	  zsystem = optarg;
108	  break;
109
110	case 'I':
111	  /* Set the configuration file name.  */
112	  zconfig = optarg;
113	  break;
114
115	case 'x':
116	  /* Set the debugging level.  There is actually no debugging
117	     information for this program.  */
118	  break;
119
120	case 'v':
121	  /* Print version and exit.  */
122	  printf ("uuchk (Taylor UUCP) %s\n", VERSION);
123	  printf ("Copyright (C) 1991, 92, 93, 94, 1995, 2002 Ian Lance Taylor\n");
124	  printf ("This program is free software; you may redistribute it under the terms of\n");
125	  printf ("the GNU General Public LIcense.  This program has ABSOLUTELY NO WARRANTY.\n");
126	  exit (EXIT_SUCCESS);
127	  /*NOTREACHED*/
128
129	case 1:
130	  /* --help.  */
131	  ukhelp ();
132	  exit (EXIT_SUCCESS);
133	  /*NOTREACHED*/
134
135	case 0:
136	  /* Long option found and flag set.  */
137	  break;
138
139	default:
140	  ukusage ();
141	  /*NOTREACHED*/
142	}
143    }
144
145  if (optind != argc)
146    {
147      fprintf (stderr, "%s: too many arguments", zKprogram);
148      ukusage ();
149    }
150
151  iret = uuconf_init (&puuconf, (const char *) NULL, zconfig);
152  if (iret != UUCONF_SUCCESS)
153    ukuuconf_error (puuconf, iret);
154
155  if (zsystem != NULL)
156    {
157      struct uuconf_system ssys;
158
159      iret = uuconf_system_info (puuconf, zsystem, &ssys);
160      if (iret == UUCONF_NOT_FOUND)
161	{
162	  fprintf (stderr, "%s: system not found\n", zsystem);
163	  exit (EXIT_FAILURE);
164	}
165      else if (iret != UUCONF_SUCCESS)
166	ukuuconf_error (puuconf, iret);
167
168      ukshow (&ssys, puuconf);
169      (void) uuconf_system_free (puuconf, &ssys);
170    }
171  else
172    {
173      struct uuconf_config_file_names snames;
174      const char *zstr;
175      int iint;
176      char **pzsystems;
177
178      iret = uuconf_config_files (puuconf, &snames);
179      if (iret != UUCONF_SUCCESS)
180	ukuuconf_error (puuconf, iret);
181      if (snames.uuconf_ztaylor_config != NULL)
182	printf ("config file: %s\n", snames.uuconf_ztaylor_config);
183      ukshow_names("sys file", snames.uuconf_pztaylor_sys);
184      ukshow_names("port file", snames.uuconf_pztaylor_port);
185      ukshow_names("dial file", snames.uuconf_pztaylor_dial);
186      ukshow_names("dialcode file", snames.uuconf_pzdialcode);
187      ukshow_names("passwd file", snames.uuconf_pztaylor_pwd);
188      ukshow_names("call file", snames.uuconf_pztaylor_call);
189
190      if (snames.uuconf_zv2_systems != NULL)
191	printf ("V2 L.sys file: %s\n", snames.uuconf_zv2_systems);
192      if (snames.uuconf_zv2_device != NULL)
193	printf ("V2 L-devices file: %s\n", snames.uuconf_zv2_device);
194      if (snames.uuconf_zv2_userfile != NULL)
195	printf ("V2 USERFILE file: %s\n", snames.uuconf_zv2_userfile);
196      if (snames.uuconf_zv2_cmds != NULL)
197	printf ("V2 L.cmds file: %s\n", snames.uuconf_zv2_cmds);
198
199      ukshow_names("HDB Systems file", snames.uuconf_pzhdb_systems);
200      ukshow_names("HDB Devices file", snames.uuconf_pzhdb_devices);
201      ukshow_names("HDB Dialers file", snames.uuconf_pzhdb_dialers);
202      if (snames.uuconf_zhdb_permissions != NULL)
203	printf ("HDB Permissions file: %s\n", snames.uuconf_zhdb_permissions);
204      /* FIXME: This doesn't dump the following HDB file names:
205         Sysfiles, Maxuuxqts, remote.unknown.  */
206
207      iret = uuconf_localname (puuconf, &zstr);
208      if (iret == UUCONF_SUCCESS)
209	printf ("Local node name %s\n", zstr);
210      else if (iret != UUCONF_NOT_FOUND)
211	ukuuconf_error (puuconf, iret);
212
213      iret = uuconf_spooldir (puuconf, &zstr);
214      if (iret != UUCONF_SUCCESS)
215	ukuuconf_error (puuconf, iret);
216      printf ("Spool directory %s\n", zstr);
217
218      iret = uuconf_pubdir (puuconf, &zstr);
219      if (iret != UUCONF_SUCCESS)
220	ukuuconf_error (puuconf, iret);
221      printf ("Public directory %s\n", zstr);
222
223      iret = uuconf_lockdir (puuconf, &zstr);
224      if (iret != UUCONF_SUCCESS)
225	ukuuconf_error (puuconf, iret);
226      printf ("Lock directory %s\n", zstr);
227
228      iret = uuconf_logfile (puuconf, &zstr);
229      if (iret != UUCONF_SUCCESS)
230	ukuuconf_error (puuconf, iret);
231      printf ("Log file %s\n", zstr);
232
233      iret = uuconf_statsfile (puuconf, &zstr);
234      if (iret != UUCONF_SUCCESS)
235	ukuuconf_error (puuconf, iret);
236      printf ("Statistics file %s\n", zstr);
237
238      iret = uuconf_debugfile (puuconf, &zstr);
239      if (iret != UUCONF_SUCCESS)
240	ukuuconf_error (puuconf, iret);
241      printf ("Debug file %s\n", zstr);
242
243      iret = uuconf_debuglevel (puuconf, &zstr);
244      if (iret != UUCONF_SUCCESS)
245	ukuuconf_error (puuconf, iret);
246      if (zstr != NULL)
247	printf ("Global debugging level %s\n", zstr);
248
249      iret = uuconf_strip (puuconf, &iint);
250      if (iret != UUCONF_SUCCESS)
251	ukuuconf_error (puuconf, iret);
252      printf ("uucico -l will %sstrip login names and passwords\n",
253	      (iint & UUCONF_STRIP_LOGIN) != 0 ? "" : "not ");
254      printf ("uucico will %sstrip UUCP protocol commands\n",
255	      (iint & UUCONF_STRIP_PROTO) != 0 ? "" : "not ");
256
257      iret = uuconf_maxuuxqts (puuconf, &iint);
258      if (iret != UUCONF_SUCCESS)
259	ukuuconf_error (puuconf, iret);
260      if (iint != 0)
261	printf ("Maximum number of uuxqt processes permitted %d\n", iint);
262
263      iret = uuconf_runuuxqt (puuconf, &iint);
264      if (iret != UUCONF_SUCCESS)
265	ukuuconf_error (puuconf, iret);
266      if (iint > 0)
267	printf ("Start uuxqt every %d jobs\n", iint);
268      else
269	{
270	  switch (iint)
271	    {
272	    case UUCONF_RUNUUXQT_NEVER:
273	      printf ("Never start uuxqt\n");
274	      break;
275	    case UUCONF_RUNUUXQT_ONCE:
276	      printf ("Start uuxqt once per uucico invocation\n");
277	      break;
278	    case UUCONF_RUNUUXQT_PERCALL:
279	      printf ("Start uuxqt once per call\n");
280	      break;
281	    default:
282	      fprintf (stderr, "Illegal value from uuconf_runuuxqt\n");
283	      exit (EXIT_FAILURE);
284	      break;
285	    }
286	}
287
288      iret = uuconf_system_names (puuconf, &pzsystems, FALSE);
289      if (iret != UUCONF_SUCCESS)
290	ukuuconf_error (puuconf, iret);
291
292      if (*pzsystems == NULL)
293	{
294	  fprintf (stderr, "%s: no systems found\n", zKprogram);
295	  exit (EXIT_FAILURE);
296	}
297
298      while (*pzsystems != NULL)
299	{
300	  struct uuconf_system ssys;
301
302	  printf ("\n");
303	  iret = uuconf_system_info (puuconf, *pzsystems, &ssys);
304	  if (iret != UUCONF_SUCCESS)
305	    ukuuconf_error (puuconf, iret);
306	  else
307	    ukshow (&ssys, puuconf);
308	  (void) uuconf_system_free (puuconf, &ssys);
309	  ++pzsystems;
310	}
311    }
312
313  exit (EXIT_SUCCESS);
314
315  /* Avoid errors about not returning a value.  */
316  return 0;
317}
318
319/* Print a usage message and die.  */
320
321static void ukusage ()
322{
323  fprintf (stderr, "Usage: %s [-s system] [-I file]\n", zKprogram);
324  fprintf (stderr, "Use %s --help for help\n", zKprogram);
325  exit (EXIT_FAILURE);
326}
327
328/* Print a help message.  */
329
330static void
331ukhelp ()
332{
333  printf ("Taylor UUCP %s, copyright (C) 1991, 92, 93, 94, 1995, 2002 Ian Lance Taylor\n",
334	  VERSION);
335  printf ("Usage: %s [-s system] [-I file] [-v]\n", zKprogram);
336  printf (" -s,--system system: Only print configuration for named system\n");
337  printf (" -I,--config file: Set configuration file to use\n");
338  printf (" -v,--version: Print version and exit\n");
339  printf (" --help: Print help and exit\n");
340  printf ("Report bugs to taylor-uucp@gnu.org\n");
341}
342
343/* Print a list of configuration file names.  */
344static void
345ukshow_names (zheader, pznames)
346     const char *zheader;
347     const char * const *pznames;
348{
349  if (pznames == NULL)
350    return;
351  if (pznames[1] == NULL)
352    printf ("%s: %s\n", zheader, pznames[0]);
353  else
354    {
355      const char * const *pz;
356
357      printf ("%s:\n", zheader);
358      for (pz = pznames; *pz != NULL; ++pz)
359	printf ("  %s\n", *pz);
360    }
361}
362
363/* Dump out the information for a system.  */
364
365static void
366ukshow (qsys, puuconf)
367     const struct uuconf_system *qsys;
368     pointer puuconf;
369{
370  char **pz;
371  int i;
372  int iret;
373  boolean fanycall;
374
375  printf ("System: %s", qsys->uuconf_zname);
376  if (qsys->uuconf_pzalias != NULL)
377    {
378      printf (" (");
379      for (pz = qsys->uuconf_pzalias; *pz != NULL; pz++)
380	{
381	  printf ("%s", *pz);
382	  if (pz[1] != NULL)
383	    printf (" ");
384	}
385      printf (")");
386    }
387  printf ("\n");
388
389  fanycall = FALSE;
390  for (i = 0; qsys != NULL; qsys = qsys->uuconf_qalternate, i++)
391    {
392      boolean fcall, fcalled;
393      struct uuconf_timespan *qtime, *qspan;
394
395      if (i != 0 || qsys->uuconf_qalternate != NULL)
396	{
397	  printf ("Alternate %d", i);
398	  if (qsys->uuconf_zalternate != NULL)
399	    printf (" (%s)", qsys->uuconf_zalternate);
400	  printf ("\n");
401	}
402
403      /* See if this alternate could be used when calling out.  */
404      fcall = qsys->uuconf_fcall;
405      if (qsys->uuconf_qtimegrade == NULL)
406	fcall = FALSE;
407
408      /* See if this alternate could be used when calling in.  */
409      fcalled = qsys->uuconf_fcalled;
410
411      if (! fcall && ! fcalled)
412	{
413	  printf (" This alternate is never used\n");
414	  continue;
415	}
416
417      if (fcall)
418	fanycall = TRUE;
419
420      if (fcalled)
421	{
422	  if (qsys->uuconf_zcalled_login != NULL
423	      && strcmp (qsys->uuconf_zcalled_login, "ANY") != 0)
424	    {
425	      if (i == 0 && qsys->uuconf_qalternate == NULL)
426		printf (" Caller must log in as %s\n",
427			qsys->uuconf_zcalled_login);
428	      else
429		printf (" When called using login name %s\n",
430			qsys->uuconf_zcalled_login);
431	    }
432	  else
433	    printf (" When called using any login name\n");
434
435	  if (qsys->uuconf_zlocalname != NULL)
436	    printf (" Will use %s as name of local system\n",
437		    qsys->uuconf_zlocalname);
438	}
439
440      if (fcalled && qsys->uuconf_fcallback)
441	{
442	  printf (" If called, will call back\n");
443	  fcalled = FALSE;
444	}
445
446      if (fcall)
447	{
448	  struct sinfo si;
449
450	  if (i == 0 && qsys->uuconf_qalternate == NULL)
451	    printf (" Call out");
452	  else
453	    printf (" This alternate applies when calling");
454
455	  if (qsys->uuconf_zport != NULL || qsys->uuconf_qport != NULL)
456	    {
457	      printf (" using ");
458	      if (qsys->uuconf_zport != NULL)
459		printf ("port %s", qsys->uuconf_zport);
460	      else
461		printf ("a specially defined port");
462	      if (qsys->uuconf_ibaud != 0)
463		{
464		  printf (" at speed %ld", qsys->uuconf_ibaud);
465		  if (qsys->uuconf_ihighbaud != 0)
466		    printf (" to %ld", qsys->uuconf_ihighbaud);
467		}
468	      printf ("\n");
469	    }
470	  else if (qsys->uuconf_ibaud != 0)
471	    {
472	      printf (" at speed %ld", qsys->uuconf_ibaud);
473	      if (qsys->uuconf_ihighbaud != 0)
474		printf (" to %ld", qsys->uuconf_ihighbaud);
475	      printf ("\n");
476	    }
477	  else
478	    printf (" using any port\n");
479
480	  si.puuconf = puuconf;
481	  si.qsys = qsys;
482	  si.fgot = FALSE;
483
484	  if (qsys->uuconf_qport != NULL)
485	    {
486	      printf (" The port is defined as:\n");
487	      (void) ikshow_port (qsys->uuconf_qport, (pointer) &si);
488	    }
489	  else
490	    {
491	      struct uuconf_port sdummy;
492
493	      printf (" The possible ports are:\n");
494	      iret = uuconf_find_port (puuconf, qsys->uuconf_zport,
495				       qsys->uuconf_ibaud,
496				       qsys->uuconf_ihighbaud,
497				       ikshow_port, (pointer) &si,
498				       &sdummy);
499	      if (iret != UUCONF_NOT_FOUND)
500		ukuuconf_error (puuconf, iret);
501	      if (! si.fgot)
502		printf (" *** There are no matching ports\n");
503	    }
504
505	  if (qsys->uuconf_zphone != NULL)
506	    {
507	      if ((qsys->uuconf_zport != NULL
508		   && strcmp (qsys->uuconf_zport, "TCP") == 0)
509		  || (qsys->uuconf_qport != NULL
510		      && (qsys->uuconf_qport->uuconf_ttype
511			  == UUCONF_PORTTYPE_TCP
512			  || qsys->uuconf_qport->uuconf_ttype
513			  == UUCONF_PORTTYPE_TLI)))
514		printf (" Remote address %s\n", qsys->uuconf_zphone);
515	      else
516		printf (" Phone number %s\n", qsys->uuconf_zphone);
517	    }
518
519	  ukshow_chat (&qsys->uuconf_schat, " Chat");
520
521	  if (qsys->uuconf_zcall_login != NULL
522	      || qsys->uuconf_zcall_password != NULL)
523	    {
524	      char *zlogin, *zpass;
525
526	      iret = uuconf_callout (puuconf, qsys, &zlogin, &zpass);
527	      if (iret == UUCONF_NOT_FOUND)
528		printf (" Can not determine login name or password\n");
529	      else if (UUCONF_ERROR_VALUE (iret) == UUCONF_FOPEN_FAILED)
530		printf (" Can not read call out file\n");
531	      else if (iret != UUCONF_SUCCESS)
532		ukuuconf_error (puuconf, iret);
533	      else
534		{
535		  if (zlogin != NULL)
536		    {
537		      printf (" Login name %s\n", zlogin);
538		      free ((pointer) zlogin);
539		    }
540		  if (zpass != NULL)
541		    {
542		      printf (" Password %s\n", zpass);
543		      free ((pointer) zpass);
544		    }
545		}
546	    }
547
548	  qtime = qcompress_span (qsys->uuconf_qtimegrade);
549
550	  for (qspan = qtime; qspan != NULL; qspan = qspan->uuconf_qnext)
551	    {
552	      printf (" ");
553	      ukshow_time (qspan);
554	      printf (" may call if ");
555	      if ((char) qspan->uuconf_ival == UUCONF_GRADE_LOW)
556		printf ("any work");
557	      else
558		printf ("work grade %c or higher", (char) qspan->uuconf_ival);
559	      if (qspan->uuconf_cretry != 0)
560		printf (" (retry %d)", qspan->uuconf_cretry);
561	      printf ("\n");
562	    }
563
564	  if (qsys->uuconf_cmax_retries > 0)
565	    printf (" May retry the call up to %d times\n",
566		    qsys->uuconf_cmax_retries);
567
568	  if (qsys->uuconf_qcalltimegrade != NULL)
569	    {
570	      boolean fprint, fother;
571
572	      qtime = qcompress_span (qsys->uuconf_qcalltimegrade);
573	      fprint = FALSE;
574	      fother = FALSE;
575	      if (qtime->uuconf_istart != 0)
576		fother = TRUE;
577	      for (qspan = qtime; qspan != NULL; qspan = qspan->uuconf_qnext)
578		{
579		  if ((char) qspan->uuconf_ival == UUCONF_GRADE_LOW)
580		    {
581		      fother = TRUE;
582		      continue;
583		    }
584		  fprint = TRUE;
585		  printf (" ");
586		  ukshow_time (qspan);
587		  printf (" may accept work grade %c or higher\n",
588			  (char) qspan->uuconf_ival);
589		  if (qspan->uuconf_qnext == NULL)
590		    {
591		      if (qspan->uuconf_iend != 7 * 24 * 60)
592			fother = TRUE;
593		    }
594		  else
595		    {
596		      if (qspan->uuconf_iend
597			  != qspan->uuconf_qnext->uuconf_istart)
598			fother = TRUE;
599		    }
600		}
601	      if (fprint && fother)
602		printf (" (At other times may accept any work)\n");
603	    }
604	}
605
606      if (fcalled)
607	{
608	  if (qsys->uuconf_qcalledtimegrade != NULL)
609	    {
610	      boolean fprint, fother;
611
612	      qtime = qcompress_span (qsys->uuconf_qcalledtimegrade);
613	      fprint = FALSE;
614	      fother = FALSE;
615	      if (qtime->uuconf_istart != 0)
616		fother = TRUE;
617	      for (qspan = qtime; qspan != NULL; qspan = qspan->uuconf_qnext)
618		{
619		  if ((char) qspan->uuconf_ival == UUCONF_GRADE_LOW)
620		    {
621		      fother = TRUE;
622		      continue;
623		    }
624		  fprint = TRUE;
625		  printf (" ");
626		  ukshow_time (qspan);
627		  printf (" will send work grade %c or higher\n",
628			  (char) qspan->uuconf_ival);
629		  if (qspan->uuconf_qnext == NULL)
630		    {
631		      if (qspan->uuconf_iend != 7 * 24 * 60)
632			fother = TRUE;
633		    }
634		  else
635		    {
636		      if (qspan->uuconf_iend
637			  != qspan->uuconf_qnext->uuconf_istart)
638			fother = TRUE;
639		    }
640		}
641	      if (fprint && fother)
642		printf (" (At other times will send any work)\n");
643	    }
644	}
645
646      if (fcall && qsys->uuconf_csuccess_wait != 0)
647	printf (" Will wait %d seconds after a successful call\n",
648		qsys->uuconf_csuccess_wait);
649
650      if (qsys->uuconf_fsequence)
651	printf (" Sequence numbers are used\n");
652
653      if (fcalled)
654	ukshow_chat (&qsys->uuconf_scalled_chat, " When called, chat");
655
656      if (qsys->uuconf_zdebug != NULL)
657	printf (" Debugging level %s\n", qsys->uuconf_zdebug);
658      if (qsys->uuconf_zmax_remote_debug != NULL)
659	printf (" Max remote debugging level %s\n",
660		qsys->uuconf_zmax_remote_debug);
661
662      if (fcall)
663	{
664	  ukshow_size (qsys->uuconf_qcall_local_size, TRUE, TRUE);
665	  ukshow_size (qsys->uuconf_qcall_remote_size, TRUE, FALSE);
666	}
667      if (fcalled)
668	{
669	  ukshow_size (qsys->uuconf_qcalled_local_size, FALSE, TRUE);
670	  ukshow_size (qsys->uuconf_qcalled_remote_size, FALSE, FALSE);
671	}
672
673      if (fcall)
674	printf (" May %smake local requests when calling\n",
675		qsys->uuconf_fcall_transfer ? "" : "not ");
676
677      if (fcalled)
678	printf (" May %smake local requests when called\n",
679		qsys->uuconf_fcalled_transfer ? "" : "not ");
680
681      if (qsys->uuconf_fcall_transfer || qsys->uuconf_fcalled_transfer)
682	{
683	  printf (" May send by local request:");
684	  for (pz = qsys->uuconf_pzlocal_send; *pz != NULL; pz++)
685	    printf (" %s", *pz);
686	  printf ("\n");
687	}
688      if (! qsys->uuconf_fsend_request)
689	printf (" May not send files by remote request\n");
690      else
691	{
692	  printf (" May send by remote request:");
693	  for (pz = qsys->uuconf_pzremote_send; *pz != NULL; pz++)
694	    printf (" %s", *pz);
695	  printf ("\n");
696	}
697      if (qsys->uuconf_fcall_transfer || qsys->uuconf_fcalled_transfer)
698	{
699	  printf (" May accept by local request:");
700	  for (pz = qsys->uuconf_pzlocal_receive; *pz != NULL; pz++)
701	    printf (" %s", *pz);
702	  printf ("\n");
703	}
704      if (! qsys->uuconf_frec_request)
705	printf (" May not receive files by remote request\n");
706      else
707	{
708	  printf (" May receive by remote request:");
709	  for (pz = qsys->uuconf_pzremote_receive; *pz != NULL; pz++)
710	    printf (" %s", *pz);
711	  printf ("\n");
712	}
713
714      printf (" May execute");
715      for (pz = qsys->uuconf_pzcmds; *pz != NULL; pz++)
716	printf (" %s", *pz);
717      printf ("\n");
718
719      printf (" Execution path");
720      for (pz = qsys->uuconf_pzpath; *pz != NULL; pz++)
721	printf (" %s" , *pz);
722      printf ("\n");
723
724      if (qsys->uuconf_cfree_space != 0)
725	printf (" Will leave %ld bytes available\n", qsys->uuconf_cfree_space);
726
727      if (qsys->uuconf_zpubdir != NULL)
728	printf (" Public directory is %s\n", qsys->uuconf_zpubdir);
729
730      if (qsys->uuconf_pzforward_from != NULL)
731	{
732	  printf (" May forward from");
733	  for (pz = qsys->uuconf_pzforward_from; *pz != NULL; pz++)
734	    printf (" %s", *pz);
735	  printf ("\n");
736	}
737
738      if (qsys->uuconf_pzforward_to != NULL)
739	{
740	  printf (" May forward to");
741	  for (pz = qsys->uuconf_pzforward_to; *pz != NULL; pz++)
742	    printf (" %s", *pz);
743	  printf ("\n");
744	}
745
746      if (qsys->uuconf_cmax_file_time > 0)
747	printf (" Maximum file send time: %ld\n", qsys->uuconf_cmax_file_time);
748
749      if (qsys->uuconf_zprotocols != NULL)
750	printf (" Will use protocols %s\n", qsys->uuconf_zprotocols);
751      else
752	printf (" Will use any known protocol\n");
753
754      if (qsys->uuconf_qproto_params != NULL)
755	ukshow_proto_params (qsys->uuconf_qproto_params, 1);
756    }
757
758  if (! fanycall)
759    printf (" Calls will never be placed to this system\n");
760}
761
762/* Show information about a port.  */
763
764/*ARGSUSED*/
765static int
766ikshow_port (qport, pinfo)
767     struct uuconf_port *qport;
768     pointer pinfo;
769{
770  struct sinfo *qi = (struct sinfo *) pinfo;
771  char **pz;
772  struct uuconf_modem_port *qmodem;
773  struct uuconf_tcp_port *qtcp;
774  struct uuconf_tli_port *qtli;
775  struct uuconf_pipe_port *qpipe;
776
777  qi->fgot = TRUE;
778
779  printf ("  Port name %s\n", qport->uuconf_zname);
780  switch (qport->uuconf_ttype)
781    {
782    case UUCONF_PORTTYPE_STDIN:
783      printf ("   Port type stdin\n");
784      break;
785    case UUCONF_PORTTYPE_DIRECT:
786      printf ("   Port type direct\n");
787      if (qport->uuconf_u.uuconf_sdirect.uuconf_zdevice != NULL)
788	printf ("   Device %s\n",
789		qport->uuconf_u.uuconf_sdirect.uuconf_zdevice);
790      else
791	printf ("   Using port name as device name\n");
792      printf ("   Speed %ld\n", qport->uuconf_u.uuconf_sdirect.uuconf_ibaud);
793      printf ("   Carrier %savailable\n",
794	      qport->uuconf_u.uuconf_sdirect.uuconf_fcarrier ? "" : "not ");
795      printf ("   Hardware flow control %savailable\n",
796	      qport->uuconf_u.uuconf_sdirect.uuconf_fhardflow ? "" : "not ");
797      break;
798    case UUCONF_PORTTYPE_MODEM:
799      qmodem = &qport->uuconf_u.uuconf_smodem;
800      printf ("   Port type modem\n");
801      if (qmodem->uuconf_zdevice != NULL)
802	printf ("   Device %s\n", qmodem->uuconf_zdevice);
803      else
804	printf ("   Using port name as device name\n");
805      if (qmodem->uuconf_zdial_device != NULL)
806	printf ("   Dial device %s\n", qmodem->uuconf_zdial_device);
807      printf ("   Speed %ld\n", qmodem->uuconf_ibaud);
808      if (qmodem->uuconf_ilowbaud != qmodem->uuconf_ihighbaud)
809	printf ("   Speed range %ld to %ld\n", qmodem->uuconf_ilowbaud,
810		qmodem->uuconf_ihighbaud);
811      printf ("   Carrier %savailable\n",
812	      qmodem->uuconf_fcarrier ? "" : "not ");
813      printf ("   Hardware flow control %savailable\n",
814	      qmodem->uuconf_fhardflow ? "" : "not ");
815      if (qmodem->uuconf_qdialer != NULL)
816	{
817	  printf ("   Specially defined dialer\n");
818	  ukshow_dialer (qmodem->uuconf_qdialer);
819	}
820      else if (qmodem->uuconf_pzdialer != NULL
821	       && qmodem->uuconf_pzdialer[0] != NULL)
822	{
823	  struct uuconf_dialer sdial;
824	  int iret;
825
826	  /* This might be a single dialer name, or it might be a
827	     sequence of dialer/token pairs.  */
828
829	  if (qmodem->uuconf_pzdialer[1] == NULL
830	      || qmodem->uuconf_pzdialer[2] == NULL)
831	    {
832	      iret = uuconf_dialer_info (qi->puuconf,
833					 qmodem->uuconf_pzdialer[0],
834					 &sdial);
835	      if (iret == UUCONF_NOT_FOUND)
836		printf ("   *** No dialer %s\n", qmodem->uuconf_pzdialer[0]);
837	      else if (iret != UUCONF_SUCCESS)
838		ukuuconf_error (qi->puuconf, iret);
839	      else
840		{
841		  printf ("   Dialer %s\n", qmodem->uuconf_pzdialer[0]);
842		  ukshow_dialer (&sdial);
843		  if (qmodem->uuconf_pzdialer[1] != NULL)
844		    printf ("   Token %s\n", qmodem->uuconf_pzdialer[1]);
845		}
846	    }
847	  else
848	    {
849	      pz = qmodem->uuconf_pzdialer;
850	      while (*pz != NULL)
851		{
852		  iret = uuconf_dialer_info (qi->puuconf, *pz, &sdial);
853		  if (iret == UUCONF_NOT_FOUND)
854		    printf ("   *** No dialer %s\n", *pz);
855		  else if (iret != UUCONF_SUCCESS)
856		    ukuuconf_error (qi->puuconf, iret);
857		  else
858		    {
859		      printf ("   Dialer %s\n", *pz);
860		      ukshow_dialer (&sdial);
861		    }
862
863		  ++pz;
864		  if (*pz != NULL)
865		    {
866		      printf ("   Token %s\n", *pz);
867		      ++pz;
868		    }
869		}
870	    }
871	}
872      else
873	printf ("   *** No dialer information\n");
874      break;
875    case UUCONF_PORTTYPE_TCP:
876      qtcp = &qport->uuconf_u.uuconf_stcp;
877      printf ("   Port type tcp\n");
878      printf ("   TCP service %s\n", qtcp->uuconf_zport);
879      if (qtcp->uuconf_iversion != 0)
880	printf ("   IP version %d\n", qtcp->uuconf_iversion);
881      if (qtcp->uuconf_pzdialer != NULL
882	  && qtcp->uuconf_pzdialer[0] != NULL)
883	{
884	  printf ("   Dialer sequence");
885	  for (pz = qtcp->uuconf_pzdialer; *pz != NULL; pz++)
886	    printf (" %s", *pz);
887	  printf ("\n");
888	}
889      break;
890    case UUCONF_PORTTYPE_TLI:
891      qtli = &qport->uuconf_u.uuconf_stli;
892      printf ("   Port type TLI%s\n",
893	      qtli->uuconf_fstream ? "S" : "");
894      if (qtli->uuconf_zdevice != NULL)
895	printf ("   Device %s\n", qtli->uuconf_zdevice);
896      else
897	printf ("   Using port name as device name\n");
898      if (qtli->uuconf_pzpush != NULL)
899	{
900	  printf ("   Push");
901	  for (pz = qtli->uuconf_pzpush; *pz != NULL; pz++)
902	    printf (" %s", *pz);
903	  printf ("\n");
904	}
905      if (qtli->uuconf_pzdialer != NULL
906	  && qtli->uuconf_pzdialer[0] != NULL)
907	{
908	  printf ("   Dialer sequence");
909	  for (pz = qtli->uuconf_pzdialer; *pz != NULL; pz++)
910	    printf (" %s", *pz);
911	  printf ("\n");
912	}
913      if (qtli->uuconf_zservaddr != NULL)
914	printf ("   Server address %s\n", qtli->uuconf_zservaddr);
915      break;
916    case UUCONF_PORTTYPE_PIPE:
917      qpipe = &qport->uuconf_u.uuconf_spipe;
918      printf ("   Port type pipe\n");
919      if (qpipe->uuconf_pzcmd != NULL)
920	{
921	  printf ("   Command");
922	  for (pz = qpipe->uuconf_pzcmd; *pz != NULL; pz++)
923	    printf (" %s", *pz);
924	  printf ("\n");
925	}
926      break;
927    default:
928      fprintf (stderr, "   CAN'T HAPPEN\n");
929      break;
930    }
931
932  if (qport->uuconf_zprotocols != NULL)
933    printf ("   Will use protocols %s\n", qport->uuconf_zprotocols);
934
935  if (qport->uuconf_zlockname != NULL)
936    printf ("   Will use lockname %s\n", qport->uuconf_zlockname);
937
938  if ((qport->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
939    ukshow_reliable (qport->uuconf_ireliable, "   ");
940
941  if (qport->uuconf_qproto_params != NULL)
942    ukshow_proto_params (qport->uuconf_qproto_params, 3);
943
944  /* Return NOT_FOUND to force find_port to continue searching.  */
945  return UUCONF_NOT_FOUND;
946}
947
948/* Show information about a dialer.  */
949
950static void
951ukshow_dialer (q)
952     struct uuconf_dialer *q;
953{
954  ukshow_chat (&q->uuconf_schat, "    Chat");
955  printf ("    Wait for dialtone %s\n", q->uuconf_zdialtone);
956  printf ("    Pause while dialing %s\n", q->uuconf_zpause);
957  printf ("    Carrier %savailable\n", q->uuconf_fcarrier ? "" : "not ");
958  if (q->uuconf_fcarrier)
959    printf ("    Wait %d seconds for carrier\n", q->uuconf_ccarrier_wait);
960  if (q->uuconf_fdtr_toggle)
961    {
962      printf ("    Toggle DTR");
963      if (q->uuconf_fdtr_toggle_wait)
964	printf (" and wait");
965      printf ("\n");
966    }
967  ukshow_chat (&q->uuconf_scomplete, "    When complete chat");
968  ukshow_chat (&q->uuconf_sabort, "    When aborting chat");
969  if ((q->uuconf_ireliable & UUCONF_RELIABLE_SPECIFIED) != 0)
970    ukshow_reliable (q->uuconf_ireliable, "   ");
971  if (q->uuconf_qproto_params != NULL)
972    ukshow_proto_params (q->uuconf_qproto_params, 4);
973}
974
975/* Show a chat script.  */
976
977static void
978ukshow_chat (qchat, zhdr)
979     const struct uuconf_chat *qchat;
980     const char *zhdr;
981{
982  char **pz;
983
984  if (qchat->uuconf_pzprogram != NULL)
985    {
986      printf ("%s program", zhdr);
987      for (pz = qchat->uuconf_pzprogram; *pz != NULL; pz++)
988	printf (" %s", *pz);
989      printf ("\n");
990    }
991
992  if (qchat->uuconf_pzchat != NULL)
993    {
994
995      printf ("%s script", zhdr);
996      for (pz = qchat->uuconf_pzchat; *pz != NULL; pz++)
997	{
998	  if ((*pz)[0] != '-' || pz == qchat->uuconf_pzchat)
999	    printf (" ");
1000	  printf ("%s", *pz);
1001	}
1002      printf ("\n");
1003      printf ("%s script timeout %d\n", zhdr, qchat->uuconf_ctimeout);
1004      if (qchat->uuconf_pzfail != NULL)
1005	{
1006	  printf ("%s failure strings", zhdr);
1007	  for (pz = qchat->uuconf_pzfail; *pz != NULL; pz++)
1008	    printf (" %s", *pz);
1009	  printf ("\n");
1010	}
1011      if (qchat->uuconf_fstrip)
1012	printf ("%s script incoming bytes stripped to seven bits\n", zhdr);
1013    }
1014}
1015
1016/* Show a size/time restriction.  */
1017
1018static void
1019ukshow_size (qspan, fcall, flocal)
1020     struct uuconf_timespan *qspan;
1021     boolean fcall;
1022     boolean flocal;
1023{
1024  struct uuconf_timespan *q;
1025  boolean fother;
1026
1027  qspan = qcompress_span (qspan);
1028  if (qspan == NULL)
1029    return;
1030
1031  printf (" If call%s the following applies to a %s request:\n",
1032	  fcall ? "ing" : "ed", flocal ? "local" : "remote");
1033
1034  fother = FALSE;
1035  if (qspan->uuconf_istart >= 60)
1036    fother = TRUE;
1037
1038  for (q = qspan; q != NULL; q = q->uuconf_qnext)
1039    {
1040      printf ("  ");
1041      ukshow_time (q);
1042      printf (" may transfer files %ld bytes or smaller\n", q->uuconf_ival);
1043      if (q->uuconf_qnext == NULL)
1044	{
1045	  if (q->uuconf_iend <= 6 * 24 * 60 + 23 * 60)
1046	    fother = TRUE;
1047	}
1048      else
1049	{
1050	  if (q->uuconf_iend + 60 <= q->uuconf_qnext->uuconf_istart)
1051	    fother = TRUE;
1052	}
1053    }
1054
1055  if (fother)
1056    printf ("  (At other times may send files of any size)\n");
1057}
1058
1059/* Show reliability information.  */
1060
1061static void
1062ukshow_reliable (i, zhdr)
1063     int i;
1064     const char *zhdr;
1065{
1066  printf ("%sCharacteristics:", zhdr);
1067  if ((i & UUCONF_RELIABLE_EIGHT) != 0)
1068    printf (" eight-bit-clean");
1069  else
1070    printf (" not-eight-bit-clean");
1071  if ((i & UUCONF_RELIABLE_RELIABLE) != 0)
1072    printf (" reliable");
1073  if ((i & UUCONF_RELIABLE_ENDTOEND) != 0)
1074    printf (" end-to-end");
1075  if ((i & UUCONF_RELIABLE_FULLDUPLEX) != 0)
1076    printf (" fullduplex");
1077  else
1078    printf (" halfduplex");
1079  printf ("\n");
1080}
1081
1082/* Show protocol parameters.  */
1083
1084static void
1085ukshow_proto_params (pas, cindent)
1086     struct uuconf_proto_param *pas;
1087     int cindent;
1088{
1089  struct uuconf_proto_param *q;
1090
1091  for (q = pas; q->uuconf_bproto != '\0'; q++)
1092    {
1093      int i;
1094      struct uuconf_proto_param_entry *qe;
1095
1096      for (i = 0; i < cindent; i++)
1097	printf (" ");
1098      printf ("For protocol %c will use the following parameters\n",
1099	      q->uuconf_bproto);
1100      for (qe = q->uuconf_qentries; qe->uuconf_cargs > 0; qe++)
1101	{
1102	  int ia;
1103
1104	  for (i = 0; i < cindent; i++)
1105	    printf (" ");
1106	  for (ia = 0; ia < qe->uuconf_cargs; ia++)
1107	    printf (" %s", qe->uuconf_pzargs[ia]);
1108	  printf ("\n");
1109	}
1110    }
1111}
1112
1113/* Display a time span.  */
1114
1115static void
1116ukshow_time (q)
1117     const struct uuconf_timespan *q;
1118{
1119  int idaystart, idayend;
1120  int ihourstart, ihourend;
1121  int iminutestart, iminuteend;
1122  const char * const zdays = "Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat\0Sun";
1123
1124  if (q->uuconf_istart == 0 && q->uuconf_iend == 7 * 24 * 60)
1125    {
1126      printf ("At any time");
1127      return;
1128    }
1129
1130  idaystart = q->uuconf_istart / (24 * 60);
1131  ihourstart = (q->uuconf_istart % (24 * 60)) / 60;
1132  iminutestart = q->uuconf_istart % 60;
1133  idayend = q->uuconf_iend / (24 * 60);
1134  ihourend = (q->uuconf_iend % (24 * 60)) / 60;
1135  iminuteend = q->uuconf_iend % 60;
1136
1137  if (idaystart == idayend)
1138    printf ("%s from %02d:%02d to %02d:%02d", zdays + idaystart * 4,
1139	    ihourstart, iminutestart, ihourend, iminuteend);
1140  else
1141    printf ("From %s %02d:%02d to %s %02d:%02d",
1142	    zdays + idaystart * 4, ihourstart, iminutestart,
1143	    zdays + idayend * 4, ihourend, iminuteend);
1144}
1145
1146/* Compress a time span by merging any two adjacent spans with
1147   identical values.  This isn't necessary for uucico, but it looks
1148   nicer when printed out.  */
1149
1150static struct uuconf_timespan *
1151qcompress_span (qlist)
1152     struct uuconf_timespan *qlist;
1153{
1154  struct uuconf_timespan **pq;
1155
1156  pq = &qlist;
1157  while (*pq != NULL)
1158    {
1159      if ((*pq)->uuconf_qnext != NULL
1160	  && (*pq)->uuconf_iend == (*pq)->uuconf_qnext->uuconf_istart
1161	  && (*pq)->uuconf_ival == (*pq)->uuconf_qnext->uuconf_ival)
1162	{
1163	  struct uuconf_timespan *qnext;
1164
1165	  qnext = (*pq)->uuconf_qnext;
1166	  (*pq)->uuconf_qnext = qnext->uuconf_qnext;
1167	  (*pq)->uuconf_iend = qnext->uuconf_iend;
1168	}
1169      else
1170	pq = &(*pq)->uuconf_qnext;
1171    }
1172
1173  return qlist;
1174}
1175
1176/* Display a uuconf error and exit.  */
1177
1178static void
1179ukuuconf_error (puuconf, iret)
1180     pointer puuconf;
1181     int iret;
1182{
1183  char ab[512];
1184
1185  (void) uuconf_error_string (puuconf, iret, ab, sizeof ab);
1186  if ((iret & UUCONF_ERROR_FILENAME) == 0)
1187    fprintf (stderr, "%s: %s\n", zKprogram, ab);
1188  else
1189    fprintf (stderr, "%s:%s\n", zKprogram, ab);
1190  exit (EXIT_FAILURE);
1191}
1192