mkalias.c revision 1.6 1 /* $NetBSD: mkalias.c,v 1.6 1998/06/01 14:09:18 kleink 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.6 1998/06/01 14:09:18 kleink 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 <stdlib.h>
51 #include <string.h>
52 #include <unistd.h>
53
54 #include <rpc/rpc.h>
55
56 #include "protos.h"
57 #include "ypdb.h"
58 #include "ypdef.h"
59
60 void capitalize __P((char *, int));
61 int check_host __P((char *, char *, int, int, int));
62 int main __P((int, char *[]));
63 void split_address __P((char *, int, char *, char *));
64 void usage __P((void));
65
66 extern char *__progname; /* from crt0.o */
67
68 void
69 split_address(address, len, user, host)
70 char *address;
71 int len;
72 char *user, *host;
73 {
74 char *c, *s, *r;
75 int i = 0;
76
77 if ((strchr(address, '@')) != NULL) {
78
79 s = user;
80
81 for(c = address; i < len; i++) {
82 if (*c == '@') {
83 *s = '\0';
84 s = host;
85 } else
86 *s++ = *c;
87 c++;
88 }
89 *s = '\0';
90 }
91
92 if ((r = strrchr(address, '!')) != NULL) {
93
94 s = host;
95
96 for(c = address; i < len; i++) {
97 if (c == r) {
98 *s = '\0';
99 s = user;
100 } else
101 *s++ = *c;
102 c++;
103 }
104 *s = '\0';
105 }
106 }
107
108 int
109 check_host(address, host, dflag, uflag, Eflag)
110 char *address, *host;
111 int dflag, uflag, Eflag;
112 {
113 char answer[PACKETSZ];
114 int status;
115
116 if ((dflag && strchr(address, '@')) ||
117 (uflag && strchr(address, '!')))
118 return(0);
119
120 if ((_res.options & RES_INIT) == 0)
121 res_init();
122
123 status = res_search(host, C_IN, T_AAAA, answer, sizeof(answer));
124
125 if (status == -1)
126 status = res_search(host, C_IN, T_A, answer, sizeof(answer));
127
128 if ((status == -1) && Eflag)
129 status = res_search(host, C_IN, T_MX, answer, sizeof(answer));
130
131 return(status == -1);
132 }
133
134 void
135 capitalize(name, len)
136 char *name;
137 int len;
138 {
139 char last = ' ';
140 char *c;
141 int i = 0;
142
143 for(c = name; i < len; i++) {
144 if (*c == '.') last = '.';
145 c++;
146 }
147
148 i = 0;
149 if (last == '.') {
150 for(c = name; i < len; i++) {
151 if (last == '.')
152 *c = toupper(*c);
153 last = *c++;
154 }
155 }
156 }
157
158 int
159 main(argc, argv)
160 int argc;
161 char *argv[];
162 {
163 int eflag = 0;
164 int dflag = 0;
165 int nflag = 0;
166 int sflag = 0;
167 int uflag = 0;
168 int vflag = 0;
169 int Eflag = 0;
170 int ch;
171 char *input = NULL;
172 char *output = NULL;
173 DBM *db;
174 datum key, val;
175 char *slash;
176 DBM *new_db = NULL;
177 static char mapname[] = "ypdbXXXXXXXXXX";
178 char db_mapname[MAXPATHLEN], db_outfile[MAXPATHLEN],
179 db_tempname[MAXPATHLEN];
180 int status;
181 char user[4096], host[4096]; /* XXX: DB bsize = 4096 in ypdb.c */
182 char datestr[11];
183 char myname[MAXHOSTNAMELEN];
184
185 while ((ch = getopt(argc, argv, "Edensuv")) != -1) {
186 switch(ch) {
187 case 'd':
188 dflag++; /* Don't check DNS hostname */
189 break;
190
191 case 'e':
192 eflag++; /* Check hostname */
193 break;
194
195 case 'E':
196 eflag++; /* Check hostname */
197 Eflag++; /* .. even check MX records */
198 break;
199
200 case 'n':
201 nflag++; /* Capitalize name parts */
202 break;
203
204 case 's':
205 sflag++; /* Don't know... */
206 break;
207
208 case 'u':
209 uflag++; /* Don't check UUCP hostname */
210 break;
211
212 case 'v':
213 vflag++; /* Verbose */
214 break;
215
216 default:
217 usage();
218 }
219 }
220
221 if (optind == argc)
222 usage();
223
224 input = argv[optind++];
225 if (optind < argc)
226 output = argv[optind++];
227 if (optind < argc)
228 usage();
229
230 db = ypdb_open(input, O_RDONLY, 0444);
231 if (db == NULL)
232 err(1, "Unable to open input database `%s'", input);
233
234 if (output != NULL) {
235 if (strlen(output) + strlen(YPDB_SUFFIX) > MAXPATHLEN)
236 warnx("file name `%s' too long", output);
237 snprintf(db_outfile, sizeof(db_outfile),
238 "%s%s", output, YPDB_SUFFIX);
239
240 slash = strrchr(output, '/');
241 if (slash != NULL)
242 slash[1] = 0; /* truncate to dir */
243 else
244 *output = 0; /* elminate */
245
246 /* note: output is now directory where map goes ! */
247
248 if (strlen(output) + strlen(mapname)
249 + strlen(YPDB_SUFFIX) > MAXPATHLEN)
250 errx(1, "Directory name `%s' too long", output);
251
252 snprintf(db_tempname, sizeof(db_tempname), "%s%s", output,
253 mapname);
254 mktemp(db_tempname);
255 snprintf(db_mapname, sizeof(db_mapname), "%s%s", db_tempname,
256 YPDB_SUFFIX);
257
258 new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444);
259 if (new_db == NULL)
260 err(1, "Unable to open output database `%s'",
261 db_outfile);
262 }
263
264 for (key = ypdb_firstkey(db);
265 key.dptr != NULL;
266 key = ypdb_nextkey(db)) {
267
268 val = ypdb_fetch(db, key);
269
270 if (val.dptr == NULL)
271 continue; /* No value */
272 if ((*key.dptr == '@') && (key.dsize == 1))
273 continue; /* Sendmail token */
274 if (strncmp(key.dptr, "YP_", 3)==0) /* YP token */
275 continue;
276 if (strchr(val.dptr, ',')) /* List... */
277 continue;
278 if (strchr(val.dptr, '|')) /* Pipe... */
279 continue;
280
281 if (!((strchr(val.dptr, '@')) ||
282 (strchr(val.dptr, '!'))))
283 continue; /* Skip local users */
284
285 split_address(val.dptr, val.dsize, user, host);
286
287 if (eflag && check_host(val.dptr, host, dflag, uflag, Eflag)) {
288 printf("Invalid host %s in %*.*s:%*.*s\n", host,
289 key.dsize, key.dsize, key.dptr,
290 val.dsize, val.dsize, val.dptr);
291 continue;
292 }
293
294 if (nflag)
295 capitalize(key.dptr, key.dsize);
296
297 if (new_db != NULL) {
298 status = ypdb_store(new_db, val, key, YPDB_INSERT);
299 if (status != 0) {
300 printf("%s: problem storing %*.*s %*.*s\n",
301 __progname,
302 val.dsize, val.dsize, val.dptr,
303 key.dsize, key.dsize, key.dptr);
304 }
305 }
306
307 if (vflag) {
308 printf("%*.*s --> %*.*s\n",
309 val.dsize, val.dsize, val.dptr,
310 key.dsize, key.dsize, key.dptr);
311 }
312
313 }
314
315 if (new_db != NULL) {
316 sprintf(datestr, "%010d", (int)time(NULL));
317 key.dptr = YP_LAST_KEY;
318 key.dsize = strlen(YP_LAST_KEY);
319 val.dptr = datestr;
320 val.dsize = strlen(datestr);
321 status = ypdb_store(new_db, key, val, YPDB_INSERT);
322 if (status != 0)
323 warnx("problem storing %*.*s %*.*s",
324 key.dsize, key.dsize, key.dptr,
325 val.dsize, val.dsize, val.dptr);
326 }
327
328 if (new_db != NULL) {
329 localhostname(myname, sizeof(myname) - 1);
330 key.dptr = YP_MASTER_KEY;
331 key.dsize = strlen(YP_MASTER_KEY);
332 val.dptr = myname;
333 val.dsize = strlen(myname);
334 status = ypdb_store(new_db, key, val, YPDB_INSERT);
335 if (status != 0)
336 warnx("problem storing %*.*s %*.*s",
337 key.dsize, key.dsize, key.dptr,
338 val.dsize, val.dsize, val.dptr);
339 }
340
341 ypdb_close(db);
342
343 if (new_db != NULL) {
344 ypdb_close(new_db);
345 if (rename(db_mapname, db_outfile) < 0)
346 err(1, "rename `%s' to `%s' failed", db_mapname,
347 db_outfile);
348 }
349
350 exit(0);
351 }
352
353 void
354 usage()
355 {
356 fprintf(stderr,
357 "usage: %s [-e|-E [-d] [-u]] [-n] [-v] input [output]\n",
358 __progname);
359 exit(1);
360 }
361