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

Annotation of src/usr.bin/cap_mkdb/getinfo.c, Revision 1.19

1.19    ! deraadt     1: /*     $OpenBSD: getinfo.c,v 1.18 2011/07/22 01:11:05 millert Exp $    */
1.1       tholo       2:
                      3: /*-
                      4:  * Copyright (c) 1992, 1993
                      5:  *     The Regents of the University of California.
                      6:  * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
                      7:  * All rights reserved.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
1.14      deraadt    17:  * 3. The name of the author may not be used to endorse or promote products
1.1       tholo      18:  *    derived from this software without specific prior written permission.
                     19:  *
                     20:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
                     21:  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
                     22:  * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
                     23:  * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
                     24:  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
                     25:  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
                     26:  * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     27:  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
                     28:  * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
                     29:  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: #include <sys/types.h>
                     33:
                     34: #include <ctype.h>
1.17      nicm       35: #include <errno.h>
1.1       tholo      36: #include <fcntl.h>
                     37: #include <limits.h>
                     38: #include <stdio.h>
                     39: #include <stdlib.h>
                     40: #include <string.h>
                     41: #include <unistd.h>
                     42:
                     43: #define        BFRAG           1024
                     44: #define        BSIZE           1024
                     45: #define        ESC             ('[' & 037)     /* ASCII ESC */
                     46: #define        MAX_RECURSION   32              /* maximum getent recursion */
                     47: #define        SFRAG           100             /* cgetstr mallocs in SFRAG chunks */
                     48:
                     49: #define RECOK  (char)0
                     50: #define TCERR  (char)1
                     51: #define        SHADOW  (char)2
                     52:
1.18      millert    53: static int      getent(char **, u_int *, char **, FILE *, char *, int);
1.5       millert    54: static char    *igetcap(char *, char *, int);
                     55: static int      igetmatch(char *, char *);
                     56: static int      igetclose(void);
1.1       tholo      57:
1.5       millert    58: int    igetnext(char **, char **);
1.1       tholo      59:
                     60: /*
1.8       jmc        61:  * Igetcap searches the capability record buf for the capability cap with
1.1       tholo      62:  * type `type'.  A pointer to the value of cap is returned on success, NULL
                     63:  * if the requested capability couldn't be found.
                     64:  *
                     65:  * Specifying a type of ',' means that nothing should follow cap (,cap,).
                     66:  * In this case a pointer to the terminating ',' or NUL will be returned if
                     67:  * cap is found.
                     68:  *
                     69:  * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator)
                     70:  * return NULL.
                     71:  */
                     72: static char *
1.7       deraadt    73: igetcap(char *buf, char *cap, int type)
1.1       tholo      74: {
1.4       mpech      75:        char *bp, *cp;
1.1       tholo      76:
                     77:        bp = buf;
                     78:        for (;;) {
                     79:                /*
                     80:                 * Skip past the current capability field - it's either the
                     81:                 * name field if this is the first time through the loop, or
                     82:                 * the remainder of a field whose name failed to match cap.
                     83:                 */
                     84:                for (;;)
                     85:                        if (*bp == '\0')
                     86:                                return (NULL);
                     87:                        else
                     88:                                if (*bp++ == ',')
                     89:                                        break;
                     90:
                     91:                /*
                     92:                 * Try to match (cap, type) in buf.
                     93:                 */
                     94:                for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++)
                     95:                        continue;
                     96:                if (*cp != '\0')
                     97:                        continue;
                     98:                if (*bp == '@')
                     99:                        return (NULL);
                    100:                if (type == ',') {
                    101:                        if (*bp != '\0' && *bp != ',')
                    102:                                continue;
                    103:                        return(bp);
                    104:                }
                    105:                if (*bp != type)
                    106:                        continue;
                    107:                bp++;
                    108:                return (*bp == '@' ? NULL : bp);
                    109:        }
                    110:        /* NOTREACHED */
                    111: }
                    112:
                    113: /*
1.18      millert   114:  * Getent implements the functions of igetent.  If fp is non-NULL,
                    115:  * *db_array has already been opened and fp is the open file descriptor.  We
1.1       tholo     116:  * do this to save time and avoid using up file descriptors for use=
                    117:  * recursions.
                    118:  *
                    119:  * Getent returns the same success/failure codes as igetent.  On success, a
                    120:  * pointer to a malloc'ed capability record with all use= capabilities fully
                    121:  * expanded and its length (not including trailing ASCII NUL) are left in
                    122:  * *cap and *len.
                    123:  *
                    124:  * Basic algorithm:
                    125:  *     + Allocate memory incrementally as needed in chunks of size BFRAG
                    126:  *       for capability buffer.
                    127:  *     + Recurse for each use=name and interpolate result.  Stop when all
                    128:  *       names interpolated, a name can't be found, or depth exceeds
                    129:  *       MAX_RECURSION.
                    130:  */
                    131: static int
