1 /* $NetBSD: services_mkdb.c,v 1.18 2010/10/07 01:28:50 christos Exp $ */
4 * Copyright (c) 1999 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Luke Mewburn and Christos Zoulas.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
32 #include <sys/cdefs.h>
34 __RCSID("$NetBSD: services_mkdb.c,v 1.18 2010/10/07 01:28:50 christos Exp $");
37 #include <sys/param.h>
50 #include <stringlist.h>
54 static char tname
[MAXPATHLEN
];
59 static StringList
***parseservices(const char *, StringList
*);
60 static void cleanup(void);
61 static char *getstring(const char *, size_t, char **, const char *);
62 static size_t getprotoindex(StringList
*, const char *);
63 static const char *getprotostr(StringList
*, size_t);
64 static void usage(void) __dead
;
67 main(int argc
, char *argv
[])
70 const char *fname
= _PATH_SERVICES
;
71 const char *dbname
= NULL
;
77 StringList
*sl
, ***svc
;
79 void (*addfn
)(StringList
*, size_t, const char *, size_t *, int);
84 while ((ch
= getopt(argc
, argv
, "o:quV:v")) != -1)
98 if (strcmp(optarg
, "db") == 0)
100 else if (strcmp(optarg
, "cdb") == 0)
116 if (argc
> 1 || (unique
&& otherflag
))
125 dbname
= use_db
? _PATH_SERVICES_DB
: _PATH_SERVICES_CDB
;
127 svc
= parseservices(fname
, sl
= sl_init());
130 err(1, "Cannot install exit handler");
132 (void)snprintf(tname
, sizeof(tname
), "%s.tmp", dbname
);
136 err(1, "Error opening temporary database `%s'", tname
);
141 err(1, "Error opening temporary database `%s'", tname
);
146 for (port
= 0; port
< PMASK
+ 1; port
++) {
147 if (svc
[port
] == NULL
)
150 for (proto
= 0; proto
< PROTOMAX
; proto
++) {
152 if ((s
= svc
[port
][proto
]) == NULL
)
154 (addfn
)(s
, port
, getprotostr(sl
, proto
), &cnt
, warndup
);
164 err(1, "Error writing temporary database `%s'", tname
);
166 if (rename(tname
, dbname
) == -1)
167 err(1, "Cannot rename `%s' to `%s'", tname
, dbname
);
172 static StringList
***
173 parseservices(const char *fname
, StringList
*sl
)
175 size_t len
, line
, pindex
;
177 StringList
***svc
, *s
;
180 if ((fp
= fopen(fname
, "r")) == NULL
)
181 err(1, "Cannot open `%s'", fname
);
184 svc
= ecalloc(PMASK
+ 1, sizeof(StringList
**));
186 /* XXX: change NULL to "\0\0#" when fparseln fixed */
187 for (; (p
= fparseln(fp
, &len
, &line
, NULL
, 0)) != NULL
; free(p
)) {
188 char *name
, *port
, *proto
, *aliases
, *cp
, *alias
;
194 for (cp
= p
; *cp
&& isspace((unsigned char)*cp
); cp
++)
197 if (*cp
== '\0' || *cp
== '#')
200 if ((name
= getstring(fname
, line
, &cp
, "name")) == NULL
)
203 if ((port
= getstring(fname
, line
, &cp
, "port")) == NULL
)
207 for (aliases
= cp
; *cp
&& *cp
!= '#'; cp
++)
215 proto
= strchr(port
, '/');
216 if (proto
== NULL
|| proto
[1] == '\0') {
217 warnx("%s, %zu: no protocol found", fname
, line
);
223 pnum
= strtoul(port
, &ep
, 0);
224 if (*port
== '\0' || *ep
!= '\0') {
225 warnx("%s, %zu: invalid port `%s'", fname
, line
, port
);
228 if ((errno
== ERANGE
&& pnum
== ULONG_MAX
) || pnum
> PMASK
) {
229 warnx("%s, %zu: port too big `%s'", fname
, line
, port
);
233 if (svc
[pnum
] == NULL
)
234 svc
[pnum
] = ecalloc(PROTOMAX
, sizeof(StringList
*));
236 pindex
= getprotoindex(sl
, proto
);
237 if (svc
[pnum
][pindex
] == NULL
)
238 s
= svc
[pnum
][pindex
] = sl_init();
240 s
= svc
[pnum
][pindex
];
242 if (strlen(name
) > 255) {
243 warnx("%s, %zu: invalid name too long `%s'", fname
,
248 /* build list of aliases */
249 if (sl_find(s
, name
) == NULL
)
250 (void)sl_add(s
, estrdup(name
));
253 while ((alias
= strsep(&aliases
, " \t")) != NULL
) {
254 if (alias
[0] == '\0')
256 if (strlen(alias
) > 255) {
257 warnx("%s, %zu: alias name too long `%s'",
261 if (sl_find(s
, alias
) == NULL
)
262 (void)sl_add(s
, estrdup(alias
));
271 * cleanup(): Remove temporary files upon exit
281 getstring(const char *fname
, size_t line
, char **cp
, const char *tag
)
285 while ((str
= strsep(cp
, " \t")) != NULL
&& *str
== '\0')
289 warnx("%s, %zu: no %s found", fname
, line
, tag
);
295 getprotoindex(StringList
*sl
, const char *str
)
299 for (i
= 0; i
< sl
->sl_cur
; i
++)
300 if (strcmp(sl
->sl_str
[i
], str
) == 0)
304 errx(1, "Ran out of protocols adding `%s';"
305 " recompile with larger PROTOMAX", str
);
306 (void)sl_add(sl
, estrdup(str
));
311 getprotostr(StringList
*sl
, size_t i
)
313 assert(i
< sl
->sl_cur
);
314 return sl
->sl_str
[i
];
320 (void)fprintf(stderr
, "Usage:\t%s [-q] [-o <db>] [-V cdb|db] [<servicefile>]\n"
321 "\t%s -u [<servicefile>]\n", getprogname(), getprogname());