[BACK]Return to info_mkdb.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / info_mkdb

Annotation of src/usr.bin/info_mkdb/info_mkdb.c, Revision 1.1

1.1     ! tholo       1: /*     $OpenBSD$       */
        !             2:
        !             3: /*-
        !             4:  * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
        !             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 SigmaSoft, Th.  Lockert.
        !            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 ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
        !            22:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
        !            23:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
        !            24:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
        !            25:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
        !            26:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
        !            27:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
        !            28:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
        !            29:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
        !            30:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
        !            31:  */
        !            32:
        !            33: #ifndef lint
        !            34: static char rcsid[] = "$OpenBSD$";
        !            35: #endif /* not lint */
        !            36:
        !            37: #include <sys/param.h>
        !            38: #include <sys/stat.h>
        !            39:
        !            40: #include <db.h>
        !            41: #include <err.h>
        !            42: #include <errno.h>
        !            43: #include <fcntl.h>
        !            44: #include <limits.h>
        !            45: #include <stdio.h>
        !            46: #include <stdlib.h>
        !            47: #include <string.h>
        !            48: #include <ctype.h>
        !            49: #include <unistd.h>
        !            50:
        !            51: void    db_build __P((char **));
        !            52: void    dounlink __P((void));
        !            53: void    usage __P((void));
        !            54: int     igetnext __P((char **, char **));
        !            55: int     main __P((int, char *[]));
        !            56:
        !            57: DB *infodbp;
        !            58: int verbose;
        !            59: char *infoname, buf[8 * 1024];
        !            60:
        !            61: HASHINFO openinfo = {
        !            62:        4096,           /* bsize */
        !            63:        16,             /* ffactor */
        !            64:        256,            /* nelem */
        !            65:        2048 * 1024,    /* cachesize */
        !            66:        NULL,           /* hash() */
        !            67:        0               /* lorder */
        !            68: };
        !            69:
        !            70: /*
        !            71:  * info_mkdb creates a capability hash database for quick retrieval of capability
        !            72:  * records.  The database contains 2 types of entries: records and references
        !            73:  * marked by the first byte in the data.  A record entry contains the actual
        !            74:  * capability record whereas a reference contains the name (key) under which
        !            75:  * the correct record is stored.
        !            76:  */
        !            77: int
        !            78: main(argc, argv)
        !            79:        int argc;
        !            80:        char *argv[];
        !            81: {
        !            82:        int c;
        !            83:
        !            84:        infoname = NULL;
        !            85:        while ((c = getopt(argc, argv, "f:v")) != EOF) {
        !            86:                switch(c) {
        !            87:                case 'f':
        !            88:                        infoname = optarg;
        !            89:                        break;
        !            90:                case 'v':
        !            91:                        verbose = 1;
        !            92:                        break;
        !            93:                case '?':
        !            94:                default:
        !            95:                        usage();
        !            96:                }
        !            97:        }
        !            98:        argc -= optind;
        !            99:        argv += optind;
        !           100:
        !           101:        if (*argv == NULL)
        !           102:                usage();
        !           103:
        !           104:        /*
        !           105:         * The database file is the first argument if no name is specified.
        !           106:         * Make arrangements to unlink it if exit badly.
        !           107:         */
        !           108:        (void)snprintf(buf, sizeof(buf), "%s.db", infoname ? infoname : *argv);
        !           109:        if ((infoname = strdup(buf)) == NULL) {
        !           110:                err(1, "strdup");
        !           111:                /* NOTREACHED */
        !           112:        }
        !           113:        if ((infodbp = dbopen(infoname, O_CREAT | O_TRUNC | O_RDWR,
        !           114:            DEFFILEMODE, DB_HASH, &openinfo)) == NULL) {
        !           115:                err(1, "%s", buf);
        !           116:                /* NOTREACHED */
        !           117:        }
        !           118:
        !           119:        if (atexit(dounlink)) {
        !           120:                err(1, "atexit");
        !           121:                /* NOTREACHED */
        !           122:        }
        !           123:
        !           124:        db_build(argv);
        !           125:
        !           126:        if (infodbp->close(infodbp) < 0) {
        !           127:                err(1, "%s", infoname);
        !           128:                /* NOTREACHED */
        !           129:        }
        !           130:        infoname = NULL;
        !           131:        exit(0);
        !           132:        /* NOTREACHED */
        !           133: }
        !           134:
        !           135: void
        !           136: dounlink()
        !           137: {
        !           138:        if (infoname != NULL)
        !           139:                (void)unlink(infoname);
        !           140: }
        !           141:
        !           142: /*
        !           143:  * Any changes to these definitions should be made also in the getcap(3)
        !           144:  * library routines.
        !           145:  */
        !           146: #define RECOK  (char)0
        !           147: #define TCERR  (char)1
        !           148: #define SHADOW (char)2
        !           149:
        !           150: /*
        !           151:  * db_build() builds the name and capability databases according to the
        !           152:  * details above.
        !           153:  */
        !           154: void
        !           155: db_build(ifiles)
        !           156:        char **ifiles;
        !           157: {
        !           158:        DBT key, data;
        !           159:        recno_t reccnt;
        !           160:        size_t len, bplen;
        !           161:        int st;
        !           162:        char *bp, *p, *t;
        !           163:
        !           164:        data.data = NULL;
        !           165:        key.data = NULL;
        !           166:        for (reccnt = 0, bplen = 0; (st = igetnext(&bp, ifiles)) > 0;) {
        !           167:
        !           168:                /*
        !           169:                 * Allocate enough memory to store record, terminating
        !           170:                 * NULL and one extra byte.
        !           171:                 */
        !           172:                len = strlen(bp);
        !           173:                if (bplen <= len + 2) {
        !           174:                        bplen += MAX(256, len + 2);
        !           175:                        if ((data.data = realloc(data.data, bplen)) == NULL) {
        !           176:                                err(1, "realloc");
        !           177:                                /* NOTREACHED */
        !           178:                        }
        !           179:                }
        !           180:
        !           181:                /* Find the end of the name field. */
        !           182:                if ((p = strchr(bp, ',')) == NULL) {
        !           183:                        warnx("no name field: %.*s", (int)MIN(len, 20), bp);
        !           184:                        continue;
        !           185:                }
        !           186:
        !           187:                if (isspace(*bp)) {
        !           188:                        warnx("bad name field: %.*s", (int)MIN(len, 20), bp);
        !           189:                        continue;
        !           190:                }
        !           191:
        !           192:                /* First byte of stored record indicates status. */
        !           193:                switch(st) {
        !           194:                case 1:
        !           195:                        ((char *)(data.data))[0] = RECOK;
        !           196:                        break;
        !           197:                case 2:
        !           198:                        ((char *)(data.data))[0] = TCERR;
        !           199:                        warnx("Record not use expanded: %.*s", (int)(p - bp), bp);
        !           200:                        break;
        !           201:                }
        !           202:
        !           203:                /* Create the stored record. */
        !           204:                (void) memmove(&((u_char *)(data.data))[1], bp, len + 1);
        !           205:                data.size = len + 2;
        !           206:                for (t = memchr((char *)data.data + 1, ',', data.size - 1) ; t ; t = memchr(t, ',', data.size - (t - (char *)data.data)))
        !           207:                        *t++ = ':';
        !           208:
        !           209:                if (memchr((char *)data.data + 1, '\0', data.size - 2)) {
        !           210:                        warnx("NUL in entry: %.*s", (int)MIN(len, 20), bp);
        !           211:                        continue;
        !           212:                }
        !           213:
        !           214:                /* Store the record under the name field. */
        !           215:                key.data = bp;
        !           216:                key.size = p - bp;
        !           217:
        !           218:                switch(infodbp->put(infodbp, &key, &data, R_NOOVERWRITE)) {
        !           219:                case -1:
        !           220:                        err(1, "put");
        !           221:                        /* NOTREACHED */
        !           222:                case 1:
        !           223:                        warnx("ignored duplicate: %.*s",
        !           224:                            (int)key.size, (char *)key.data);
        !           225:                        continue;
        !           226:                }
        !           227:                ++reccnt;
        !           228:
        !           229:                /* If only one name, ignore the rest. */
        !           230:                if ((p = strchr(bp, '|')) == NULL)
        !           231:                        continue;
        !           232:
        !           233:                /* The rest of the names reference the entire name. */
        !           234:                ((char *)(data.data))[0] = SHADOW;
        !           235:                (void) memmove(&((u_char *)(data.data))[1], key.data, key.size);
        !           236:                data.size = key.size + 1;
        !           237:
        !           238:                /* Store references for other names. */
        !           239:                for (p = t = bp;; ++p) {
        !           240:                        if (p > t && (*p == ',' || *p == '|')) {
        !           241:                                key.size = p - t;
        !           242:                                key.data = t;
        !           243:
        !           244:                                switch(infodbp->put(infodbp,
        !           245:                                    &key, &data, R_NOOVERWRITE)) {
        !           246:                                case -1:
        !           247:                                        err(1, "put");
        !           248:                                        /* NOTREACHED */
        !           249:                                case 1:
        !           250:                                        warnx("ignored duplicate: %.*s",
        !           251:                                            (int)key.size, (char *)key.data);
        !           252:                                }
        !           253:                                t = p + 1;
        !           254:                        }
        !           255:                        if (*p == ',')
        !           256:                                break;
        !           257:                }
        !           258:        }
        !           259:
        !           260:        switch(st) {
        !           261:        case -1:
        !           262:                err(1, "file argument");
        !           263:                /* NOTREACHED */
        !           264:        case -2:
        !           265:                errx(1, "potential reference loop detected");
        !           266:                /* NOTREACHED */
        !           267:        }
        !           268:
        !           269:        if (verbose)
        !           270:                (void)printf("info_mkdb: %d capability records\n", reccnt);
        !           271: }
        !           272:
        !           273: void
        !           274: usage()
        !           275: {
        !           276:        (void)fprintf(stderr,
        !           277:            "usage: info_mkdb [-v] [-f outfile] file1 [file2 ...]\n");
        !           278:        exit(1);
        !           279: }