xref: /illumos-gate/usr/src/lib/libpkg/common/gpkgmap.c (revision 4656d4747c8743290bfbe910c64cd75eb4e4af8d)
15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland 
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland 
325c51f124SMoriah Waterland #include <stdio.h>
335c51f124SMoriah Waterland #include <limits.h>
345c51f124SMoriah Waterland #include <stdlib.h>
355c51f124SMoriah Waterland #include <unistd.h>
365c51f124SMoriah Waterland #include <string.h>
375c51f124SMoriah Waterland #include <ctype.h>
385c51f124SMoriah Waterland #include <fcntl.h>
395c51f124SMoriah Waterland #include <sys/types.h>
405c51f124SMoriah Waterland #include <sys/stat.h>
415c51f124SMoriah Waterland #include <errno.h>
425c51f124SMoriah Waterland #include "pkgstrct.h"
435c51f124SMoriah Waterland #include "pkglib.h"
445c51f124SMoriah Waterland #include "pkglibmsgs.h"
455c51f124SMoriah Waterland #include "pkglocale.h"
465c51f124SMoriah Waterland 
475c51f124SMoriah Waterland #define	ERR_CANT_READ_LCLPATH		"unable to read local pathname"
485c51f124SMoriah Waterland #define	ERR_BAD_VOLUME_NUMBER		"bad volume number"
495c51f124SMoriah Waterland #define	ERR_CANNOT_READ_PATHNAME_FIELD	"unable to read pathname field"
505c51f124SMoriah Waterland #define	ERR_CANNOT_READ_CONTENT_INFO	"unable to read content info"
515c51f124SMoriah Waterland #define	ERR_EXTRA_TOKENS_PRESENT	"extra tokens on input line"
525c51f124SMoriah Waterland #define	ERR_CANNOT_READ_CLASS_TOKEN	"unable to read class token"
535c51f124SMoriah Waterland #define	ERR_BAD_LINK_SPEC		"missing or invalid link specification"
545c51f124SMoriah Waterland #define	ERR_UNKNOWN_FTYPE		"unknown ftype"
555c51f124SMoriah Waterland #define	ERR_NO_LINKSOURCE		"no link source specified"
565c51f124SMoriah Waterland #define	ERR_CANNOT_READ_MM_DEVNUMS	"unable to read major/minor "\
575c51f124SMoriah Waterland 					"device numbers"
585c51f124SMoriah Waterland static int	eatwhite(FILE *fp);
595c51f124SMoriah Waterland static int	getend(FILE *fp);
605c51f124SMoriah Waterland static int	getstr(FILE *fp, char *sep, int n, char *str);
615c51f124SMoriah Waterland static int	getnum(FILE *fp, int base, long *d, long bad);
625c51f124SMoriah Waterland static int	getlnum(FILE *fp, int base, fsblkcnt_t *d, long bad);
635c51f124SMoriah Waterland static int	getvalmode(FILE *fp, mode_t *d, long bad, int map);
645c51f124SMoriah Waterland 
655c51f124SMoriah Waterland static int	getendvfp(char **cp);
665c51f124SMoriah Waterland static void	findendvfp(char **cp);
675c51f124SMoriah Waterland static int	getstrvfp(char **cp, char *sep, int n, char *str);
685c51f124SMoriah Waterland static int	getvalmodevfp(char **cp, mode_t *d, long bad, int map);
695c51f124SMoriah Waterland int		getnumvfp(char **cp, int base, long *d, long bad);
705c51f124SMoriah Waterland int		getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad);
715c51f124SMoriah Waterland 
725c51f124SMoriah Waterland static char	mypath[PATH_MAX];
735c51f124SMoriah Waterland static char	mylocal[PATH_MAX];
745c51f124SMoriah Waterland static int	mapmode = MAPNONE;
755c51f124SMoriah Waterland static char	*maptype = "";
765c51f124SMoriah Waterland static mode_t	d_mode = BADMODE;
775c51f124SMoriah Waterland static char 	*d_owner = BADOWNER;
785c51f124SMoriah Waterland static char	*d_group = BADGROUP;
795c51f124SMoriah Waterland 
805c51f124SMoriah Waterland /*
815c51f124SMoriah Waterland  * These determine how gpkgmap() deals with mode, owner and group defaults.
825c51f124SMoriah Waterland  * It is assumed that the owner and group arguments represent static fields
835c51f124SMoriah Waterland  * which will persist until attrdefault() is called.
845c51f124SMoriah Waterland  */
855c51f124SMoriah Waterland void
865c51f124SMoriah Waterland attrpreset(int mode, char *owner, char *group)
875c51f124SMoriah Waterland {
885c51f124SMoriah Waterland 	d_mode = mode;
895c51f124SMoriah Waterland 	d_owner = owner;
905c51f124SMoriah Waterland 	d_group = group;
915c51f124SMoriah Waterland }
925c51f124SMoriah Waterland 
935c51f124SMoriah Waterland void
945c51f124SMoriah Waterland attrdefault()
955c51f124SMoriah Waterland {
965c51f124SMoriah Waterland 	d_mode = NOMODE;
975c51f124SMoriah Waterland 	d_owner = NOOWNER;
985c51f124SMoriah Waterland 	d_group = NOGROUP;
995c51f124SMoriah Waterland }
1005c51f124SMoriah Waterland 
1015c51f124SMoriah Waterland /*
1025c51f124SMoriah Waterland  * This determines how gpkgmap() deals with environment variables in the
1035c51f124SMoriah Waterland  * mode, owner and group. Path is evaluated at a higher level based upon
1045c51f124SMoriah Waterland  * other circumstances.
1055c51f124SMoriah Waterland  */
1065c51f124SMoriah Waterland void
1075c51f124SMoriah Waterland setmapmode(int mode)
1085c51f124SMoriah Waterland {
1095c51f124SMoriah Waterland 	if (mode >= 0 || mode <= 3) {
1105c51f124SMoriah Waterland 		mapmode = mode;
1115c51f124SMoriah Waterland 		if (mode == MAPBUILD)
1125c51f124SMoriah Waterland 			maptype = " build";
1135c51f124SMoriah Waterland 		else if (mode == MAPINSTALL)
1145c51f124SMoriah Waterland 			maptype = " install";
1155c51f124SMoriah Waterland 		else
1165c51f124SMoriah Waterland 			maptype = "";
1175c51f124SMoriah Waterland 	}
1185c51f124SMoriah Waterland }
1195c51f124SMoriah Waterland 
1205c51f124SMoriah Waterland /* This is the external query interface for mapmode. */
1215c51f124SMoriah Waterland int
1225c51f124SMoriah Waterland getmapmode(void)
1235c51f124SMoriah Waterland {
1245c51f124SMoriah Waterland 	return (mapmode);
1255c51f124SMoriah Waterland }
1265c51f124SMoriah Waterland 
1275c51f124SMoriah Waterland /*
1285c51f124SMoriah Waterland  * Unpack the pkgmap or the contents file or whatever file is in that format.
1295c51f124SMoriah Waterland  * Based upon mapmode, environment parameters will be resolved for mode,
1305c51f124SMoriah Waterland  * owner and group.
1315c51f124SMoriah Waterland  */
1325c51f124SMoriah Waterland 
1335c51f124SMoriah Waterland int
1345c51f124SMoriah Waterland gpkgmap(struct cfent *ept, FILE *fp)
1355c51f124SMoriah Waterland {
1365c51f124SMoriah Waterland 	int		c;
1375c51f124SMoriah Waterland 	boolean_t	first_char = B_TRUE;
1385c51f124SMoriah Waterland 
1395c51f124SMoriah Waterland 	setErrstr(NULL);
1405c51f124SMoriah Waterland 	ept->volno = 0;
1415c51f124SMoriah Waterland 	ept->ftype = BADFTYPE;
1425c51f124SMoriah Waterland 	(void) strcpy(ept->pkg_class, BADCLASS);
1435c51f124SMoriah Waterland 	ept->pkg_class_idx = -1;
1445c51f124SMoriah Waterland 	ept->path = NULL;
1455c51f124SMoriah Waterland 	ept->ainfo.local = NULL;
1465c51f124SMoriah Waterland 	/* default attributes were supplied, so don't reset */
1475c51f124SMoriah Waterland 	ept->ainfo.mode = d_mode;
1485c51f124SMoriah Waterland 	(void) strcpy(ept->ainfo.owner, d_owner);
1495c51f124SMoriah Waterland 	(void) strcpy(ept->ainfo.group, d_group);
1505c51f124SMoriah Waterland 	ept->ainfo.major = BADMAJOR;
1515c51f124SMoriah Waterland 	ept->ainfo.minor = BADMINOR;
1525c51f124SMoriah Waterland 	ept->cinfo.cksum = ept->cinfo.modtime = ept->cinfo.size = (-1L);
1535c51f124SMoriah Waterland 
1545c51f124SMoriah Waterland 	ept->npkgs = 0;
1555c51f124SMoriah Waterland 
1565c51f124SMoriah Waterland 	if (!fp)
1575c51f124SMoriah Waterland 		return (-1);
1585c51f124SMoriah Waterland readline:
1595c51f124SMoriah Waterland 	c = eatwhite(fp);
1605c51f124SMoriah Waterland 
1615c51f124SMoriah Waterland 	/*
1625c51f124SMoriah Waterland 	 * If the first character is not a digit, we assume that the
1635c51f124SMoriah Waterland 	 * volume number is 1.
1645c51f124SMoriah Waterland 	 */
1655c51f124SMoriah Waterland 	if (first_char && !isdigit(c)) {
1665c51f124SMoriah Waterland 		ept->volno = 1;
1675c51f124SMoriah Waterland 	}
1685c51f124SMoriah Waterland 	first_char = B_FALSE;
1695c51f124SMoriah Waterland 
1705c51f124SMoriah Waterland 	switch (c) {
1715c51f124SMoriah Waterland 	    case EOF:
1725c51f124SMoriah Waterland 		return (0);
1735c51f124SMoriah Waterland 
1745c51f124SMoriah Waterland 	    case '0':
1755c51f124SMoriah Waterland 	    case '1':
1765c51f124SMoriah Waterland 	    case '2':
1775c51f124SMoriah Waterland 	    case '3':
1785c51f124SMoriah Waterland 	    case '4':
1795c51f124SMoriah Waterland 	    case '5':
1805c51f124SMoriah Waterland 	    case '6':
1815c51f124SMoriah Waterland 	    case '7':
1825c51f124SMoriah Waterland 	    case '8':
1835c51f124SMoriah Waterland 	    case '9':
1845c51f124SMoriah Waterland 		if (ept->volno) {
1855c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_BAD_VOLUME_NUMBER));
1865c51f124SMoriah Waterland 			goto error;
1875c51f124SMoriah Waterland 		}
1885c51f124SMoriah Waterland 		do {
1895c51f124SMoriah Waterland 			ept->volno = (ept->volno*10)+c-'0';
1905c51f124SMoriah Waterland 			c = getc(fp);
1915c51f124SMoriah Waterland 		} while (isdigit(c));
1925c51f124SMoriah Waterland 		if (ept->volno == 0)
1935c51f124SMoriah Waterland 			ept->volno = 1;
1945c51f124SMoriah Waterland 
1955c51f124SMoriah Waterland 		goto readline;
1965c51f124SMoriah Waterland 
1975c51f124SMoriah Waterland 	    case ':':
1985c51f124SMoriah Waterland 	    case '#':
1995c51f124SMoriah Waterland 		(void) getend(fp);
2005c51f124SMoriah Waterland 		/*FALLTHRU*/
2015c51f124SMoriah Waterland 	    case '\n':
2025c51f124SMoriah Waterland 		/*
2035c51f124SMoriah Waterland 		 * Since we are going to scan the next line,
2045c51f124SMoriah Waterland 		 * we need to reset volume number and first_char.
2055c51f124SMoriah Waterland 		 */
2065c51f124SMoriah Waterland 		ept->volno = 0;
2075c51f124SMoriah Waterland 		first_char = B_TRUE;
2085c51f124SMoriah Waterland 		goto readline;
2095c51f124SMoriah Waterland 
2105c51f124SMoriah Waterland 	    case 'i':
2115c51f124SMoriah Waterland 		ept->ftype = (char)c;
2125c51f124SMoriah Waterland 		c = eatwhite(fp);
2135c51f124SMoriah Waterland 		/*FALLTHRU*/
2145c51f124SMoriah Waterland 	    case '.':
2155c51f124SMoriah Waterland 	    case '/':
2165c51f124SMoriah Waterland 		(void) ungetc(c, fp);
2175c51f124SMoriah Waterland 
2185c51f124SMoriah Waterland 		if (getstr(fp, "=", PATH_MAX, mypath)) {
2195c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD));
2205c51f124SMoriah Waterland 			goto error;
2215c51f124SMoriah Waterland 		}
2225c51f124SMoriah Waterland 		ept->path = mypath;
2235c51f124SMoriah Waterland 		c = getc(fp);
2245c51f124SMoriah Waterland 		if (c == '=') {
2255c51f124SMoriah Waterland 			if (getstr(fp, NULL, PATH_MAX, mylocal)) {
2265c51f124SMoriah Waterland 				setErrstr(pkg_gt(ERR_CANT_READ_LCLPATH));
2275c51f124SMoriah Waterland 				goto error;
2285c51f124SMoriah Waterland 			}
2295c51f124SMoriah Waterland 			ept->ainfo.local = mylocal;
2305c51f124SMoriah Waterland 		} else
2315c51f124SMoriah Waterland 			(void) ungetc(c, fp);
2325c51f124SMoriah Waterland 
2335c51f124SMoriah Waterland 		if (ept->ftype == 'i') {
2345c51f124SMoriah Waterland 			/* content info might exist */
2355c51f124SMoriah Waterland 			if (!getlnum(fp, 10, (fsblkcnt_t *)&ept->cinfo.size,
2365c51f124SMoriah Waterland 			    BADCONT) &&
2375c51f124SMoriah Waterland 			    (getnum(fp, 10, (long *)&ept->cinfo.cksum,
2385c51f124SMoriah Waterland 			    BADCONT) ||
2395c51f124SMoriah Waterland 			    getnum(fp, 10, (long *)&ept->cinfo.modtime,
2405c51f124SMoriah Waterland 			    BADCONT))) {
2415c51f124SMoriah Waterland 				setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO));
2425c51f124SMoriah Waterland 				goto error;
2435c51f124SMoriah Waterland 			}
2445c51f124SMoriah Waterland 		}
2455c51f124SMoriah Waterland 		if (getend(fp)) {
2465c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT));
2475c51f124SMoriah Waterland 			return (-1);
2485c51f124SMoriah Waterland 		}
2495c51f124SMoriah Waterland 		return (1);
2505c51f124SMoriah Waterland 
2515c51f124SMoriah Waterland 	    case '?':
2525c51f124SMoriah Waterland 	    case 'f':
2535c51f124SMoriah Waterland 	    case 'v':
2545c51f124SMoriah Waterland 	    case 'e':
2555c51f124SMoriah Waterland 	    case 'l':
2565c51f124SMoriah Waterland 	    case 's':
2575c51f124SMoriah Waterland 	    case 'p':
2585c51f124SMoriah Waterland 	    case 'c':
2595c51f124SMoriah Waterland 	    case 'b':
2605c51f124SMoriah Waterland 	    case 'd':
2615c51f124SMoriah Waterland 	    case 'x':
2625c51f124SMoriah Waterland 		ept->ftype = (char)c;
2635c51f124SMoriah Waterland 		if (getstr(fp, NULL, CLSSIZ, ept->pkg_class)) {
2645c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_CLASS_TOKEN));
2655c51f124SMoriah Waterland 			goto error;
2665c51f124SMoriah Waterland 		}
2675c51f124SMoriah Waterland 		if (getstr(fp, "=", PATH_MAX, mypath)) {
2685c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD));
2695c51f124SMoriah Waterland 			goto error;
2705c51f124SMoriah Waterland 		}
2715c51f124SMoriah Waterland 		ept->path = mypath;
2725c51f124SMoriah Waterland 
2735c51f124SMoriah Waterland 		c = getc(fp);
2745c51f124SMoriah Waterland 		if (c == '=') {
2755c51f124SMoriah Waterland 			/* local path */
2765c51f124SMoriah Waterland 			if (getstr(fp, NULL, PATH_MAX, mylocal)) {
2775c51f124SMoriah Waterland 				if (ept->ftype == 's' || ept->ftype == 'l') {
2785c51f124SMoriah Waterland 					setErrstr(pkg_gt(ERR_READLINK));
2795c51f124SMoriah Waterland 				} else {
2805c51f124SMoriah Waterland 					setErrstr(
2815c51f124SMoriah Waterland 						pkg_gt(ERR_CANT_READ_LCLPATH));
2825c51f124SMoriah Waterland 				}
2835c51f124SMoriah Waterland 				goto error;
2845c51f124SMoriah Waterland 			}
2855c51f124SMoriah Waterland 			ept->ainfo.local = mylocal;
2865c51f124SMoriah Waterland 		} else if (strchr("sl", ept->ftype)) {
2875c51f124SMoriah Waterland 			if ((c != EOF) && (c != '\n'))
2885c51f124SMoriah Waterland 				(void) getend(fp);
2895c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_BAD_LINK_SPEC));
2905c51f124SMoriah Waterland 			return (-1);
2915c51f124SMoriah Waterland 		} else
2925c51f124SMoriah Waterland 			(void) ungetc(c, fp);
2935c51f124SMoriah Waterland 		break;
2945c51f124SMoriah Waterland 
2955c51f124SMoriah Waterland 	    default:
2965c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_UNKNOWN_FTYPE));
2975c51f124SMoriah Waterland error:
2985c51f124SMoriah Waterland 		(void) getend(fp);
2995c51f124SMoriah Waterland 		return (-1);
3005c51f124SMoriah Waterland 	}
3015c51f124SMoriah Waterland 
3025c51f124SMoriah Waterland 	if (strchr("sl", ept->ftype) && (ept->ainfo.local == NULL)) {
3035c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_NO_LINKSOURCE));
3045c51f124SMoriah Waterland 		goto error;
3055c51f124SMoriah Waterland 	}
3065c51f124SMoriah Waterland 
3075c51f124SMoriah Waterland 	if (strchr("cb", ept->ftype)) {
3085c51f124SMoriah Waterland 		ept->ainfo.major = BADMAJOR;
3095c51f124SMoriah Waterland 		ept->ainfo.minor = BADMINOR;
3105c51f124SMoriah Waterland 		if (getnum(fp, 10, (long *)&ept->ainfo.major, BADMAJOR) ||
311*4656d474SGarrett D'Amore 		    getnum(fp, 10, (long *)&ept->ainfo.minor, BADMINOR)) {
3125c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_MM_DEVNUMS));
3135c51f124SMoriah Waterland 			goto error;
3145c51f124SMoriah Waterland 		}
3155c51f124SMoriah Waterland 	}
3165c51f124SMoriah Waterland 
3175c51f124SMoriah Waterland 	/*
3185c51f124SMoriah Waterland 	 * Links and information files don't have attributes associated with
3195c51f124SMoriah Waterland 	 * them. The following either resolves potential variables or passes
3205c51f124SMoriah Waterland 	 * them through. Mode is tested for validity to some degree. BAD???
3215c51f124SMoriah Waterland 	 * is returned to indicate that no meaningful mode was provided. A
3225c51f124SMoriah Waterland 	 * higher authority will decide if that's OK or not. CUR??? means that
3235c51f124SMoriah Waterland 	 * the prototype file specifically requires a wildcard ('?') for
3245c51f124SMoriah Waterland 	 * that entry. We issue an error if attributes were entered wrong.
3255c51f124SMoriah Waterland 	 * We just return BAD??? if there was no entry at all.
3265c51f124SMoriah Waterland 	 */
3275c51f124SMoriah Waterland 	if (strchr("cbdxpfve", ept->ftype)) {
3285c51f124SMoriah Waterland 		int retval;
3295c51f124SMoriah Waterland 
3305c51f124SMoriah Waterland 		if ((retval = getvalmode(fp, &(ept->ainfo.mode), CURMODE,
3315c51f124SMoriah Waterland 		    (mapmode != MAPNONE))) == 1)
3325c51f124SMoriah Waterland 			goto end;	/* nothing else on the line */
3335c51f124SMoriah Waterland 		else if (retval == 2)
3345c51f124SMoriah Waterland 			goto error;	/* mode is too no good */
3355c51f124SMoriah Waterland 
3365c51f124SMoriah Waterland 		/* owner & group should be here */
3375c51f124SMoriah Waterland 		if ((retval = getstr(fp, NULL, ATRSIZ,
3385c51f124SMoriah Waterland 		    ept->ainfo.owner)) == 1)
3395c51f124SMoriah Waterland 			goto end;	/* no owner or group - warning */
3405c51f124SMoriah Waterland 		if (retval == -1) {
3415c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_OWNTOOLONG));
3425c51f124SMoriah Waterland 			goto error;
3435c51f124SMoriah Waterland 		}
3445c51f124SMoriah Waterland 
3455c51f124SMoriah Waterland 		if ((retval = getstr(fp, NULL, ATRSIZ,
3465c51f124SMoriah Waterland 		    ept->ainfo.group)) == 1)
3475c51f124SMoriah Waterland 			goto end;	/* no group - warning */
3485c51f124SMoriah Waterland 		if (retval == -1) {
3495c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_GRPTOOLONG));
3505c51f124SMoriah Waterland 			goto error;
3515c51f124SMoriah Waterland 		}
3525c51f124SMoriah Waterland 
3535c51f124SMoriah Waterland 		/* Resolve the parameters if required. */
3545c51f124SMoriah Waterland 		if (mapmode != MAPNONE) {
3555c51f124SMoriah Waterland 			if (mapvar(mapmode, ept->ainfo.owner)) {
3565c51f124SMoriah Waterland 				(void) snprintf(getErrbufAddr(),
3575c51f124SMoriah Waterland 					getErrbufSize(),
3585c51f124SMoriah Waterland 					pkg_gt(ERR_NOVAR),
3595c51f124SMoriah Waterland 					maptype, ept->ainfo.owner);
3605c51f124SMoriah Waterland 				setErrstr(getErrbufAddr());
3615c51f124SMoriah Waterland 				goto error;
3625c51f124SMoriah Waterland 			}
3635c51f124SMoriah Waterland 			if (mapvar(mapmode, ept->ainfo.group)) {
3645c51f124SMoriah Waterland 				(void) snprintf(getErrbufAddr(),
3655c51f124SMoriah Waterland 					getErrbufSize(), pkg_gt(ERR_NOVAR),
3665c51f124SMoriah Waterland 					maptype, ept->ainfo.group);
3675c51f124SMoriah Waterland 				setErrstr(getErrbufAddr());
3685c51f124SMoriah Waterland 				goto error;
3695c51f124SMoriah Waterland 			}
3705c51f124SMoriah Waterland 		}
3715c51f124SMoriah Waterland 	}
3725c51f124SMoriah Waterland 
3735c51f124SMoriah Waterland 	if (strchr("ifve", ept->ftype)) {
3745c51f124SMoriah Waterland 		/* look for content description */
3755c51f124SMoriah Waterland 		if (!getlnum(fp, 10, (fsblkcnt_t *)&ept->cinfo.size, BADCONT) &&
3765c51f124SMoriah Waterland 		(getnum(fp, 10, (long *)&ept->cinfo.cksum, BADCONT) ||
3775c51f124SMoriah Waterland 		getnum(fp, 10, (long *)&ept->cinfo.modtime, BADCONT))) {
3785c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO));
3795c51f124SMoriah Waterland 			goto error;
3805c51f124SMoriah Waterland 		}
3815c51f124SMoriah Waterland 	}
3825c51f124SMoriah Waterland 
3835c51f124SMoriah Waterland 	if (ept->ftype == 'i')
3845c51f124SMoriah Waterland 		goto end;
3855c51f124SMoriah Waterland 
3865c51f124SMoriah Waterland end:
3875c51f124SMoriah Waterland 	if (getend(fp) && ept->pinfo) {
3885c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT));
3895c51f124SMoriah Waterland 		return (-1);
3905c51f124SMoriah Waterland 	}
3915c51f124SMoriah Waterland 
3925c51f124SMoriah Waterland done:
3935c51f124SMoriah Waterland 	return (1);
3945c51f124SMoriah Waterland }
3955c51f124SMoriah Waterland 
3965c51f124SMoriah Waterland /*
3975c51f124SMoriah Waterland  * Get and validate the mode attribute. This returns an error if
3985c51f124SMoriah Waterland  *	1. the mode string is too long
3995c51f124SMoriah Waterland  *	2. the mode string includes alpha characters
4005c51f124SMoriah Waterland  *	3. the mode string is not octal
4015c51f124SMoriah Waterland  *	4. mode string is an install parameter
4025c51f124SMoriah Waterland  *	5. mode is an unresolved build parameter and MAPBUILD is
4035c51f124SMoriah Waterland  *	   in effect.
4045c51f124SMoriah Waterland  * If the mode is a build parameter, it is
4055c51f124SMoriah Waterland  *	1. returned as is if MAPNONE is in effect
4065c51f124SMoriah Waterland  *	2. evaluated if MAPBUILD is in effect
4075c51f124SMoriah Waterland  *
4085c51f124SMoriah Waterland  * NOTE : We use "mapmode!=MAPBUILD" to gather that it is install
4095c51f124SMoriah Waterland  * time. At install time we just fix a mode with bad bits set by
4105c51f124SMoriah Waterland  * setting it to CURMODE. This should be an error in a few releases
4115c51f124SMoriah Waterland  * (2.8 maybe) but faulty modes are so common in existing packages
4125c51f124SMoriah Waterland  * that this is a reasonable exception. -- JST 1994-11-9
4135c51f124SMoriah Waterland  *
4145c51f124SMoriah Waterland  * RETURNS
4155c51f124SMoriah Waterland  *	0 if mode is being returned as a valid value
4165c51f124SMoriah Waterland  *	1 if no attributes are present on the line
4175c51f124SMoriah Waterland  *	2 if there was a fundamental error
4185c51f124SMoriah Waterland  */
4195c51f124SMoriah Waterland static int
4205c51f124SMoriah Waterland getvalmode(FILE *fp, mode_t *d, long bad, int map)
4215c51f124SMoriah Waterland {
4225c51f124SMoriah Waterland 	char tempmode[20];
4235c51f124SMoriah Waterland 	mode_t tempmode_t;
4245c51f124SMoriah Waterland 	int retval;
4255c51f124SMoriah Waterland 
4265c51f124SMoriah Waterland 	if ((retval = getstr(fp, NULL, ATRSIZ, tempmode)) == 1)
4275c51f124SMoriah Waterland 		return (1);
4285c51f124SMoriah Waterland 	else if (retval == -1) {
4295c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_MODELONG));
4305c51f124SMoriah Waterland 		return (2);
4315c51f124SMoriah Waterland 	} else {
4325c51f124SMoriah Waterland 		/*
4335c51f124SMoriah Waterland 		 * If it isn't a '?' (meaning go with whatever mode is
4345c51f124SMoriah Waterland 		 * there), validate the mode and convert it to a mode_t. The
4355c51f124SMoriah Waterland 		 * "bad" variable here is a misnomer. It doesn't necessarily
4365c51f124SMoriah Waterland 		 * mean bad.
4375c51f124SMoriah Waterland 		 */
4385c51f124SMoriah Waterland 		if (tempmode[0] == '?') {
4395c51f124SMoriah Waterland 			*d = WILDCARD;
4405c51f124SMoriah Waterland 		} else {
4415c51f124SMoriah Waterland 			/*
4425c51f124SMoriah Waterland 			 * Mode may not be an install parameter or a
4435c51f124SMoriah Waterland 			 * non-build parameter.
4445c51f124SMoriah Waterland 			 */
4455c51f124SMoriah Waterland 			if (tempmode[0] == '$' &&
4465c51f124SMoriah Waterland 			    (isupper(tempmode[1]) || !islower(tempmode[1]))) {
4475c51f124SMoriah Waterland 				setErrstr(pkg_gt(ERR_IMODE));
4485c51f124SMoriah Waterland 				return (2);
4495c51f124SMoriah Waterland 			}
4505c51f124SMoriah Waterland 
4515c51f124SMoriah Waterland 			if ((map) && (mapvar(mapmode, tempmode))) {
4525c51f124SMoriah Waterland 				(void) snprintf(getErrbufAddr(),
4535c51f124SMoriah Waterland 						getErrbufSize(),
4545c51f124SMoriah Waterland 						pkg_gt(ERR_NOVAR),
4555c51f124SMoriah Waterland 						maptype, tempmode);
4565c51f124SMoriah Waterland 				setErrstr(getErrbufAddr());
4575c51f124SMoriah Waterland 				return (2);
4585c51f124SMoriah Waterland 			}
4595c51f124SMoriah Waterland 
4605c51f124SMoriah Waterland 
4615c51f124SMoriah Waterland 			if (tempmode[0] == '$') {
4625c51f124SMoriah Waterland 				*d = BADMODE;	/* may be a problem */
4635c51f124SMoriah Waterland 			} else {
4645c51f124SMoriah Waterland 				/*
4655c51f124SMoriah Waterland 				 * At this point it's supposed to be
4665c51f124SMoriah Waterland 				 * something we can convert to a number.
4675c51f124SMoriah Waterland 				 */
4685c51f124SMoriah Waterland 				int n = 0;
4695c51f124SMoriah Waterland 
4705c51f124SMoriah Waterland 				/*
4715c51f124SMoriah Waterland 				 * We reject it if it contains nonnumbers or
4725c51f124SMoriah Waterland 				 * it's not octal.
4735c51f124SMoriah Waterland 				 */
4745c51f124SMoriah Waterland 				while (tempmode[n] && !isspace(tempmode[n])) {
4755c51f124SMoriah Waterland 					if (!isdigit(tempmode[n])) {
4765c51f124SMoriah Waterland 						setErrstr(
4775c51f124SMoriah Waterland 							pkg_gt(ERR_MODEALPHA));
4785c51f124SMoriah Waterland 						return (2);
4795c51f124SMoriah Waterland 					}
4805c51f124SMoriah Waterland 
4815c51f124SMoriah Waterland 					if (strchr("89abcdefABCDEF",
4825c51f124SMoriah Waterland 					    tempmode[n])) {
4835c51f124SMoriah Waterland 						setErrstr(
4845c51f124SMoriah Waterland 							pkg_gt(ERR_BASEINVAL));
4855c51f124SMoriah Waterland 						return (2);
4865c51f124SMoriah Waterland 					}
4875c51f124SMoriah Waterland 					n++;
4885c51f124SMoriah Waterland 				}
4895c51f124SMoriah Waterland 
4905c51f124SMoriah Waterland 				tempmode_t = strtol(tempmode, NULL, 8);
4915c51f124SMoriah Waterland 
4925c51f124SMoriah Waterland 				/*
4935c51f124SMoriah Waterland 				 * We reject it if it contains inappropriate
4945c51f124SMoriah Waterland 				 * bits.
4955c51f124SMoriah Waterland 				 */
4965c51f124SMoriah Waterland 				if (tempmode_t & ~(S_IAMB |
4975c51f124SMoriah Waterland 				    S_ISUID | S_ISGID | S_ISVTX)) {
4985c51f124SMoriah Waterland 					if (mapmode != MAPBUILD) {
4995c51f124SMoriah Waterland 						tempmode_t = bad;
5005c51f124SMoriah Waterland 					} else {
5015c51f124SMoriah Waterland 						setErrstr(pkg_gt(ERR_MODEBITS));
5025c51f124SMoriah Waterland 						return (2);
5035c51f124SMoriah Waterland 					}
5045c51f124SMoriah Waterland 				}
5055c51f124SMoriah Waterland 				*d = tempmode_t;
5065c51f124SMoriah Waterland 			}
5075c51f124SMoriah Waterland 		}
5085c51f124SMoriah Waterland 		return (0);
5095c51f124SMoriah Waterland 	}
5105c51f124SMoriah Waterland }
5115c51f124SMoriah Waterland 
5125c51f124SMoriah Waterland static int
5135c51f124SMoriah Waterland getnum(FILE *fp, int base, long *d, long bad)
5145c51f124SMoriah Waterland {
5155c51f124SMoriah Waterland 	int c, b;
5165c51f124SMoriah Waterland 
5175c51f124SMoriah Waterland 	/* leading white space ignored */
5185c51f124SMoriah Waterland 	c = eatwhite(fp);
5195c51f124SMoriah Waterland 	if (c == '?') {
5205c51f124SMoriah Waterland 		*d = bad;
5215c51f124SMoriah Waterland 		return (0);
5225c51f124SMoriah Waterland 	}
5235c51f124SMoriah Waterland 
5245c51f124SMoriah Waterland 	if ((c == EOF) || (c == '\n') || !isdigit(c)) {
5255c51f124SMoriah Waterland 		(void) ungetc(c, fp);
5265c51f124SMoriah Waterland 		return (1);
5275c51f124SMoriah Waterland 	}
5285c51f124SMoriah Waterland 
5295c51f124SMoriah Waterland 	*d = 0;
5305c51f124SMoriah Waterland 	while (isdigit(c)) {
5315c51f124SMoriah Waterland 		b = (c & 017);
5325c51f124SMoriah Waterland 		if (b >= base)
5335c51f124SMoriah Waterland 			return (2);
5345c51f124SMoriah Waterland 		*d = (*d * base) + b;
5355c51f124SMoriah Waterland 		c = getc(fp);
5365c51f124SMoriah Waterland 	}
5375c51f124SMoriah Waterland 	(void) ungetc(c, fp);
5385c51f124SMoriah Waterland 	return (0);
5395c51f124SMoriah Waterland }
5405c51f124SMoriah Waterland 
5415c51f124SMoriah Waterland static int
5425c51f124SMoriah Waterland getlnum(FILE *fp, int base, fsblkcnt_t *d, long bad)
5435c51f124SMoriah Waterland {
5445c51f124SMoriah Waterland 	int c, b;
5455c51f124SMoriah Waterland 
5465c51f124SMoriah Waterland 	/* leading white space ignored */
5475c51f124SMoriah Waterland 	c = eatwhite(fp);
5485c51f124SMoriah Waterland 	if (c == '?') {
5495c51f124SMoriah Waterland 		*d = bad;
5505c51f124SMoriah Waterland 		return (0);
5515c51f124SMoriah Waterland 	}
5525c51f124SMoriah Waterland 
5535c51f124SMoriah Waterland 	if ((c == EOF) || (c == '\n') || !isdigit(c)) {
5545c51f124SMoriah Waterland 		(void) ungetc(c, fp);
5555c51f124SMoriah Waterland 		return (1);
5565c51f124SMoriah Waterland 	}
5575c51f124SMoriah Waterland 
5585c51f124SMoriah Waterland 	*d = 0;
5595c51f124SMoriah Waterland 	while (isdigit(c)) {
5605c51f124SMoriah Waterland 		b = (c & 017);
5615c51f124SMoriah Waterland 		if (b >= base)
5625c51f124SMoriah Waterland 			return (2);
5635c51f124SMoriah Waterland 		*d = (*d * base) + b;
5645c51f124SMoriah Waterland 		c = getc(fp);
5655c51f124SMoriah Waterland 	}
5665c51f124SMoriah Waterland 	(void) ungetc(c, fp);
5675c51f124SMoriah Waterland 	return (0);
5685c51f124SMoriah Waterland }
5695c51f124SMoriah Waterland 
5705c51f124SMoriah Waterland /*
5715c51f124SMoriah Waterland  *  Get a string from the file. Returns
5725c51f124SMoriah Waterland  *	0 if all OK
5735c51f124SMoriah Waterland  *	1 if nothing there
5745c51f124SMoriah Waterland  *	-1 if string is too long
5755c51f124SMoriah Waterland  */
5765c51f124SMoriah Waterland static int
5775c51f124SMoriah Waterland getstr(FILE *fp, char *sep, int n, char *str)
5785c51f124SMoriah Waterland {
5795c51f124SMoriah Waterland 	int c;
5805c51f124SMoriah Waterland 
5815c51f124SMoriah Waterland 	/* leading white space ignored */
5825c51f124SMoriah Waterland 	c = eatwhite(fp);
5835c51f124SMoriah Waterland 	if ((c == EOF) || (c == '\n')) {
5845c51f124SMoriah Waterland 		(void) ungetc(c, fp);
5855c51f124SMoriah Waterland 		return (1); /* nothing there */
5865c51f124SMoriah Waterland 	}
5875c51f124SMoriah Waterland 
5885c51f124SMoriah Waterland 	/* fill up string until space, tab, or separator */
5895c51f124SMoriah Waterland 	while (!strchr(" \t", c) && (!sep || !strchr(sep, c))) {
5905c51f124SMoriah Waterland 		if (n-- < 1) {
5915c51f124SMoriah Waterland 			*str = '\0';
5925c51f124SMoriah Waterland 			return (-1); /* too long */
5935c51f124SMoriah Waterland 		}
5945c51f124SMoriah Waterland 		*str++ = (char)c;
5955c51f124SMoriah Waterland 		c = getc(fp);
5965c51f124SMoriah Waterland 		if ((c == EOF) || (c == '\n'))
5975c51f124SMoriah Waterland 			break; /* no more on this line */
5985c51f124SMoriah Waterland 	}
5995c51f124SMoriah Waterland 	*str = '\0';
6005c51f124SMoriah Waterland 	(void) ungetc(c, fp);
6015c51f124SMoriah Waterland 
6025c51f124SMoriah Waterland 	return (0);
6035c51f124SMoriah Waterland }
6045c51f124SMoriah Waterland 
6055c51f124SMoriah Waterland static int
6065c51f124SMoriah Waterland getend(FILE *fp)
6075c51f124SMoriah Waterland {
6085c51f124SMoriah Waterland 	int c;
6095c51f124SMoriah Waterland 	int n;
6105c51f124SMoriah Waterland 
6115c51f124SMoriah Waterland 	n = 0;
6125c51f124SMoriah Waterland 	do {
6135c51f124SMoriah Waterland 		if ((c = getc(fp)) == EOF)
6145c51f124SMoriah Waterland 			return (n);
6155c51f124SMoriah Waterland 		if (!isspace(c))
6165c51f124SMoriah Waterland 			n++;
6175c51f124SMoriah Waterland 	} while (c != '\n');
6185c51f124SMoriah Waterland 	return (n);
6195c51f124SMoriah Waterland }
6205c51f124SMoriah Waterland 
6215c51f124SMoriah Waterland static int
6225c51f124SMoriah Waterland eatwhite(FILE *fp)
6235c51f124SMoriah Waterland {
6245c51f124SMoriah Waterland 	int c;
6255c51f124SMoriah Waterland 
6265c51f124SMoriah Waterland 	/* this test works around a side effect of getc() */
6275c51f124SMoriah Waterland 	if (feof(fp))
6285c51f124SMoriah Waterland 		return (EOF);
6295c51f124SMoriah Waterland 	do
6305c51f124SMoriah Waterland 		c = getc(fp);
6315c51f124SMoriah Waterland 	while ((c == ' ') || (c == '\t'));
6325c51f124SMoriah Waterland 	return (c);
6335c51f124SMoriah Waterland }
6345c51f124SMoriah Waterland 
6355c51f124SMoriah Waterland int
6365c51f124SMoriah Waterland gpkgmapvfp(struct cfent *ept, VFP_T *vfp)
6375c51f124SMoriah Waterland {
6385c51f124SMoriah Waterland 	int		c;
6395c51f124SMoriah Waterland 	boolean_t	first_char = B_TRUE;
6405c51f124SMoriah Waterland 	(void) strlcpy(ept->pkg_class, BADCLASS, sizeof (ept->pkg_class));
6415c51f124SMoriah Waterland 	(void) strlcpy(ept->ainfo.owner, d_owner, sizeof (ept->ainfo.owner));
6425c51f124SMoriah Waterland 	(void) strlcpy(ept->ainfo.group, d_group, sizeof (ept->ainfo.group));
6435c51f124SMoriah Waterland 
6445c51f124SMoriah Waterland 	setErrstr(NULL);
6455c51f124SMoriah Waterland 	ept->volno = 0;
6465c51f124SMoriah Waterland 	ept->ftype = BADFTYPE;
6475c51f124SMoriah Waterland 	ept->pkg_class_idx = -1;
6485c51f124SMoriah Waterland 	ept->path = NULL;
6495c51f124SMoriah Waterland 	ept->ainfo.local = NULL;
6505c51f124SMoriah Waterland 	ept->ainfo.mode = d_mode;
6515c51f124SMoriah Waterland 	ept->ainfo.major = BADMAJOR;
6525c51f124SMoriah Waterland 	ept->ainfo.minor = BADMINOR;
6535c51f124SMoriah Waterland 	ept->cinfo.cksum = (-1L);
6545c51f124SMoriah Waterland 	ept->cinfo.modtime = (-1L);
6555c51f124SMoriah Waterland 	ept->cinfo.size = (-1L);
6565c51f124SMoriah Waterland 
6575c51f124SMoriah Waterland 	ept->npkgs = 0;
6585c51f124SMoriah Waterland 
6595c51f124SMoriah Waterland 	/* return error if no vfp specified */
6605c51f124SMoriah Waterland 
6615c51f124SMoriah Waterland 	if (vfp == (VFP_T *)NULL) {
6625c51f124SMoriah Waterland 		return (-1);
6635c51f124SMoriah Waterland 	}
6645c51f124SMoriah Waterland 
6655c51f124SMoriah Waterland readline:
6665c51f124SMoriah Waterland 	while (((c = vfpGetcNoInc(vfp)) != '\0') && (isspace(vfpGetc(vfp))))
6675c51f124SMoriah Waterland 		;
6685c51f124SMoriah Waterland 
6695c51f124SMoriah Waterland 	/*
6705c51f124SMoriah Waterland 	 * If the first character is not a digit, we assume that the
6715c51f124SMoriah Waterland 	 * volume number is 1.
6725c51f124SMoriah Waterland 	 */
6735c51f124SMoriah Waterland 	if (first_char && !isdigit(c)) {
6745c51f124SMoriah Waterland 		ept->volno = 1;
6755c51f124SMoriah Waterland 	}
6765c51f124SMoriah Waterland 	first_char = B_FALSE;
6775c51f124SMoriah Waterland 
6785c51f124SMoriah Waterland 	/*
6795c51f124SMoriah Waterland 	 * In case of hsfs the zero-padding of partial pages
6805c51f124SMoriah Waterland 	 * returned by mmap is not done properly. A separate bug has been filed
6815c51f124SMoriah Waterland 	 * on this.
6825c51f124SMoriah Waterland 	 */
6835c51f124SMoriah Waterland 
6845c51f124SMoriah Waterland 	if (vfp->_vfpCurr && (vfp->_vfpCurr > vfp->_vfpEnd)) {
6855c51f124SMoriah Waterland 		return (0);
6865c51f124SMoriah Waterland 	}
6875c51f124SMoriah Waterland 
6885c51f124SMoriah Waterland 	switch (c) {
6895c51f124SMoriah Waterland 	    case '\0':
6905c51f124SMoriah Waterland 		return (0);
6915c51f124SMoriah Waterland 
6925c51f124SMoriah Waterland 	    case '0':
6935c51f124SMoriah Waterland 	    case '1':
6945c51f124SMoriah Waterland 	    case '2':
6955c51f124SMoriah Waterland 	    case '3':
6965c51f124SMoriah Waterland 	    case '4':
6975c51f124SMoriah Waterland 	    case '5':
6985c51f124SMoriah Waterland 	    case '6':
6995c51f124SMoriah Waterland 	    case '7':
7005c51f124SMoriah Waterland 	    case '8':
7015c51f124SMoriah Waterland 	    case '9':
7025c51f124SMoriah Waterland 		if (ept->volno) {
7035c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_BAD_VOLUME_NUMBER));
7045c51f124SMoriah Waterland 			goto error;
7055c51f124SMoriah Waterland 		}
7065c51f124SMoriah Waterland 		do {
7075c51f124SMoriah Waterland 			ept->volno = (ept->volno*10)+c-'0';
7085c51f124SMoriah Waterland 			c = vfpGetc(vfp);
7095c51f124SMoriah Waterland 		} while (isdigit(c));
7105c51f124SMoriah Waterland 		if (ept->volno == 0) {
7115c51f124SMoriah Waterland 			ept->volno = 1;
7125c51f124SMoriah Waterland 		}
7135c51f124SMoriah Waterland 
7145c51f124SMoriah Waterland 		goto readline;
7155c51f124SMoriah Waterland 
7165c51f124SMoriah Waterland 	    case ':':
7175c51f124SMoriah Waterland 	    case '#':
7185c51f124SMoriah Waterland 		(void) findendvfp(&vfpGetCurrCharPtr(vfp));
7195c51f124SMoriah Waterland 		/*FALLTHRU*/
7205c51f124SMoriah Waterland 	    case '\n':
7215c51f124SMoriah Waterland 		/*
7225c51f124SMoriah Waterland 		 * Since we are going to scan the next line,
7235c51f124SMoriah Waterland 		 * we need to reset volume number and first_char.
7245c51f124SMoriah Waterland 		 */
7255c51f124SMoriah Waterland 		ept->volno = 0;
7265c51f124SMoriah Waterland 		first_char = B_TRUE;
7275c51f124SMoriah Waterland 		goto readline;
7285c51f124SMoriah Waterland 
7295c51f124SMoriah Waterland 	    case 'i':
7305c51f124SMoriah Waterland 		ept->ftype = (char)c;
7315c51f124SMoriah Waterland 		while (((c = vfpGetcNoInc(vfp)) != '\0') &&
7325c51f124SMoriah Waterland 						(isspace(vfpGetc(vfp))))
7335c51f124SMoriah Waterland 			;
7345c51f124SMoriah Waterland 		/*FALLTHRU*/
7355c51f124SMoriah Waterland 	    case '.':
7365c51f124SMoriah Waterland 	    case '/':
7375c51f124SMoriah Waterland 		vfpDecCurrPtr(vfp);
7385c51f124SMoriah Waterland 
7395c51f124SMoriah Waterland 		if (getstrvfp(&vfpGetCurrCharPtr(vfp), "=", PATH_MAX, mypath)) {
7405c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD));
7415c51f124SMoriah Waterland 			goto error;
7425c51f124SMoriah Waterland 		}
7435c51f124SMoriah Waterland 		ept->path = mypath;
7445c51f124SMoriah Waterland 		c = vfpGetc(vfp);
7455c51f124SMoriah Waterland 		if (c == '=') {
7465c51f124SMoriah Waterland 			if (getstrvfp(&vfpGetCurrCharPtr(vfp), NULL, PATH_MAX,
7475c51f124SMoriah Waterland 							mylocal)) {
7485c51f124SMoriah Waterland 				setErrstr(pkg_gt(ERR_CANT_READ_LCLPATH));
7495c51f124SMoriah Waterland 				goto error;
7505c51f124SMoriah Waterland 			}
7515c51f124SMoriah Waterland 			ept->ainfo.local = mylocal;
7525c51f124SMoriah Waterland 		} else {
7535c51f124SMoriah Waterland 			vfpDecCurrPtr(vfp);
7545c51f124SMoriah Waterland 		}
7555c51f124SMoriah Waterland 
7565c51f124SMoriah Waterland 		if (ept->ftype == 'i') {
7575c51f124SMoriah Waterland 			/* content info might exist */
7585c51f124SMoriah Waterland 			if (!getlnumvfp(&vfpGetCurrCharPtr(vfp), 10,
7595c51f124SMoriah Waterland 				(fsblkcnt_t *)&ept->cinfo.size, BADCONT) &&
7605c51f124SMoriah Waterland 			    (getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
7615c51f124SMoriah Waterland 				(long *)&ept->cinfo.cksum, BADCONT) ||
7625c51f124SMoriah Waterland 			    getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
7635c51f124SMoriah Waterland 				(long *)&ept->cinfo.modtime, BADCONT))) {
7645c51f124SMoriah Waterland 				setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO));
7655c51f124SMoriah Waterland 				goto error;
7665c51f124SMoriah Waterland 			}
7675c51f124SMoriah Waterland 		}
7685c51f124SMoriah Waterland 
7695c51f124SMoriah Waterland 		if (getendvfp(&vfpGetCurrCharPtr(vfp))) {
7705c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT));
7715c51f124SMoriah Waterland 			return (-1);
7725c51f124SMoriah Waterland 		}
7735c51f124SMoriah Waterland 		return (1);
7745c51f124SMoriah Waterland 
7755c51f124SMoriah Waterland 	    case '?':
7765c51f124SMoriah Waterland 	    case 'f':
7775c51f124SMoriah Waterland 	    case 'v':
7785c51f124SMoriah Waterland 	    case 'e':
7795c51f124SMoriah Waterland 	    case 'l':
7805c51f124SMoriah Waterland 	    case 's':
7815c51f124SMoriah Waterland 	    case 'p':
7825c51f124SMoriah Waterland 	    case 'c':
7835c51f124SMoriah Waterland 	    case 'b':
7845c51f124SMoriah Waterland 	    case 'd':
7855c51f124SMoriah Waterland 	    case 'x':
7865c51f124SMoriah Waterland 		ept->ftype = (char)c;
7875c51f124SMoriah Waterland 		if (getstrvfp(&vfpGetCurrCharPtr(vfp), NULL,
7885c51f124SMoriah Waterland 						CLSSIZ, ept->pkg_class)) {
7895c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_CLASS_TOKEN));
7905c51f124SMoriah Waterland 			goto error;
7915c51f124SMoriah Waterland 		}
7925c51f124SMoriah Waterland 		if (getstrvfp(&vfpGetCurrCharPtr(vfp), "=", PATH_MAX, mypath)) {
7935c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD));
7945c51f124SMoriah Waterland 			goto error;
7955c51f124SMoriah Waterland 		}
7965c51f124SMoriah Waterland 		ept->path = mypath;
7975c51f124SMoriah Waterland 
7985c51f124SMoriah Waterland 		c = vfpGetc(vfp);
7995c51f124SMoriah Waterland 		if (c == '=') {
8005c51f124SMoriah Waterland 			/* local path */
8015c51f124SMoriah Waterland 			if (getstrvfp(&vfpGetCurrCharPtr(vfp), NULL,
8025c51f124SMoriah Waterland 							PATH_MAX, mylocal)) {
8035c51f124SMoriah Waterland 				if (ept->ftype == 's' || ept->ftype == 'l') {
8045c51f124SMoriah Waterland 					setErrstr(pkg_gt(ERR_READLINK));
8055c51f124SMoriah Waterland 				} else {
8065c51f124SMoriah Waterland 					setErrstr(
8075c51f124SMoriah Waterland 						pkg_gt(ERR_CANT_READ_LCLPATH));
8085c51f124SMoriah Waterland 				}
8095c51f124SMoriah Waterland 				goto error;
8105c51f124SMoriah Waterland 			}
8115c51f124SMoriah Waterland 			ept->ainfo.local = mylocal;
8125c51f124SMoriah Waterland 		} else if ((ept->ftype == 's') || (ept->ftype == 'l')) {
8135c51f124SMoriah Waterland 			if ((c != '\0') && (c != '\n'))
8145c51f124SMoriah Waterland 				(void) findendvfp(&vfpGetCurrCharPtr(vfp));
8155c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_BAD_LINK_SPEC));
8165c51f124SMoriah Waterland 			return (-1);
8175c51f124SMoriah Waterland 		} else {
8185c51f124SMoriah Waterland 			vfpDecCurrPtr(vfp);
8195c51f124SMoriah Waterland 		}
8205c51f124SMoriah Waterland 		break;
8215c51f124SMoriah Waterland 
8225c51f124SMoriah Waterland 	    default:
8235c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_UNKNOWN_FTYPE));
8245c51f124SMoriah Waterland error:
8255c51f124SMoriah Waterland 		(void) findendvfp(&vfpGetCurrCharPtr(vfp));
8265c51f124SMoriah Waterland 		return (-1);
8275c51f124SMoriah Waterland 	}
8285c51f124SMoriah Waterland 
8295c51f124SMoriah Waterland 	if (((ept->ftype == 's') || (ept->ftype == 'l')) &&
8305c51f124SMoriah Waterland 					(ept->ainfo.local == NULL)) {
8315c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_NO_LINKSOURCE));
8325c51f124SMoriah Waterland 		goto error;
8335c51f124SMoriah Waterland 	}
8345c51f124SMoriah Waterland 
8355c51f124SMoriah Waterland 	if (((ept->ftype == 'c') || (ept->ftype == 'b'))) {
8365c51f124SMoriah Waterland 		ept->ainfo.major = BADMAJOR;
8375c51f124SMoriah Waterland 		ept->ainfo.minor = BADMINOR;
8385c51f124SMoriah Waterland 
8395c51f124SMoriah Waterland 		if (getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
8405c51f124SMoriah Waterland 				(long *)&ept->ainfo.major, BADMAJOR) ||
8415c51f124SMoriah Waterland 		    getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
8425c51f124SMoriah Waterland 				(long *)&ept->ainfo.minor, BADMINOR)) {
8435c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_MM_DEVNUMS));
8445c51f124SMoriah Waterland 			goto error;
8455c51f124SMoriah Waterland 		}
8465c51f124SMoriah Waterland 	}
8475c51f124SMoriah Waterland 
8485c51f124SMoriah Waterland 	/*
8495c51f124SMoriah Waterland 	 * Links and information files don't have attributes associated with
8505c51f124SMoriah Waterland 	 * them. The following either resolves potential variables or passes
8515c51f124SMoriah Waterland 	 * them through. Mode is tested for validity to some degree. BAD???
8525c51f124SMoriah Waterland 	 * is returned to indicate that no meaningful mode was provided. A
8535c51f124SMoriah Waterland 	 * higher authority will decide if that's OK or not. CUR??? means that
8545c51f124SMoriah Waterland 	 * the prototype file specifically requires a wildcard ('?') for
8555c51f124SMoriah Waterland 	 * that entry. We issue an error if attributes were entered wrong.
8565c51f124SMoriah Waterland 	 * We just return BAD??? if there was no entry at all.
8575c51f124SMoriah Waterland 	 */
8585c51f124SMoriah Waterland 	if ((ept->ftype == 'd') || (ept->ftype == 'x') || (ept->ftype == 'c') ||
8595c51f124SMoriah Waterland 		(ept->ftype == 'b') || (ept->ftype == 'p') ||
8605c51f124SMoriah Waterland 		(ept->ftype == 'f') || (ept->ftype == 'v') ||
8615c51f124SMoriah Waterland 		(ept->ftype == 'e')) {
8625c51f124SMoriah Waterland 		int retval;
8635c51f124SMoriah Waterland 
8645c51f124SMoriah Waterland 		retval = getvalmodevfp(&vfpGetCurrCharPtr(vfp),
8655c51f124SMoriah Waterland 				&(ept->ainfo.mode),
8665c51f124SMoriah Waterland 				CURMODE, (mapmode != MAPNONE));
8675c51f124SMoriah Waterland 
8685c51f124SMoriah Waterland 		if (retval == 1) {
8695c51f124SMoriah Waterland 			goto end;	/* nothing else on the line */
8705c51f124SMoriah Waterland 		} else if (retval == 2) {
8715c51f124SMoriah Waterland 			goto error;	/* mode is too no good */
8725c51f124SMoriah Waterland 		}
8735c51f124SMoriah Waterland 
8745c51f124SMoriah Waterland 		/* owner & group should be here */
8755c51f124SMoriah Waterland 		if ((retval = getstrvfp(&vfpGetCurrCharPtr(vfp), NULL, ATRSIZ,
8765c51f124SMoriah Waterland 		    ept->ainfo.owner)) == 1)
8775c51f124SMoriah Waterland 			goto end;	/* no owner or group - warning */
8785c51f124SMoriah Waterland 		if (retval == -1) {
8795c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_OWNTOOLONG));
8805c51f124SMoriah Waterland 			goto error;
8815c51f124SMoriah Waterland 		}
8825c51f124SMoriah Waterland 
8835c51f124SMoriah Waterland 		if ((retval = getstrvfp(&vfpGetCurrCharPtr(vfp), NULL, ATRSIZ,
8845c51f124SMoriah Waterland 		    ept->ainfo.group)) == 1)
8855c51f124SMoriah Waterland 			goto end;	/* no group - warning */
8865c51f124SMoriah Waterland 		if (retval == -1) {
8875c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_GRPTOOLONG));
8885c51f124SMoriah Waterland 			goto error;
8895c51f124SMoriah Waterland 		}
8905c51f124SMoriah Waterland 
8915c51f124SMoriah Waterland 		/* Resolve the parameters if required. */
8925c51f124SMoriah Waterland 		if (mapmode != MAPNONE) {
8935c51f124SMoriah Waterland 			if (mapvar(mapmode, ept->ainfo.owner)) {
8945c51f124SMoriah Waterland 				(void) snprintf(getErrbufAddr(),
8955c51f124SMoriah Waterland 					getErrbufSize(), pkg_gt(ERR_NOVAR),
8965c51f124SMoriah Waterland 					maptype, ept->ainfo.owner);
8975c51f124SMoriah Waterland 				setErrstr(getErrbufAddr());
8985c51f124SMoriah Waterland 				goto error;
8995c51f124SMoriah Waterland 			}
9005c51f124SMoriah Waterland 			if (mapvar(mapmode, ept->ainfo.group)) {
9015c51f124SMoriah Waterland 				(void) snprintf(getErrbufAddr(),
9025c51f124SMoriah Waterland 					getErrbufSize(), pkg_gt(ERR_NOVAR),
9035c51f124SMoriah Waterland 					maptype, ept->ainfo.group);
9045c51f124SMoriah Waterland 				setErrstr(getErrbufAddr());
9055c51f124SMoriah Waterland 				goto error;
9065c51f124SMoriah Waterland 			}
9075c51f124SMoriah Waterland 		}
9085c51f124SMoriah Waterland 	}
9095c51f124SMoriah Waterland 
9105c51f124SMoriah Waterland 	if ((ept->ftype == 'i') || (ept->ftype == 'f') ||
9115c51f124SMoriah Waterland 			(ept->ftype == 'v') || (ept->ftype == 'e')) {
9125c51f124SMoriah Waterland 		/* look for content description */
9135c51f124SMoriah Waterland 		if (!getlnumvfp(&vfpGetCurrCharPtr(vfp), 10,
9145c51f124SMoriah Waterland 				(fsblkcnt_t *)&ept->cinfo.size, BADCONT) &&
9155c51f124SMoriah Waterland 		(getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
9165c51f124SMoriah Waterland 				(long *)&ept->cinfo.cksum, BADCONT) ||
9175c51f124SMoriah Waterland 		getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
9185c51f124SMoriah Waterland 				(long *)&ept->cinfo.modtime, BADCONT))) {
9195c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO));
9205c51f124SMoriah Waterland 			goto error;
9215c51f124SMoriah Waterland 		}
9225c51f124SMoriah Waterland 	}
9235c51f124SMoriah Waterland 
9245c51f124SMoriah Waterland 	if (ept->ftype == 'i')
9255c51f124SMoriah Waterland 		goto end;
9265c51f124SMoriah Waterland 
9275c51f124SMoriah Waterland end:
9285c51f124SMoriah Waterland 	if (getendvfp(&vfpGetCurrCharPtr(vfp)) && ept->pinfo) {
9295c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT));
9305c51f124SMoriah Waterland 		return (-1);
9315c51f124SMoriah Waterland 	}
9325c51f124SMoriah Waterland 
9335c51f124SMoriah Waterland done:
9345c51f124SMoriah Waterland 	return (1);
9355c51f124SMoriah Waterland }
9365c51f124SMoriah Waterland 
9375c51f124SMoriah Waterland /*
9385c51f124SMoriah Waterland  * Get and validate the mode attribute. This returns an error if
9395c51f124SMoriah Waterland  *	1. the mode string is too long
9405c51f124SMoriah Waterland  *	2. the mode string includes alpha characters
9415c51f124SMoriah Waterland  *	3. the mode string is not octal
9425c51f124SMoriah Waterland  *	4. mode string is an install parameter
9435c51f124SMoriah Waterland  *	5. mode is an unresolved build parameter and MAPBUILD is
9445c51f124SMoriah Waterland  *	   in effect.
9455c51f124SMoriah Waterland  * If the mode is a build parameter, it is
9465c51f124SMoriah Waterland  *	1. returned as is if MAPNONE is in effect
9475c51f124SMoriah Waterland  *	2. evaluated if MAPBUILD is in effect
9485c51f124SMoriah Waterland  *
9495c51f124SMoriah Waterland  * NOTE : We use "mapmode!=MAPBUILD" to gather that it is install
9505c51f124SMoriah Waterland  * time. At install time we just fix a mode with bad bits set by
9515c51f124SMoriah Waterland  * setting it to CURMODE. This should be an error in a few releases
9525c51f124SMoriah Waterland  * (2.8 maybe) but faulty modes are so common in existing packages
9535c51f124SMoriah Waterland  * that this is a reasonable exception. -- JST 1994-11-9
9545c51f124SMoriah Waterland  *
9555c51f124SMoriah Waterland  * RETURNS
9565c51f124SMoriah Waterland  *	0 if mode is being returned as a valid value
9575c51f124SMoriah Waterland  *	1 if no attributes are present on the line
9585c51f124SMoriah Waterland  *	2 if there was a fundamental error
9595c51f124SMoriah Waterland  */
9605c51f124SMoriah Waterland static int
9615c51f124SMoriah Waterland getvalmodevfp(char **cp, mode_t *d, long bad, int map)
9625c51f124SMoriah Waterland {
9635c51f124SMoriah Waterland 	char	tempmode[ATRSIZ+1];
9645c51f124SMoriah Waterland 	mode_t	tempmode_t;
9655c51f124SMoriah Waterland 	int	retval;
9665c51f124SMoriah Waterland 	int	n;
9675c51f124SMoriah Waterland 
9685c51f124SMoriah Waterland 	if ((retval = getstrvfp(cp, NULL, sizeof (tempmode), tempmode)) == 1) {
9695c51f124SMoriah Waterland 		return (1);
9705c51f124SMoriah Waterland 	} else if (retval == -1) {
9715c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_MODELONG));
9725c51f124SMoriah Waterland 		return (2);
9735c51f124SMoriah Waterland 	}
9745c51f124SMoriah Waterland 
9755c51f124SMoriah Waterland 	/*
9765c51f124SMoriah Waterland 	 * If it isn't a '?' (meaning go with whatever mode is
9775c51f124SMoriah Waterland 	 * there), validate the mode and convert it to a mode_t. The
9785c51f124SMoriah Waterland 	 * "bad" variable here is a misnomer. It doesn't necessarily
9795c51f124SMoriah Waterland 	 * mean bad.
9805c51f124SMoriah Waterland 	 */
9815c51f124SMoriah Waterland 	if (tempmode[0] == '?') {
9825c51f124SMoriah Waterland 		*d = WILDCARD;
9835c51f124SMoriah Waterland 		return (0);
9845c51f124SMoriah Waterland 	}
9855c51f124SMoriah Waterland 
9865c51f124SMoriah Waterland 	/*
9875c51f124SMoriah Waterland 	 * Mode may not be an install parameter or a
9885c51f124SMoriah Waterland 	 * non-build parameter.
9895c51f124SMoriah Waterland 	 */
9905c51f124SMoriah Waterland 
9915c51f124SMoriah Waterland 	if (tempmode[0] == '$' &&
9925c51f124SMoriah Waterland 	    (isupper(tempmode[1]) || !islower(tempmode[1]))) {
9935c51f124SMoriah Waterland 		setErrstr(pkg_gt(ERR_IMODE));
9945c51f124SMoriah Waterland 		return (2);
9955c51f124SMoriah Waterland 	}
9965c51f124SMoriah Waterland 
9975c51f124SMoriah Waterland 	if ((map) && (mapvar(mapmode, tempmode))) {
9985c51f124SMoriah Waterland 		(void) snprintf(getErrbufAddr(), getErrbufSize(),
9995c51f124SMoriah Waterland 				pkg_gt(ERR_NOVAR), maptype, tempmode);
10005c51f124SMoriah Waterland 		setErrstr(getErrbufAddr());
10015c51f124SMoriah Waterland 		return (2);
10025c51f124SMoriah Waterland 	}
10035c51f124SMoriah Waterland 
10045c51f124SMoriah Waterland 	if (tempmode[0] == '$') {
10055c51f124SMoriah Waterland 		*d = BADMODE;	/* may be a problem */
10065c51f124SMoriah Waterland 		return (0);
10075c51f124SMoriah Waterland 	}
10085c51f124SMoriah Waterland 
10095c51f124SMoriah Waterland 	/* it's supposed to be something we can convert to a number */
10105c51f124SMoriah Waterland 
10115c51f124SMoriah Waterland 	n = 0;
10125c51f124SMoriah Waterland 
10135c51f124SMoriah Waterland 	/* reject it if it contains nonnumbers or it's not octal */
10145c51f124SMoriah Waterland 
10155c51f124SMoriah Waterland 	while (tempmode[n] && !isspace(tempmode[n])) {
10165c51f124SMoriah Waterland 		if (!isdigit(tempmode[n])) {
10175c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_MODEALPHA));
10185c51f124SMoriah Waterland 			return (2);
10195c51f124SMoriah Waterland 		}
10205c51f124SMoriah Waterland 
10215c51f124SMoriah Waterland 		if (strchr("89abcdefABCDEF", tempmode[n])) {
10225c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_BASEINVAL));
10235c51f124SMoriah Waterland 			return (2);
10245c51f124SMoriah Waterland 		}
10255c51f124SMoriah Waterland 		n++;
10265c51f124SMoriah Waterland 	}
10275c51f124SMoriah Waterland 
10285c51f124SMoriah Waterland 	tempmode_t = strtol(tempmode, NULL, 8);
10295c51f124SMoriah Waterland 
10305c51f124SMoriah Waterland 	/*
10315c51f124SMoriah Waterland 	 * We reject it if it contains inappropriate
10325c51f124SMoriah Waterland 	 * bits.
10335c51f124SMoriah Waterland 	 */
10345c51f124SMoriah Waterland 	if (tempmode_t & (~(S_IAMB | S_ISUID | S_ISGID | S_ISVTX))) {
10355c51f124SMoriah Waterland 		if (mapmode == MAPBUILD) {
10365c51f124SMoriah Waterland 			setErrstr(pkg_gt(ERR_MODEBITS));
10375c51f124SMoriah Waterland 			return (2);
10385c51f124SMoriah Waterland 		}
10395c51f124SMoriah Waterland 		tempmode_t = bad;
10405c51f124SMoriah Waterland 	}
10415c51f124SMoriah Waterland 
10425c51f124SMoriah Waterland 	*d = tempmode_t;
10435c51f124SMoriah Waterland 
10445c51f124SMoriah Waterland 	return (0);
10455c51f124SMoriah Waterland }
10465c51f124SMoriah Waterland 
10475c51f124SMoriah Waterland int
10485c51f124SMoriah Waterland getnumvfp(char **cp, int base, long *d, long bad)
10495c51f124SMoriah Waterland {
10505c51f124SMoriah Waterland 	int c;
10515c51f124SMoriah Waterland 	char	*p = *cp;
10525c51f124SMoriah Waterland 
10535c51f124SMoriah Waterland 	if (*p == '\0') {
10545c51f124SMoriah Waterland 		return (0);
10555c51f124SMoriah Waterland 	}
10565c51f124SMoriah Waterland 
10575c51f124SMoriah Waterland 	/* leading white space ignored */
10585c51f124SMoriah Waterland 	while (((c = *p) != '\0') && (isspace(*p++)))
10595c51f124SMoriah Waterland 		;
10605c51f124SMoriah Waterland 	if (c == '?') {
10615c51f124SMoriah Waterland 		*d = bad;
10625c51f124SMoriah Waterland 		*cp = p;
10635c51f124SMoriah Waterland 		return (0);
10645c51f124SMoriah Waterland 	}
10655c51f124SMoriah Waterland 
10665c51f124SMoriah Waterland 	if ((c == '\0') || (c == '\n') || !isdigit(c)) {
10675c51f124SMoriah Waterland 		p--;
10685c51f124SMoriah Waterland 		*cp = p;
10695c51f124SMoriah Waterland 		return (1);
10705c51f124SMoriah Waterland 	}
10715c51f124SMoriah Waterland 
10725c51f124SMoriah Waterland 	*d = 0;
10735c51f124SMoriah Waterland 	while (isdigit(c)) {
10745c51f124SMoriah Waterland 		*d = (*d * base) + (c & 017);
10755c51f124SMoriah Waterland 		c = *p++;
10765c51f124SMoriah Waterland 	}
10775c51f124SMoriah Waterland 	p--;
10785c51f124SMoriah Waterland 	*cp = p;
10795c51f124SMoriah Waterland 	return (0);
10805c51f124SMoriah Waterland }
10815c51f124SMoriah Waterland 
10825c51f124SMoriah Waterland int
10835c51f124SMoriah Waterland getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad)
10845c51f124SMoriah Waterland {
10855c51f124SMoriah Waterland 	int c;
10865c51f124SMoriah Waterland 	char	*p = *cp;
10875c51f124SMoriah Waterland 
10885c51f124SMoriah Waterland 	if (*p == '\0') {
10895c51f124SMoriah Waterland 		return (0);
10905c51f124SMoriah Waterland 	}
10915c51f124SMoriah Waterland 
10925c51f124SMoriah Waterland 	/* leading white space ignored */
10935c51f124SMoriah Waterland 	while (((c = *p) != '\0') && (isspace(*p++)))
10945c51f124SMoriah Waterland 		;
10955c51f124SMoriah Waterland 	if (c == '?') {
10965c51f124SMoriah Waterland 		*d = bad;
10975c51f124SMoriah Waterland 		*cp = p;
10985c51f124SMoriah Waterland 		return (0);
10995c51f124SMoriah Waterland 	}
11005c51f124SMoriah Waterland 
11015c51f124SMoriah Waterland 	if ((c == '\0') || (c == '\n') || !isdigit(c)) {
11025c51f124SMoriah Waterland 		p--;
11035c51f124SMoriah Waterland 		*cp = p;
11045c51f124SMoriah Waterland 		return (1);
11055c51f124SMoriah Waterland 	}
11065c51f124SMoriah Waterland 
11075c51f124SMoriah Waterland 	*d = 0;
11085c51f124SMoriah Waterland 	while (isdigit(c)) {
11095c51f124SMoriah Waterland 		*d = (*d * base) + (c & 017);
11105c51f124SMoriah Waterland 		c = *p++;
11115c51f124SMoriah Waterland 	}
11125c51f124SMoriah Waterland 	p--;
11135c51f124SMoriah Waterland 	*cp = p;
11145c51f124SMoriah Waterland 	return (0);
11155c51f124SMoriah Waterland }
11165c51f124SMoriah Waterland 
11175c51f124SMoriah Waterland static int
11185c51f124SMoriah Waterland getstrvfp(char **cp, char *sep, int n, char *str)
11195c51f124SMoriah Waterland {
11205c51f124SMoriah Waterland 	char	delims[256];
11215c51f124SMoriah Waterland 	int	c;
11225c51f124SMoriah Waterland 	char	*p = *cp;
11235c51f124SMoriah Waterland 	char	*p1;
11245c51f124SMoriah Waterland 	size_t	len;
11255c51f124SMoriah Waterland 
11265c51f124SMoriah Waterland 	if (*p == '\0') {
11275c51f124SMoriah Waterland 		return (1);
11285c51f124SMoriah Waterland 	}
11295c51f124SMoriah Waterland 
11305c51f124SMoriah Waterland 	/* leading white space ignored */
11315c51f124SMoriah Waterland 
11325c51f124SMoriah Waterland 	while (((c = *p) != '\0') && (isspace(*p++)))
11335c51f124SMoriah Waterland 		;
11345c51f124SMoriah Waterland 	if ((c == '\0') || (c == '\n')) {
11355c51f124SMoriah Waterland 		p--;
11365c51f124SMoriah Waterland 		*cp = p;
11375c51f124SMoriah Waterland 		return (1); /* nothing there */
11385c51f124SMoriah Waterland 	}
11395c51f124SMoriah Waterland 
11405c51f124SMoriah Waterland 	p--;
11415c51f124SMoriah Waterland 
11425c51f124SMoriah Waterland 	/* generate complete list of delimiters to scan for */
11435c51f124SMoriah Waterland 
11445c51f124SMoriah Waterland 	(void) strlcpy(delims, " \t\n", sizeof (delims));
11455c51f124SMoriah Waterland 	if ((sep != (char *)NULL) && (*sep != '\0')) {
11465c51f124SMoriah Waterland 		(void) strlcat(delims, sep, sizeof (delims));
11475c51f124SMoriah Waterland 	}
11485c51f124SMoriah Waterland 
11495c51f124SMoriah Waterland 	/* compute length based on delimiter found or not */
11505c51f124SMoriah Waterland 
11515c51f124SMoriah Waterland 	p1 = strpbrk(p, delims);
11525c51f124SMoriah Waterland 	if (p1 == (char *)NULL) {
11535c51f124SMoriah Waterland 		len = strlen(p);
11545c51f124SMoriah Waterland 	} else {
11555c51f124SMoriah Waterland 		len = (ptrdiff_t)p1 - (ptrdiff_t)p;
11565c51f124SMoriah Waterland 	}
11575c51f124SMoriah Waterland 
11585c51f124SMoriah Waterland 	/* if string will fit in result buffer copy string and return success */
11595c51f124SMoriah Waterland 
11605c51f124SMoriah Waterland 	if (len < n) {
11615c51f124SMoriah Waterland 		(void) memcpy(str, p, len);
11625c51f124SMoriah Waterland 		str[len] = '\0';
11635c51f124SMoriah Waterland 		p += len;
11645c51f124SMoriah Waterland 		*cp = p;
11655c51f124SMoriah Waterland 		return (0);
11665c51f124SMoriah Waterland 	}
11675c51f124SMoriah Waterland 
11685c51f124SMoriah Waterland 	/* result buffer too small; copy partial string, return error */
11695c51f124SMoriah Waterland 	(void) memcpy(str, p, n-1);
11705c51f124SMoriah Waterland 	str[n-1] = '\0';
11715c51f124SMoriah Waterland 	p += n;
11725c51f124SMoriah Waterland 	*cp = p;
11735c51f124SMoriah Waterland 	return (-1);
11745c51f124SMoriah Waterland }
11755c51f124SMoriah Waterland 
11765c51f124SMoriah Waterland /*
11775c51f124SMoriah Waterland  * Name:	getendvfp
11785c51f124SMoriah Waterland  * Description:	Locate the end of the current line given a pointer into a buffer
11795c51f124SMoriah Waterland  *		containing characters that is null terminated.
11805c51f124SMoriah Waterland  * Arguments:	char **cp - pointer to pointer to null-terminated string buffer
11815c51f124SMoriah Waterland  * Returns:	int == 0 -- no non-space characters preceeded the newline
11825c51f124SMoriah Waterland  *		    != 0 -- one or more non-space characters preceeded newline
11835c51f124SMoriah Waterland  * Effects:	cp is updated to point to the first character PAST the first new
11845c51f124SMoriah Waterland  *		line character found. If no newline character is found, cp is
11855c51f124SMoriah Waterland  *		updated to point to the '\0' at the end of the buffer.
11865c51f124SMoriah Waterland  */
11875c51f124SMoriah Waterland 
11885c51f124SMoriah Waterland static int
11895c51f124SMoriah Waterland getendvfp(char **cp)
11905c51f124SMoriah Waterland {
11915c51f124SMoriah Waterland 	int	n;
11925c51f124SMoriah Waterland 	char	*p = *cp;
11935c51f124SMoriah Waterland 
11945c51f124SMoriah Waterland 	n = 0;
11955c51f124SMoriah Waterland 
11965c51f124SMoriah Waterland 	/* if at end of buffer return no more characters left */
11975c51f124SMoriah Waterland 
11985c51f124SMoriah Waterland 	if (*p == '\0') {
11995c51f124SMoriah Waterland 		return (0);
12005c51f124SMoriah Waterland 	}
12015c51f124SMoriah Waterland 
12025c51f124SMoriah Waterland 	/* find the first null or end of line character */
12035c51f124SMoriah Waterland 
12045c51f124SMoriah Waterland 	while ((*p != '\0') && (*p != '\n')) {
12055c51f124SMoriah Waterland 		if (n == 0) {
12065c51f124SMoriah Waterland 			if (!isspace(*p)) {
12075c51f124SMoriah Waterland 				n++;
12085c51f124SMoriah Waterland 			}
12095c51f124SMoriah Waterland 		}
12105c51f124SMoriah Waterland 		p++;
12115c51f124SMoriah Waterland 	}
12125c51f124SMoriah Waterland 
12135c51f124SMoriah Waterland 	/* if at newline, increment pointer to first character past newline */
12145c51f124SMoriah Waterland 
12155c51f124SMoriah Waterland 	if (*p == '\n') {
12165c51f124SMoriah Waterland 		p++;
12175c51f124SMoriah Waterland 	}
12185c51f124SMoriah Waterland 
12195c51f124SMoriah Waterland 	/* set return pointer to null or first character past newline */
12205c51f124SMoriah Waterland 
12215c51f124SMoriah Waterland 	*cp = p;
12225c51f124SMoriah Waterland 
12235c51f124SMoriah Waterland 	/* return space/nospace indicator */
12245c51f124SMoriah Waterland 
12255c51f124SMoriah Waterland 	return (n);
12265c51f124SMoriah Waterland }
12275c51f124SMoriah Waterland 
12285c51f124SMoriah Waterland /*
12295c51f124SMoriah Waterland  * Name:	findendvfp
12305c51f124SMoriah Waterland  * Description:	Locate the end of the current line given a pointer into a buffer
12315c51f124SMoriah Waterland  *		containing characters that is null terminated.
12325c51f124SMoriah Waterland  * Arguments:	char **cp - pointer to pointer to null-terminated string buffer
12335c51f124SMoriah Waterland  * Returns:	none
12345c51f124SMoriah Waterland  * Effects:	cp is updated to point to the first character PAST the first new
12355c51f124SMoriah Waterland  *		line character found. If no newline character is found, cp is
12365c51f124SMoriah Waterland  *		updated to point to the '\0' at the end of the buffer.
12375c51f124SMoriah Waterland  */
12385c51f124SMoriah Waterland 
12395c51f124SMoriah Waterland static void
12405c51f124SMoriah Waterland findendvfp(char **cp)
12415c51f124SMoriah Waterland {
12425c51f124SMoriah Waterland 	char	*p1;
12435c51f124SMoriah Waterland 	char	*p = *cp;
12445c51f124SMoriah Waterland 
12455c51f124SMoriah Waterland 	/* if at end of buffer return no more characters left */
12465c51f124SMoriah Waterland 
12475c51f124SMoriah Waterland 	if (*p == '\0') {
12485c51f124SMoriah Waterland 		return;
12495c51f124SMoriah Waterland 	}
12505c51f124SMoriah Waterland 
12515c51f124SMoriah Waterland 	/* find the end of the line */
12525c51f124SMoriah Waterland 
12535c51f124SMoriah Waterland 	p1 = strchr(p, '\n');
12545c51f124SMoriah Waterland 	if (p1 != (char *)NULL) {
12555c51f124SMoriah Waterland 		*cp = ++p1;
12565c51f124SMoriah Waterland 		return;
12575c51f124SMoriah Waterland 	}
12585c51f124SMoriah Waterland 
12595c51f124SMoriah Waterland 	/* no newline found - point to null terminator */
12605c51f124SMoriah Waterland 
12615c51f124SMoriah Waterland 	*cp = strchr(p, '\0');
12625c51f124SMoriah Waterland }
1263