1.18      millert   132: getent(char **cap, u_int *len, char **db_array, FILE *fp, char *name, int depth)
1.1       tholo     133: {
1.4       mpech     134:        char *r_end, *rp, **db_p;
1.1       tholo     135:        int myfd, eof, foundit;
1.12      ray       136:        char *record, *s;
1.1       tholo     137:        int tc_not_resolved;
1.17      nicm      138:
1.1       tholo     139:        /*
                    140:         * Return with ``loop detected'' error if we've recursed more than
                    141:         * MAX_RECURSION times.
                    142:         */
                    143:        if (depth > MAX_RECURSION)
                    144:                return (-3);
                    145:
1.18      millert   146:         /*
                    147:          * If no name we better have a record in cap
                    148:          */
                    149:         if (depth == 0 && name == NULL) {
                    150:                 if ((record = malloc(*len + 1 + BFRAG)) == NULL)
                    151:                         return (-2);
                    152:                 memcpy(record, *cap, *len);
                    153:                 myfd = 0;
                    154:                 db_p = db_array;
                    155:                 rp = record + *len + 1;
                    156:                 r_end = rp + BFRAG;
                    157:                *rp = '\0';
                    158:                 goto exp_use;
                    159:         }
                    160:
1.1       tholo     161:        /*
                    162:         * Allocate first chunk of memory.
                    163:         */
                    164:        if ((record = malloc(BFRAG)) == NULL) {
                    165:                errno = ENOMEM;
                    166:                return (-2);
                    167:        }
                    168:        r_end = record + BFRAG;
                    169:        foundit = 0;
                    170:        rp = NULL;
                    171:        myfd = -1;
1.18      millert   172:
1.1       tholo     173:        /*
                    174:         * Loop through database array until finding the record.
                    175:         */
                    176:        for (db_p = db_array; *db_p != NULL; db_p++) {
                    177:                eof = 0;
                    178:
                    179:                /*
                    180:                 * Open database if not already open.
                    181:                 */
                    182:
1.18      millert   183:                if (fp != NULL) {
                    184:                        (void)fseek(fp, 0L, SEEK_SET);
1.1       tholo     185:                        myfd = 0;
                    186:                } else {
1.18      millert   187:                        fp = fopen(*db_p, "r");
                    188:                        if (fp == NULL) {
1.1       tholo     189:                                /* No error on unfound file. */
                    190:                                continue;
                    191:                        }
                    192:                        myfd = 1;
                    193:                }
                    194:                /*
                    195:                 * Find the requested capability record ...
                    196:                 */
                    197:                {
                    198:                char buf[BUFSIZ];
1.4       mpech     199:                char *b_end, *bp;
                    200:                int c;
1.1       tholo     201:
                    202:                /*
                    203:                 * Loop invariants:
                    204:                 *      There is always room for one more character in record.
                    205:                 *      R_end always points just past end of record.
                    206:                 *      Rp always points just past last character in record.
                    207:                 *      B_end always points just past last character in buf.
                    208:                 *      Bp always points at next character in buf.
                    209:                 */
                    210:                b_end = buf;
                    211:                bp = buf;
                    212:                for (;;) {
                    213:
                    214:                        /*
1.18      millert   215:                         * Read in a record implementing line continuation.
1.1       tholo     216:                         */
                    217:                        rp = record;
                    218:                        for (;;) {
                    219:                                if (bp >= b_end) {
1.18      millert   220:                                        size_t n;
1.17      nicm      221:
1.18      millert   222:                                        n = fread(buf, 1, sizeof(buf), fp);
                    223:                                        if (n == 0) {
                    224:                                                eof = feof(fp);
1.1       tholo     225:                                                if (myfd)
1.18      millert   226:                                                        (void)fclose(fp);
                    227:                                                if (eof) {
                    228:                                                        fp = NULL;
1.1       tholo     229:                                                        break;
                    230:                                                }
1.18      millert   231:                                                free(record);
                    232:                                                return (-2);
1.1       tholo     233:                                        }
                    234:                                        b_end = buf+n;
                    235:                                        bp = buf;
                    236:                                }
1.17      nicm      237:
1.19    ! deraadt   238:                                c = (unsigned char)*bp++;
1.1       tholo     239:                                if (c == '\n') {
                    240:                                        if (bp >= b_end) {
1.18      millert   241:                                                size_t n;
1.1       tholo     242:
1.18      millert   243:                                                n = fread(buf, 1, sizeof(buf), fp);
                    244:                                                if (n == 0) {
                    245:                                                        eof = feof(fp);
1.1       tholo     246:                                                        if (myfd)
1.18      millert   247:                                                                (void)fclose(fp);
                    248:                                                        if (eof) {
                    249:                                                                fp = NULL;
1.1       tholo     250:                                                                break;
                    251:                                                        }
1.18      millert   252:                                                        free(record);
                    253:                                                        return (-2);
1.1       tholo     254:                                                }
                    255:                                                b_end = buf+n;
                    256:                                                bp = buf;
                    257:                                        }
                    258:                                        if (rp > record && isspace(*bp))
                    259:                                                continue;
                    260:                                        else
                    261:                                                break;
                    262:                                }
                    263:                                if (rp <= record || *(rp - 1) != ',' || !isspace(c))
                    264:                                        *rp++ = c;
                    265:
                    266:                                /*
1.17      nicm      267:                                 * Enforce loop invariant: if no room
1.1       tholo     268:                                 * left in record buffer, try to get
                    269:                                 * some more.
                    270:                                 */
                    271:                                if (rp >= r_end) {
1.18      millert   272:                                        size_t off;
1.1       tholo     273:                                        size_t newsize;
                    274:
1.18      millert   275:                                        off = rp - record;
1.1       tholo     276:                                        newsize = r_end - record + BFRAG;
1.12      ray       277:                                        s = realloc(record, newsize);
                    278:                                        if (s == NULL) {
                    279:                                                free(record);
1.1       tholo     280:                                                errno = ENOMEM;
                    281:                                                if (myfd)
1.18      millert   282:                                                        (void)fclose(fp);
1.1       tholo     283:                                                return (-2);
                    284:                                        }
1.12      ray       285:                                        record = s;
1.1       tholo     286:                                        r_end = record + newsize;
1.18      millert   287:                                        rp = record + off;
1.1       tholo     288:                                }
                    289:                        }
1.11      ray       290:                        /* loop invariant lets us do this */
1.1       tholo     291:                        *rp++ = '\0';
1.17      nicm      292:
1.1       tholo     293:                        /*
                    294:                         * Toss blank lines and comments.
                    295:                         */
                    296:                        if (*record == '\0' || *record == '#')
                    297:                                continue;
1.17      nicm      298:
1.1       tholo     299:                        /*
                    300:                         * See if this is the record we want ...
                    301:                         */
                    302:                        if (igetmatch(record, name) == 0) {
                    303:                                foundit = 1;
                    304:                                break;  /* found it! */
                    305:                        }
1.2       naddy     306:
                    307:                        /*
                    308:                         * If encountered eof check next file.
                    309:                         */
                    310:                        if (eof)
                    311:                                break;
1.1       tholo     312:                }
                    313:        }
                    314:                if (foundit)
                    315:                        break;
                    316:        }
                    317:
1.16      nicm      318:        if (!foundit) {
                    319:                free(record);
1.1       tholo     320:                return (-1);
1.16      nicm      321:        }
1.1       tholo     322:
                    323:        /*
                    324:         * Got the capability record, but now we have to expand all use=name
                    325:         * references in it ...
                    326:         */
1.18      millert   327: exp_use: {
1.12      ray       328:                char *newicap;
1.4       mpech     329:                int newilen;
1.1       tholo     330:                u_int ilen;
                    331:                int diff, iret, tclen;
                    332:                char *icap, *scan, *tc, *tcstart, *tcend;
                    333:
                    334:                /*
                    335:                 * Loop invariants:
                    336:                 *      There is room for one more character in record.
                    337:                 *      R_end points just past end of record.
                    338:                 *      Rp points just past last character in record.
                    339:                 *      Scan points at remainder of record that needs to be
                    340:                 *      scanned for use=name constructs.
                    341:                 */
                    342:                scan = record;
                    343:                tc_not_resolved = 0;
                    344:                for (;;) {
                    345:                        if ((tc = igetcap(scan, "use", '=')) == NULL)
                    346:                                break;
                    347:
                    348:                        /*
                    349:                         * Find end of use=name and stomp on the trailing `,'
                    350:                         * (if present) so we can use it to call ourselves.
                    351:                         */
1.12      ray       352:                        s = tc + strcspn(tc, ",");
                    353:                        if (*s == ',') {
                    354:                                *s = '\0';
                    355:                                ++s;
                    356:                        }
1.1       tholo     357:                        tcstart = tc - 4;
                    358:                        tclen = s - tcstart;
                    359:                        tcend = s;
                    360:
1.18      millert   361:                        iret = getent(&icap, &ilen, db_p, fp, tc, depth+1);
1.1       tholo     362:                        newicap = icap;         /* Put into a register. */
                    363:                        newilen = ilen;
                    364:                        if (iret != 0) {
                    365:                                /* an error */
                    366:                                if (iret < -1) {
                    367:                                        if (myfd)
1.18      millert   368:                                                (void)fclose(fp);
1.1       tholo     369:                                        free(record);
                    370:                                        return (iret);
                    371:                                }
                    372:                                if (iret == 1)
                    373:                                        tc_not_resolved = 1;
                    374:                                /* couldn't resolve tc */
                    375:                                if (iret == -1) {
1.17      nicm      376:                                        *(s - 1) = ',';
1.1       tholo     377:                                        scan = s - 1;
                    378:                                        tc_not_resolved = 1;
                    379:                                        continue;
1.17      nicm      380:
1.1       tholo     381:                                }
                    382:                        }
                    383:                        /* not interested in name field of tc'ed record */
1.12      ray       384:                        s = newicap + strcspn(newicap, ",");
                    385:                        if (*s == ',')
                    386:                                ++s;
1.1       tholo     387:                        newilen -= s - newicap;
                    388:                        newicap = s;
                    389:
                    390:                        /* make sure interpolated record is `,'-terminated */
                    391:                        s += newilen;
                    392:                        if (*(s-1) != ',') {
                    393:                                *s = ',';       /* overwrite NUL with , */
                    394:                                newilen++;
                    395:                        }
                    396:
                    397:                        /*
                    398:                         * Make sure there's enough room to insert the
                    399:                         * new record.
                    400:                         */
                    401:                        diff = newilen - tclen;
                    402:                        if (diff >= r_end - rp) {
1.18      millert   403:                                size_t off, tcoff, tcoffend;
1.1       tholo     404:                                size_t newsize;
                    405:
1.18      millert   406:                                off = rp - record;
1.1       tholo     407:                                newsize = r_end - record + diff + BFRAG;
1.18      millert   408:                                tcoff = tcstart - record;
                    409:                                tcoffend = tcend - record;
1.12      ray       410:                                s = realloc(record, newsize);
                    411:                                if (s == NULL) {
                    412:                                        free(record);
1.1       tholo     413:                                        errno = ENOMEM;
                    414:                                        if (myfd)
1.18      millert   415:                                                (void)fclose(fp);
1.1       tholo     416:                                        free(icap);
                    417:                                        return (-2);
                    418:                                }
1.12      ray       419:                                record = s;
1.1       tholo     420:                                r_end = record + newsize;
1.18      millert   421:                                rp = record + off;
                    422:                                tcstart = record + tcoff;
                    423:                                tcend = record + tcoffend;
1.1       tholo     424:                        }
                    425:
                    426:                        /*
                    427:                         * Insert tc'ed record into our record.
                    428:                         */
                    429:                        s = tcstart + newilen;
                    430:                        bcopy(tcend, s, (size_t)(rp - tcend));
                    431:                        bcopy(newicap, tcstart, (size_t)newilen);
                    432:                        rp += diff;
                    433:                        free(icap);
                    434:
                    435:                        /*
                    436:                         * Start scan on `,' so next igetcap works properly
                    437:                         * (igetcap always skips first field).
                    438:                         */
                    439:                        scan = s-1;
                    440:                }
1.17      nicm      441:
1.1       tholo     442:        }
                    443:        /*
                    444:         * Close file (if we opened it), give back any extra memory, and
                    445:         * return capability, length and success.
                    446:         */
                    447:        if (myfd)
1.18      millert   448:                (void)fclose(fp);
1.1       tholo     449:        *len = rp - record - 1; /* don't count NUL */
1.12      ray       450:        if (r_end > rp) {
1.17      nicm      451:                if ((s =
1.1       tholo     452:                     realloc(record, (size_t)(rp - record))) == NULL) {
1.12      ray       453:                        free(record);
1.1       tholo     454:                        errno = ENOMEM;
                    455:                        return (-2);
1.12      ray       456:                } else
                    457:                        record = s;
                    458:        }
1.17      nicm      459:
1.1       tholo     460:        *cap = record;
                    461:        if (tc_not_resolved)
                    462:                return (1);
                    463:        return (0);
1.17      nicm      464: }
1.1       tholo     465:
                    466: /*
1.8       jmc       467:  * Igetmatch will return 0 if name is one of the names of the capability
1.1       tholo     468:  * record buf, -1 if not.
                    469:  */
                    470: static int
