/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ /* All Rights Reserved */ /* * Portions of this source code were derived from Berkeley * under license from the Regents of the University of * California. */ #undef NULL #include #include #include #include #include #include #include #include #include #include #include #include #include "ypdefs.h" #include "ypsym.h" USE_YP_MASTER_NAME USE_YP_LAST_MODIFIED USE_YP_INPUT_FILE USE_YP_OUTPUT_NAME USE_YP_DOMAIN_NAME USE_YP_SECURE USE_YP_INTERDOMAIN USE_DBM #ifdef SYSVCONFIG extern void sysvconfig(); #endif extern int yp_getalias(); #define MAXLINE 4096 /* max length of input line */ #define DEFAULT_SEP " " static char *get_date(); static char *any(); static void addpair(); static void unmake(); static void usage(); int inode_dev_valid = 0; ino64_t inode; dev_t dev; /* * Interpose close(2) to enable us to keep one of the output * files open until process exit. */ #pragma weak _close = close int close(int filedes) { struct stat64 sb; static int (*fptr)() = 0; if (fptr == 0) { fptr = (int (*)())dlsym(RTLD_NEXT, "close"); if (fptr == 0) { fprintf(stderr, "makedbm: dlopen(close): %s\n", dlerror()); errno = ELIBACC; return (-1); } } if (inode_dev_valid != 0 && fstat64(filedes, &sb) == 0) { if (sb.st_ino == inode && sb.st_dev == dev) { /* Keep open; pretend successful */ return (0); } } return ((*fptr)(filedes)); } int main(argc, argv) int argc; char **argv; { FILE *infp, *outfp; datum key, content, tmp; char buf[MAXLINE]; char pagbuf[MAXPATHLEN]; char tmppagbuf[MAXPATHLEN]; char dirbuf[MAXPATHLEN]; char tmpdirbuf[MAXPATHLEN]; char *p, ic; char *infile, *outfile; char outalias[MAXPATHLEN]; char outaliasmap[MAXNAMLEN]; char outaliasdomain[MAXNAMLEN]; char *last_slash, *next_to_last_slash; char *infilename, *outfilename, *mastername, *domainname, *interdomain_bind, *security, *lower_case_keys; char key_sep[] = DEFAULT_SEP; char local_host[MAX_MASTER_NAME]; int cnt, i; DBM *fdb; struct stat64 statbuf; int num_del_to_match = 0; /* flag to indicate if matching char can be escaped */ int count_esp = 0; /* Ignore existing umask, always force 077 (owner rw only) */ umask(077); infile = outfile = NULL; /* where to get files */ /* name to imbed in database */ infilename = outfilename = mastername = domainname = interdomain_bind = security = lower_case_keys = NULL; argv++; argc--; while (argc > 0) { if (argv[0][0] == '-' && argv[0][1]) { switch (argv[0][1]) { case 'i': infilename = argv[1]; argv++; argc--; break; case 'o': outfilename = argv[1]; argv++; argc--; break; case 'm': mastername = argv[1]; argv++; argc--; break; case 'b': interdomain_bind = argv[0]; break; case 'd': domainname = argv[1]; argv++; argc--; break; case 'l': lower_case_keys = argv[0]; break; case 's': security = argv[0]; break; case 'S' : if (strlen(argv[1]) != 1) { fprintf(stderr, "bad separator\n"); usage(); } key_sep[0] = argv[1][0]; argv++; argc--; break; case 'D' : num_del_to_match = atoi(argv[1]); argv++; argc--; break; case 'E' : count_esp = 1; break; case 'u': unmake(argv[1]); argv++; argc--; exit(0); default: usage(); } } else if (infile == NULL) infile = argv[0]; else if (outfile == NULL) outfile = argv[0]; else usage(); argv++; argc--; } if (infile == NULL || outfile == NULL) usage(); /* * do alias mapping if necessary */ last_slash = strrchr(outfile, '/'); if (last_slash) { *last_slash = '\0'; next_to_last_slash = strrchr(outfile, '/'); if (next_to_last_slash) *next_to_last_slash = '\0'; } else next_to_last_slash = NULL; #ifdef DEBUG if (last_slash) printf("last_slash=%s\n", last_slash+1); if (next_to_last_slash) printf("next_to_last_slash=%s\n", next_to_last_slash+1); #endif /* DEBUG */ /* reads in alias file for system v filename translation */ #ifdef SYSVCONFIG sysvconfig(); #endif if (last_slash && next_to_last_slash) { if (yp_getalias(last_slash+1, outaliasmap, MAXALIASLEN) < 0) { if ((int)strlen(last_slash+1) <= MAXALIASLEN) strcpy(outaliasmap, last_slash+1); else fprintf(stderr, "makedbm: warning: no alias for %s\n", last_slash+1); } #ifdef DEBUG printf("%s\n", last_slash+1); printf("%s\n", outaliasmap); #endif /* DEBUG */ if (yp_getalias(next_to_last_slash+1, outaliasdomain, NAME_MAX) < 0) { if ((int)strlen(last_slash+1) <= NAME_MAX) strcpy(outaliasdomain, next_to_last_slash+1); else fprintf(stderr, "makedbm: warning: no alias for %s\n", next_to_last_slash+1); } #ifdef DEBUG printf("%s\n", next_to_last_slash+1); printf("%s\n", outaliasdomain); #endif /* DEBUG */ sprintf(outalias, "%s/%s/%s", outfile, outaliasdomain, outaliasmap); #ifdef DEBUG printf("outlias=%s\n", outalias); #endif /* DEBUG */ } else if (last_slash) { if (yp_getalias(last_slash+1, outaliasmap, MAXALIASLEN) < 0) { if ((int)strlen(last_slash+1) <= MAXALIASLEN) strcpy(outaliasmap, last_slash+1); else fprintf(stderr, "makedbm: warning: no alias for %s\n", last_slash+1); } if (yp_getalias(outfile, outaliasdomain, NAME_MAX) < 0) { if ((int)strlen(outfile) <= NAME_MAX) strcpy(outaliasdomain, outfile); else fprintf(stderr, "makedbm: warning: no alias for %s\n", last_slash+1); } sprintf(outalias, "%s/%s", outaliasdomain, outaliasmap); } else { if (yp_getalias(outfile, outalias, MAXALIASLEN) < 0) { if ((int)strlen(last_slash+1) <= MAXALIASLEN) strcpy(outalias, outfile); else fprintf(stderr, "makedbm: warning: no alias for %s\n", outfile); } } #ifdef DEBUG fprintf(stderr, "outalias=%s\n", outalias); fprintf(stderr, "outfile=%s\n", outfile); #endif /* DEBUG */ strcpy(tmppagbuf, outalias); strcat(tmppagbuf, ".tmp"); strcpy(tmpdirbuf, tmppagbuf); strcat(tmpdirbuf, dbm_dir); strcat(tmppagbuf, dbm_pag); /* Loop until we can lock the tmpdirbuf file */ for (;;) { if (strcmp(infile, "-") != 0) infp = fopen(infile, "r"); else if (fstat64(fileno(stdin), &statbuf) == -1) { fprintf(stderr, "makedbm: can't open stdin\n"); exit(1); } else infp = stdin; if (infp == NULL) { fprintf(stderr, "makedbm: can't open %s\n", infile); exit(1); } if ((outfp = fopen(tmpdirbuf, "w")) == (FILE *)NULL) { fprintf(stderr, "makedbm: can't create %s\n", tmpdirbuf); exit(1); } if (lockf(fileno(outfp), F_TLOCK, 0) == 0) { /* Got exclusive access; save inode and dev */ if (fstat64(fileno(outfp), &statbuf) != 0) { fprintf(stderr, "makedbm: can't fstat "); perror(tmpdirbuf); exit(1); } inode = statbuf.st_ino; dev = statbuf.st_dev; inode_dev_valid = 1; break; } if (errno != EAGAIN) { fprintf(stderr, "makedbm: can't lock "); perror(tmpdirbuf); exit(1); } /* * Someone else is holding the lock. * Close both output and input file * (the latter to ensure consistency * if the input file is updated while * we're suspended), wait a little, * and try again. */ if (infp != stdin) (void) fclose(infp); (void) fclose(outfp); sleep(1); } if (fopen(tmppagbuf, "w") == (FILE *)NULL) { fprintf(stderr, "makedbm: can't create %s\n", tmppagbuf); exit(1); } strcpy(dirbuf, outalias); strcat(dirbuf, ".tmp"); if ((fdb = dbm_open(dirbuf, O_RDWR | O_CREAT, 0644)) == NULL) { fprintf(stderr, "makedbm: can't open %s\n", dirbuf); exit(1); } strcpy(dirbuf, outalias); strcpy(pagbuf, outalias); strcat(dirbuf, dbm_dir); strcat(pagbuf, dbm_pag); while (fgets(buf, sizeof (buf), infp) != NULL) { p = buf; cnt = strlen(buf) - 1; /* erase trailing newline */ while (p[cnt-1] == '\\') { p += cnt-1; if (fgets(p, sizeof (buf)-(p-buf), infp) == NULL) goto breakout; cnt = strlen(p) - 1; } if (strcmp(key_sep, DEFAULT_SEP) == 0) { p = any(buf, " \t\n", num_del_to_match, count_esp); } else { p = any(buf, key_sep, num_del_to_match, count_esp); } key.dptr = buf; key.dsize = p - buf; for (;;) { if (p == NULL || *p == NULL) { fprintf(stderr, "makedbm: source files is garbage!\n"); exit(1); } if (*p != ' ' && *p != '\t' && *p != key_sep[0]) break; p++; } content.dptr = p; content.dsize = strlen(p) - 1; /* erase trailing newline */ if (lower_case_keys) { for (i = (strncmp(key.dptr, "YP_MULTI_", 9) ? 0 : 9); i < key.dsize; i++) { ic = *(key.dptr+i); if (isascii(ic) && isupper(ic)) *(key.dptr+i) = tolower(ic); } } tmp = dbm_fetch(fdb, key); if (tmp.dptr == NULL) { if (dbm_store(fdb, key, content, 1) != 0) { printf("problem storing %.*s %.*s\n", key.dsize, key.dptr, content.dsize, content.dptr); exit(1); } } #ifdef DEBUG else { printf("duplicate: %.*s %.*s\n", key.dsize, key.dptr, content.dsize, content.dptr); } #endif } breakout: addpair(fdb, yp_last_modified, get_date(infile)); if (infilename) addpair(fdb, yp_input_file, infilename); if (outfilename) addpair(fdb, yp_output_file, outfilename); if (domainname) addpair(fdb, yp_domain_name, domainname); if (security) addpair(fdb, yp_secure, ""); if (interdomain_bind) addpair(fdb, yp_interdomain, ""); if (!mastername) { sysinfo(SI_HOSTNAME, local_host, sizeof (local_host) - 1); mastername = local_host; } addpair(fdb, yp_master_name, mastername); (void) dbm_close(fdb); #ifdef DEBUG fprintf(stderr, ".tmp ndbm map closed. ndbm successful !\n"); #endif if (rename(tmppagbuf, pagbuf) < 0) { perror("makedbm: rename"); unlink(tmppagbuf); /* Remove the tmp files */ unlink(tmpdirbuf); exit(1); } if (rename(tmpdirbuf, dirbuf) < 0) { perror("makedbm: rename"); unlink(tmppagbuf); /* Remove the tmp files */ unlink(tmpdirbuf); exit(1); } /* * sprintf(buf, "mv %s %s", tmppagbuf, pagbuf); * if (system(buf) < 0) * perror("makedbm: rename"); * sprintf(buf, "mv %s %s", tmpdirbuf, dirbuf); * if (system(buf) < 0) * perror("makedbm: rename"); */ exit(0); } /* * scans cp, looking for a match with any character * in match. Returns pointer to place in cp that matched * (or NULL if no match) * * It will find the num_del_to_match+1 * matching character in the line. * * The backslash escapes a delimiter if count_esp==1 * We don't count it as a character match if * an escape character precedes a matching character. * */ static char * any(cp, match, num_del_to_match, count_esp) register char *cp; char *match; int num_del_to_match; int count_esp; { register char *mp, c, prev_char; int num_del_matched; num_del_matched = 0; prev_char = ' '; while (c = *cp) { for (mp = match; *mp; mp++) { if (*mp == c) { if (!count_esp) { num_del_matched++; } else if (prev_char != '\\') { num_del_matched++; } if (num_del_matched > num_del_to_match) return (cp); } } prev_char = c; cp++; } return ((char *)0); } static char * get_date(name) char *name; { struct stat filestat; static char ans[MAX_ASCII_ORDER_NUMBER_LENGTH]; /* ASCII numeric string */ if (strcmp(name, "-") == 0) sprintf(ans, "%010ld", (long)time(0)); else { if (stat(name, &filestat) < 0) { fprintf(stderr, "makedbm: can't stat %s\n", name); exit(1); } sprintf(ans, "%010ld", (long)filestat.st_mtime); } return (ans); } void usage() { fprintf(stderr, "usage: makedbm -u file\n makedbm [-b] [-l] [-s] [-i YP_INPUT_FILE] " "[-o YP_OUTPUT_FILE] [-d YP_DOMAIN_NAME] [-m YP_MASTER_NAME] " "[-S DELIMITER] [-D NUM_DELIMITER_TO_SKIP] [-E] " "infile outfile\n"); exit(1); } void addpair(fdb, str1, str2) DBM *fdb; char *str1, *str2; { datum key; datum content; key.dptr = str1; key.dsize = strlen(str1); content.dptr = str2; content.dsize = strlen(str2); if (dbm_store(fdb, key, content, 1) != 0) { printf("makedbm: problem storing %.*s %.*s\n", key.dsize, key.dptr, content.dsize, content.dptr); exit(1); } } void unmake(file) char *file; { datum key, content; DBM *fdb; if (file == NULL) usage(); if ((fdb = dbm_open(file, O_RDONLY, 0644)) == NULL) { fprintf(stderr, "makedbm: couldn't open %s dbm file\n", file); exit(1); } for (key = dbm_firstkey(fdb); key.dptr != NULL; key = dbm_nextkey(fdb)) { content = dbm_fetch(fdb, key); printf("%.*s %.*s\n", key.dsize, key.dptr, content.dsize, content.dptr); } dbm_close(fdb); }