1 /* $NetBSD: makedbm.c,v 1.17 2001/02/19 23:22:50 cgd Exp $ */ 2 3 /* 4 * Copyright (c) 1994 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: makedbm.c,v 1.17 2001/02/19 23:22:50 cgd Exp $"); 37 #endif 38 39 #include <sys/param.h> 40 #include <sys/stat.h> 41 42 #include <ctype.h> 43 #include <err.h> 44 #include <errno.h> 45 #include <fcntl.h> 46 #include <stdio.h> 47 #include <stdlib.h> 48 #include <string.h> 49 #include <time.h> 50 #include <unistd.h> 51 #include <util.h> 52 53 #include <rpc/rpc.h> 54 #include <rpc/xdr.h> 55 56 #include "protos.h" 57 #include "ypdb.h" 58 #include "ypdef.h" 59 60 int main __P((int, char *[])); 61 void usage __P((void)); 62 int add_record __P((DBM *, char *, char *, int)); 63 char *file_date __P((char *)); 64 void list_database __P((char *)); 65 void create_database __P((char *, char *, char *, char *, 66 char *, char *, int, int, int)); 67 68 int 69 main(argc, argv) 70 int argc; 71 char *argv[]; 72 { 73 int aflag, uflag, bflag, lflag, sflag; 74 char *yp_input_file, *yp_output_file; 75 char *yp_master_name, *yp_domain_name; 76 char *infile, *outfile; 77 int ch; 78 79 yp_input_file = yp_output_file = NULL; 80 yp_master_name = yp_domain_name = NULL; 81 aflag = uflag = bflag = lflag = sflag = 0; 82 infile = outfile = NULL; 83 84 while ((ch = getopt(argc, argv, "blsui:o:m:d:")) != -1) { 85 switch (ch) { 86 case 'b': 87 bflag = aflag = 1; 88 break; 89 90 case 'l': 91 lflag = aflag = 1; 92 break; 93 94 case 's': 95 sflag = aflag = 1; 96 break; 97 98 case 'i': 99 yp_input_file = optarg; 100 aflag = 1; 101 break; 102 103 case 'o': 104 yp_output_file = optarg; 105 aflag = 1; 106 break; 107 108 case 'm': 109 yp_master_name = optarg; 110 aflag = 1; 111 break; 112 113 case 'd': 114 yp_domain_name = optarg; 115 aflag = 1; 116 break; 117 118 case 'u': 119 uflag = 1; 120 break; 121 122 default: 123 usage(); 124 } 125 } 126 argc -= optind; argv += optind; 127 128 if ((uflag != 0) && (aflag != 0)) 129 usage(); 130 else { 131 if (uflag != 0) { 132 if (argc == 1) 133 infile = argv[0]; 134 else 135 usage(); 136 } else { 137 if (argc == 2) { 138 infile = argv[0]; 139 outfile = argv[1]; 140 } else 141 usage(); 142 } 143 } 144 145 if (uflag != 0) 146 list_database(infile); 147 else 148 create_database(infile, outfile, 149 yp_input_file, yp_output_file, yp_master_name, 150 yp_domain_name, bflag, lflag, sflag); 151 152 exit(0); 153 } 154 155 int 156 add_record(db, str1, str2, check) 157 DBM *db; 158 char *str1, *str2; 159 int check; 160 { 161 datum key, val; 162 int status; 163 164 key.dptr = str1; 165 key.dsize = strlen(str1); 166 167 if (check) { 168 val = ypdb_fetch(db, key); 169 170 if (val.dptr != NULL) 171 return 0; /* already there */ 172 } 173 val.dptr = str2; 174 val.dsize = strlen(str2); 175 status = ypdb_store(db, key, val, YPDB_INSERT); 176 177 if (status != 0) { 178 warnx("can't store `%s %s'", str1, str2); 179 return -1; 180 } 181 return 0; 182 } 183 184 char * 185 file_date(filename) 186 char *filename; 187 { 188 struct stat finfo; 189 static char datestr[11]; 190 191 memset(datestr, 0, sizeof(datestr)); 192 193 if (strcmp(filename, "-") == 0) 194 snprintf(datestr, sizeof(datestr), "%010d", 195 (int)time(NULL)); 196 else { 197 if (stat(filename, &finfo) != 0) 198 err(1, "can't stat %s", filename); 199 snprintf(datestr, sizeof(datestr), "%010d", 200 (int)finfo.st_mtime); 201 } 202 203 return datestr; 204 } 205 206 void 207 list_database(database) 208 char *database; 209 { 210 DBM *db; 211 datum key, val; 212 213 db = ypdb_open(database, O_RDONLY, 0444); 214 if (db == NULL) 215 err(1, "can't open database `%s'", database); 216 217 key = ypdb_firstkey(db); 218 219 while (key.dptr != NULL) { 220 val = ypdb_fetch(db, key); 221 /* workround trailing \0 in aliases.db */ 222 if (key.dptr[key.dsize - 1] == '\0') 223 key.dsize--; 224 printf("%*.*s", key.dsize, key.dsize, key.dptr); 225 if (val.dsize > 0) { 226 if (val.dptr[val.dsize - 1] == '\0') 227 val.dsize--; 228 printf(" %*.*s", val.dsize, val.dsize, val.dptr); 229 } 230 printf("\n"); 231 key = ypdb_nextkey(db); 232 } 233 234 ypdb_close(db); 235 } 236 237 void 238 create_database(infile, database, yp_input_file, yp_output_file, 239 yp_master_name, yp_domain_name, bflag, lflag, sflag) 240 char *infile, *database, *yp_input_file, *yp_output_file; 241 char *yp_master_name, *yp_domain_name; 242 int bflag, lflag, sflag; 243 { 244 FILE *data_file; 245 char myname[MAXHOSTNAMELEN]; 246 size_t line_no = 0; 247 size_t len; 248 char *p, *k, *v, *slash; 249 DBM *new_db; 250 static char mapname[] = "ypdbXXXXXX"; 251 char db_mapname[MAXPATHLEN + 1], db_outfile[MAXPATHLEN + 1]; 252 char db_tempname[MAXPATHLEN + 1]; 253 char empty_str[] = ""; 254 255 memset(db_mapname, 0, sizeof(db_mapname)); 256 memset(db_outfile, 0, sizeof(db_outfile)); 257 memset(db_tempname, 0, sizeof(db_tempname)); 258 259 if (strcmp(infile, "-") == 0) 260 data_file = stdin; 261 else { 262 data_file = fopen(infile, "r"); 263 if (data_file == NULL) 264 err(1, "can't open `%s'", infile); 265 } 266 267 if (strlen(database) + strlen(YPDB_SUFFIX) > MAXPATHLEN) 268 errx(1, "file name `%s' too long", database); 269 270 snprintf(db_outfile, sizeof(db_outfile), "%s%s", database, YPDB_SUFFIX); 271 272 slash = strrchr(database, '/'); 273 if (slash != NULL) 274 slash[1] = '\0'; /* truncate to dir */ 275 else 276 *database = '\0'; /* eliminate */ 277 278 /* NOTE: database is now directory where map goes ! */ 279 280 if (strlen(database) + strlen(mapname) + 281 strlen(YPDB_SUFFIX) > MAXPATHLEN) 282 errx(1, "directory name `%s' too long", database); 283 284 snprintf(db_tempname, sizeof(db_tempname), "%s%s", 285 database, mapname); 286 mktemp(db_tempname); /* OK */ 287 snprintf(db_mapname, sizeof(db_mapname), "%s%s", 288 db_tempname, YPDB_SUFFIX); 289 290 new_db = ypdb_open(db_tempname, O_RDWR | O_CREAT | O_EXCL, 0644); 291 if (new_db == NULL) 292 err(1, "can't create temp database `%s'", db_tempname); 293 294 for (; 295 (p = fparseln(data_file, &len, &line_no, NULL, FPARSELN_UNESCALL)); 296 free(p)) { 297 k = p; /* set start of key */ 298 while (*k && isspace(*k)) /* skip leading whitespace */ 299 k++; 300 301 if (! *k) 302 continue; 303 304 v = k; 305 while (*v && !isspace(*v)) { /* find leading whitespace */ 306 /* convert key to lower case if forcing. */ 307 if (lflag && isupper(*v)) 308 *v = tolower(*v); 309 v++; 310 } 311 while (*v && isspace(*v)) /* replace space with <NUL> */ 312 *v++ = '\0'; 313 314 if (add_record(new_db, k, v, TRUE)) { /* save record */ 315 bad_record: 316 ypdb_close(new_db); 317 unlink(db_mapname); 318 errx(1, "error adding record for line %lu", 319 (unsigned long)line_no); 320 } 321 } 322 323 if (strcmp(infile, "-") != 0) 324 (void) fclose(data_file); 325 326 if (add_record(new_db, YP_LAST_KEY, file_date(infile), FALSE)) 327 goto bad_record; 328 329 if (yp_input_file) { 330 if (add_record(new_db, YP_INPUT_KEY, yp_input_file, FALSE)) 331 goto bad_record; 332 } 333 334 if (yp_output_file) { 335 if (add_record(new_db, YP_OUTPUT_KEY, yp_output_file, FALSE)) 336 goto bad_record; 337 } 338 339 if (yp_master_name) { 340 if (add_record(new_db, YP_MASTER_KEY, yp_master_name, FALSE)) 341 goto bad_record; 342 } else { 343 localhostname(myname, sizeof(myname) - 1); 344 if (add_record(new_db, YP_MASTER_KEY, myname, FALSE)) 345 goto bad_record; 346 } 347 348 if (yp_domain_name) { 349 if (add_record(new_db, YP_DOMAIN_KEY, yp_domain_name, FALSE)) 350 goto bad_record; 351 } 352 353 if (bflag) { 354 if (add_record(new_db, YP_INTERDOMAIN_KEY, empty_str, FALSE)) 355 goto bad_record; 356 } 357 358 if (sflag) { 359 if (add_record(new_db, YP_SECURE_KEY, empty_str, FALSE)) 360 goto bad_record; 361 } 362 363 ypdb_close(new_db); 364 if (rename(db_mapname, db_outfile) < 0) { 365 unlink(db_mapname); 366 err(1, "rename `%s' -> `%s'", db_mapname, db_outfile); 367 } 368 } 369 370 void 371 usage() 372 { 373 374 fprintf(stderr, "usage: %s -u file\n", getprogname()); 375 fprintf(stderr, " %s [-lbs] %s\n", getprogname(), 376 "[-i YP_INPUT_FILE] [-o YP_OUTPUT_FILE]"); 377 fprintf(stderr, " %s infile outfile\n", 378 "[-d YP_DOMAIN_NAME] [-m YP_MASTER_NAME]"); 379 exit(1); 380 } 381