1.7       deraadt   471: igetmatch(char *buf, char *name)
1.1       tholo     472: {
1.4       mpech     473:        char *np, *bp;
1.1       tholo     474:
                    475:        /*
                    476:         * Start search at beginning of record.
                    477:         */
                    478:        bp = buf;
                    479:        for (;;) {
                    480:                /*
                    481:                 * Try to match a record name.
                    482:                 */
                    483:                np = name;
                    484:                for (;;)
                    485:                        if (*np == '\0') {
                    486:                                if (*bp == '|' || *bp == ',' || *bp == '\0')
                    487:                                        return (0);
                    488:                                else
                    489:                                        break;
                    490:                        } else {
                    491:                                if (*bp++ != *np++)
                    492:                                        break;
                    493:                        }
                    494:
                    495:                /*
                    496:                 * Match failed, skip to next name in record.
                    497:                 */
                    498:                bp--;   /* a '|' or ',' may have stopped the match */
                    499:                for (;;)
                    500:                        if (*bp == '\0' || *bp == ',')
                    501:                                return (-1);    /* match failed totally */
                    502:                        else
                    503:                                if (*bp++ == '|')
                    504:                                        break;  /* found next name */
                    505:        }
                    506: }
                    507:
                    508: static FILE *pfp;
                    509: static int slash;
                    510: static char **dbp;
                    511:
                    512: static int
