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