1 /* $NetBSD: mkalias.c,v 1.9 2001/02/19 23:22:50 cgd 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.9 2001/02/19 23:22:50 cgd 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 __P((char *, int)); 62 int check_host __P((char *, char *, int, int, int)); 63 int main __P((int, char *[])); 64 void split_address __P((char *, int, char *, char *)); 65 void usage __P((void)); 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); /* OK */ 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 getprogname(), 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 getprogname()); 358 exit(1); 359 } 360