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