services_mkdb.c revision 1.1 1 /* $NetBSD: services_mkdb.c,v 1.1 1999/02/08 03:57:05 lukem Exp $ */
2
3 /*-
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Luke Mewburn.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #include <sys/cdefs.h>
40 #ifndef lint
41 __RCSID("$NetBSD: services_mkdb.c,v 1.1 1999/02/08 03:57:05 lukem Exp $");
42 #endif /* not lint */
43
44
45 #include <sys/param.h>
46
47 #include <db.h>
48 #include <err.h>
49 #include <fcntl.h>
50 #include <netdb.h>
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <unistd.h>
55 #include <util.h>
56
57 #ifndef _PATH_SERVICES_DB
58 #define _PATH_SERVICES_DB "/etc/services.db";
59 #endif
60
61 static char *dbname = _PATH_SERVICES_DB;
62
63 void cleanup __P((void));
64 int main __P((int, char *[]));
65 void usage __P((void));
66
67 int
68 main(argc, argv)
69 int argc;
70 char *argv[];
71 {
72 DB *db;
73 FILE *fp;
74 int ch, len, line;
75 char tname[MAXPATHLEN], *p;
76 char keyb[BUFSIZ], datab[BUFSIZ];
77 char *fname = _PATH_SERVICES;
78 DBT data, key;
79
80 while ((ch = getopt(argc, argv, "o:")) != -1)
81 switch (ch) {
82 case 'o':
83 dbname = optarg;
84 break;
85 case '?':
86 default:
87 usage();
88 }
89
90 argc -= optind;
91 argv += optind;
92
93 if (argc == 1)
94 fname = argv[0];
95 else if (argc > 1)
96 usage();
97 if ((fp = fopen(fname, "r")) == NULL)
98 err(1, "Cannot open `%s'", fname);
99 if (atexit(cleanup))
100 err(1, "Cannot install exit handler");
101 (void) snprintf(tname, sizeof(tname), "%s.tmp", dbname);
102 db = dbopen(tname, O_RDWR | O_CREAT | O_EXCL,
103 (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH), DB_HASH, NULL);
104 if (!db)
105 err(1, "Error opening temporary database `%s'", tname);
106
107 key.data = (u_char *)keyb;
108 data.data = (u_char *)datab;
109
110 /* XXX: change NULL to "\0\0#" when fparseln fixed */
111 for (; (p = fparseln(fp, &len, &line, NULL, 0)) != NULL; free(p)) {
112 char *name, *port, *proto, *aliases, *cp;
113 #define MAXALIASES 35
114 char *aliasv[MAXALIASES];
115 int aliasc, i;
116
117 if (len == 0)
118 continue;
119 cp = p;
120 while ((name = strsep(&cp, " \t")) != NULL && *name == '\0')
121 ;
122 if (name == NULL) {
123 warnx("%s line %d: no name found", fname, line);
124 continue;
125 }
126 while ((port = strsep(&cp, " \t")) != NULL && *port == '\0')
127 ;
128 if (port == NULL) {
129 warnx("%s line %d: no port found", fname, line);
130 continue;
131 }
132 proto = strchr(port, '/');
133 if (proto == NULL || proto[1] == '\0') {
134 warnx("%s line %d: no protocol found", fname, line);
135 continue;
136 }
137 *proto++ = '\0';
138 while ((aliases = strsep(&cp, " \t")) != NULL &&
139 *aliases == '\0')
140 ;
141
142 /* key `port/proto', data = full line */
143 key.size = snprintf(keyb, sizeof(keyb), "%s/%s",
144 port, proto) + 1;
145 data.size = snprintf(datab, sizeof(datab), "%s %s/%s %s",
146 name, port, proto, aliases == NULL ? "" : aliases) + 1;
147 switch ((db->put)(db, &key, &data, R_NOOVERWRITE)) {
148 case 0:
149 break;
150 case 1:
151 warnx("%s line %d: duplicate service `%s'",
152 fname, line, keyb);
153 break;
154 case -1:
155 err(1, "put");
156 break;
157 default:
158 abort();
159 break;
160 }
161
162 /* key `port/.', data = full line */
163 key.size = snprintf(keyb, sizeof(keyb), "%s/.", port) + 1;
164 if ((db->put)(db, &key, &data, R_NOOVERWRITE) == -1)
165 err(1, "put");
166
167
168 /* build list of aliases */
169 cp = aliases;
170 aliasv[0] = name;
171 for (aliasc = 1;
172 (aliasv[aliasc] = strsep(&cp, " \t")) != NULL;) {
173 if (aliasv[aliasc][0] == '\0')
174 continue;
175 if (++aliasc > MAXALIASES)
176 break;
177 }
178 aliasv[aliasc] = NULL;
179
180 /* add references for service and all aliases */
181 for (i = 0; i < aliasc; i++) {
182
183 /* key `service/proto', data = `.port/proto' */
184 key.size = snprintf(keyb, sizeof(keyb), "%s/%s",
185 aliasv[i], proto) + 1;
186 data.size = snprintf(datab, sizeof(datab), ".%s/%s",
187 port, proto) + 1;
188 switch ((db->put)(db, &key, &data, R_NOOVERWRITE)) {
189 case 0:
190 break;
191 case 1:
192 warnx("%s line %d: duplicate service `%s'",
193 fname, line, keyb);
194 break;
195 case -1:
196 err(1, "put");
197 break;
198 default:
199 abort();
200 break;
201 }
202
203 /* key `service/.', data = `.port/.' */
204 key.size = snprintf(keyb, sizeof(keyb), "%s/.",
205 aliasv[i]) + 1;
206 data.size = snprintf(datab, sizeof(datab), ".%s/.",
207 port) + 1;
208 if ((db->put)(db, &key, &data, R_NOOVERWRITE) == -1)
209 err(1, "put");
210 }
211 }
212
213 if ((db->close)(db))
214 err(1, "Error closing temporary database `%s'", tname);
215 if (rename(tname, dbname) == -1)
216 err(1, "Cannot rename `%s' to `%s'", tname, dbname);
217
218 return (0);
219 }
220
221 /*
222 * cleanup(): Remove temporary files upon exit
223 */
224 void
225 cleanup()
226 {
227 char tname[MAXPATHLEN];
228 (void) snprintf(tname, sizeof(tname), "%s.tmp", dbname);
229 (void) unlink(tname);
230 }
231
232 void
233 usage()
234 {
235 extern const char *__progname;
236
237 fprintf(stderr, "usage: %s [-o db]\n", __progname);
238 exit(1);
239 }
240