]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - gnu/libexec/uucp/libuuconf/vsinfo.c
This commit was generated by cvs2svn to compensate for changes in r53796,
[FreeBSD/FreeBSD.git] / gnu / libexec / uucp / libuuconf / vsinfo.c
1 /* vsinfo.c
2    Get information about a system from the V2 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_vsinfo_rcsid[] = "$FreeBSD$";
30 #endif
31
32 #include <errno.h>
33 #include <ctype.h>
34 \f
35 /* Get the information for a particular system from the V2
36    configuration files.  This does not make sure that all the default
37    values are set.  */
38
39 int
40 _uuconf_iv2_system_internal (qglobal, zsystem, qsys)
41      struct sglobal *qglobal;
42      const char *zsystem;
43      struct uuconf_system *qsys;
44 {
45   char *zline;
46   size_t cline;
47   char **pzsplit;
48   size_t csplit;
49   char **pzcomma;
50   size_t ccomma;
51   FILE *e;
52   int cchars;
53   pointer pblock;
54   int iret;
55
56   e = fopen (qglobal->qprocess->zv2systems, "r");
57   if (e == NULL)
58     {
59       if (FNO_SUCH_FILE ())
60         return UUCONF_NOT_FOUND;
61       qglobal->ierrno = errno;
62       qglobal->zfilename = qglobal->qprocess->zv2systems;
63       return (UUCONF_FOPEN_FAILED
64               | UUCONF_ERROR_ERRNO
65               | UUCONF_ERROR_FILENAME);
66     }
67
68   zline = NULL;
69   cline = 0;
70   pzsplit = NULL;
71   csplit = 0;
72   pzcomma = NULL;
73   ccomma = 0;
74
75   pblock = NULL;
76   iret = UUCONF_SUCCESS;
77
78   qglobal->ilineno = 0;
79
80   while ((cchars = _uuconf_getline (qglobal, &zline, &cline, e)) > 0)
81     {
82       int ctoks, ctimes, i;
83       struct uuconf_system *qset;
84       char *z, *zretry;
85       int cretry;
86
87       ++qglobal->ilineno;
88
89       --cchars;
90       if (zline[cchars] == '\n')
91         zline[cchars] = '\0';
92       zline[strcspn (zline, "#")] = '\0';
93
94       ctoks = _uuconf_istrsplit (zline, '\0', &pzsplit, &csplit);
95       if (ctoks < 0)
96         {
97           qglobal->ierrno = errno;
98           iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
99           break;
100         }
101
102       /* If this isn't the system we're looking for, keep reading
103          the file.  */
104       if (ctoks < 1
105           || strcmp (zsystem, pzsplit[0]) != 0)
106         continue;
107
108       /* If this is the first time we've found the system, we want
109          to set *qsys directly.  Otherwise, we allocate a new
110          alternate.  */
111       if (pblock == NULL)
112         {
113           pblock = uuconf_malloc_block ();
114           if (pblock == NULL)
115             {
116               qglobal->ierrno = errno;
117               iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
118               break;
119             }
120           _uuconf_uclear_system (qsys);
121           qsys->uuconf_palloc = pblock;
122           qset = qsys;
123         }
124       else
125         {
126           struct uuconf_system **pq;
127
128           qset = ((struct uuconf_system *)
129                   uuconf_malloc (pblock, sizeof (struct uuconf_system)));
130           if (qset == NULL)
131             {
132               qglobal->ierrno = errno;
133               iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
134               break;
135             }
136           _uuconf_uclear_system (qset);
137           for (pq = &qsys->uuconf_qalternate;
138                *pq != NULL;
139                pq = &(*pq)->uuconf_qalternate)
140             ;
141           *pq = qset;
142         }
143
144       /* Add this line to the memory block we are building for the
145          system.  */
146       if (uuconf_add_block (pblock, zline) != 0)
147         {
148           qglobal->ierrno = errno;
149           iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
150           break;
151         }
152
153       zline = NULL;
154       cline = 0;
155
156       /* The format of a line in Systems is
157          system time device speed phone chat
158          For example,
159          airs Any ACU 9600 5551212 ogin: foo pass: bar
160          */
161
162       /* Get the system name.  */
163
164       qset->uuconf_zname = pzsplit[0];
165       qset->uuconf_fcall = TRUE;
166       qset->uuconf_fcalled = TRUE;
167
168       if (ctoks < 2)
169         continue;
170
171       /* A time string is "time/grade,time/grade;retry".  A missing
172          grade is taken as BGRADE_LOW.  On some versions the retry
173          time is actually separated by a comma, which won't work right
174          here.  */
175       zretry = strchr (pzsplit[1], ';');
176       if (zretry == NULL)
177         cretry = 55;
178       else
179         {
180           *zretry = '\0';
181           cretry = (int) strtol (zretry + 1, (char **) NULL, 10);
182         }
183
184       ctimes = _uuconf_istrsplit (pzsplit[1], ',', &pzcomma, &ccomma);
185       if (ctimes < 0)
186         {
187           qglobal->ierrno = errno;
188           iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
189           break;
190         }
191
192       for (i = 0; i < ctimes; i++)
193         {
194           char *zslash;
195           char bgrade;
196
197           z = pzcomma[i];
198           zslash = strchr (z, '/');
199           if (zslash == NULL)
200             bgrade = UUCONF_GRADE_LOW;
201           else
202             {
203               *zslash = '\0';
204               bgrade = zslash[1];
205               if (! UUCONF_GRADE_LEGAL (bgrade))
206                 bgrade = UUCONF_GRADE_LOW;
207             }
208
209           iret = _uuconf_itime_parse (qglobal, z, (long) bgrade, cretry,
210                                       _uuconf_itime_grade_cmp,
211                                       &qset->uuconf_qtimegrade,
212                                       pblock);
213
214           /* We treat a syntax error in the time field as equivalent
215              to ``never'', on the assumption that that is what V2
216              does.  */
217           if (iret == UUCONF_SYNTAX_ERROR)
218             iret = UUCONF_SUCCESS;
219
220           if (iret != UUCONF_SUCCESS)
221             break;
222
223           /* Treat any time/grade setting as both a timegrade and a
224              call-timegrade.  */
225           if (bgrade != UUCONF_GRADE_LOW)
226             qset->uuconf_qcalltimegrade = qset->uuconf_qtimegrade;
227         }
228
229       if (iret != UUCONF_SUCCESS)
230         break;
231
232       if (ctoks < 3)
233         continue;
234
235       /* Pick up the device name.  It can be followed by a comma and a
236          list of protocols (this is not actually supported by most V2
237          systems, but it should be compatible).  */
238       qset->uuconf_zport = pzsplit[2];
239       z = strchr (pzsplit[2], ',');
240       if (z != NULL)
241         {
242           qset->uuconf_zprotocols = z + 1;
243           *z = '\0';
244         }
245
246       /* If the port is "TCP", we set up a system specific port.  The
247          baud rate becomes the service number and the phone number
248          becomes the address (still stored in qsys->zphone).  */
249       if (strcmp (qset->uuconf_zport, "TCP") == 0)
250         {
251           qset->uuconf_zport = NULL;
252           qset->uuconf_qport = ((struct uuconf_port *)
253                                 uuconf_malloc (pblock,
254                                                sizeof (struct uuconf_port)));
255           if (qset->uuconf_qport == NULL)
256             {
257               qglobal->ierrno = errno;
258               iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
259               break;
260             }
261           _uuconf_uclear_port (qset->uuconf_qport);
262           qset->uuconf_qport->uuconf_zname = (char *) "TCP";
263           qset->uuconf_qport->uuconf_ttype = UUCONF_PORTTYPE_TCP;
264           qset->uuconf_qport->uuconf_ireliable
265             = (UUCONF_RELIABLE_ENDTOEND | UUCONF_RELIABLE_RELIABLE
266                | UUCONF_RELIABLE_EIGHT | UUCONF_RELIABLE_FULLDUPLEX
267                | UUCONF_RELIABLE_SPECIFIED);
268           if (ctoks < 4)
269             qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_zport
270               = (char *) "uucp";
271           else
272             qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_zport
273               = pzsplit[3];
274           qset->uuconf_qport->uuconf_u.uuconf_stcp.uuconf_pzdialer = NULL;
275         }
276
277       if (ctoks < 4)
278         continue;
279
280       qset->uuconf_ibaud = strtol (pzsplit[3], (char **) NULL, 10);
281
282       if (ctoks < 5)
283         continue;
284
285       /* Get the phone number.  */
286       qset->uuconf_zphone = pzsplit[4];
287
288       if (ctoks < 6)
289         continue;
290
291       /* Get the chat script.  We just hand this off to the chat
292          script processor, so that it will parse subsend and
293          subexpect strings correctly.  */
294       pzsplit[4] = (char *) "chat";
295       iret = _uuconf_ichat_cmd (qglobal, ctoks - 4, pzsplit + 4,
296                                 &qset->uuconf_schat, pblock);
297       iret &=~ UUCONF_CMDTABRET_KEEP;
298       if (iret != UUCONF_SUCCESS)
299         break;
300     }
301
302   (void) fclose (e);
303
304   if (pzcomma != NULL)
305     free ((pointer) pzcomma);
306
307   if (iret != UUCONF_SUCCESS)
308     {
309       if (zline != NULL)
310         free ((pointer) zline);
311       if (pzsplit != NULL)
312         free ((pointer) pzsplit);
313       qglobal->zfilename = qglobal->qprocess->zv2systems;
314       return iret | UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
315     }
316
317   if (pblock == NULL)
318     {
319       if (zline != NULL)
320         free ((pointer) zline);
321       if (pzsplit != NULL)
322         free ((pointer) pzsplit);
323       return UUCONF_NOT_FOUND;
324     }
325
326   /* Now read USERFILE and L.cmds to get permissions.  We can't fully
327      handle USERFILE since that specifies permissions based on local
328      users which we do not support.  */
329   {
330     e = fopen (qglobal->qprocess->zv2userfile, "r");
331     if (e != NULL)
332       {
333         char **pzlocal, **pzremote;
334         boolean fdefault_callback;
335         char *zdefault_login;
336         struct uuconf_system *q;
337
338         pzlocal = NULL;
339         pzremote = NULL;
340         fdefault_callback = FALSE;
341         zdefault_login = NULL;
342
343         qglobal->ilineno = 0;
344
345         while ((cchars = getline (&zline, &cline, e)) > 0)
346           {
347             int ctoks;
348             char *zcomma;
349             boolean fcallback;
350             char **pzlist, **pznew;
351
352             ++qglobal->ilineno;
353
354             --cchars;
355             if (zline[cchars] == '\n')
356               zline[cchars] = '\0';
357             zline[strcspn (zline, "#")] = '\0';
358
359             ctoks = _uuconf_istrsplit (zline, '\0', &pzsplit, &csplit);
360             if (ctoks < 0)
361               {
362                 qglobal->ierrno = errno;
363                 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
364                 break;
365               }
366
367             if (ctoks == 0)
368               continue;
369
370             /* The first field is username,machinename */
371             zcomma = strchr (pzsplit[0], ',');
372             if (zcomma == NULL)
373               continue;
374
375             *zcomma++ = '\0';
376
377             /* The rest of the line is the list of directories, except
378                that if the first directory is "c" we must call the
379                system back.  */
380             fcallback = FALSE;
381             pzlist = pzsplit + 1;
382             --ctoks;
383             if (ctoks > 0
384                 && pzsplit[1][0] == 'c'
385                 && pzsplit[1][1] == '\0')
386               {
387                 fcallback = TRUE;
388                 pzlist = pzsplit + 2;
389                 --ctoks;
390               }
391
392             /* Now pzsplit[0] is the user name, zcomma is the system
393                name, fcallback indicates whether a call back is
394                required, ctoks is the number of directories and pzlist
395                points to the directories.  If the system name matches,
396                then the user name is the name that the system must use
397                to log in, and the list of directories is what may be
398                transferred in by either local or remote request.
399                Otherwise, if no system name matches, then the first
400                line with no user name gives the list of directories
401                that may be transferred by local request, and the first
402                line with no system name gives the list of directories
403                that may be transferred by remote request.  */
404             if ((pzsplit[0][0] != '\0' || pzlocal != NULL)
405                 && (zcomma[0] != '\0' || pzremote != NULL)
406                 && strcmp (zcomma, zsystem) != 0)
407               continue;
408
409             /* NULL terminate the list of directories.  */
410             pznew = (char **) uuconf_malloc (pblock,
411                                               (ctoks + 1) * sizeof (char *));
412             if (pznew == NULL)
413               {
414                 qglobal->ierrno = errno;
415                 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
416                 break;
417               }
418             memcpy ((pointer) pznew, (pointer) pzlist,
419                     ctoks * sizeof (char *));
420             pznew[ctoks] = NULL;
421
422             if (uuconf_add_block (pblock, zline) != 0)
423               {
424                 qglobal->ierrno = errno;
425                 iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
426                 break;
427               }
428             zline = NULL;
429             cline = 0;
430
431             if (pzsplit[0][0] == '\0')
432               {
433                 pzlocal = pznew;
434                 fdefault_callback = fcallback;
435               }
436             else if (zcomma[0] == '\0')
437               {
438                 pzremote = pznew;
439                 zdefault_login = pzsplit[0];
440               }
441             else
442               {
443                 /* Both the login name and the machine name were
444                    listed; require the machine to be logged in under
445                    this name.  This is not fully backward compatible,
446                    and perhaps should be changed.  On the other hand,
447                    it is more useful.  */
448                 for (q = qsys; q != NULL; q = q->uuconf_qalternate)
449                   {
450                     q->uuconf_zcalled_login = pzsplit[0];
451                     q->uuconf_fcallback = fcallback;
452                     q->uuconf_pzlocal_send = pznew;
453                     q->uuconf_pzlocal_receive = pznew;
454                     q->uuconf_pzremote_send = pznew;
455                     q->uuconf_pzremote_receive = pznew;
456                   }
457
458                 break;
459               }
460           }
461
462         (void) fclose (e);
463
464         if (iret != UUCONF_SUCCESS)
465           {
466             if (zline != NULL)
467               free ((pointer) zline);
468             if (pzsplit != NULL)
469               free ((pointer) pzsplit);
470             qglobal->zfilename = qglobal->qprocess->zv2userfile;
471             return iret | UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
472           }
473
474         if (qsys->uuconf_pzlocal_send == (char **) &_uuconf_unset
475             && pzlocal != NULL)
476           {
477             for (q = qsys; q != NULL; q = q->uuconf_qalternate)
478               {
479                 q->uuconf_fcallback = fdefault_callback;
480                 q->uuconf_pzlocal_send = pzlocal;
481                 q->uuconf_pzlocal_receive = pzlocal;
482               }
483           }
484
485         if (qsys->uuconf_pzremote_send == (char **) &_uuconf_unset
486             && pzremote != NULL)
487           {
488             for (q = qsys; q != NULL; q = q->uuconf_qalternate)
489               {
490                 q->uuconf_zcalled_login = zdefault_login;
491                 q->uuconf_pzremote_send = pzremote;
492                 q->uuconf_pzremote_receive = pzremote;
493               }
494           }
495       }
496   }
497
498   /* Now we must read L.cmds to determine which commands may be
499      executed.  */
500   {
501     e = fopen (qglobal->qprocess->zv2cmds, "r");
502     if (e != NULL)
503       {
504         qglobal->ilineno = 0;
505
506         if (getline (&zline, &cline, e) > 0)
507           {
508             ++qglobal->ilineno;
509
510             zline[strcspn (zline, "#\n")] = '\0';
511
512             while (*zline == '\0')
513               {
514                 if (getline (&zline, &cline, e) <= 0)
515                   {
516                     if (zline != NULL)
517                       {
518                         free ((pointer) zline);
519                         zline = NULL;
520                       }
521                   }
522                 else
523                   {
524                     ++qglobal->ilineno;
525                     zline[strcspn (zline, "#\n")] = '\0';
526                   }
527               }
528
529             if (zline != NULL
530                 && strncmp (zline, "PATH=", sizeof "PATH=" - 1) == 0)
531               {
532                 int ctoks;
533                 char **pznew;
534
535                 zline += sizeof "PATH=" - 1;
536                 ctoks = _uuconf_istrsplit (zline, ':', &pzsplit, &csplit);
537                 if (ctoks < 0)
538                   {
539                     qglobal->ierrno = errno;
540                     iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
541                   }
542
543                 pznew = NULL;
544                 if (iret == UUCONF_SUCCESS)
545                   {
546                     pznew = ((char **)
547                              uuconf_malloc (pblock,
548                                              (ctoks + 1) * sizeof (char *)));
549                     if (pznew == NULL)
550                       iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
551                   }
552                 if (iret == UUCONF_SUCCESS)
553                   {
554                     memcpy ((pointer) pznew, (pointer) pzsplit,
555                             ctoks * sizeof (char *));
556                     pznew[ctoks] = NULL;
557                     qsys->uuconf_pzpath = pznew;
558                     zline = NULL;
559                     cline = 0;
560                   }      
561
562                 if (getline (&zline, &cline, e) < 0)
563                   {
564                     if (zline != NULL)
565                       {
566                         free ((pointer) zline);
567                         zline = NULL;
568                       }
569                   }
570                 else
571                   ++qglobal->ilineno;
572               }
573           }
574
575         if (iret == UUCONF_SUCCESS && zline != NULL)
576           {
577             while (TRUE)
578               {
579                 zline[strcspn (zline, "#,\n")] = '\0';
580                 if (*zline != '\0')
581                   {
582                     iret = _uuconf_iadd_string (qglobal, zline, TRUE, FALSE,
583                                                 &qsys->uuconf_pzcmds,
584                                                 pblock);
585                     if (iret != UUCONF_SUCCESS)
586                       break;
587                   }
588                 if (getline (&zline, &cline, e) < 0)
589                   break;
590                 ++qglobal->ilineno;
591               }
592           }
593
594         (void) fclose (e);
595
596         if (iret != UUCONF_SUCCESS)
597           {
598             qglobal->zfilename = qglobal->qprocess->zv2cmds;
599             iret |= UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
600           }
601       }
602   }
603
604   if (zline != NULL)
605     free ((pointer) zline);
606   if (pzsplit != NULL)
607     free ((pointer) pzsplit);
608
609   return iret;
610 }