1/* hinit.c
2   Initialize for reading HDB configuration files.
3
4   Copyright (C) 1992, 1994 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_hinit_rcsid[] = "$Id: hinit.c,v 1.9 2002/03/05 19:10:42 ian Rel $";
29#endif
30
31#include <errno.h>
32#include <ctype.h>
33
34/* Avoid replicating OLDCONFIGLIB several times if not necessary.  */
35static const char abHoldconfiglib[] = OLDCONFIGLIB;
36
37/* Initialize the routines which read HDB configuration files.  */
38
39int
40uuconf_hdb_init (ppglobal, zprogram)
41     pointer *ppglobal;
42     const char *zprogram;
43{
44  struct sglobal **pqglobal = (struct sglobal **) ppglobal;
45  int iret;
46  struct sglobal *qglobal;
47  pointer pblock;
48  char abdialcodes[sizeof OLDCONFIGLIB + sizeof HDB_DIALCODES - 1];
49  char *zsys;
50  FILE *e;
51
52  if (*pqglobal == NULL)
53    {
54      iret = _uuconf_iinit_global (pqglobal);
55      if (iret != UUCONF_SUCCESS)
56	return iret;
57    }
58
59  qglobal = *pqglobal;
60  pblock = qglobal->pblock;
61
62  if (zprogram == NULL
63      || strcmp (zprogram, "uucp") == 0)
64    zprogram = "uucico";
65
66  /* Add the Dialcodes file to the global list.  */
67  memcpy ((pointer) abdialcodes, (pointer) abHoldconfiglib,
68	  sizeof OLDCONFIGLIB - 1);
69  memcpy ((pointer) (abdialcodes + sizeof OLDCONFIGLIB - 1),
70	  (pointer) HDB_DIALCODES, sizeof HDB_DIALCODES);
71  iret = _uuconf_iadd_string (qglobal, abdialcodes, TRUE, FALSE,
72			      &qglobal->qprocess->pzdialcodefiles,
73			      pblock);
74  if (iret != UUCONF_SUCCESS)
75    return iret;
76
77  /* Read the Sysfiles file.  We allocate the name on the heap rather
78     than the stack so that we can return it in
79     qerr->uuconf_zfilename.  */
80
81  zsys = uuconf_malloc (pblock,
82			sizeof OLDCONFIGLIB + sizeof HDB_SYSFILES - 1);
83  if (zsys == NULL)
84    {
85      qglobal->ierrno = errno;
86      return UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
87    }
88  memcpy ((pointer) zsys, (pointer) abHoldconfiglib, sizeof OLDCONFIGLIB - 1);
89  memcpy ((pointer) (zsys + sizeof OLDCONFIGLIB - 1), (pointer) HDB_SYSFILES,
90	  sizeof HDB_SYSFILES);
91
92  iret = UUCONF_SUCCESS;
93
94  e = fopen (zsys, "r");
95  if (e == NULL)
96    uuconf_free (pblock, zsys);
97  else
98    {
99      char *zline;
100      size_t cline;
101      char **pzargs;
102      size_t cargs;
103      char **pzcolon;
104      size_t ccolon;
105      int cchars;
106
107      zline = NULL;
108      cline = 0;
109      pzargs = NULL;
110      cargs = 0;
111      pzcolon = NULL;
112      ccolon = 0;
113
114      qglobal->ilineno = 0;
115
116      while (iret == UUCONF_SUCCESS
117	     && (cchars = _uuconf_getline (qglobal, &zline, &cline, e)) > 0)
118	{
119	  int ctypes, cnames;
120	  int i;
121
122	  ++qglobal->ilineno;
123
124	  --cchars;
125	  if (zline[cchars] == '\n')
126	    zline[cchars] = '\0';
127	  if (zline[0] == '#')
128	    continue;
129
130	  ctypes = _uuconf_istrsplit (zline, '\0', &pzargs, &cargs);
131	  if (ctypes < 0)
132	    {
133	      qglobal->ierrno = errno;
134	      iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
135	      break;
136	    }
137
138	  if (ctypes == 0)
139	    continue;
140
141	  if (strncmp (pzargs[0], "service=", sizeof "service=" - 1) != 0)
142	    {
143	      iret = UUCONF_SYNTAX_ERROR;
144	      break;
145	    }
146	  pzargs[0] += sizeof "service=" - 1;
147
148	  cnames = _uuconf_istrsplit (pzargs[0], ':', &pzcolon, &ccolon);
149	  if (cnames < 0)
150	    {
151	      qglobal->ierrno = errno;
152	      iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
153	      break;
154	    }
155
156	  for (i = 0; i < cnames; i++)
157	    if (strcmp (zprogram, pzcolon[i]) == 0)
158	      break;
159
160	  if (i >= cnames)
161	    continue;
162
163	  for (i = 1; i < ctypes && iret == UUCONF_SUCCESS; i++)
164	    {
165	      char ***ppz;
166	      int cfiles, ifile;
167
168	      if (strncmp (pzargs[i], "systems=", sizeof "systems=" - 1)
169		  == 0)
170		{
171		  ppz = &qglobal->qprocess->pzhdb_systems;
172		  pzargs[i] += sizeof "systems=" - 1;
173		}
174	      else if (strncmp (pzargs[i], "devices=", sizeof "devices=" - 1)
175		       == 0)
176		{
177		  ppz = &qglobal->qprocess->pzhdb_devices;
178		  pzargs[i] += sizeof "devices=" - 1;
179		}
180	      else if (strncmp (pzargs[i], "dialers=", sizeof "dialers=" - 1)
181		       == 0)
182		{
183		  ppz = &qglobal->qprocess->pzhdb_dialers;
184		  pzargs[i] += sizeof "dialers=" - 1;
185		}
186	      else
187		{
188		  iret = UUCONF_SYNTAX_ERROR;
189		  break;
190		}
191
192	      cfiles = _uuconf_istrsplit (pzargs[i], ':', &pzcolon, &ccolon);
193	      if (cfiles < 0)
194		{
195		  qglobal->ierrno = errno;
196		  iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
197		  break;
198		}
199
200	      for (ifile = 0;
201		   ifile < cfiles && iret == UUCONF_SUCCESS;
202		   ifile++)
203		{
204		  /* Looking for a leading '/' is Unix dependent, and
205		     should probably be changed.  */
206		  if (pzcolon[ifile][0] == '/')
207		    iret = _uuconf_iadd_string (qglobal, pzcolon[ifile], TRUE,
208						FALSE, ppz, pblock);
209		  else
210		    {
211		      char *zdir;
212		      size_t clen;
213
214		      clen = strlen (pzcolon[ifile]);
215		      zdir = (char *) uuconf_malloc (pblock,
216						     (sizeof OLDCONFIGLIB
217						      + sizeof HDB_SEPARATOR
218						      + clen
219						      - 1));
220		      if (zdir == NULL)
221			{
222			  qglobal->ierrno = errno;
223			  iret = UUCONF_MALLOC_FAILED | UUCONF_ERROR_ERRNO;
224			  break;
225			}
226		      memcpy ((pointer) zdir, (pointer) abHoldconfiglib,
227			      sizeof OLDCONFIGLIB - 1);
228		      memcpy ((pointer) (zdir + sizeof OLDCONFIGLIB - 1),
229			      HDB_SEPARATOR, sizeof HDB_SEPARATOR - 1);
230		      memcpy ((pointer) (zdir
231					 + sizeof OLDCONFIGLIB - 1
232					 + sizeof HDB_SEPARATOR - 1),
233			      (pointer) pzcolon[ifile], clen + 1);
234		      iret = _uuconf_iadd_string (qglobal, zdir, FALSE, FALSE,
235						  ppz, pblock);
236		    }
237		}
238	    }
239	}
240
241      (void) fclose (e);
242      if (zline != NULL)
243	free ((pointer) zline);
244      if (pzargs != NULL)
245	free ((pointer) pzargs);
246      if (pzcolon != NULL)
247	free ((pointer) pzcolon);
248
249      if (iret != UUCONF_SUCCESS)
250	{
251	  qglobal->zfilename = zsys;
252	  return iret | UUCONF_ERROR_FILENAME | UUCONF_ERROR_LINENO;
253	}
254    }
255
256  if (qglobal->qprocess->pzhdb_systems == NULL)
257    {
258      char ab[sizeof OLDCONFIGLIB + sizeof HDB_SYSTEMS - 1];
259
260      memcpy ((pointer) ab, (pointer) abHoldconfiglib,
261	      sizeof OLDCONFIGLIB - 1);
262      memcpy ((pointer) (ab + sizeof OLDCONFIGLIB - 1),
263	      (pointer) HDB_SYSTEMS, sizeof HDB_SYSTEMS);
264      iret = _uuconf_iadd_string (qglobal, ab, TRUE, FALSE,
265				  &qglobal->qprocess->pzhdb_systems,
266				  pblock);
267    }
268  if (qglobal->qprocess->pzhdb_devices == NULL && iret == UUCONF_SUCCESS)
269    {
270      char ab[sizeof OLDCONFIGLIB + sizeof HDB_DEVICES - 1];
271
272      memcpy ((pointer) ab, (pointer) abHoldconfiglib,
273	      sizeof OLDCONFIGLIB - 1);
274      memcpy ((pointer) (ab + sizeof OLDCONFIGLIB - 1),
275	      (pointer) HDB_DEVICES, sizeof HDB_DEVICES);
276      iret = _uuconf_iadd_string (qglobal, ab, TRUE, FALSE,
277				  &qglobal->qprocess->pzhdb_devices,
278				  pblock);
279    }
280  if (qglobal->qprocess->pzhdb_dialers == NULL && iret == UUCONF_SUCCESS)
281    {
282      char ab[sizeof OLDCONFIGLIB + sizeof HDB_DIALERS - 1];
283
284      memcpy ((pointer) ab, (pointer) abHoldconfiglib,
285	      sizeof OLDCONFIGLIB - 1);
286      memcpy ((pointer) (ab + sizeof OLDCONFIGLIB - 1),
287	      (pointer) HDB_DIALERS, sizeof HDB_DIALERS);
288      iret = _uuconf_iadd_string (qglobal, ab, TRUE, FALSE,
289				  &qglobal->qprocess->pzhdb_dialers,
290				  pblock);
291    }
292
293  return iret;
294}
295