1 /* $OpenBSD: makedbm.c,v 1.33 2015/02/09 23:00:15 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS 17 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 #include <stdio.h> 30 #include <stdlib.h> 31 #include <fcntl.h> 32 #include <ctype.h> 33 #include <sys/stat.h> 34 #include <unistd.h> 35 #include <string.h> 36 #include <errno.h> 37 #include "ypdb.h" 38 #include "ypdef.h" 39 #include "db.h" 40 41 extern char *__progname; /* from crt0.o */ 42 43 /* 44 * Read one line 45 */ 46 47 static int 48 read_line(FILE *fp, char *buf, int size) 49 { 50 int done = 0; 51 52 do { 53 while (fgets(buf, size, fp)) { 54 int len = strlen(buf); 55 56 done += len; 57 if (len > 1 && buf[len-2] == '\\' && 58 buf[len-1] == '\n') { 59 int ch; 60 61 buf += len - 2; 62 size -= len - 2; 63 *buf = '\n'; buf[1] = '\0'; 64 65 /* Skip leading white space on next line */ 66 while ((ch = getc(fp)) != EOF && 67 isascii(ch) && isspace(ch)) 68 ; 69 (void) ungetc(ch, fp); 70 } else { 71 return done; 72 } 73 } 74 } while (size > 0 && !feof(fp)); 75 return done; 76 } 77 78 static void 79 add_record(DBM *db, char *str1, char *str2, int check) 80 { 81 datum key, val; 82 int status; 83 84 key.dptr = str1; 85 key.dsize = strlen(str1); 86 87 if (check) { 88 val = ypdb_fetch(db, key); 89 90 if (val.dptr != NULL) 91 return; /* already there */ 92 } 93 94 val.dptr = str2; 95 val.dsize = strlen(str2); 96 status = ypdb_store(db, key, val, YPDB_INSERT); 97 98 if (status != 0) { 99 printf("%s: problem storing %s %s\n", 100 __progname, str1, str2); 101 exit(1); 102 } 103 } 104 105 static char * 106 file_date(char *filename) 107 { 108 struct stat finfo; 109 static char datestr[11]; 110 int status; 111 112 if (strcmp(filename,"-") == 0) { 113 snprintf(datestr, sizeof datestr, "%010lld", 114 (long long)time(0)); 115 } else { 116 status = stat(filename, &finfo); 117 if (status < 0) { 118 fprintf(stderr, "%s: can't stat %s\n", __progname, filename); 119 exit(1); 120 } 121 snprintf(datestr, sizeof datestr, "%010lld", 122 (long long)finfo.st_mtime); 123 } 124 return datestr; 125 } 126 127 static void 128 list_database(char *database, int Uflag) 129 { 130 DBM *db; 131 datum key, val; 132 133 db = ypdb_open(database, O_RDONLY, 0444); 134 135 if (db == NULL) { 136 if (Uflag != 0) 137 if (db_hash_list_database(database)) 138 return; 139 140 fprintf(stderr, "%s: can't open database %s: %s\n", __progname, 141 database, strerror(errno)); 142 exit(1); 143 } 144 145 key = ypdb_firstkey(db); 146 147 while (key.dptr != NULL) { 148 val = ypdb_fetch(db, key); 149 printf("%*.*s %*.*s\n", 150 key.dsize, key.dsize, key.dptr, 151 val.dsize, val.dsize, val.dptr); 152 key = ypdb_nextkey(db); 153 } 154 ypdb_close(db); 155 } 156 157 static void 158 create_database(char *infile, char *database, char *yp_input_file, 159 char *yp_output_file, char *yp_master_name, char *yp_domain_name, 160 int bflag, int lflag, int sflag) 161 { 162 FILE *data_file; 163 char data_line[4096]; /* XXX: DB bsize = 4096 in ypdb.c */ 164 char myname[HOST_NAME_MAX+1]; 165 int line_no = 0, len; 166 char *p, *k, *v, *slash; 167 DBM *new_db; 168 static char mapname[] = "ypdbXXXXXXXXXX"; 169 char db_mapname[PATH_MAX], db_outfile[PATH_MAX]; 170 char db_tempname[PATH_MAX], empty_str[] = ""; 171 172 if (strcmp(infile,"-") == 0) { 173 data_file = stdin; 174 } else { 175 data_file = fopen(infile, "r"); 176 if (errno != 0) { 177 (void)fprintf(stderr,"%s: ", __progname); 178 perror(infile); 179 exit(1); 180 } 181 } 182 183 if (strlen(database) + strlen(YPDB_SUFFIX) > PATH_MAX) { 184 fprintf(stderr,"%s: %s: file name too long\n", 185 __progname, database); 186 exit(1); 187 } 188 snprintf(db_outfile, sizeof(db_outfile), "%s%s", database, YPDB_SUFFIX); 189 190 slash = strrchr(database, '/'); 191 if (slash != NULL) 192 slash[1] = 0; /* truncate to dir */ 193 else 194 *database = 0; /* eliminate */ 195 196 /* note: database is now directory where map goes ! */ 197 198 if (strlen(database) + strlen(mapname) + 199 strlen(YPDB_SUFFIX) > PATH_MAX) { 200 fprintf(stderr,"%s: %s: directory name too long\n", 201 __progname, database); 202 exit(1); 203 } 204 205 snprintf(db_mapname, sizeof(db_mapname), "%s%s%s", 206 database, mapname, YPDB_SUFFIX); 207 mkstemps(db_mapname, sizeof(YPDB_SUFFIX)); 208 strlcpy(db_tempname, db_mapname, sizeof db_tempname); 209 db_tempname[strlen(db_tempname) - sizeof(YPDB_SUFFIX) + 1] = '\0'; 210 211 new_db = ypdb_open(db_tempname, O_RDWR|O_CREAT, 0444); 212 if (new_db == NULL) { 213 fprintf(stderr, "%s: Unable to open output database %s\n", 214 __progname, db_outfile); 215 exit(1); 216 } 217 218 while (read_line(data_file, data_line, sizeof(data_line))) { 219 line_no++; 220 len = strlen(data_line); 221 222 /* Check if we have the whole line */ 223 224 if (data_line[len-1] != '\n') { 225 fprintf(stderr, "line %d in \"%s\" is too long", 226 line_no, infile); 227 } else { 228 data_line[len-1] = '\0'; 229 } 230 231 p = (char *) &data_line; 232 233 k = p; /* save start of key */ 234 while (!isspace((unsigned char)*p)) { /* find first "space" */ 235 if (lflag && isupper((unsigned char)*p)) /* if force lower case */ 236 *p = (char)tolower((unsigned char)*p); /* fix it */ 237 p++; 238 } 239 while (isspace((unsigned char)*p)) { /* replace space with <NUL> */ 240 *p = '\0'; 241 p++; 242 } 243 244 v = p; /* save start of value */ 245 while (*p != '\0') /* find end of string */ 246 p++; 247 248 add_record(new_db, k, v, TRUE); /* save record */ 249 250 } 251 252 if (strcmp(infile,"-") != 0) 253 (void) fclose(data_file); 254 255 add_record(new_db, YP_LAST_KEY, file_date(infile), FALSE); 256 257 if (yp_input_file) 258 add_record(new_db, YP_INPUT_KEY, yp_input_file, FALSE); 259 260 if (yp_output_file) 261 add_record(new_db, YP_OUTPUT_KEY, yp_output_file, FALSE); 262 263 if (yp_master_name) 264 add_record(new_db, YP_MASTER_KEY, yp_master_name, FALSE); 265 else { 266 gethostname(myname, sizeof(myname)); 267 add_record(new_db, YP_MASTER_KEY, myname, FALSE); 268 } 269 270 if (yp_domain_name) 271 add_record(new_db, YP_DOMAIN_KEY, yp_domain_name, FALSE); 272 if (bflag) 273 add_record(new_db, YP_INTERDOMAIN_KEY, empty_str, FALSE); 274 if (sflag) 275 add_record(new_db, YP_SECURE_KEY, empty_str, FALSE); 276 277 ypdb_close(new_db); 278 if (rename(db_mapname, db_outfile) < 0) { 279 perror("rename"); 280 fprintf(stderr,"rename %s -> %s failed!\n", db_mapname, 281 db_outfile); 282 exit(1); 283 } 284 285 } 286 287 static void 288 usage(void) 289 { 290 fprintf(stderr,"usage: makedbm [-blsUu] [-d yp_domain_name] " 291 "[-i yp_input_file]\n" 292 "\t[-m yp_master_name] [-o yp_output_file] infile outfile\n"); 293 exit(1); 294 } 295 296 int 297 main(int argc, char *argv[]) 298 { 299 int aflag, uflag, bflag, lflag, sflag, Uflag; 300 char *yp_input_file, *yp_output_file; 301 char *yp_master_name, *yp_domain_name; 302 char *infile, *outfile; 303 int ch; 304 305 extern int optind; 306 extern char *optarg; 307 308 yp_input_file = yp_output_file = NULL; 309 yp_master_name = yp_domain_name = NULL; 310 aflag = uflag = bflag = lflag = sflag = Uflag = 0; 311 infile = outfile = NULL; 312 313 while ((ch = getopt(argc, argv, "Ublsui:o:m:d:")) != -1) 314 switch (ch) { 315 case 'U': 316 uflag = 1; 317 Uflag = 1; 318 break; 319 case 'b': 320 bflag = 1; 321 aflag = 1; 322 break; 323 case 'l': 324 lflag = 1; 325 aflag = 1; 326 break; 327 case 's': 328 sflag = 1; 329 aflag = 1; 330 break; 331 case 'i': 332 yp_input_file = optarg; 333 aflag = 1; 334 break; 335 case 'o': 336 yp_output_file = optarg; 337 aflag = 1; 338 break; 339 case 'm': 340 yp_master_name = optarg; 341 aflag = 1; 342 break; 343 case 'd': 344 yp_domain_name = optarg; 345 aflag = 1; 346 break; 347 case 'u': 348 uflag = 1; 349 break; 350 default: 351 usage(); 352 break; 353 } 354 355 if ((uflag != 0) && (aflag != 0)) 356 usage(); 357 358 if (uflag != 0) { 359 if (argc == (optind + 1)) 360 infile = argv[optind]; 361 else 362 usage(); 363 } else { 364 if (argc == (optind + 2)) { 365 infile = argv[optind]; 366 outfile = argv[optind+1]; 367 } else 368 usage(); 369 } 370 371 if (uflag != 0) { 372 list_database(infile,Uflag); 373 } else { 374 create_database(infile, outfile, yp_input_file, 375 yp_output_file, yp_master_name, yp_domain_name, 376 bflag, lflag, sflag); 377 } 378 379 return(0); 380 } 381