1.7       deraadt   513: igetclose(void)
1.1       tholo     514: {
                    515:        if (pfp != NULL) {
                    516:                (void)fclose(pfp);
                    517:                pfp = NULL;
                    518:        }
                    519:        dbp = NULL;
                    520:        slash = 0;
                    521:        return(0);
                    522: }
                    523:
                    524: /*
1.17      nicm      525:  * Igetnext() gets either the first or next entry in the logical database
1.1       tholo     526:  * specified by db_array.  It returns 0 upon completion of the database, 1
                    527:  * upon returning an entry with more remaining, and -1 if an error occurs.
                    528:  */
                    529: int
1.18      millert   530: igetnext(char **cap, char **db_array)
1.1       tholo     531: {
1.18      millert   532:        int c, eof = 0, serrno, status = -1;
                    533:        char buf[BUFSIZ];
                    534:        char *b_end, *bp, *r_end, *rp;
                    535:        char *record = NULL;
                    536:        u_int len;
                    537:        off_t pos;
1.1       tholo     538:
                    539:        if (dbp == NULL)
                    540:                dbp = db_array;
                    541:
1.18      millert   542:        if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL)
                    543:                goto done;
                    544:
                    545:        /*
                    546:         * Allocate first chunk of memory.
                    547:         */
                    548:        if ((record = malloc(BFRAG)) == NULL)
                    549:                goto done;
                    550:        r_end = record + BFRAG;
                    551:
                    552:        /*
                    553:         * Find the next capability record
                    554:         */
                    555:        /*
                    556:         * Loop invariants:
                    557:         *      There is always room for one more character in record.
                    558:         *      R_end always points just past end of record.
                    559:         *      Rp always points just past last character in record.
                    560:         *      B_end always points just past last character in buf.
                    561:         *      Bp always points at next character in buf.
                    562:         */
                    563:        b_end = buf;
                    564:        bp = buf;
