mk-amd-map.c revision 38494
1/*
2 * Copyright (c) 1997-1998 Erez Zadok
3 * Copyright (c) 1990 Jan-Simon Pendry
4 * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
5 * Copyright (c) 1990 The Regents of the University of California.
6 * All rights reserved.
7 *
8 * This code is derived from software contributed to Berkeley by
9 * Jan-Simon Pendry at Imperial College, London.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 * 3. All advertising materials mentioning features or use of this software
20 *    must display the following acknowledgement:
21 *      This product includes software developed by the University of
22 *      California, Berkeley and its contributors.
23 * 4. Neither the name of the University nor the names of its contributors
24 *    may be used to endorse or promote products derived from this software
25 *    without specific prior written permission.
26 *
27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
30 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 * SUCH DAMAGE.
38 *
39 *      %W% (Berkeley) %G%
40 *
41 * $Id: mk-amd-map.c,v 5.2.2.1 1992/02/09 15:09:18 jsp beta $
42 */
43
44/*
45 * Convert a file map into an ndbm map
46 */
47
48#ifdef HAVE_CONFIG_H
49# include <config.h>
50#endif /* HAVE_CONFIG_H */
51#include <am_defs.h>
52
53/* dummy variables */
54char *progname;
55char hostname[MAXHOSTNAMELEN];
56int orig_umask, foreground, debug_flags;
57pid_t mypid;
58serv_state amd_state;
59
60
61#ifdef HAVE_MAP_NDBM
62
63static int
64store_data(voidp db, char *k, char *v)
65{
66  datum key, val;
67
68  key.dptr = k;
69  val.dptr = v;
70  key.dsize = strlen(k) + 1;
71  val.dsize = strlen(v) + 1;
72  return dbm_store((DBM *) db, key, val, DBM_INSERT);
73}
74
75
76/*
77 * Read one line from file.
78 */
79static int
80read_line(char *buf, int size, FILE *fp)
81{
82  int done = 0;
83
84  do {
85    while (fgets(buf, size, fp)) {
86      int len = strlen(buf);
87
88      done += len;
89      if (len > 1 && buf[len - 2] == '\\' && buf[len - 1] == '\n') {
90	int ch;
91	buf += len - 2;
92	size -= len - 2;
93	*buf = '\n';
94	buf[1] = '\0';
95
96	/*
97	 * Skip leading white space on next line
98	 */
99	while ((ch = getc(fp)) != EOF && isascii(ch) && isspace(ch)) ;
100	(void) ungetc(ch, fp);
101      } else {
102	return done;
103      }
104    }
105  } while (size > 0 && !feof(fp));
106
107  return done;
108}
109
110
111/*
112 * Read through a map.
113 */
114static int
115read_file(FILE *fp, char *map, voidp db)
116{
117  char key_val[2048];
118  int chuck = 0;
119  int line_no = 0;
120  int errs = 0;
121
122  while (read_line(key_val, sizeof(key_val), fp)) {
123    char *kp;
124    char *cp;
125    char *hash;
126    int len = strlen(key_val);
127
128    line_no++;
129
130    /*
131     * Make sure we got the whole line
132     */
133    if (key_val[len - 1] != '\n') {
134      fprintf(stderr, "line %d in \"%s\" is too long", line_no, map);
135      chuck = 1;
136    } else {
137      key_val[len - 1] = '\0';
138    }
139
140    /*
141     * Strip comments
142     */
143    hash = strchr(key_val, '#');
144    if (hash)
145      *hash = '\0';
146
147    /*
148     * Find start of key
149     */
150    for (kp = key_val; *kp && isascii(*kp) && isspace((int)*kp); kp++) ;
151
152    /*
153     * Ignore blank lines
154     */
155    if (!*kp)
156      goto again;
157
158    /*
159     * Find end of key
160     */
161    for (cp = kp; *cp && (!isascii(*cp) || !isspace((int)*cp)); cp++) ;
162
163    /*
164     * Check whether key matches, or whether
165     * the entry is a wildcard entry.
166     */
167    if (*cp)
168      *cp++ = '\0';
169    while (*cp && isascii(*cp) && isspace((int)*cp))
170      cp++;
171    if (*kp == '+') {
172      fprintf(stderr, "Can't interpolate %s\n", kp);
173      errs++;
174    } else if (*cp) {
175      if (db) {
176	if (store_data(db, kp, cp) < 0) {
177	  fprintf(stderr, "Could store %s -> %s\n", kp, cp);
178	  errs++;
179	}
180      } else {
181	printf("%s\t%s\n", kp, cp);
182      }
183    } else {
184      fprintf(stderr, "%s: line %d has no value field", map, line_no);
185      errs++;
186    }
187
188  again:
189    /*
190     * If the last read didn't get a whole line then
191     * throw away the remainder before continuing...
192     */
193    if (chuck) {
194      while (fgets(key_val, sizeof(key_val), fp) &&
195	     !strchr(key_val, '\n')) ;
196      chuck = 0;
197    }
198  }
199  return errs;
200}
201
202
203static int
204remove_file(char *f)
205{
206  if (unlink(f) < 0 && errno != ENOENT)
207    return -1;
208
209  return 0;
210}
211
212
213int
214main(int argc, char *argv[])
215{
216  FILE *mapf;
217  int mapfd = -1;
218  char *map;
219  int rc = 0;
220  DBM *mapd = NULL;
221  static char maptmp[] = "dbmXXXXXX";
222  char maptpag[16], maptdir[16];
223  char *mappag = (char *) NULL, *mapdir = (char *) NULL;
224  int len;
225  char *sl;
226  int printit = 0;
227  int usage = 0;
228  int ch;
229  extern int optind;
230
231  /* test options */
232  while ((ch = getopt(argc, argv, "p")) != EOF)
233    switch (ch) {
234    case 'p':
235      printit = 1;
236      break;
237    default:
238      usage++;
239      break;
240    }
241
242  if (usage || optind != (argc - 1)) {
243    fputs("Usage: mk-amd-map [-p] file-map\n", stderr);
244    exit(1);
245  }
246  map = argv[optind];
247
248  /* test if can get to the map directory */
249  sl = strrchr(map, '/');
250  if (sl) {
251    *sl = '\0';
252    if (chdir(map) < 0) {
253      fputs("Can't chdir to ", stderr);
254      perror(map);
255      exit(1);
256    }
257    map = sl + 1;
258  }
259
260  if (!printit) {
261    len = strlen(map);
262    mappag = (char *) malloc(len + 5);
263    mapdir = (char *) malloc(len + 5);
264    if (!mappag || !mapdir) {
265      perror("mk-amd-map: malloc");
266      exit(1);
267    }
268#ifdef HAVE_MKSTEMP
269    mapfd = mkstemp(maptmp);
270#else /* not HAVE_MKSTEMP */
271    map = mktemp(maptmp);
272    if (!maptmp) {
273      fprintf(stderr, "cannot create temporary file\n");
274      exit(1);
275    }
276    mapfd = open(map, O_RDONLY);
277#endif /* not HAVE_MKSTEMP */
278
279    /* open DBM files */
280    sprintf(maptpag, "%s.pag", maptmp);
281    sprintf(maptdir, "%s.dir", maptmp);
282    if (remove_file(maptpag) < 0 || remove_file(maptdir) < 0) {
283      fprintf(stderr, "Can't remove existing temporary files; %s and", maptpag);
284      perror(maptdir);
285      exit(1);
286    }
287  }
288  /* open and check if map file was opened OK */
289  mapf = fdopen(mapfd, "r");
290  if (mapf && !printit)
291    mapd = dbm_open(maptmp, O_RDWR|O_CREAT, 0444);
292  else
293    mapd = 0;
294
295#ifndef DEBUG
296  /* ignore ^C if debuggung is on (but why?) */
297  signal(SIGINT, SIG_IGN);
298#endif /* not DEBUG */
299
300  if (mapd || printit) {
301    int error = read_file(mapf, map, mapd);
302    (void) close(mapfd);
303    (void) fclose(mapf);
304    if (printit) {
305      if (error) {
306	fprintf(stderr, "Error creating ndbm map for %s\n", map);
307	rc = 1;
308      }
309    } else {
310
311      if (error) {
312	fprintf(stderr, "Error reading source file  %s\n", map);
313	rc = 1;
314      } else {
315	sprintf(mappag, "%s.pag", map);
316	sprintf(mapdir, "%s.dir", map);
317	if (rename(maptpag, mappag) < 0) {
318	  fprintf(stderr, "Couldn't rename %s to ", maptpag);
319	  perror(mappag);
320	  /* Throw away the temporary map */
321	  unlink(maptpag);
322	  unlink(maptdir);
323	  rc = 1;
324
325	} else if (rename(maptdir, mapdir) < 0) {
326	  fprintf(stderr, "Couldn't rename %s to ", maptdir);
327	  perror(mapdir);
328	  /* Put the .pag file back */
329	  rename(mappag, maptpag);
330	  /* Throw away remaining part of original map */
331	  unlink(mapdir);
332	  fprintf(stderr,
333		  "WARNING: existing map \"%s.{dir,pag}\" destroyed\n",
334		  map);
335	  rc = 1;
336	}
337      }
338    }
339
340  } else {
341    fprintf(stderr, "Can't open \"%s.{dir,pag}\" for ", map);
342    perror("writing");
343    rc = 1;
344  }
345  exit(rc);
346}
347
348#else /* not HAVE_MAP_NDBM */
349
350main()
351{
352  fputs("mk-amd-map: This system does not support hashed database files\n", stderr);
353  exit(1);
354}
355
356#endif /* not HAVE_MAP_NDBM */
357