1/* rdlocs.c
2   Get the locations of systems in the Taylor UUCP configuration files.
3
4   Copyright (C) 1992, 2002 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.
23   */
24
25#include "uucnfi.h"
26
27#if USE_RCS_ID
28const char _uuconf_rdlocs_rcsid[] = "$Id: rdlocs.c,v 1.10 2002/03/05 19:10:42 ian Rel $";
29#endif
30
31#include <errno.h>
32
33static int itsystem P((pointer pglobal, int argc, char **argv,
34		       pointer pvar, pointer pinfo));
35static int itcalled_login P((pointer pglobal, int argc, char **argv,
36			     pointer pvar, pointer pinfo));
37static int itmyname P((pointer pglobal, int argc, char **argv,
38		       pointer pvar, pointer pinfo));
39
40/* This code scans through the Taylor UUCP system files in order to
41   locate each system and to gather the login restrictions (since this
42   information is held in additional arguments to the "called-login"
43   command, it can appear anywhere in the systems files).  It also
44   records whether any "myname" appears, as an optimization for
45   uuconf_taylor_localname.
46
47   This table is used to dispatch the appropriate commands.  Most
48   commands are simply ignored.  Note that this is a uuconf_cmdtab,
49   not a cmdtab_offset.  */
50
51static const struct uuconf_cmdtab asTcmds[] =
52{
53  { "system", UUCONF_CMDTABTYPE_FN | 2, NULL, itsystem },
54  { "alias", UUCONF_CMDTABTYPE_FN | 2, (pointer) asTcmds, itsystem },
55  { "called-login", UUCONF_CMDTABTYPE_FN | 0, NULL, itcalled_login },
56  { "myname", UUCONF_CMDTABTYPE_FN | 2, NULL, itmyname },
57  { NULL, 0, NULL, NULL }
58};
59
60/* This structure is used to pass information into the command table
61   functions.  */
62
63struct sinfo
64{
65  /* The sys file name.  */
66  const char *zname;
67  /* The open sys file.  */
68  FILE *e;
69  /* The list of locations we are building.  */
70  struct stsysloc *qlocs;
71  /* The list of validation restrictions we are building.  */
72  struct svalidate *qvals;
73};
74
75/* Look through the sys files to find the location and names of all
76   the systems.  Since we're scanning the sys files, we also record
77   the validation information specified by the additional arguments to
78   the called-login command.  We don't use uuconf_cmd_file to avoid
79   the overhead of breaking the line up into arguments if not
80   necessary.  */
81
82int
83_uuconf_iread_locations (qglobal)
84     struct sglobal *qglobal;
85{
86  char *zline;
87  size_t cline;
88  struct sinfo si;
89  int iret;
90  char **pz;
91
92  if (qglobal->qprocess->fread_syslocs)
93    return UUCONF_SUCCESS;
94
95  zline = NULL;
96  cline = 0;
97
98  si.qlocs = NULL;
99  si.qvals = NULL;
100
101  iret = UUCONF_SUCCESS;
102
103  for (pz = qglobal->qprocess->pzsysfiles; *pz != NULL; pz++)
104    {
105      FILE *e;
106      int cchars;
107
108      qglobal->ilineno = 0;
109
110      e = fopen (*pz, "r");
111      if (e == NULL)
112	{
113	  if (FNO_SUCH_FILE ())
114	    continue;
115	  qglobal->ierrno = errno;
116	  iret = UUCONF_FOPEN_FAILED | UUCONF_ERROR_ERRNO;
117	  break;
118	}
119
120#ifdef CLOSE_ON_EXEC
121      CLOSE_ON_EXEC (e);
122#endif
123
124      si.zname = *pz;
125      si.e = e;
126
127      while ((cchars = _uuconf_getline (qglobal, &zline, &cline, e)) > 0)
128	{
129	  char *zcmd;
130
131	  ++qglobal->ilineno;
132
133	  zcmd = zline + strspn (zline, " \t");
134	  if (strncasecmp (zcmd, "system", sizeof "system" - 1) == 0
135	      || strncasecmp (zcmd, "alias", sizeof "alias" - 1) == 0
136	      || strncasecmp (zcmd, "called-login",
137			      sizeof "called-login" - 1) == 0
138	      || strncasecmp (zcmd, "myname", sizeof "myname" - 1) == 0)
139	    {
140	      iret = uuconf_cmd_line ((pointer) qglobal, zline, asTcmds,
141				      (pointer) &si, (uuconf_cmdtabfn) NULL,
142				      0, qglobal->pblock);
143	      if ((iret & UUCONF_CMDTABRET_KEEP) != 0)
144		{
145		  iret &=~ UUCONF_CMDTABRET_KEEP;
146		  zline = NULL;
147		  cline = 0;
148		}
149	      if (iret != UUCONF_SUCCESS)
150		{
151		  iret &=~ UUCONF_CMDTABRET_EXIT;
152		  break;
153		}
154	    }
155	}
156
157      if (iret != UUCONF_SUCCESS)
158	break;
159    }
160
161  if (zline != NULL)
162    free ((pointer) zline);
163
164  if (iret != UUCONF_SUCCESS)
165    {
166      qglobal->zfilename = *pz;
167      iret |= UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
168      if (UUCONF_ERROR_VALUE (iret) != UUCONF_MALLOC_FAILED)
169	qglobal->qprocess->fread_syslocs = TRUE;
170    }
171  else
172    {
173      qglobal->qprocess->qsyslocs = si.qlocs;
174      qglobal->qprocess->qvalidate = si.qvals;
175      qglobal->qprocess->fread_syslocs = TRUE;
176    }
177
178  return iret;
179}
180
181/* Handle a "system" or "alias" command by recording the file and
182   location.  If pvar is not NULL, this is an "alias" command.  */
183
184/*ARGSUSED*/
185static int
186itsystem (pglobal, argc, argv, pvar, pinfo)
187     pointer pglobal;
188     int argc ATTRIBUTE_UNUSED;
189     char **argv;
190     pointer pvar;
191     pointer pinfo;
192{
193  struct sglobal *qglobal = (struct sglobal *) pglobal;
194  struct sinfo *qinfo = (struct sinfo *) pinfo;
195  struct stsysloc *q;
196  size_t csize;
197
198  q = (struct stsysloc *) uuconf_malloc (qglobal->pblock,
199					 sizeof (struct stsysloc));
200  if (q == NULL)
201    {
202      qglobal->ierrno = errno;
203      return (UUCONF_MALLOC_FAILED
204	      | UUCONF_ERROR_ERRNO
205	      | UUCONF_CMDTABRET_EXIT);
206    }
207
208  csize = strlen (argv[1]) + 1;
209  q->zname = uuconf_malloc (qglobal->pblock, csize);
210  if (q->zname == NULL)
211    {
212      qglobal->ierrno = errno;
213      return (UUCONF_MALLOC_FAILED
214	      | UUCONF_ERROR_ERRNO
215	      | UUCONF_CMDTABRET_EXIT);
216    }
217
218  q->qnext = qinfo->qlocs;
219  memcpy ((pointer) q->zname, (pointer) argv[1], csize);
220  q->falias = pvar != NULL;
221  q->zfile = qinfo->zname;
222  q->e = qinfo->e;
223  q->iloc = ftell (qinfo->e);
224  q->ilineno = qglobal->ilineno;
225
226  qinfo->qlocs = q;
227
228  return UUCONF_CMDTABRET_CONTINUE;
229}
230
231/* Handle the "called-login" command.  This just records any extra
232   arguments, so that uuconf_validate can check them later if
233   necessary.  */
234
235/*ARGSUSED*/
236static int
237itcalled_login (pglobal, argc, argv, pvar, pinfo)
238     pointer pglobal;
239     int argc;
240     char **argv;
241     pointer pvar ATTRIBUTE_UNUSED;
242     pointer pinfo;
243{
244  struct sglobal *qglobal = (struct sglobal *) pglobal;
245  struct sinfo *qinfo = (struct sinfo *) pinfo;
246  register struct svalidate *qval;
247  int i;
248
249  if (argc <= 2)
250    return UUCONF_CMDTABRET_CONTINUE;
251
252  for (qval = qinfo->qvals; qval != NULL; qval = qval->qnext)
253    if (strcmp (argv[1], qval->zlogname) == 0)
254      break;
255
256  if (qval == NULL)
257    {
258      qval = (struct svalidate *) uuconf_malloc (qglobal->pblock,
259						 sizeof (struct svalidate));
260      if (qval == NULL)
261	{
262	  qglobal->ierrno = errno;
263	  return (UUCONF_MALLOC_FAILED
264		  | UUCONF_ERROR_ERRNO
265		  | UUCONF_CMDTABRET_EXIT);
266	}
267
268      qval->qnext = qinfo->qvals;
269      qval->zlogname = argv[1];
270      qval->pzmachines = NULL;
271
272      qinfo->qvals = qval;
273    }
274
275  for (i = 2; i < argc; i++)
276    {
277      int iret;
278
279      iret = _uuconf_iadd_string (qglobal, argv[i], FALSE, TRUE,
280				  &qval->pzmachines, qglobal->pblock);
281      if (iret != UUCONF_SUCCESS)
282	return iret | UUCONF_CMDTABRET_EXIT;
283    }
284
285  return UUCONF_CMDTABRET_KEEP;
286}
287
288/* Handle the "myname" command by simply recording that it appears.
289   This information is used by uuconf_taylor_localname.  */
290
291/*ARGSUSED*/
292static int
293itmyname (pglobal, argc, argv, pvar, pinfo)
294     pointer pglobal;
295     int argc ATTRIBUTE_UNUSED;
296     char **argv ATTRIBUTE_UNUSED;
297     pointer pvar ATTRIBUTE_UNUSED;
298     pointer pinfo ATTRIBUTE_UNUSED;
299{
300  struct sglobal *qglobal = (struct sglobal *) pglobal;
301
302  qglobal->qprocess->fuses_myname = TRUE;
303  return UUCONF_CMDTABRET_CONTINUE;
304}
305