1.10      ray       565:        for (;;) {
1.18      millert   566:                /*
                    567:                 * If encountered EOF check next file.
                    568:                 */
                    569:                if (eof) {
                    570:                        (void)fclose(pfp);
                    571:                        pfp = NULL;
                    572:                        if (*++dbp == NULL) {
                    573:                                status = 0;
                    574:                                break;
1.1       tholo     575:                        }
1.18      millert   576:                        if ((pfp = fopen(*dbp, "r")) == NULL)
                    577:                                break;
                    578:                        eof = 0;
1.1       tholo     579:                }
                    580:
1.17      nicm      581:                /*
1.18      millert   582:                 * Read in a record implementing line continuation.
1.1       tholo     583:                 */
1.18      millert   584:                rp = record;
1.1       tholo     585:                for (;;) {
1.18      millert   586:                        if (bp >= b_end) {
                    587:                                size_t n;
                    588:
                    589:                                n = fread(buf, 1, sizeof(buf), pfp);
                    590:                                if (n == 0) {
                    591:                                        eof = feof(pfp);
                    592:                                        if (eof)
                    593:                                                break;
                    594:                                        else
                    595:                                                goto done;
1.1       tholo     596:                                }
1.18      millert   597:                                b_end = buf + n;
                    598:                                bp = buf;
1.1       tholo     599:                        }
1.18      millert   600:
1.19    ! deraadt   601:                        c = (unsigned char)*bp++;
1.18      millert   602:                        if (c == '\n') {
                    603:                                if (bp >= b_end) {
                    604:                                        size_t n;
                    605:
                    606:                                        n = fread(buf, 1, sizeof(buf), pfp);
                    607:                                        if (n == 0) {
                    608:                                                eof = feof(pfp);
                    609:                                                if (eof)
                    610:                                                        break;
                    611:                                                else
                    612:                                                        goto done;
1.1       tholo     613:                                        }
1.18      millert   614:                                        b_end = buf + n;
                    615:                                        bp = buf;
                    616:                                }
                    617:                                if (rp > record && isspace(*bp))
                    618:                                        continue;
                    619:                                else
1.9       ray       620:                                        break;
1.18      millert   621:                        }
                    622:                        if (rp <= record || *(rp - 1) != ',' || !isspace(c))
                    623:                                *rp++ = c;
                    624:
                    625:                        /*
                    626:                         * Enforce loop invariant: if no room
                    627:                         * left in record buffer, try to get
                    628:                         * some more.
                    629:                         */
                    630:                        if (rp >= r_end) {
                    631:                                size_t newsize, off;
                    632:                                char *nrecord;
                    633:
                    634:                                off = rp - record;
                    635:                                newsize = r_end - record + BFRAG;
                    636:                                nrecord = realloc(record, newsize);
                    637:                                if (nrecord == NULL)
                    638:                                        goto done;
                    639:                                record = nrecord;
                    640:                                r_end = record + newsize;
                    641:                                rp = record + off;
1.1       tholo     642:                        }
                    643:                }
1.18      millert   644:                /* loop invariant lets us do this */
                    645:                *rp++ = '\0';
                    646:
                    647:                /*
                    648:                 * Toss blank lines and comments.
                    649:                 */
                    650:                if (*record == '\0' || *record == '#')
                    651:                        continue;
                    652:
                    653:                /* rewind to end of record */
                    654:                fseeko(pfp, (off_t)(bp - b_end), SEEK_CUR);
1.1       tholo     655:
1.18      millert   656:                /* we pass the record to getent() in cap */
                    657:                *cap = record;
                    658:                len = rp - record;
                    659:
                    660:                /* return value of getent() is one less than igetnext() */
                    661:                pos = ftello(pfp);
                    662:                status = getent(cap, &len, dbp, pfp, NULL, 0) + 1;
                    663:                if (status > 0)
                    664:                        fseeko(pfp, pos, SEEK_SET);
                    665:                break;
                    666:        }
                    667: done:
                    668:        serrno = errno;
                    669:        free(record);
                    670:        if (status <= 0)
                    671:                (void)igetclose();
                    672:        errno = serrno;
1.1       tholo     673:
1.18      millert   674:        return (status);
1.1       tholo     675: }