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