1 /* $OpenBSD: makedbm.c,v 1.16 2002/02/13 23:05:48 deraadt Exp $ */ 2 3 /* 4 * Copyright (c) 1994-97 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 #ifndef LINT 35 static char rcsid[] = "$OpenBSD: makedbm.c,v 1.16 2002/02/13 23:05:48 deraadt Exp $"; 36 #endif 37 38 #include <stdio.h> 39 #include <fcntl.h> 40 #include <ctype.h> 41 #include <sys/stat.h> 42 #include <sys/param.h> 43 #include <unistd.h> 44 #include <string.h> 45 #include <sys/errno.h> 46 #include "ypdb.h" 47 #include "ypdef.h" 48 #include "db.h" 49 50 extern char *__progname; /* from crt0.o */ 51 52 /* 53 * Read one line 54 */ 55 56 static int read_line(fp, buf, size) 57 FILE *fp; 58 char *buf; 59 int size; 60 { 61 int done; 62 63 done = 0; 64 65 do { 66 while (fgets(buf, size, fp)) { 67 int len = strlen(buf); 68 done += len; 69 if (len > 1 && buf[len-2] == '\\' && 70 buf[len-1] == '\n') { 71 int ch; 72 buf += len - 2; 73 size -= len - 2; 74 *buf = '\n'; buf[1] = '\0'; 75 76 /* Skip leading white space on next line */ 77 while ((ch = getc(fp)) != EOF && 78 isascii(ch) && isspace(ch)) 79 ; 80 (void) ungetc(ch, fp); 81 } else { 82 return done; 83 } 84 } 85 } while (size > 0 && !feof(fp)); 86 87 return done; 88 } 89 90 void 91 add_record(db, str1, str2, check) 92 DBM *db; 93 char *str1, *str2; 94 int check; 95 { 96 datum key, val; 97 int status; 98 99 key.dptr = str1; 100 key.dsize = strlen(str1); 101 102 if (check) { 103 val = ypdb_fetch(db,key); 104 105 if (val.dptr != NULL) 106 return; /* already there */ 107 108 } 109 110 val.dptr = str2; 111 val.dsize = strlen(str2); 112 status = ypdb_store(db, key, val, YPDB_INSERT); 113 114 if (status != 0) { 115 printf("%s: problem storing %s %s\n",__progname,str1,str2); 116 exit(1); 117 } 118 } 119 120 static char * 121 file_date(filename) 122 char *filename; 123 { 124 struct stat finfo; 125 static char datestr[11]; 126 int status; 127 128 if (strcmp(filename,"-") == 0) { 129 snprintf(datestr, sizeof datestr, "%010u", time(0)); 130 } else { 131 status = stat(filename, &finfo); 132 if (status < 0) { 133 fprintf(stderr, "%s: can't stat %s\n", __progname, filename); 134 exit(1); 135 } 136 snprintf(datestr, sizeof datestr, "%010u", finfo.st_mtime); 137 } 138 return datestr; 139 } 140 141 void 142 list_database(database,Uflag) 143 char *database; 144 int Uflag; 145 { 146 DBM *db; 147 datum key, val; 148 149 db = ypdb_open(database, O_RDONLY, 0444); 150 151 if (db == NULL) { 152 if (Uflag != 0) 153 if (db_hash_list_database(database)) return; 154 155 fprintf(stderr, "%s: can't open database %s\n", __progname, database); 156 exit(1); 157 } 158 159 key = ypdb_firstkey(db); 160 161 while (key.dptr != NULL) { 162 val = ypdb_fetch(db,key); 163 printf("%*.*s %*.*s\n", 164 key.dsize, key.dsize, key.dptr, 165 val.dsize, val.dsize, val.dptr); 166 key = ypdb_nextkey(db); 167 } 168 169 ypdb_close(db); 170 } 171 172 void 173 174 create_database(infile, database, yp_input_file, yp_output_file, 175 yp_master_name, yp_domain_name, bflag, lflag, sflag) 176 char *infile, *database; 177 char *yp_input_file, *yp_output_file; 178 char *yp_master_name, *yp_domain_name; 179 int bflag, lflag, sflag; 180 { 181 FILE *data_file; 182 char data_line[4096]; /* XXX: DB bsize = 4096 in ypdb.c */ 183 char myname[MAXHOSTNAMELEN]; 184 int line_no = 0; 185 int len; 186 char *p, *k, *v; 187 char *slash; 188 DBM *new_db; 189 static char mapname[] = "ypdbXXXXXXXXXX"; 190 char db_mapname[MAXPATHLEN], db_outfile[MAXPATHLEN], 191 db_tempname[MAXPATHLEN]; 192 char empty_str[] = ""; 193 194 if (strcmp(infile,"-") == 0) { 195 data_file = stdin; 196 } else { 197 data_file = fopen(infile, "r"); 198 if (errno != 0) { 199 (void)fprintf(stderr,"%s: ",__progname); 200 perror(infile); 201 exit(1); 202 } 203 } 204 205 if (strlen(database) + strlen(YPDB_SUFFIX) > MAXPATHLEN) { 206 fprintf(stderr,"%s: %s: file name too long\n", 207 __progname, database); 208 exit(1); 209 } 210 snprintf(db_outfile, sizeof(db_outfile), "%s%s", database, YPDB_SUFFIX); 211 212 slash = strrchr(database, '/'); 213 if (slash != NULL) 214 slash[1] = 0; /* truncate to dir */ 215 else 216 *database = 0; /* elminate */ 217 218 /* note: database is now directory where map goes ! */ 219 220 if (strlen(database) + strlen(mapname) + 221 strlen(YPDB_SUFFIX) > MAXPATHLEN) { 222 fprintf(stderr,"%s: %s: directory name too long\n", 223 __progname, database); 224 exit(1); 225 } 226 227 snprintf(db_mapname, sizeof(db_mapname), "%s%s%s", 228 database, mapname, YPDB_SUFFIX); 229 mkstemps(db_mapname, sizeof(YPDB_SUFFIX)); 230 strlcpy(db_tempname, db_mapname, sizeof db_tempname); 231 db_tempname[strlen(db_tempname) - sizeof(YPDB_SUFFIX) + 1] = '\0'; 232 233 new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444); 234 if (new_db == NULL) { 235 fprintf(stderr, "%s: Unable to open output database %s\n", 236 __progname, db_outfile); 237 exit(1); 238 } 239 240 while (read_line(data_file,data_line,sizeof(data_line))) { 241 242 line_no++; 243 len = strlen(data_line); 244 245 /* Check if we have the whole line */ 246 247 if (data_line[len-1] != '\n') { 248 fprintf(stderr, "line %d in \"%s\" is too long", 249 line_no, infile); 250 } else { 251 data_line[len-1] = '\0'; 252 } 253 254 p = (char *) &data_line; 255 256 k = p; /* save start of key */ 257 while (!isspace(*p)) { /* find first "space" */ 258 if (lflag && isupper(*p)) /* if force lower case */ 259 *p = tolower(*p); /* fix it */ 260 p++; 261 } 262 while (isspace(*p)) { /* replace space with <NUL> */ 263 *p = '\0'; 264 p++; 265 } 266 267 v = p; /* save start of value */ 268 while (*p != '\0') /* find end of string */ 269 p++; 270 271 add_record(new_db, k, v, TRUE); /* save record */ 272 273 } 274 275 if (strcmp(infile,"-") != 0) 276 (void) fclose(data_file); 277 278 add_record(new_db, YP_LAST_KEY, file_date(infile), FALSE); 279 280 if (yp_input_file) 281 add_record(new_db, YP_INPUT_KEY, yp_input_file, FALSE); 282 283 if (yp_output_file) 284 add_record(new_db, YP_OUTPUT_KEY, yp_output_file, FALSE); 285 286 if (yp_master_name) 287 add_record(new_db, YP_MASTER_KEY, yp_master_name, FALSE); 288 else { 289 gethostname(myname, sizeof(myname)); 290 add_record(new_db, YP_MASTER_KEY, myname, FALSE); 291 } 292 293 if (yp_domain_name) 294 add_record(new_db, YP_DOMAIN_KEY, yp_domain_name, FALSE); 295 if (bflag) 296 add_record(new_db, YP_INTERDOMAIN_KEY, empty_str, FALSE); 297 if (sflag) 298 add_record(new_db, YP_SECURE_KEY, empty_str, FALSE); 299 300 ypdb_close(new_db); 301 if (rename(db_mapname, db_outfile) < 0) { 302 perror("rename"); 303 fprintf(stderr,"rename %s -> %s failed!\n", db_mapname, 304 db_outfile); 305 exit(1); 306 } 307 308 } 309 310 int 311 main (argc,argv) 312 int argc; 313 char *argv[]; 314 { 315 int aflag, uflag, bflag, lflag, sflag, Uflag; 316 char *yp_input_file, *yp_output_file; 317 char *yp_master_name,*yp_domain_name; 318 char *infile,*outfile; 319 int usage = 0; 320 int ch; 321 322 extern int optind; 323 extern char *optarg; 324 325 yp_input_file = yp_output_file = NULL; 326 yp_master_name = yp_domain_name = NULL; 327 aflag = uflag = bflag = lflag = sflag = Uflag = 0; 328 infile = outfile = NULL; 329 330 while ((ch = getopt(argc, argv, "Ublsui:o:m:d:")) != -1) 331 switch (ch) { 332 case 'U': 333 uflag++; 334 Uflag++; 335 break; 336 case 'b': 337 bflag++; 338 aflag++; 339 break; 340 case 'l': 341 lflag++; 342 aflag++; 343 break; 344 case 's': 345 sflag++; 346 aflag++; 347 break; 348 case 'i': 349 yp_input_file = optarg; 350 aflag++; 351 break; 352 case 'o': 353 yp_output_file = optarg; 354 aflag++; 355 break; 356 case 'm': 357 yp_master_name = optarg; 358 aflag++; 359 break; 360 case 'd': 361 yp_domain_name = optarg; 362 aflag++; 363 break; 364 case 'u': 365 uflag++; 366 break; 367 default: 368 usage++; 369 break; 370 } 371 372 if ((uflag != 0) && (aflag != 0)) { 373 usage++; 374 } else { 375 376 if (uflag != 0) { 377 if (argc == (optind + 1)) { 378 infile = argv[optind]; 379 } else { 380 usage++; 381 } 382 } else { 383 if (argc == (optind + 2)) { 384 infile = argv[optind]; 385 outfile = argv[optind+1]; 386 } else { 387 usage++; 388 } 389 } 390 } 391 392 if (usage) { 393 fprintf(stderr,"%s%s%s", 394 "usage:\tmakedbm [-u|-U] file\n\tmakedbm [-bls]", 395 " [-i YP_INPUT_FILE] [-o YP_OUTPUT_FILE]\n\t\t", 396 "[-d YP_DOMAIN_NAME] [-m YP_MASTER_NAME] infile outfile\n"); 397 exit(1); 398 } 399 400 if (uflag != 0) { 401 list_database(infile,Uflag); 402 } else { 403 create_database(infile, outfile, yp_input_file, 404 yp_output_file, yp_master_name, yp_domain_name, 405 bflag, lflag, sflag); 406 } 407 408 return(0); 409 410 } 411