summaryrefslogtreecommitdiff
path: root/usr.bin/cap_mkdb
diff options
context:
space:
mode:
Diffstat (limited to 'usr.bin/cap_mkdb')
-rw-r--r--usr.bin/cap_mkdb/Makefile4
-rw-r--r--usr.bin/cap_mkdb/cap_mkdb.125
-rw-r--r--usr.bin/cap_mkdb/cap_mkdb.c110
-rw-r--r--usr.bin/cap_mkdb/getinfo.c675
4 files changed, 38 insertions, 776 deletions
diff --git a/usr.bin/cap_mkdb/Makefile b/usr.bin/cap_mkdb/Makefile
index 55b86c5c7f8..63ce2f5b974 100644
--- a/usr.bin/cap_mkdb/Makefile
+++ b/usr.bin/cap_mkdb/Makefile
@@ -1,6 +1,6 @@
-# $OpenBSD: Makefile,v 1.4 1999/03/05 04:47:45 tholo Exp $
+# $OpenBSD: Makefile,v 1.5 2015/12/04 13:58:09 nicm Exp $
PROG= cap_mkdb
-SRCS= cap_mkdb.c getinfo.c
+SRCS= cap_mkdb.c
.include <bsd.prog.mk>
diff --git a/usr.bin/cap_mkdb/cap_mkdb.1 b/usr.bin/cap_mkdb/cap_mkdb.1
index 796a0c6f0e0..36861c8f85e 100644
--- a/usr.bin/cap_mkdb/cap_mkdb.1
+++ b/usr.bin/cap_mkdb/cap_mkdb.1
@@ -1,4 +1,4 @@
-.\" $OpenBSD: cap_mkdb.1,v 1.18 2015/12/03 11:32:34 nicm Exp $
+.\" $OpenBSD: cap_mkdb.1,v 1.19 2015/12/04 13:58:09 nicm Exp $
.\" $NetBSD: cap_mkdb.1,v 1.4 1995/03/26 03:59:36 glass Exp $
.\"
.\" Copyright (c) 1992, 1993
@@ -30,7 +30,7 @@
.\"
.\" @(#)cap_mkdb.1 8.1 (Berkeley) 6/6/93
.\"
-.Dd $Mdocdate: December 3 2015 $
+.Dd $Mdocdate: December 4 2015 $
.Dt CAP_MKDB 1
.Os
.Sh NAME
@@ -46,8 +46,6 @@
.Nm
builds a hashed database out of the
.Xr getcap 3
-or
-.Xr terminfo 5
logical database constructed by the concatenation of the specified
files.
.Pp
@@ -68,10 +66,6 @@ The options are as follows:
.Bl -tag -width Ds
.It Fl f Ar outfile
Specify a different database basename.
-.It Fl i
-Expect the capability records to be parsed to be in
-.Xr terminfo 5
-format.
.It Fl v
Print out the number of capability records in the database.
.El
@@ -99,22 +93,9 @@ in a key/data pair of the second type.
The data field of this key/data pair is used to look up a key/data
pair of the first type which has the real data associated with the
name.
-.Sh FILES
-.Bl -tag -width /usr/share/misc/termcap.db -compact
-.It Pa /usr/share/misc/termcap
-uncompiled terminal capabilities file
-.It Pa /usr/share/misc/termcap.db
-terminal capabilities database
-.It Pa /usr/share/terminfo
-terminal information database
-.It Pa /etc/termcap
-symbolic link to
-.Pa /usr/share/misc/termcap
-.El
.Sh EXIT STATUS
.Ex -std cap_mkdb
.Sh SEE ALSO
.Xr dbopen 3 ,
.Xr getcap 3 ,
-.Xr termcap 5 ,
-.Xr terminfo 5
+.Xr termcap 5
diff --git a/usr.bin/cap_mkdb/cap_mkdb.c b/usr.bin/cap_mkdb/cap_mkdb.c
index 7175d2603d6..4911a65ea7a 100644
--- a/usr.bin/cap_mkdb/cap_mkdb.c
+++ b/usr.bin/cap_mkdb/cap_mkdb.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: cap_mkdb.c,v 1.20 2015/10/29 02:58:00 deraadt Exp $ */
+/* $OpenBSD: cap_mkdb.c,v 1.21 2015/12/04 13:58:09 nicm Exp $ */
/* $NetBSD: cap_mkdb.c,v 1.5 1995/09/02 05:47:12 jtc Exp $ */
/*-
@@ -53,7 +53,7 @@ int igetnext(char **, char **);
int main(int, char *[]);
DB *capdbp;
-int info, verbose;
+int verbose;
char *capname, buf[8 * 1024];
HASHINFO openinfo = {
@@ -89,9 +89,6 @@ main(int argc, char *argv[])
case 'v':
verbose = 1;
break;
- case 'i':
- info = 1;
- break;
case '?':
default:
usage();
@@ -151,23 +148,21 @@ db_build(char **ifiles)
recno_t reccnt;
size_t len, bplen;
int st;
- char *bp, *p, *t, *out, ch;
+ char *bp, *p, *t, *capbeg, *capend;
cgetusedb(0); /* disable reading of .db files in getcap(3) */
data.data = NULL;
key.data = NULL;
- for (reccnt = 0, bplen = 0;
- (st = (info ? igetnext(&bp, ifiles) : cgetnext(&bp, ifiles))) > 0;) {
+ for (reccnt = 0, bplen = 0; (st = cgetnext(&bp, ifiles)) > 0;) {
/*
- * Allocate enough memory to store four times the size of the
- * record (so an existing ':' can be expanded to '\072' for
- * terminfo) plus a terminating NULL and one extra byte.
+ * Allocate enough memory to store the size of the record plus
+ * a terminating NULL and one extra byte.
*/
len = strlen(bp);
- if (bplen <= 4 * len + 2) {
- int newbplen = bplen + MAXIMUM(256, 4 * len + 2);
+ if (bplen <= len + 2) {
+ int newbplen = bplen + MAXIMUM(256, len + 2);
void *newdata;
if ((newdata = realloc(data.data, newbplen)) == NULL)
@@ -177,7 +172,7 @@ db_build(char **ifiles)
}
/* Find the end of the name field. */
- if ((p = strchr(bp, info ? ',' : ':')) == NULL) {
+ if ((p = strchr(bp, ':')) == NULL) {
warnx("no name field: %.*s", (int)MINIMUM(len, 20), bp);
continue;
}
@@ -194,70 +189,31 @@ db_build(char **ifiles)
}
/* Create the stored record. */
- if (info) {
- /*
- * The record separator is :, so it is necessary to
- * change commas into colons. However, \, should be
- * left alone, unless the \ is the last part of ^\.
- */
- data.size = len + 2;
- out = ((char *) data.data) + 1;
- t = bp;
- while (t < bp + len) {
- switch (ch = *t++) {
- case '^':
- case '\\':
- *out++ = ch;
- if (*t != '\0')
- *out++ = *t++;
- break;
- case ':':
- memcpy(out, "\\072", 4);
- out += 4;
- data.size += 3; /* : already counted */
- break;
- case ',':
- *out++ = ':';
- break;
- default:
- *out++ = ch;
- break;
- }
- }
- *out++ = '\0';
- if (memchr((char *)data.data + 1, '\0', data.size - 2)) {
- warnx("NUL in entry: %.*s", (int)MINIMUM(len, 20), bp);
- continue;
- }
- } else {
- char *capbeg, *capend;
+ t = (char *)data.data + 1;
+ /* Copy the cap name and trailing ':' */
+ len = p - bp + 1;
+ memcpy(t, bp, len);
+ t += len;
+
+ /* Copy entry, collapsing empty fields. */
+ capbeg = p + 1;
+ while (*capbeg) {
+ /* Skip empty fields. */
+ if ((len = strspn(capbeg, ": \t\n\r")))
+ capbeg += len;
- t = (char *)data.data + 1;
- /* Copy the cap name and trailing ':' */
- len = p - bp + 1;
- memcpy(t, bp, len);
+ /* Find the end of this cap and copy it w/ : */
+ capend = strchr(capbeg, ':');
+ if (capend)
+ len = capend - capbeg + 1;
+ else
+ len = strlen(capbeg);
+ memcpy(t, capbeg, len);
t += len;
-
- /* Copy entry, collapsing empty fields. */
- capbeg = p + 1;
- while (*capbeg) {
- /* Skip empty fields. */
- if ((len = strspn(capbeg, ": \t\n\r")))
- capbeg += len;
-
- /* Find the end of this cap and copy it w/ : */
- capend = strchr(capbeg, ':');
- if (capend)
- len = capend - capbeg + 1;
- else
- len = strlen(capbeg);
- memcpy(t, capbeg, len);
- t += len;
- capbeg += len;
- }
- *t = '\0';
- data.size = t - (char *)data.data + 1;
+ capbeg += len;
}
+ *t = '\0';
+ data.size = t - (char *)data.data + 1;
/* Store the record under the name field. */
key.data = bp;
@@ -285,7 +241,7 @@ db_build(char **ifiles)
/* Store references for other names. */
for (p = t = bp;; ++p) {
- if (p > t && (*p == (info ? ',' : ':') || *p == '|')) {
+ if (p > t && (*p == ':' || *p == '|')) {
key.size = p - t;
key.data = t;
@@ -309,7 +265,7 @@ db_build(char **ifiles)
}
t = p + 1;
}
- if (*p == (info ? ',' : ':'))
+ if (*p == ':')
break;
}
free(bp);
diff --git a/usr.bin/cap_mkdb/getinfo.c b/usr.bin/cap_mkdb/getinfo.c
deleted file mode 100644
index 228cb448afc..00000000000
--- a/usr.bin/cap_mkdb/getinfo.c
+++ /dev/null
@@ -1,675 +0,0 @@
-/* $OpenBSD: getinfo.c,v 1.19 2013/11/26 18:47:06 deraadt Exp $ */
-
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California.
- * Copyright (c) 1996 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
- * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
- * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
- * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
- * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
- * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
- * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define BFRAG 1024
-#define BSIZE 1024
-#define ESC ('[' & 037) /* ASCII ESC */
-#define MAX_RECURSION 32 /* maximum getent recursion */
-#define SFRAG 100 /* cgetstr mallocs in SFRAG chunks */
-
-#define RECOK (char)0
-#define TCERR (char)1
-#define SHADOW (char)2
-
-static int getent(char **, u_int *, char **, FILE *, char *, int);
-static char *igetcap(char *, char *, int);
-static int igetmatch(char *, char *);
-static int igetclose(void);
-
-int igetnext(char **, char **);
-
-/*
- * Igetcap searches the capability record buf for the capability cap with
- * type `type'. A pointer to the value of cap is returned on success, NULL
- * if the requested capability couldn't be found.
- *
- * Specifying a type of ',' means that nothing should follow cap (,cap,).
- * In this case a pointer to the terminating ',' or NUL will be returned if
- * cap is found.
- *
- * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator)
- * return NULL.
- */
-static char *
-igetcap(char *buf, char *cap, int type)
-{
- char *bp, *cp;
-
- bp = buf;
- for (;;) {
- /*
- * Skip past the current capability field - it's either the
- * name field if this is the first time through the loop, or
- * the remainder of a field whose name failed to match cap.
- */
- for (;;)
- if (*bp == '\0')
- return (NULL);
- else
- if (*bp++ == ',')
- break;
-
- /*
- * Try to match (cap, type) in buf.
- */
- for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++)
- continue;
- if (*cp != '\0')
- continue;
- if (*bp == '@')
- return (NULL);
- if (type == ',') {
- if (*bp != '\0' && *bp != ',')
- continue;
- return(bp);
- }
- if (*bp != type)
- continue;
- bp++;
- return (*bp == '@' ? NULL : bp);
- }
- /* NOTREACHED */
-}
-
-/*
- * Getent implements the functions of igetent. If fp is non-NULL,
- * *db_array has already been opened and fp is the open file descriptor. We
- * do this to save time and avoid using up file descriptors for use=
- * recursions.
- *
- * Getent returns the same success/failure codes as igetent. On success, a
- * pointer to a malloc'ed capability record with all use= capabilities fully
- * expanded and its length (not including trailing ASCII NUL) are left in
- * *cap and *len.
- *
- * Basic algorithm:
- * + Allocate memory incrementally as needed in chunks of size BFRAG
- * for capability buffer.
- * + Recurse for each use=name and interpolate result. Stop when all
- * names interpolated, a name can't be found, or depth exceeds
- * MAX_RECURSION.
- */
-static int
-getent(char **cap, u_int *len, char **db_array, FILE *fp, char *name, int depth)
-{
- char *r_end, *rp, **db_p;
- int myfd, eof, foundit;
- char *record, *s;
- int tc_not_resolved;
-
- /*
- * Return with ``loop detected'' error if we've recursed more than
- * MAX_RECURSION times.
- */
- if (depth > MAX_RECURSION)
- return (-3);
-
- /*
- * If no name we better have a record in cap
- */
- if (depth == 0 && name == NULL) {
- if ((record = malloc(*len + 1 + BFRAG)) == NULL)
- return (-2);
- memcpy(record, *cap, *len);
- myfd = 0;
- db_p = db_array;
- rp = record + *len + 1;
- r_end = rp + BFRAG;
- *rp = '\0';
- goto exp_use;
- }
-
- /*
- * Allocate first chunk of memory.
- */
- if ((record = malloc(BFRAG)) == NULL) {
- errno = ENOMEM;
- return (-2);
- }
- r_end = record + BFRAG;
- foundit = 0;
- rp = NULL;
- myfd = -1;
-
- /*
- * Loop through database array until finding the record.
- */
- for (db_p = db_array; *db_p != NULL; db_p++) {
- eof = 0;
-
- /*
- * Open database if not already open.
- */
-
- if (fp != NULL) {
- (void)fseek(fp, 0L, SEEK_SET);
- myfd = 0;
- } else {
- fp = fopen(*db_p, "r");
- if (fp == NULL) {
- /* No error on unfound file. */
- continue;
- }
- myfd = 1;
- }
- /*
- * Find the requested capability record ...
- */
- {
- char buf[BUFSIZ];
- char *b_end, *bp;
- int c;
-
- /*
- * Loop invariants:
- * There is always room for one more character in record.
- * R_end always points just past end of record.
- * Rp always points just past last character in record.
- * B_end always points just past last character in buf.
- * Bp always points at next character in buf.
- */
- b_end = buf;
- bp = buf;
- for (;;) {
-
- /*
- * Read in a record implementing line continuation.
- */
- rp = record;
- for (;;) {
- if (bp >= b_end) {
- size_t n;
-
- n = fread(buf, 1, sizeof(buf), fp);
- if (n == 0) {
- eof = feof(fp);
- if (myfd)
- (void)fclose(fp);
- if (eof) {
- fp = NULL;
- break;
- }
- free(record);
- return (-2);
- }
- b_end = buf+n;
- bp = buf;
- }
-
- c = (unsigned char)*bp++;
- if (c == '\n') {
- if (bp >= b_end) {
- size_t n;
-
- n = fread(buf, 1, sizeof(buf), fp);
- if (n == 0) {
- eof = feof(fp);
- if (myfd)
- (void)fclose(fp);
- if (eof) {
- fp = NULL;
- break;
- }
- free(record);
- return (-2);
- }
- b_end = buf+n;
- bp = buf;
- }
- if (rp > record && isspace(*bp))
- continue;
- else
- break;
- }
- if (rp <= record || *(rp - 1) != ',' || !isspace(c))
- *rp++ = c;
-
- /*
- * Enforce loop invariant: if no room
- * left in record buffer, try to get
- * some more.
- */
- if (rp >= r_end) {
- size_t off;
- size_t newsize;
-
- off = rp - record;
- newsize = r_end - record + BFRAG;
- s = realloc(record, newsize);
- if (s == NULL) {
- free(record);
- errno = ENOMEM;
- if (myfd)
- (void)fclose(fp);
- return (-2);
- }
- record = s;
- r_end = record + newsize;
- rp = record + off;
- }
- }
- /* loop invariant lets us do this */
- *rp++ = '\0';
-
- /*
- * Toss blank lines and comments.
- */
- if (*record == '\0' || *record == '#')
- continue;
-
- /*
- * See if this is the record we want ...
- */
- if (igetmatch(record, name) == 0) {
- foundit = 1;
- break; /* found it! */
- }
-
- /*
- * If encountered eof check next file.
- */
- if (eof)
- break;
- }
- }
- if (foundit)
- break;
- }
-
- if (!foundit) {
- free(record);
- return (-1);
- }
-
- /*
- * Got the capability record, but now we have to expand all use=name
- * references in it ...
- */
-exp_use: {
- char *newicap;
- int newilen;
- u_int ilen;
- int diff, iret, tclen;
- char *icap, *scan, *tc, *tcstart, *tcend;
-
- /*
- * Loop invariants:
- * There is room for one more character in record.
- * R_end points just past end of record.
- * Rp points just past last character in record.
- * Scan points at remainder of record that needs to be
- * scanned for use=name constructs.
- */
- scan = record;
- tc_not_resolved = 0;
- for (;;) {
- if ((tc = igetcap(scan, "use", '=')) == NULL)
- break;
-
- /*
- * Find end of use=name and stomp on the trailing `,'
- * (if present) so we can use it to call ourselves.
- */
- s = tc + strcspn(tc, ",");
- if (*s == ',') {
- *s = '\0';
- ++s;
- }
- tcstart = tc - 4;
- tclen = s - tcstart;
- tcend = s;
-
- iret = getent(&icap, &ilen, db_p, fp, tc, depth+1);
- newicap = icap; /* Put into a register. */
- newilen = ilen;
- if (iret != 0) {
- /* an error */
- if (iret < -1) {
- if (myfd)
- (void)fclose(fp);
- free(record);
- return (iret);
- }
- if (iret == 1)
- tc_not_resolved = 1;
- /* couldn't resolve tc */
- if (iret == -1) {
- *(s - 1) = ',';
- scan = s - 1;
- tc_not_resolved = 1;
- continue;
-
- }
- }
- /* not interested in name field of tc'ed record */
- s = newicap + strcspn(newicap, ",");
- if (*s == ',')
- ++s;
- newilen -= s - newicap;
- newicap = s;
-
- /* make sure interpolated record is `,'-terminated */
- s += newilen;
- if (*(s-1) != ',') {
- *s = ','; /* overwrite NUL with , */
- newilen++;
- }
-
- /*
- * Make sure there's enough room to insert the
- * new record.
- */
- diff = newilen - tclen;
- if (diff >= r_end - rp) {
- size_t off, tcoff, tcoffend;
- size_t newsize;
-
- off = rp - record;
- newsize = r_end - record + diff + BFRAG;
- tcoff = tcstart - record;
- tcoffend = tcend - record;
- s = realloc(record, newsize);
- if (s == NULL) {
- free(record);
- errno = ENOMEM;
- if (myfd)
- (void)fclose(fp);
- free(icap);
- return (-2);
- }
- record = s;
- r_end = record + newsize;
- rp = record + off;
- tcstart = record + tcoff;
- tcend = record + tcoffend;
- }
-
- /*
- * Insert tc'ed record into our record.
- */
- s = tcstart + newilen;
- bcopy(tcend, s, (size_t)(rp - tcend));
- bcopy(newicap, tcstart, (size_t)newilen);
- rp += diff;
- free(icap);
-
- /*
- * Start scan on `,' so next igetcap works properly
- * (igetcap always skips first field).
- */
- scan = s-1;
- }
-
- }
- /*
- * Close file (if we opened it), give back any extra memory, and
- * return capability, length and success.
- */
- if (myfd)
- (void)fclose(fp);
- *len = rp - record - 1; /* don't count NUL */
- if (r_end > rp) {
- if ((s =
- realloc(record, (size_t)(rp - record))) == NULL) {
- free(record);
- errno = ENOMEM;
- return (-2);
- } else
- record = s;
- }
-
- *cap = record;
- if (tc_not_resolved)
- return (1);
- return (0);
-}
-
-/*
- * Igetmatch will return 0 if name is one of the names of the capability
- * record buf, -1 if not.
- */
-static int
-igetmatch(char *buf, char *name)
-{
- char *np, *bp;
-
- /*
- * Start search at beginning of record.
- */
- bp = buf;
- for (;;) {
- /*
- * Try to match a record name.
- */
- np = name;
- for (;;)
- if (*np == '\0') {
- if (*bp == '|' || *bp == ',' || *bp == '\0')
- return (0);
- else
- break;
- } else {
- if (*bp++ != *np++)
- break;
- }
-
- /*
- * Match failed, skip to next name in record.
- */
- bp--; /* a '|' or ',' may have stopped the match */
- for (;;)
- if (*bp == '\0' || *bp == ',')
- return (-1); /* match failed totally */
- else
- if (*bp++ == '|')
- break; /* found next name */
- }
-}
-
-static FILE *pfp;
-static int slash;
-static char **dbp;
-
-static int
-igetclose(void)
-{
- if (pfp != NULL) {
- (void)fclose(pfp);
- pfp = NULL;
- }
- dbp = NULL;
- slash = 0;
- return(0);
-}
-
-/*
- * Igetnext() gets either the first or next entry in the logical database
- * specified by db_array. It returns 0 upon completion of the database, 1
- * upon returning an entry with more remaining, and -1 if an error occurs.
- */
-int
-igetnext(char **cap, char **db_array)
-{
- int c, eof = 0, serrno, status = -1;
- char buf[BUFSIZ];
- char *b_end, *bp, *r_end, *rp;
- char *record = NULL;
- u_int len;
- off_t pos;
-
- if (dbp == NULL)
- dbp = db_array;
-
- if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL)
- goto done;
-
- /*
- * Allocate first chunk of memory.
- */
- if ((record = malloc(BFRAG)) == NULL)
- goto done;
- r_end = record + BFRAG;
-
- /*
- * Find the next capability record
- */
- /*
- * Loop invariants:
- * There is always room for one more character in record.
- * R_end always points just past end of record.
- * Rp always points just past last character in record.
- * B_end always points just past last character in buf.
- * Bp always points at next character in buf.
- */
- b_end = buf;
- bp = buf;
- for (;;) {
- /*
- * If encountered EOF check next file.
- */
- if (eof) {
- (void)fclose(pfp);
- pfp = NULL;
- if (*++dbp == NULL) {
- status = 0;
- break;
- }
- if ((pfp = fopen(*dbp, "r")) == NULL)
- break;
- eof = 0;
- }
-
- /*
- * Read in a record implementing line continuation.
- */
- rp = record;
- for (;;) {
- if (bp >= b_end) {
- size_t n;
-
- n = fread(buf, 1, sizeof(buf), pfp);
- if (n == 0) {
- eof = feof(pfp);
- if (eof)
- break;
- else
- goto done;
- }
- b_end = buf + n;
- bp = buf;
- }
-
- c = (unsigned char)*bp++;
- if (c == '\n') {
- if (bp >= b_end) {
- size_t n;
-
- n = fread(buf, 1, sizeof(buf), pfp);
- if (n == 0) {
- eof = feof(pfp);
- if (eof)
- break;
- else
- goto done;
- }
- b_end = buf + n;
- bp = buf;
- }
- if (rp > record && isspace(*bp))
- continue;
- else
- break;
- }
- if (rp <= record || *(rp - 1) != ',' || !isspace(c))
- *rp++ = c;
-
- /*
- * Enforce loop invariant: if no room
- * left in record buffer, try to get
- * some more.
- */
- if (rp >= r_end) {
- size_t newsize, off;
- char *nrecord;
-
- off = rp - record;
- newsize = r_end - record + BFRAG;
- nrecord = realloc(record, newsize);
- if (nrecord == NULL)
- goto done;
- record = nrecord;
- r_end = record + newsize;
- rp = record + off;
- }
- }
- /* loop invariant lets us do this */
- *rp++ = '\0';
-
- /*
- * Toss blank lines and comments.
- */
- if (*record == '\0' || *record == '#')
- continue;
-
- /* rewind to end of record */
- fseeko(pfp, (off_t)(bp - b_end), SEEK_CUR);
-
- /* we pass the record to getent() in cap */
- *cap = record;
- len = rp - record;
-
- /* return value of getent() is one less than igetnext() */
- pos = ftello(pfp);
- status = getent(cap, &len, dbp, pfp, NULL, 0) + 1;
- if (status > 0)
- fseeko(pfp, pos, SEEK_SET);
- break;
- }
-done:
- serrno = errno;
- free(record);
- if (status <= 0)
- (void)igetclose();
- errno = serrno;
-
- return (status);
-}