]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gnu/libexec/uucp/libuuconf/tsinfo.c
This commit was generated by cvs2svn to compensate for changes in r53654,
[FreeBSD/FreeBSD.git] / gnu / libexec / uucp / libuuconf / tsinfo.c
1 /* tsinfo.c
2    Get information about a system from the Taylor UUCP configuration files.
3
4    Copyright (C) 1992, 1993, 1995 Ian Lance Taylor
5
6    This file is part of the Taylor UUCP uuconf library.
7
8    This library is free software; you can redistribute it and/or
9    modify it under the terms of the GNU Library General Public License
10    as published by the Free Software Foundation; either version 2 of
11    the License, or (at your option) any later version.
12
13    This library 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    Library General Public License for more details.
17
18    You should have received a copy of the GNU Library General Public
19    License along with this library; 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 or
23    c/o Cygnus Support, 48 Grove Street, Somerville, MA 02144.
24    */
25
26 #include "uucnfi.h"
27
28 #if USE_RCS_ID
29 const char _uuconf_tsinfo_rcsid[] = "$FreeBSD$";
30 #endif
31
32 #include <errno.h>
33 #include <ctype.h>
34
35 #ifndef SEEK_SET
36 #define SEEK_SET 0
37 #endif
38 \f
39 static void uiset_call P((struct uuconf_system *qsys));
40 static int iisizecmp P((long i1, long i2));
41
42 /* Local functions needed to parse the system information file.  */
43
44 #define CMDTABFN(z) \
45   static int z P((pointer, int, char **, pointer, pointer))
46
47 CMDTABFN (iisystem);
48 CMDTABFN (iialias);
49 CMDTABFN (iialternate);
50 CMDTABFN (iidefault_alternates);
51 CMDTABFN (iitime);
52 CMDTABFN (iitimegrade);
53 CMDTABFN (iisize);
54 CMDTABFN (iibaud_range);
55 CMDTABFN (iiport);
56 CMDTABFN (iichat);
57 CMDTABFN (iidebug);
58 CMDTABFN (iicalled_login);
59 CMDTABFN (iiproto_param);
60 CMDTABFN (iirequest);
61 CMDTABFN (iitransfer);
62 CMDTABFN (iiforward);
63 CMDTABFN (iiunknown);
64
65 #undef CMDTABFN
66 \f
67 /* We have to pass a fair amount of information in and out of the
68    various system commands.  Using global variables would make the
69    code non-reentrant, so we instead pass a pointer to single
70    structure as the pinfo argument to the system commands.  */
71
72 struct sinfo
73 {
74   /* The system information we're building up.  */
75   struct uuconf_system *qsys;
76   /* Whether any alternates have been used.  */
77   boolean falternates;
78   /* A list of the previous alternates.  */
79   struct uuconf_system salternate;
80   /* Whether to use extra alternates from the file wide defaults.  */
81   int fdefault_alternates;
82 };
83 \f
84 /* The command table for system commands.  */
85 static const struct cmdtab_offset asIcmds[] =
86 {
87   { "system", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, iisystem },
88   { "alias", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, iialias },
89   { "alternate", UUCONF_CMDTABTYPE_FN | 0, (size_t) -1, iialternate },
90   { "default-alternates", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1,
91       iidefault_alternates },
92   { "time", UUCONF_CMDTABTYPE_FN | 0,
93       offsetof (struct uuconf_system, uuconf_qtimegrade), iitime },
94   { "timegrade", UUCONF_CMDTABTYPE_FN | 0,
95       offsetof (struct uuconf_system, uuconf_qtimegrade), iitimegrade },
96   { "max-retries", UUCONF_CMDTABTYPE_INT,
97       offsetof (struct uuconf_system, uuconf_cmax_retries), NULL },
98   { "success-wait", UUCONF_CMDTABTYPE_INT,
99       offsetof (struct uuconf_system, uuconf_csuccess_wait), NULL },
100   { "call-timegrade", UUCONF_CMDTABTYPE_FN | 3,
101       offsetof (struct uuconf_system, uuconf_qcalltimegrade), iitimegrade },
102   { "called-timegrade", UUCONF_CMDTABTYPE_FN | 3,
103       offsetof (struct uuconf_system, uuconf_qcalledtimegrade), iitimegrade },
104   { "call-local-size", UUCONF_CMDTABTYPE_FN | 3,
105       offsetof (struct uuconf_system, uuconf_qcall_local_size), iisize },
106   { "call-remote-size", UUCONF_CMDTABTYPE_FN | 3,
107       offsetof (struct uuconf_system, uuconf_qcall_remote_size), iisize },
108   { "called-local-size", UUCONF_CMDTABTYPE_FN | 3,
109       offsetof (struct uuconf_system, uuconf_qcalled_local_size), iisize },
110   { "called-remote-size", UUCONF_CMDTABTYPE_FN | 3,
111       offsetof (struct uuconf_system, uuconf_qcalled_remote_size), iisize },
112   { "timetable", UUCONF_CMDTABTYPE_FN | 3, (size_t) -1, _uuconf_itimetable },
113   { "baud", UUCONF_CMDTABTYPE_LONG,
114       offsetof (struct uuconf_system, uuconf_ibaud), NULL },
115   { "speed", UUCONF_CMDTABTYPE_LONG,
116       offsetof (struct uuconf_system, uuconf_ibaud), NULL },
117   { "baud-range", UUCONF_CMDTABTYPE_FN | 3, 0, iibaud_range },
118   { "speed-range", UUCONF_CMDTABTYPE_FN | 3, 0, iibaud_range },
119   { "port", UUCONF_CMDTABTYPE_FN | 0, (size_t) -1, iiport },
120   { "phone", UUCONF_CMDTABTYPE_STRING,
121       offsetof (struct uuconf_system, uuconf_zphone), NULL },
122   { "address", UUCONF_CMDTABTYPE_STRING,
123       offsetof (struct uuconf_system, uuconf_zphone), NULL },
124   { "chat", UUCONF_CMDTABTYPE_PREFIX | 0,
125       offsetof (struct uuconf_system, uuconf_schat), iichat },
126   { "call-login", UUCONF_CMDTABTYPE_STRING,
127       offsetof (struct uuconf_system, uuconf_zcall_login), NULL },
128   { "call-password", UUCONF_CMDTABTYPE_STRING,
129       offsetof (struct uuconf_system, uuconf_zcall_password), NULL },
130   { "called-login", UUCONF_CMDTABTYPE_FN | 0,
131       offsetof (struct uuconf_system, uuconf_zcalled_login), iicalled_login },
132   { "callback", UUCONF_CMDTABTYPE_BOOLEAN,
133       offsetof (struct uuconf_system, uuconf_fcallback), NULL },
134   { "sequence", UUCONF_CMDTABTYPE_BOOLEAN,
135       offsetof (struct uuconf_system, uuconf_fsequence), NULL },
136   { "protocol", UUCONF_CMDTABTYPE_STRING,
137       offsetof (struct uuconf_system, uuconf_zprotocols), NULL },
138   { "protocol-parameter", UUCONF_CMDTABTYPE_FN | 0,
139       offsetof (struct uuconf_system, uuconf_qproto_params), iiproto_param },
140   { "called-chat", UUCONF_CMDTABTYPE_PREFIX | 0,
141       offsetof (struct uuconf_system, uuconf_scalled_chat), iichat },
142   { "debug", UUCONF_CMDTABTYPE_FN | 0,
143       offsetof (struct uuconf_system, uuconf_zdebug), iidebug },
144   { "max-remote-debug", UUCONF_CMDTABTYPE_STRING,
145       offsetof (struct uuconf_system, uuconf_zmax_remote_debug), NULL },
146   { "send-request", UUCONF_CMDTABTYPE_BOOLEAN,
147       offsetof (struct uuconf_system, uuconf_fsend_request), NULL },
148   { "receive-request", UUCONF_CMDTABTYPE_BOOLEAN,
149       offsetof (struct uuconf_system, uuconf_frec_request), NULL },
150   { "request", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, iirequest },
151   { "call-transfer", UUCONF_CMDTABTYPE_BOOLEAN,
152       offsetof (struct uuconf_system, uuconf_fcall_transfer), NULL },
153   { "called-transfer", UUCONF_CMDTABTYPE_BOOLEAN,
154       offsetof (struct uuconf_system, uuconf_fcalled_transfer), NULL },
155   { "transfer", UUCONF_CMDTABTYPE_FN | 2, (size_t) -1, iitransfer },
156   { "local-send", UUCONF_CMDTABTYPE_FULLSTRING,
157       offsetof (struct uuconf_system, uuconf_pzlocal_send), NULL },
158   { "remote-send", UUCONF_CMDTABTYPE_FULLSTRING,
159       offsetof (struct uuconf_system, uuconf_pzremote_send), NULL },
160   { "local-receive", UUCONF_CMDTABTYPE_FULLSTRING,
161       offsetof (struct uuconf_system, uuconf_pzlocal_receive), NULL },
162   { "remote-receive", UUCONF_CMDTABTYPE_FULLSTRING,
163       offsetof (struct uuconf_system, uuconf_pzremote_receive), NULL },
164   { "command-path", UUCONF_CMDTABTYPE_FULLSTRING,
165       offsetof (struct uuconf_system, uuconf_pzpath), NULL },
166   { "commands", UUCONF_CMDTABTYPE_FULLSTRING,
167       offsetof (struct uuconf_system, uuconf_pzcmds), NULL },
168   { "free-space", UUCONF_CMDTABTYPE_LONG,
169       offsetof (struct uuconf_system, uuconf_cfree_space), NULL },
170   { "forward-from", UUCONF_CMDTABTYPE_FULLSTRING,
171       offsetof (struct uuconf_system, uuconf_pzforward_from), NULL },
172   { "forward-to", UUCONF_CMDTABTYPE_FULLSTRING,
173       offsetof (struct uuconf_system, uuconf_pzforward_to), NULL },
174   { "forward", UUCONF_CMDTABTYPE_FN | 0, (size_t) -1, iiforward },
175   { "pubdir", UUCONF_CMDTABTYPE_STRING,
176       offsetof (struct uuconf_system, uuconf_zpubdir), NULL },
177   { "myname", UUCONF_CMDTABTYPE_STRING,
178       offsetof (struct uuconf_system, uuconf_zlocalname), NULL },
179   { NULL, 0, 0, NULL }
180 };
181
182 #define CSYSTEM_CMDS (sizeof asIcmds / sizeof asIcmds[0])
183 \f
184 /* Get information about the system zsystem from the Taylor UUCP
185    configuration files.  Sets *qsys.  This does not ensure that all
186    default information is set.  */
187
188 int
189 _uuconf_itaylor_system_internal (qglobal, zsystem, qsys)
190      struct sglobal *qglobal;
191      const char *zsystem;
192      struct uuconf_system *qsys;
193 {
194   int iret;
195   struct stsysloc *qloc;
196   struct uuconf_cmdtab as[CSYSTEM_CMDS];
197   struct sinfo si;
198   struct uuconf_system sdefaults;
199
200   if (! qglobal->qprocess->fread_syslocs)
201     {
202       iret = _uuconf_iread_locations (qglobal);
203       if (iret != UUCONF_SUCCESS)
204         return iret;
205     }
206
207   /* Find the system in the list of locations.  */
208   for (qloc = qglobal->qprocess->qsyslocs; qloc != NULL; qloc = qloc->qnext)
209     if (qloc->zname[0] == zsystem[0]
210         && strcmp (qloc->zname, zsystem) == 0)
211       break;
212   if (qloc == NULL)
213     return UUCONF_NOT_FOUND;
214
215   /* If this is an alias, then the real system is the next non-alias
216      in the list.  */
217   while (qloc->falias)
218     {
219       qloc = qloc->qnext;
220       if (qloc == NULL)
221         return UUCONF_NOT_FOUND;
222     }
223
224   _uuconf_ucmdtab_base (asIcmds, CSYSTEM_CMDS, (char *) qsys, as);
225
226   rewind (qloc->e);
227
228   /* Read the file wide defaults from the start of the file.  */
229   _uuconf_uclear_system (qsys);
230
231   si.qsys = qsys;
232   si.falternates = FALSE;
233   si.fdefault_alternates = TRUE;
234   qsys->uuconf_palloc = uuconf_malloc_block ();
235   if (qsys->uuconf_palloc == NULL)
236     {
237       qglobal->ierrno = errno;
238       return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
239     }
240
241   iret = uuconf_cmd_file ((pointer) qglobal, qloc->e, as, (pointer) &si,
242                           iiunknown, UUCONF_CMDTABFLAG_BACKSLASH,
243                           qsys->uuconf_palloc);
244   if (iret != UUCONF_SUCCESS)
245     {
246       qglobal->zfilename = qloc->zfile;
247       return iret | UUCONF_ERROR_FILENAME;
248     }
249
250   if (! si.falternates)
251     uiset_call (qsys);
252   else
253     {
254       /* Attach the final alternate.  */
255       iret = iialternate ((pointer) qglobal, 0, (char **) NULL,
256                           (pointer) NULL, (pointer) &si);
257       if (iret != UUCONF_SUCCESS)
258         return iret;
259     }
260
261   /* Save off the defaults.  */
262   sdefaults = *qsys;
263
264   /* Advance to the information for the system we want.  */
265   if (fseek (qloc->e, qloc->iloc, SEEK_SET) != 0)
266     {
267       qglobal->ierrno = errno;
268       qglobal->zfilename = qloc->zfile;
269       return (UUCONF_FSEEK_FAILED
270               | UUCONF_ERROR_ERRNO
271               | UUCONF_ERROR_FILENAME);
272     }
273
274   /* Read in the system we want.  */
275   _uuconf_uclear_system (qsys);
276   qsys->uuconf_zname = (char *) qloc->zname;
277   qsys->uuconf_palloc = sdefaults.uuconf_palloc;
278
279   si.falternates = FALSE;
280
281   iret = uuconf_cmd_file (qglobal, qloc->e, as, (pointer) &si, iiunknown,
282                           UUCONF_CMDTABFLAG_BACKSLASH, qsys->uuconf_palloc);
283   qglobal->ilineno += qloc->ilineno;
284
285   if (iret == UUCONF_SUCCESS)
286     {
287       if (! si.falternates)
288         uiset_call (qsys);
289       else
290         iret = iialternate ((pointer) qglobal, 0, (char **) NULL,
291                             (pointer) NULL, (pointer) &si);
292     }
293
294   /* Merge in the defaults.  */
295   if (iret == UUCONF_SUCCESS)
296     iret = _uuconf_isystem_default (qglobal, qsys, &sdefaults,
297                                     si.fdefault_alternates);
298
299   /* The first alternate is always available for calling in.  It is
300      always available for calling out if it has some way to choose a
301      port (this would normally be set by uiset_call anyhow, but it
302      won't be if all the port information comes from the defaults).  */
303   if (iret == UUCONF_SUCCESS)
304     {
305       qsys->uuconf_fcalled = TRUE;
306       if (qsys->uuconf_zport != (char *) &_uuconf_unset
307           || qsys->uuconf_qport != (struct uuconf_port *) &_uuconf_unset
308           || qsys->uuconf_ibaud >= 0
309           || qsys->uuconf_zphone != (char *) &_uuconf_unset)
310         qsys->uuconf_fcall = TRUE;
311     }
312
313   if (iret != UUCONF_SUCCESS)
314     {
315       qglobal->zfilename = qloc->zfile;
316       iret |= UUCONF_ERROR_FILENAME;
317     }
318
319   return iret;
320 }
321 \f
322 /* Set the fcall and fcalled field for the system.  This marks a
323    particular alternate for use when calling out or calling in.  This
324    is where we implement the semantics described in the documentation:
325    a change to a relevant field implies that the alternate is used.
326    If all the relevant fields are unchanged, the alternate is not
327    used.  */
328
329 static void
330 uiset_call (qsys)
331      struct uuconf_system *qsys;
332 {
333   qsys->uuconf_fcall =
334     (qsys->uuconf_qtimegrade != (struct uuconf_timespan *) &_uuconf_unset
335      || qsys->uuconf_zport != (char *) &_uuconf_unset
336      || qsys->uuconf_qport != (struct uuconf_port *) &_uuconf_unset
337      || qsys->uuconf_ibaud >= 0
338      || qsys->uuconf_zphone != (char *) &_uuconf_unset
339      || qsys->uuconf_schat.uuconf_pzchat != (char **) &_uuconf_unset
340      || qsys->uuconf_schat.uuconf_pzprogram != (char **) &_uuconf_unset);
341
342   qsys->uuconf_fcalled =
343     qsys->uuconf_zcalled_login != (char *) &_uuconf_unset;
344 }
345 \f
346 /* Handle the "system" command.  Because we skip directly to the
347    system we want to read, a "system" command means we've reached the
348    end of it.  */
349
350 static int
351 iisystem (pglobal, argc, argv, pvar, pinfo)
352      pointer pglobal;
353      int argc;
354      char **argv;
355      pointer pvar;
356      pointer pinfo;
357 {
358   return UUCONF_CMDTABRET_EXIT;
359 }
360
361 /* Handle the "alias" command.  */
362
363 /*ARGSUSED*/
364 static int
365 iialias (pglobal, argc, argv, pvar, pinfo)
366      pointer pglobal;
367      int argc;
368      char **argv;
369      pointer pvar;
370      pointer pinfo;
371 {
372   struct sglobal *qglobal = (struct sglobal *) pglobal;
373   struct sinfo *qinfo = (struct sinfo *) pinfo;
374   int iret;
375
376   iret = _uuconf_iadd_string (qglobal, argv[1], TRUE, FALSE,
377                               &qinfo->qsys->uuconf_pzalias,
378                               qinfo->qsys->uuconf_palloc);
379   if (iret != UUCONF_SUCCESS)
380     iret |= UUCONF_CMDTABRET_EXIT;
381   return iret;
382 }
383 \f
384 /* Handle the "alternate" command.  The information just read is in
385    sIhold.  If this is the first "alternate" command for this system,
386    we save off the current information in sIalternate.  Otherwise we
387    default this information to sIalternate, and then add it to the end
388    of the list of alternates in sIalternate.  */
389
390 static int
391 iialternate (pglobal, argc, argv, pvar, pinfo)
392      pointer pglobal;
393      int argc;
394      char **argv;
395      pointer pvar;
396      pointer pinfo;
397 {
398   struct sglobal *qglobal = (struct sglobal *) pglobal;
399   struct sinfo *qinfo = (struct sinfo *) pinfo;
400
401   uiset_call (qinfo->qsys);
402
403   if (! qinfo->falternates)
404     {
405       qinfo->salternate = *qinfo->qsys;
406       qinfo->falternates = TRUE;
407     }
408   else
409     {
410       int iret;
411       struct uuconf_system *qnew, **pq;
412
413       iret = _uuconf_isystem_default (qglobal, qinfo->qsys,
414                                       &qinfo->salternate, FALSE);
415       if (iret != UUCONF_SUCCESS)
416         return iret | UUCONF_CMDTABRET_EXIT;
417       qnew = ((struct uuconf_system *)
418               uuconf_malloc (qinfo->qsys->uuconf_palloc,
419                               sizeof (struct uuconf_system)));
420       if (qnew == NULL)
421         {
422           qglobal->ierrno = errno;;
423           return (UUCONF_MALLOC_FAILED
424                   | UUCONF_ERROR_ERRNO
425                   | UUCONF_CMDTABRET_EXIT);
426         }
427       *qnew = *qinfo->qsys;
428       for (pq = &qinfo->salternate.uuconf_qalternate;
429            *pq != NULL;
430            pq = &(*pq)->uuconf_qalternate)
431         ;
432       *pq = qnew;
433     }
434
435   /* If this is the last alternate command, move the information back
436      to qinfo->qsys.  */
437   if (argc == 0)
438     *qinfo->qsys = qinfo->salternate;
439   else
440     {
441       _uuconf_uclear_system (qinfo->qsys);
442       qinfo->qsys->uuconf_zname = qinfo->salternate.uuconf_zname;
443       qinfo->qsys->uuconf_palloc = qinfo->salternate.uuconf_palloc;
444       if (argc > 1)
445         {
446           qinfo->qsys->uuconf_zalternate = argv[1];
447           return UUCONF_CMDTABRET_KEEP;
448         }
449     }
450
451   return UUCONF_CMDTABRET_CONTINUE;
452 }
453
454 /* Handle the "default-alternates" command.  This just takes a boolean
455    argument which is used to set the fdefault_alternates field of the
456    sinfo structure.  */
457
458 /*ARGSUSED*/
459 static int
460 iidefault_alternates (pglobal, argc, argv, pvar, pinfo)
461      pointer pglobal;
462      int argc;
463      char **argv;
464      pointer pvar;
465      pointer pinfo;
466 {
467   struct sglobal *qglobal = (struct sglobal *) pglobal;
468   struct sinfo *qinfo = (struct sinfo *) pinfo;
469
470   return _uuconf_iboolean (qglobal, argv[1], &qinfo->fdefault_alternates);
471 }
472 \f
473 /* Handle the "time" command.  We do this by turning it into a
474    "timegrade" command with a grade of BGRADE_LOW.  The first argument
475    is a time string, and the optional second argument is the retry
476    time.  */
477
478 /*ARGSUSED*/
479 static int
480 iitime (pglobal, argc, argv, pvar, pinfo)
481      pointer pglobal;
482      int argc;
483      char **argv;
484      pointer pvar;
485      pointer pinfo;
486 {
487   char *aznew[4];
488   char ab[2];
489
490   if (argc != 2 && argc != 3)
491     return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
492
493   aznew[0] = argv[0];
494   ab[0] = UUCONF_GRADE_LOW;
495   ab[1] = '\0';
496   aznew[1] = ab;
497   aznew[2] = argv[1];
498   if (argc > 2)
499     aznew[3] = argv[2];
500
501   return iitimegrade (pglobal, argc + 1, aznew, pvar, pinfo);
502 }
503
504 /* Handle the "timegrade" command by calling _uuconf_itime_parse with
505    appropriate ival (the work grade) and cretry (the retry time)
506    arguments.  */
507
508 static int
509 iitimegrade (pglobal, argc, argv, pvar, pinfo)
510      pointer pglobal;
511      int argc;
512      char **argv;
513      pointer pvar;
514      pointer pinfo;
515 {
516   struct sglobal *qglobal = (struct sglobal *) pglobal;
517   struct uuconf_timespan **pqspan = (struct uuconf_timespan **) pvar;
518   struct sinfo *qinfo = (struct sinfo *) pinfo;
519   int cretry;
520   int iret;
521
522   if (argc < 3 || argc > 4)
523     return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
524
525   if (argv[1][1] != '\0' || ! UUCONF_GRADE_LEGAL (argv[1][0]))
526     return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
527
528   if (argc == 3)
529     cretry = 0;
530   else
531     {
532       iret = _uuconf_iint (qglobal, argv[3], (pointer) &cretry, TRUE);
533       if (iret != UUCONF_SUCCESS)
534         return iret;
535     }
536
537   iret = _uuconf_itime_parse (qglobal, argv[2], (long) argv[1][0],
538                               cretry, _uuconf_itime_grade_cmp, pqspan,
539                               qinfo->qsys->uuconf_palloc);
540   if (iret != UUCONF_SUCCESS)
541     iret |= UUCONF_CMDTABRET_EXIT;
542   return iret;
543 }
544 \f
545 /* Handle the "baud-range" command, also known as "speed-range".  */
546
547 static int
548 iibaud_range (pglobal, argc, argv, pvar, pinfo)
549      pointer pglobal;
550      int argc;
551      char **argv;
552      pointer pvar;
553      pointer pinfo;
554 {
555   struct sglobal *qglobal = (struct sglobal *) pglobal;
556   struct uuconf_system *qsys = (struct uuconf_system *) pvar;
557   int iret;
558
559   iret = _uuconf_iint (qglobal, argv[1], (pointer) &qsys->uuconf_ibaud,
560                        FALSE);
561   if (iret != UUCONF_SUCCESS)
562     return iret;
563   return _uuconf_iint (qglobal, argv[2], (pointer) &qsys->uuconf_ihighbaud,
564                        FALSE);
565 }
566 \f
567 /* Handle one of the size commands ("call-local-size", etc.).  The
568    first argument is a number of bytes, and the second argument is a
569    time string.  The pvar argument points to the string array to which
570    we add this new string.  */
571
572 /*ARGSUSED*/
573 static int
574 iisize (pglobal, argc, argv, pvar, pinfo)
575      pointer pglobal;
576      int argc;
577      char **argv;
578      pointer pvar;
579      pointer pinfo;
580 {
581   struct sglobal *qglobal = (struct sglobal *) pglobal;
582   struct uuconf_timespan **pqspan = (struct uuconf_timespan **) pvar;
583   struct sinfo *qinfo = (struct sinfo *) pinfo;
584   long ival;
585   int iret;
586
587   iret = _uuconf_iint (qglobal, argv[1], (pointer) &ival, FALSE);
588   if (iret != UUCONF_SUCCESS)
589     return iret;
590
591   iret = _uuconf_itime_parse (qglobal, argv[2], ival, 0, iisizecmp,
592                               pqspan, qinfo->qsys->uuconf_palloc);
593   if (iret != UUCONF_SUCCESS)
594     iret |= UUCONF_CMDTABRET_EXIT;
595   return iret;
596 }
597
598 /* A comparison function for sizes to pass to _uuconf_itime_parse.  */
599
600 static int
601 iisizecmp (i1, i2)
602      long i1;
603      long i2;
604 {
605   /* We can't just return i1 - i2 because that would be a long.  */
606   if (i1 < i2)
607     return -1;
608   else if (i1 == i2)
609     return 0;
610   else
611     return 1;
612 }
613 \f
614 /* Handle the "port" command.  If there is one argument, this names a
615    port.  Otherwise, the remaining arguments form a command describing
616    the port.  */
617
618 /*ARGSUSED*/
619 static int
620 iiport (pglobal, argc, argv, pvar, pinfo)
621      pointer pglobal;
622      int argc;
623      char **argv;
624      pointer pvar;
625      pointer pinfo;
626 {
627   struct sglobal *qglobal = (struct sglobal *) pglobal;
628   struct sinfo *qinfo = (struct sinfo *) pinfo;
629
630   if (argc < 2)
631     return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
632   else if (argc == 2)
633     {
634       qinfo->qsys->uuconf_zport = argv[1];
635       return UUCONF_CMDTABRET_KEEP;
636     }
637   else
638     {
639       int iret;
640
641       if (qinfo->qsys->uuconf_qport
642           == (struct uuconf_port *) &_uuconf_unset)
643         {
644           struct uuconf_port *qnew;
645
646           qnew = ((struct uuconf_port *)
647                   uuconf_malloc (qinfo->qsys->uuconf_palloc,
648                                   sizeof (struct uuconf_port)));
649           if (qnew == NULL)
650             {
651               qglobal->ierrno = errno;
652               return (UUCONF_MALLOC_FAILED
653                       | UUCONF_ERROR_ERRNO
654                       | UUCONF_CMDTABRET_EXIT);
655             }
656
657           _uuconf_uclear_port (qnew);
658
659           if (qinfo->qsys->uuconf_zname == NULL)
660             qnew->uuconf_zname = (char *) "default system file port";
661           else
662             {
663               char *zname;
664               size_t clen;
665
666               clen = strlen (qinfo->qsys->uuconf_zname);
667               zname = (char *) uuconf_malloc (qinfo->qsys->uuconf_palloc,
668                                               clen + sizeof "system  port");
669               if (zname == NULL)
670                 {
671                   qglobal->ierrno = errno;
672                   return (UUCONF_MALLOC_FAILED
673                           | UUCONF_ERROR_ERRNO
674                           | UUCONF_CMDTABRET_EXIT);
675                 }
676
677               memcpy ((pointer) zname, (pointer) "system ",
678                       sizeof "system " - 1);
679               memcpy ((pointer) (zname + sizeof "system " - 1),
680                       (pointer) qinfo->qsys->uuconf_zname,
681                       clen);
682               memcpy ((pointer) (zname + sizeof "system " - 1 + clen),
683                       (pointer) " port", sizeof " port");
684
685               qnew->uuconf_zname = zname;
686             }
687
688           qnew->uuconf_palloc = qinfo->qsys->uuconf_palloc;
689
690           qinfo->qsys->uuconf_qport = qnew;
691         }
692
693       iret = _uuconf_iport_cmd (qglobal, argc - 1, argv + 1,
694                                 qinfo->qsys->uuconf_qport);
695       if (UUCONF_ERROR_VALUE (iret) != UUCONF_SUCCESS)
696         iret |= UUCONF_CMDTABRET_EXIT;
697       return iret;
698     }
699 }
700 \f
701 /* Handle the "chat" and "called-chat" set of commands.  These just
702    hand off to the generic chat script function.  */
703
704 static int
705 iichat (pglobal, argc, argv, pvar, pinfo)
706      pointer pglobal;
707      int argc;
708      char **argv;
709      pointer pvar;
710      pointer pinfo;
711 {
712   struct sglobal *qglobal = (struct sglobal *) pglobal;
713   struct sinfo *qinfo = (struct sinfo *) pinfo;
714   struct uuconf_chat *qchat = (struct uuconf_chat *) pvar;
715   int iret;
716
717   iret = _uuconf_ichat_cmd (qglobal, argc, argv, qchat,
718                             qinfo->qsys->uuconf_palloc);
719   if (UUCONF_ERROR_VALUE (iret) != UUCONF_SUCCESS)
720     iret |= UUCONF_CMDTABRET_EXIT;
721   return iret;
722 }
723 \f
724 /* Local interface to the _uuconf_idebug_cmd function, which handles
725    the "debug" command.  */
726
727 static int
728 iidebug (pglobal, argc, argv, pvar, pinfo)
729      pointer pglobal;
730      int argc;
731      char **argv;
732      pointer pvar;
733      pointer pinfo;
734 {
735   struct sglobal *qglobal = (struct sglobal *) pglobal;
736   struct sinfo *qinfo = (struct sinfo *) pinfo;
737   char **pzdebug = (char **) pvar;
738
739   return _uuconf_idebug_cmd (qglobal, pzdebug, argc, argv,
740                              qinfo->qsys->uuconf_palloc);
741 }
742 \f
743 /* Handle the "called-login" command.  This only needs to be in a
744    function because there can be additional arguments listing the
745    remote systems which are permitted to use this login name.  The
746    additional arguments are not actually handled here; they are
747    handled by uuconf_taylor_system_names, which already has to go
748    through all the system files.  */
749
750 /*ARGSUSED*/
751 static int
752 iicalled_login (pglobal, argc, argv, pvar, pinfo)
753      pointer pglobal;
754      int argc;
755      char **argv;
756      pointer pvar;
757      pointer pinfo;
758 {
759   char **pz = (char **) pvar;
760
761   if (argc < 2)
762     return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
763   *pz = argv[1];
764   return UUCONF_CMDTABRET_KEEP;
765 }
766 \f
767 /* Handle the "protocol-parameter" command.  This just hands off to
768    the generic protocol parameter handler.  */
769
770 static int
771 iiproto_param (pglobal, argc, argv, pvar, pinfo)
772      pointer pglobal;
773      int argc;
774      char **argv;
775      pointer pvar;
776      pointer pinfo;
777 {
778   struct sglobal *qglobal = (struct sglobal *) pglobal;
779   struct uuconf_proto_param **pqparam = (struct uuconf_proto_param **) pvar;
780   struct sinfo *qinfo = (struct sinfo *) pinfo;
781
782   if (*pqparam == (struct uuconf_proto_param *) &_uuconf_unset)
783     *pqparam = NULL;
784   return _uuconf_iadd_proto_param (qglobal, argc - 1, argv + 1, pqparam,
785                                    qinfo->qsys->uuconf_palloc);
786 }
787 \f
788 /* Handle the "request" command.  This is equivalent to specifying
789    both "call-request" and "called-request".  */
790
791 /*ARGSUSED*/
792 static int
793 iirequest (pglobal, argc, argv, pvar, pinfo)
794      pointer pglobal;
795      int argc;
796      char **argv;
797      pointer pvar;
798      pointer pinfo;
799 {
800   struct sglobal *qglobal = (struct sglobal *) pglobal;
801   struct sinfo *qinfo = (struct sinfo *) pinfo;
802   int iret;
803
804   iret = _uuconf_iboolean (qglobal, argv[1],
805                            &qinfo->qsys->uuconf_fsend_request);
806   if (UUCONF_ERROR_VALUE (iret) == UUCONF_SUCCESS)
807     qinfo->qsys->uuconf_frec_request = qinfo->qsys->uuconf_fsend_request;
808
809   return iret;
810 }
811
812 /* Handle the "transfer" command.  This is equivalent to specifying
813    both "call-transfer" and "called-transfer".  */
814
815 /*ARGSUSED*/
816 static int
817 iitransfer (pglobal, argc, argv, pvar, pinfo)
818      pointer pglobal;
819      int argc;
820      char **argv;
821      pointer pvar;
822      pointer pinfo;
823 {
824   struct sglobal *qglobal = (struct sglobal *) pglobal;
825   struct sinfo *qinfo = (struct sinfo *) pinfo;
826   int iret;
827
828   iret = _uuconf_iboolean (qglobal, argv[1],
829                            &qinfo->qsys->uuconf_fcall_transfer);
830   if (UUCONF_ERROR_VALUE (iret) == UUCONF_SUCCESS)
831     qinfo->qsys->uuconf_fcalled_transfer = qinfo->qsys->uuconf_fcall_transfer;
832
833   return iret;
834 }
835 \f
836 /* Handle the "forward" command.  This is equivalent to specifying
837    both "forward-from" and "forward-to".  */
838
839 /*ARGSUSED*/
840 static int
841 iiforward (pglobal, argc, argv, pvar, pinfo)
842      pointer pglobal;
843      int argc;
844      char **argv;
845      pointer pvar;
846      pointer pinfo;
847 {
848   struct sglobal *qglobal = (struct sglobal *) pglobal;
849   struct sinfo *qinfo = (struct sinfo *) pinfo;
850   struct uuconf_system *qsys;
851   int i;
852   int iret;
853
854   qsys = qinfo->qsys;
855   qsys->uuconf_pzforward_from = NULL;
856   qsys->uuconf_pzforward_to = NULL;
857   for (i = 1; i < argc; i++)
858     {
859       iret = _uuconf_iadd_string (qglobal, argv[i], FALSE, FALSE,
860                                   &qsys->uuconf_pzforward_to,
861                                   qsys->uuconf_palloc);
862       if (iret != UUCONF_SUCCESS)
863         return iret | UUCONF_CMDTABRET_KEEP | UUCONF_CMDTABRET_EXIT;
864       iret = _uuconf_iadd_string (qglobal, argv[i], FALSE, FALSE,
865                                   &qsys->uuconf_pzforward_from,
866                                   qsys->uuconf_palloc);
867       if (iret != UUCONF_SUCCESS)
868         return iret | UUCONF_CMDTABRET_KEEP | UUCONF_CMDTABRET_EXIT;
869     }
870
871   return UUCONF_CMDTABRET_KEEP;
872 }
873 \f
874 /* Handle an unknown command.  This should probably be done more
875    intelligently.  */
876
877 /*ARGSUSED*/
878 static int
879 iiunknown (pglobal, argc, argv, pvar, pinfo)
880      pointer pglobal;
881      int argc;
882      char **argv;
883      pointer pvar;
884      pointer pinfo;
885 {
886   return UUCONF_SYNTAX_ERROR | UUCONF_CMDTABRET_EXIT;
887 }
888 \f
889 /* Return information for an unknown system.  It would be better to
890    put this in a different file, but it would require breaking several
891    functions out of this file.  Perhaps I will do it sometime.  */
892
893 int
894 uuconf_taylor_system_unknown (pglobal, qsys)
895      pointer pglobal;
896      struct uuconf_system *qsys;
897 {
898   struct sglobal *qglobal = (struct sglobal *) pglobal;
899   struct uuconf_cmdtab as[CSYSTEM_CMDS];
900   struct sinfo si;
901   struct sunknown *q;
902   int iret;
903
904   if (qglobal->qprocess->qunknown == NULL)
905     return UUCONF_NOT_FOUND;
906
907   _uuconf_ucmdtab_base (asIcmds, CSYSTEM_CMDS, (char *) qsys, as);
908
909   _uuconf_uclear_system (qsys);
910
911   si.qsys = qsys;
912   si.falternates = FALSE;
913   si.fdefault_alternates = TRUE;
914   qsys->uuconf_palloc = uuconf_malloc_block ();
915   if (qsys->uuconf_palloc == NULL)
916     {
917       qglobal->ierrno = errno;
918       return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
919     }
920
921   for (q = qglobal->qprocess->qunknown; q != NULL; q = q->qnext)
922     {
923       iret = uuconf_cmd_args (pglobal, q->cargs, q->pzargs, as,
924                               (pointer) &si, iiunknown,
925                               UUCONF_CMDTABFLAG_BACKSLASH,
926                               qsys->uuconf_palloc);
927       iret &=~ UUCONF_CMDTABRET_KEEP;
928       if (UUCONF_ERROR_VALUE (iret) != UUCONF_SUCCESS)
929         {
930           qglobal->zfilename = qglobal->qprocess->zconfigfile;
931           qglobal->ilineno = q->ilineno;
932           return ((iret &~ UUCONF_CMDTABRET_EXIT)
933                   | UUCONF_ERROR_FILENAME
934                   | UUCONF_ERROR_LINENO);
935         }
936       if ((iret & UUCONF_CMDTABRET_EXIT) != 0)
937         break;
938     }
939
940   if (! si.falternates)
941     uiset_call (qsys);
942   else
943     {
944       iret = iialternate (pglobal, 0, (char **) NULL, (pointer) NULL,
945                           (pointer) &si);
946       if (iret != UUCONF_SUCCESS)
947         return iret;
948     }
949
950   /* The first alternate is always available for calling in.  */
951   qsys->uuconf_fcalled = TRUE;
952
953   return _uuconf_isystem_basic_default (qglobal, qsys);
954 }