mkalias.c revision 1.5 1 /* $NetBSD: mkalias.c,v 1.5 1997/11/04 11:43:49 lukem Exp $ */
2
3 /*
4 * Copyright (c) 1997 Mats O Jansson <moj (at) stacken.kth.se>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 * must display the following acknowledgement:
17 * This product includes software developed by Mats O Jansson
18 * 4. The name of the author may not be used to endorse or promote products
19 * derived from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
22 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
25 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34 #include <sys/cdefs.h>
35 #ifndef lint
36 __RCSID("$NetBSD: mkalias.c,v 1.5 1997/11/04 11:43:49 lukem Exp $");
37 #endif
38
39 #include <sys/types.h>
40 #include <sys/param.h>
41 #include <netinet/in.h>
42 #include <arpa/nameser.h>
43
44 #include <ctype.h>
45 #include <err.h>
46 #include <fcntl.h>
47 #include <netdb.h>
48 #include <resolv.h>
49 #include <stdio.h>
50 #include <string.h>
51 #include <unistd.h>
52
53 #include <rpc/rpc.h>
54
55 #include "protos.h"
56 #include "ypdb.h"
57 #include "ypdef.h"
58
59 void capitalize __P((char *, int));
60 int check_host __P((char *, char *, int, int, int));
61 int main __P((int, char *[]));
62 void split_address __P((char *, int, char *, char *));
63 void usage __P((void));
64
65 extern char *__progname; /* from crt0.o */
66
67 void
68 split_address(address, len, user, host)
69 char *address;
70 int len;
71 char *user, *host;
72 {
73 char *c, *s, *r;
74 int i = 0;
75
76 if ((strchr(address, '@')) != NULL) {
77
78 s = user;
79
80 for(c = address; i < len; i++) {
81 if (*c == '@') {
82 *s = '\0';
83 s = host;
84 } else
85 *s++ = *c;
86 c++;
87 }
88 *s = '\0';
89 }
90
91 if ((r = strrchr(address, '!')) != NULL) {
92
93 s = host;
94
95 for(c = address; i < len; i++) {
96 if (c == r) {
97 *s = '\0';
98 s = user;
99 } else
100 *s++ = *c;
101 c++;
102 }
103 *s = '\0';
104 }
105 }
106
107 int
108 check_host(address, host, dflag, uflag, Eflag)
109 char *address, *host;
110 int dflag, uflag, Eflag;
111 {
112 char answer[PACKETSZ];
113 int status;
114
115 if ((dflag && strchr(address, '@')) ||
116 (uflag && strchr(address, '!')))
117 return(0);
118
119 if ((_res.options & RES_INIT) == 0)
120 res_init();
121
122 status = res_search(host, C_IN, T_AAAA, answer, sizeof(answer));
123
124 if (status == -1)
125 status = res_search(host, C_IN, T_A, answer, sizeof(answer));
126
127 if ((status == -1) && Eflag)
128 status = res_search(host, C_IN, T_MX, answer, sizeof(answer));
129
130 return(status == -1);
131 }
132
133 void
134 capitalize(name, len)
135 char *name;
136 int len;
137 {
138 char last = ' ';
139 char *c;
140 int i = 0;
141
142 for(c = name; i < len; i++) {
143 if (*c == '.') last = '.';
144 c++;
145 }
146
147 i = 0;
148 if (last == '.') {
149 for(c = name; i < len; i++) {
150 if (last == '.')
151 *c = toupper(*c);
152 last = *c++;
153 }
154 }
155 }
156
157 int
158 main(argc, argv)
159 int argc;
160 char *argv[];
161 {
162 int eflag = 0;
163 int dflag = 0;
164 int nflag = 0;
165 int sflag = 0;
166 int uflag = 0;
167 int vflag = 0;
168 int Eflag = 0;
169 int ch;
170 char *input = NULL;
171 char *output = NULL;
172 DBM *db;
173 datum key, val;
174 char *slash;
175 DBM *new_db = NULL;
176 static char mapname[] = "ypdbXXXXXXXXXX";
177 char db_mapname[MAXPATHLEN], db_outfile[MAXPATHLEN],
178 db_tempname[MAXPATHLEN];
179 int status;
180 char user[4096], host[4096]; /* XXX: DB bsize = 4096 in ypdb.c */
181 char datestr[11];
182 char myname[MAXHOSTNAMELEN];
183
184 while ((ch = getopt(argc, argv, "Edensuv")) != -1) {
185 switch(ch) {
186 case 'd':
187 dflag++; /* Don't check DNS hostname */
188 break;
189
190 case 'e':
191 eflag++; /* Check hostname */
192 break;
193
194 case 'E':
195 eflag++; /* Check hostname */
196 Eflag++; /* .. even check MX records */
197 break;
198
199 case 'n':
200 nflag++; /* Capitalize name parts */
201 break;
202
203 case 's':
204 sflag++; /* Don't know... */
205 break;
206
207 case 'u':
208 uflag++; /* Don't check UUCP hostname */
209 break;
210
211 case 'v':
212 vflag++; /* Verbose */
213 break;
214
215 default:
216 usage();
217 }
218 }
219
220 if (optind == argc)
221 usage();
222
223 input = argv[optind++];
224 if (optind < argc)
225 output = argv[optind++];
226 if (optind < argc)
227 usage();
228
229 db = ypdb_open(input, O_RDONLY, 0444);
230 if (db == NULL)
231 err(1, "Unable to open input database `%s'", input);
232
233 if (output != NULL) {
234 if (strlen(output) + strlen(YPDB_SUFFIX) > MAXPATHLEN)
235 warnx("file name `%s' too long", output);
236 snprintf(db_outfile, sizeof(db_outfile),
237 "%s%s", output, YPDB_SUFFIX);
238
239 slash = strrchr(output, '/');
240 if (slash != NULL)
241 slash[1] = 0; /* truncate to dir */
242 else
243 *output = 0; /* elminate */
244
245 /* note: output is now directory where map goes ! */
246
247 if (strlen(output) + strlen(mapname)
248 + strlen(YPDB_SUFFIX) > MAXPATHLEN)
249 errx(1, "Directory name `%s' too long", output);
250
251 snprintf(db_tempname, sizeof(db_tempname), "%s%s", output,
252 mapname);
253 mktemp(db_tempname);
254 snprintf(db_mapname, sizeof(db_mapname), "%s%s", db_tempname,
255 YPDB_SUFFIX);
256
257 new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444);
258 if (new_db == NULL)
259 err(1, "Unable to open output database `%s'",
260 db_outfile);
261 }
262
263 for (key = ypdb_firstkey(db);
264 key.dptr != NULL;
265 key = ypdb_nextkey(db)) {
266
267 val = ypdb_fetch(db, key);
268
269 if (val.dptr == NULL)
270 continue; /* No value */
271 if ((*key.dptr == '@') && (key.dsize == 1))
272 continue; /* Sendmail token */
273 if (strncmp(key.dptr, "YP_", 3)==0) /* YP token */
274 continue;
275 if (strchr(val.dptr, ',')) /* List... */
276 continue;
277 if (strchr(val.dptr, '|')) /* Pipe... */
278 continue;
279
280 if (!((strchr(val.dptr, '@')) ||
281 (strchr(val.dptr, '!'))))
282 continue; /* Skip local users */
283
284 split_address(val.dptr, val.dsize, user, host);
285
286 if (eflag && check_host(val.dptr, host, dflag, uflag, Eflag)) {
287 printf("Invalid host %s in %*.*s:%*.*s\n", host,
288 key.dsize, key.dsize, key.dptr,
289 val.dsize, val.dsize, val.dptr);
290 continue;
291 }
292
293 if (nflag)
294 capitalize(key.dptr, key.dsize);
295
296 if (new_db != NULL) {
297 status = ypdb_store(new_db, val, key, YPDB_INSERT);
298 if (status != 0) {
299 printf("%s: problem storing %*.*s %*.*s\n",
300 __progname,
301 val.dsize, val.dsize, val.dptr,
302 key.dsize, key.dsize, key.dptr);
303 }
304 }
305
306 if (vflag) {
307 printf("%*.*s --> %*.*s\n",
308 val.dsize, val.dsize, val.dptr,
309 key.dsize, key.dsize, key.dptr);
310 }
311
312 }
313
314 if (new_db != NULL) {
315 sprintf(datestr, "%010d", (int)time(NULL));
316 key.dptr = YP_LAST_KEY;
317 key.dsize = strlen(YP_LAST_KEY);
318 val.dptr = datestr;
319 val.dsize = strlen(datestr);
320 status = ypdb_store(new_db, key, val, YPDB_INSERT);
321 if (status != 0)
322 warnx("problem storing %*.*s %*.*s",
323 key.dsize, key.dsize, key.dptr,
324 val.dsize, val.dsize, val.dptr);
325 }
326
327 if (new_db != NULL) {
328 localhostname(myname, sizeof(myname) - 1);
329 key.dptr = YP_MASTER_KEY;
330 key.dsize = strlen(YP_MASTER_KEY);
331 val.dptr = myname;
332 val.dsize = strlen(myname);
333 status = ypdb_store(new_db, key, val, YPDB_INSERT);
334 if (status != 0)
335 warnx("problem storing %*.*s %*.*s",
336 key.dsize, key.dsize, key.dptr,
337 val.dsize, val.dsize, val.dptr);
338 }
339
340 ypdb_close(db);
341
342 if (new_db != NULL) {
343 ypdb_close(new_db);
344 if (rename(db_mapname, db_outfile) < 0)
345 err(1, "rename `%s' to `%s' failed", db_mapname,
346 db_outfile);
347 }
348
349 exit(0);
350 }
351
352 void
353 usage()
354 {
355 fprintf(stderr,
356 "usage: %s [-e|-E [-d] [-u]] [-n] [-v] input [output]\n",
357 __progname);
358 exit(1);
359 }
360