1 /* $NetBSD: mkalias.c,v 1.10 2002/07/06 21:31:55 wiz Exp $ */ 2 3 /* 4 * Copyright (c) 1997 Mats O Jansson <moj@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.10 2002/07/06 21:31:55 wiz 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(*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) > MAXPATHLEN) 226 warnx("file name `%s' too long", output); 227 snprintf(db_outfile, sizeof(db_outfile), 228 "%s%s", output, YPDB_SUFFIX); 229 230 slash = strrchr(output, '/'); 231 if (slash != NULL) 232 slash[1] = 0; /* truncate to dir */ 233 else 234 *output = 0; /* elminate */ 235 236 /* note: output is now directory where map goes ! */ 237 238 if (strlen(output) + strlen(mapname) 239 + strlen(YPDB_SUFFIX) > MAXPATHLEN) 240 errx(1, "Directory name `%s' too long", output); 241 242 snprintf(db_tempname, sizeof(db_tempname), "%s%s", output, 243 mapname); 244 mktemp(db_tempname); /* OK */ 245 snprintf(db_mapname, sizeof(db_mapname), "%s%s", db_tempname, 246 YPDB_SUFFIX); 247 248 new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444); 249 if (new_db == NULL) 250 err(1, "Unable to open output database `%s'", 251 db_outfile); 252 } 253 254 for (key = ypdb_firstkey(db); 255 key.dptr != NULL; 256 key = ypdb_nextkey(db)) { 257 258 val = ypdb_fetch(db, key); 259 260 if (val.dptr == NULL) 261 continue; /* No value */ 262 if ((*key.dptr == '@') && (key.dsize == 1)) 263 continue; /* Sendmail token */ 264 if (strncmp(key.dptr, "YP_", 3)==0) /* YP token */ 265 continue; 266 if (strchr(val.dptr, ',')) /* List... */ 267 continue; 268 if (strchr(val.dptr, '|')) /* Pipe... */ 269 continue; 270 271 if (!((strchr(val.dptr, '@')) || 272 (strchr(val.dptr, '!')))) 273 continue; /* Skip local users */ 274 275 split_address(val.dptr, val.dsize, user, host); 276 277 if (eflag && check_host(val.dptr, host, dflag, uflag, Eflag)) { 278 printf("Invalid host %s in %*.*s:%*.*s\n", host, 279 key.dsize, key.dsize, key.dptr, 280 val.dsize, val.dsize, val.dptr); 281 continue; 282 } 283 284 if (nflag) 285 capitalize(key.dptr, key.dsize); 286 287 if (new_db != NULL) { 288 status = ypdb_store(new_db, val, key, YPDB_INSERT); 289 if (status != 0) { 290 printf("%s: problem storing %*.*s %*.*s\n", 291 getprogname(), 292 val.dsize, val.dsize, val.dptr, 293 key.dsize, key.dsize, key.dptr); 294 } 295 } 296 297 if (vflag) { 298 printf("%*.*s --> %*.*s\n", 299 val.dsize, val.dsize, val.dptr, 300 key.dsize, key.dsize, key.dptr); 301 } 302 303 } 304 305 if (new_db != NULL) { 306 sprintf(datestr, "%010d", (int)time(NULL)); 307 key.dptr = YP_LAST_KEY; 308 key.dsize = strlen(YP_LAST_KEY); 309 val.dptr = datestr; 310 val.dsize = strlen(datestr); 311 status = ypdb_store(new_db, key, val, YPDB_INSERT); 312 if (status != 0) 313 warnx("problem storing %*.*s %*.*s", 314 key.dsize, key.dsize, key.dptr, 315 val.dsize, val.dsize, val.dptr); 316 } 317 318 if (new_db != NULL) { 319 localhostname(myname, sizeof(myname) - 1); 320 key.dptr = YP_MASTER_KEY; 321 key.dsize = strlen(YP_MASTER_KEY); 322 val.dptr = myname; 323 val.dsize = strlen(myname); 324 status = ypdb_store(new_db, key, val, YPDB_INSERT); 325 if (status != 0) 326 warnx("problem storing %*.*s %*.*s", 327 key.dsize, key.dsize, key.dptr, 328 val.dsize, val.dsize, val.dptr); 329 } 330 331 ypdb_close(db); 332 333 if (new_db != NULL) { 334 ypdb_close(new_db); 335 if (rename(db_mapname, db_outfile) < 0) 336 err(1, "rename `%s' to `%s' failed", db_mapname, 337 db_outfile); 338 } 339 340 exit(0); 341 } 342 343 void 344 usage(void) 345 { 346 fprintf(stderr, 347 "usage: %s [-e|-E [-d] [-u]] [-n] [-v] input [output]\n", 348 getprogname()); 349 exit(1); 350 } 351