xref: /onnv-gate/usr/src/lib/libpkg/common/gpkgmap.c (revision 9781:ccf49524d5dc)
1*9781SMoriah.Waterland@Sun.COM /*
2*9781SMoriah.Waterland@Sun.COM  * CDDL HEADER START
3*9781SMoriah.Waterland@Sun.COM  *
4*9781SMoriah.Waterland@Sun.COM  * The contents of this file are subject to the terms of the
5*9781SMoriah.Waterland@Sun.COM  * Common Development and Distribution License (the "License").
6*9781SMoriah.Waterland@Sun.COM  * You may not use this file except in compliance with the License.
7*9781SMoriah.Waterland@Sun.COM  *
8*9781SMoriah.Waterland@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*9781SMoriah.Waterland@Sun.COM  * or http://www.opensolaris.org/os/licensing.
10*9781SMoriah.Waterland@Sun.COM  * See the License for the specific language governing permissions
11*9781SMoriah.Waterland@Sun.COM  * and limitations under the License.
12*9781SMoriah.Waterland@Sun.COM  *
13*9781SMoriah.Waterland@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
14*9781SMoriah.Waterland@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*9781SMoriah.Waterland@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
16*9781SMoriah.Waterland@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
17*9781SMoriah.Waterland@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
18*9781SMoriah.Waterland@Sun.COM  *
19*9781SMoriah.Waterland@Sun.COM  * CDDL HEADER END
20*9781SMoriah.Waterland@Sun.COM  */
21*9781SMoriah.Waterland@Sun.COM 
22*9781SMoriah.Waterland@Sun.COM /*
23*9781SMoriah.Waterland@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
24*9781SMoriah.Waterland@Sun.COM  * Use is subject to license terms.
25*9781SMoriah.Waterland@Sun.COM  */
26*9781SMoriah.Waterland@Sun.COM 
27*9781SMoriah.Waterland@Sun.COM /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*9781SMoriah.Waterland@Sun.COM /* All Rights Reserved */
29*9781SMoriah.Waterland@Sun.COM 
30*9781SMoriah.Waterland@Sun.COM 
31*9781SMoriah.Waterland@Sun.COM 
32*9781SMoriah.Waterland@Sun.COM #include <stdio.h>
33*9781SMoriah.Waterland@Sun.COM #include <limits.h>
34*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
35*9781SMoriah.Waterland@Sun.COM #include <unistd.h>
36*9781SMoriah.Waterland@Sun.COM #include <string.h>
37*9781SMoriah.Waterland@Sun.COM #include <ctype.h>
38*9781SMoriah.Waterland@Sun.COM #include <fcntl.h>
39*9781SMoriah.Waterland@Sun.COM #include <sys/types.h>
40*9781SMoriah.Waterland@Sun.COM #include <sys/stat.h>
41*9781SMoriah.Waterland@Sun.COM #include <errno.h>
42*9781SMoriah.Waterland@Sun.COM #include "pkgstrct.h"
43*9781SMoriah.Waterland@Sun.COM #include "pkglib.h"
44*9781SMoriah.Waterland@Sun.COM #include "pkglibmsgs.h"
45*9781SMoriah.Waterland@Sun.COM #include "pkglocale.h"
46*9781SMoriah.Waterland@Sun.COM 
47*9781SMoriah.Waterland@Sun.COM #define	ERR_CANT_READ_LCLPATH		"unable to read local pathname"
48*9781SMoriah.Waterland@Sun.COM #define	ERR_BAD_VOLUME_NUMBER		"bad volume number"
49*9781SMoriah.Waterland@Sun.COM #define	ERR_CANNOT_READ_PATHNAME_FIELD	"unable to read pathname field"
50*9781SMoriah.Waterland@Sun.COM #define	ERR_CANNOT_READ_CONTENT_INFO	"unable to read content info"
51*9781SMoriah.Waterland@Sun.COM #define	ERR_EXTRA_TOKENS_PRESENT	"extra tokens on input line"
52*9781SMoriah.Waterland@Sun.COM #define	ERR_CANNOT_READ_CLASS_TOKEN	"unable to read class token"
53*9781SMoriah.Waterland@Sun.COM #define	ERR_BAD_LINK_SPEC		"missing or invalid link specification"
54*9781SMoriah.Waterland@Sun.COM #define	ERR_UNKNOWN_FTYPE		"unknown ftype"
55*9781SMoriah.Waterland@Sun.COM #define	ERR_NO_LINKSOURCE		"no link source specified"
56*9781SMoriah.Waterland@Sun.COM #define	ERR_CANNOT_READ_MM_DEVNUMS	"unable to read major/minor "\
57*9781SMoriah.Waterland@Sun.COM 					"device numbers"
58*9781SMoriah.Waterland@Sun.COM static int	eatwhite(FILE *fp);
59*9781SMoriah.Waterland@Sun.COM static int	getend(FILE *fp);
60*9781SMoriah.Waterland@Sun.COM static int	getstr(FILE *fp, char *sep, int n, char *str);
61*9781SMoriah.Waterland@Sun.COM static int	getnum(FILE *fp, int base, long *d, long bad);
62*9781SMoriah.Waterland@Sun.COM static int	getlnum(FILE *fp, int base, fsblkcnt_t *d, long bad);
63*9781SMoriah.Waterland@Sun.COM static int	getvalmode(FILE *fp, mode_t *d, long bad, int map);
64*9781SMoriah.Waterland@Sun.COM 
65*9781SMoriah.Waterland@Sun.COM static int	getendvfp(char **cp);
66*9781SMoriah.Waterland@Sun.COM static void	findendvfp(char **cp);
67*9781SMoriah.Waterland@Sun.COM static int	getstrvfp(char **cp, char *sep, int n, char *str);
68*9781SMoriah.Waterland@Sun.COM static int	getvalmodevfp(char **cp, mode_t *d, long bad, int map);
69*9781SMoriah.Waterland@Sun.COM int		getnumvfp(char **cp, int base, long *d, long bad);
70*9781SMoriah.Waterland@Sun.COM int		getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad);
71*9781SMoriah.Waterland@Sun.COM 
72*9781SMoriah.Waterland@Sun.COM static char	mypath[PATH_MAX];
73*9781SMoriah.Waterland@Sun.COM static char	mylocal[PATH_MAX];
74*9781SMoriah.Waterland@Sun.COM static int	mapmode = MAPNONE;
75*9781SMoriah.Waterland@Sun.COM static char	*maptype = "";
76*9781SMoriah.Waterland@Sun.COM static mode_t	d_mode = BADMODE;
77*9781SMoriah.Waterland@Sun.COM static char 	*d_owner = BADOWNER;
78*9781SMoriah.Waterland@Sun.COM static char	*d_group = BADGROUP;
79*9781SMoriah.Waterland@Sun.COM 
80*9781SMoriah.Waterland@Sun.COM /*
81*9781SMoriah.Waterland@Sun.COM  * These determine how gpkgmap() deals with mode, owner and group defaults.
82*9781SMoriah.Waterland@Sun.COM  * It is assumed that the owner and group arguments represent static fields
83*9781SMoriah.Waterland@Sun.COM  * which will persist until attrdefault() is called.
84*9781SMoriah.Waterland@Sun.COM  */
85*9781SMoriah.Waterland@Sun.COM void
attrpreset(int mode,char * owner,char * group)86*9781SMoriah.Waterland@Sun.COM attrpreset(int mode, char *owner, char *group)
87*9781SMoriah.Waterland@Sun.COM {
88*9781SMoriah.Waterland@Sun.COM 	d_mode = mode;
89*9781SMoriah.Waterland@Sun.COM 	d_owner = owner;
90*9781SMoriah.Waterland@Sun.COM 	d_group = group;
91*9781SMoriah.Waterland@Sun.COM }
92*9781SMoriah.Waterland@Sun.COM 
93*9781SMoriah.Waterland@Sun.COM void
attrdefault()94*9781SMoriah.Waterland@Sun.COM attrdefault()
95*9781SMoriah.Waterland@Sun.COM {
96*9781SMoriah.Waterland@Sun.COM 	d_mode = NOMODE;
97*9781SMoriah.Waterland@Sun.COM 	d_owner = NOOWNER;
98*9781SMoriah.Waterland@Sun.COM 	d_group = NOGROUP;
99*9781SMoriah.Waterland@Sun.COM }
100*9781SMoriah.Waterland@Sun.COM 
101*9781SMoriah.Waterland@Sun.COM /*
102*9781SMoriah.Waterland@Sun.COM  * This determines how gpkgmap() deals with environment variables in the
103*9781SMoriah.Waterland@Sun.COM  * mode, owner and group. Path is evaluated at a higher level based upon
104*9781SMoriah.Waterland@Sun.COM  * other circumstances.
105*9781SMoriah.Waterland@Sun.COM  */
106*9781SMoriah.Waterland@Sun.COM void
setmapmode(int mode)107*9781SMoriah.Waterland@Sun.COM setmapmode(int mode)
108*9781SMoriah.Waterland@Sun.COM {
109*9781SMoriah.Waterland@Sun.COM 	if (mode >= 0 || mode <= 3) {
110*9781SMoriah.Waterland@Sun.COM 		mapmode = mode;
111*9781SMoriah.Waterland@Sun.COM 		if (mode == MAPBUILD)
112*9781SMoriah.Waterland@Sun.COM 			maptype = " build";
113*9781SMoriah.Waterland@Sun.COM 		else if (mode == MAPINSTALL)
114*9781SMoriah.Waterland@Sun.COM 			maptype = " install";
115*9781SMoriah.Waterland@Sun.COM 		else
116*9781SMoriah.Waterland@Sun.COM 			maptype = "";
117*9781SMoriah.Waterland@Sun.COM 	}
118*9781SMoriah.Waterland@Sun.COM }
119*9781SMoriah.Waterland@Sun.COM 
120*9781SMoriah.Waterland@Sun.COM /* This is the external query interface for mapmode. */
121*9781SMoriah.Waterland@Sun.COM int
getmapmode(void)122*9781SMoriah.Waterland@Sun.COM getmapmode(void)
123*9781SMoriah.Waterland@Sun.COM {
124*9781SMoriah.Waterland@Sun.COM 	return (mapmode);
125*9781SMoriah.Waterland@Sun.COM }
126*9781SMoriah.Waterland@Sun.COM 
127*9781SMoriah.Waterland@Sun.COM /*
128*9781SMoriah.Waterland@Sun.COM  * Unpack the pkgmap or the contents file or whatever file is in that format.
129*9781SMoriah.Waterland@Sun.COM  * Based upon mapmode, environment parameters will be resolved for mode,
130*9781SMoriah.Waterland@Sun.COM  * owner and group.
131*9781SMoriah.Waterland@Sun.COM  */
132*9781SMoriah.Waterland@Sun.COM 
133*9781SMoriah.Waterland@Sun.COM int
gpkgmap(struct cfent * ept,FILE * fp)134*9781SMoriah.Waterland@Sun.COM gpkgmap(struct cfent *ept, FILE *fp)
135*9781SMoriah.Waterland@Sun.COM {
136*9781SMoriah.Waterland@Sun.COM 	int		c;
137*9781SMoriah.Waterland@Sun.COM 	boolean_t	first_char = B_TRUE;
138*9781SMoriah.Waterland@Sun.COM 
139*9781SMoriah.Waterland@Sun.COM 	setErrstr(NULL);
140*9781SMoriah.Waterland@Sun.COM 	ept->volno = 0;
141*9781SMoriah.Waterland@Sun.COM 	ept->ftype = BADFTYPE;
142*9781SMoriah.Waterland@Sun.COM 	(void) strcpy(ept->pkg_class, BADCLASS);
143*9781SMoriah.Waterland@Sun.COM 	ept->pkg_class_idx = -1;
144*9781SMoriah.Waterland@Sun.COM 	ept->path = NULL;
145*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.local = NULL;
146*9781SMoriah.Waterland@Sun.COM 	/* default attributes were supplied, so don't reset */
147*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.mode = d_mode;
148*9781SMoriah.Waterland@Sun.COM 	(void) strcpy(ept->ainfo.owner, d_owner);
149*9781SMoriah.Waterland@Sun.COM 	(void) strcpy(ept->ainfo.group, d_group);
150*9781SMoriah.Waterland@Sun.COM #ifdef SUNOS41
151*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.xmajor = BADMAJOR;
152*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.xminor = BADMINOR;
153*9781SMoriah.Waterland@Sun.COM #else
154*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.major = BADMAJOR;
155*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.minor = BADMINOR;
156*9781SMoriah.Waterland@Sun.COM #endif
157*9781SMoriah.Waterland@Sun.COM 	ept->cinfo.cksum = ept->cinfo.modtime = ept->cinfo.size = (-1L);
158*9781SMoriah.Waterland@Sun.COM 
159*9781SMoriah.Waterland@Sun.COM 	ept->npkgs = 0;
160*9781SMoriah.Waterland@Sun.COM 
161*9781SMoriah.Waterland@Sun.COM 	if (!fp)
162*9781SMoriah.Waterland@Sun.COM 		return (-1);
163*9781SMoriah.Waterland@Sun.COM readline:
164*9781SMoriah.Waterland@Sun.COM 	c = eatwhite(fp);
165*9781SMoriah.Waterland@Sun.COM 
166*9781SMoriah.Waterland@Sun.COM 	/*
167*9781SMoriah.Waterland@Sun.COM 	 * If the first character is not a digit, we assume that the
168*9781SMoriah.Waterland@Sun.COM 	 * volume number is 1.
169*9781SMoriah.Waterland@Sun.COM 	 */
170*9781SMoriah.Waterland@Sun.COM 	if (first_char && !isdigit(c)) {
171*9781SMoriah.Waterland@Sun.COM 		ept->volno = 1;
172*9781SMoriah.Waterland@Sun.COM 	}
173*9781SMoriah.Waterland@Sun.COM 	first_char = B_FALSE;
174*9781SMoriah.Waterland@Sun.COM 
175*9781SMoriah.Waterland@Sun.COM 	switch (c) {
176*9781SMoriah.Waterland@Sun.COM 	    case EOF:
177*9781SMoriah.Waterland@Sun.COM 		return (0);
178*9781SMoriah.Waterland@Sun.COM 
179*9781SMoriah.Waterland@Sun.COM 	    case '0':
180*9781SMoriah.Waterland@Sun.COM 	    case '1':
181*9781SMoriah.Waterland@Sun.COM 	    case '2':
182*9781SMoriah.Waterland@Sun.COM 	    case '3':
183*9781SMoriah.Waterland@Sun.COM 	    case '4':
184*9781SMoriah.Waterland@Sun.COM 	    case '5':
185*9781SMoriah.Waterland@Sun.COM 	    case '6':
186*9781SMoriah.Waterland@Sun.COM 	    case '7':
187*9781SMoriah.Waterland@Sun.COM 	    case '8':
188*9781SMoriah.Waterland@Sun.COM 	    case '9':
189*9781SMoriah.Waterland@Sun.COM 		if (ept->volno) {
190*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_BAD_VOLUME_NUMBER));
191*9781SMoriah.Waterland@Sun.COM 			goto error;
192*9781SMoriah.Waterland@Sun.COM 		}
193*9781SMoriah.Waterland@Sun.COM 		do {
194*9781SMoriah.Waterland@Sun.COM 			ept->volno = (ept->volno*10)+c-'0';
195*9781SMoriah.Waterland@Sun.COM 			c = getc(fp);
196*9781SMoriah.Waterland@Sun.COM 		} while (isdigit(c));
197*9781SMoriah.Waterland@Sun.COM 		if (ept->volno == 0)
198*9781SMoriah.Waterland@Sun.COM 			ept->volno = 1;
199*9781SMoriah.Waterland@Sun.COM 
200*9781SMoriah.Waterland@Sun.COM 		goto readline;
201*9781SMoriah.Waterland@Sun.COM 
202*9781SMoriah.Waterland@Sun.COM 	    case ':':
203*9781SMoriah.Waterland@Sun.COM 	    case '#':
204*9781SMoriah.Waterland@Sun.COM 		(void) getend(fp);
205*9781SMoriah.Waterland@Sun.COM 		/*FALLTHRU*/
206*9781SMoriah.Waterland@Sun.COM 	    case '\n':
207*9781SMoriah.Waterland@Sun.COM 		/*
208*9781SMoriah.Waterland@Sun.COM 		 * Since we are going to scan the next line,
209*9781SMoriah.Waterland@Sun.COM 		 * we need to reset volume number and first_char.
210*9781SMoriah.Waterland@Sun.COM 		 */
211*9781SMoriah.Waterland@Sun.COM 		ept->volno = 0;
212*9781SMoriah.Waterland@Sun.COM 		first_char = B_TRUE;
213*9781SMoriah.Waterland@Sun.COM 		goto readline;
214*9781SMoriah.Waterland@Sun.COM 
215*9781SMoriah.Waterland@Sun.COM 	    case 'i':
216*9781SMoriah.Waterland@Sun.COM 		ept->ftype = (char)c;
217*9781SMoriah.Waterland@Sun.COM 		c = eatwhite(fp);
218*9781SMoriah.Waterland@Sun.COM 		/*FALLTHRU*/
219*9781SMoriah.Waterland@Sun.COM 	    case '.':
220*9781SMoriah.Waterland@Sun.COM 	    case '/':
221*9781SMoriah.Waterland@Sun.COM 		(void) ungetc(c, fp);
222*9781SMoriah.Waterland@Sun.COM 
223*9781SMoriah.Waterland@Sun.COM 		if (getstr(fp, "=", PATH_MAX, mypath)) {
224*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD));
225*9781SMoriah.Waterland@Sun.COM 			goto error;
226*9781SMoriah.Waterland@Sun.COM 		}
227*9781SMoriah.Waterland@Sun.COM 		ept->path = mypath;
228*9781SMoriah.Waterland@Sun.COM 		c = getc(fp);
229*9781SMoriah.Waterland@Sun.COM 		if (c == '=') {
230*9781SMoriah.Waterland@Sun.COM 			if (getstr(fp, NULL, PATH_MAX, mylocal)) {
231*9781SMoriah.Waterland@Sun.COM 				setErrstr(pkg_gt(ERR_CANT_READ_LCLPATH));
232*9781SMoriah.Waterland@Sun.COM 				goto error;
233*9781SMoriah.Waterland@Sun.COM 			}
234*9781SMoriah.Waterland@Sun.COM 			ept->ainfo.local = mylocal;
235*9781SMoriah.Waterland@Sun.COM 		} else
236*9781SMoriah.Waterland@Sun.COM 			(void) ungetc(c, fp);
237*9781SMoriah.Waterland@Sun.COM 
238*9781SMoriah.Waterland@Sun.COM 		if (ept->ftype == 'i') {
239*9781SMoriah.Waterland@Sun.COM 			/* content info might exist */
240*9781SMoriah.Waterland@Sun.COM 			if (!getlnum(fp, 10, (fsblkcnt_t *)&ept->cinfo.size,
241*9781SMoriah.Waterland@Sun.COM 			    BADCONT) &&
242*9781SMoriah.Waterland@Sun.COM 			    (getnum(fp, 10, (long *)&ept->cinfo.cksum,
243*9781SMoriah.Waterland@Sun.COM 			    BADCONT) ||
244*9781SMoriah.Waterland@Sun.COM 			    getnum(fp, 10, (long *)&ept->cinfo.modtime,
245*9781SMoriah.Waterland@Sun.COM 			    BADCONT))) {
246*9781SMoriah.Waterland@Sun.COM 				setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO));
247*9781SMoriah.Waterland@Sun.COM 				goto error;
248*9781SMoriah.Waterland@Sun.COM 			}
249*9781SMoriah.Waterland@Sun.COM 		}
250*9781SMoriah.Waterland@Sun.COM 		if (getend(fp)) {
251*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT));
252*9781SMoriah.Waterland@Sun.COM 			return (-1);
253*9781SMoriah.Waterland@Sun.COM 		}
254*9781SMoriah.Waterland@Sun.COM 		return (1);
255*9781SMoriah.Waterland@Sun.COM 
256*9781SMoriah.Waterland@Sun.COM 	    case '?':
257*9781SMoriah.Waterland@Sun.COM 	    case 'f':
258*9781SMoriah.Waterland@Sun.COM 	    case 'v':
259*9781SMoriah.Waterland@Sun.COM 	    case 'e':
260*9781SMoriah.Waterland@Sun.COM 	    case 'l':
261*9781SMoriah.Waterland@Sun.COM 	    case 's':
262*9781SMoriah.Waterland@Sun.COM 	    case 'p':
263*9781SMoriah.Waterland@Sun.COM 	    case 'c':
264*9781SMoriah.Waterland@Sun.COM 	    case 'b':
265*9781SMoriah.Waterland@Sun.COM 	    case 'd':
266*9781SMoriah.Waterland@Sun.COM 	    case 'x':
267*9781SMoriah.Waterland@Sun.COM 		ept->ftype = (char)c;
268*9781SMoriah.Waterland@Sun.COM 		if (getstr(fp, NULL, CLSSIZ, ept->pkg_class)) {
269*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_CLASS_TOKEN));
270*9781SMoriah.Waterland@Sun.COM 			goto error;
271*9781SMoriah.Waterland@Sun.COM 		}
272*9781SMoriah.Waterland@Sun.COM 		if (getstr(fp, "=", PATH_MAX, mypath)) {
273*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD));
274*9781SMoriah.Waterland@Sun.COM 			goto error;
275*9781SMoriah.Waterland@Sun.COM 		}
276*9781SMoriah.Waterland@Sun.COM 		ept->path = mypath;
277*9781SMoriah.Waterland@Sun.COM 
278*9781SMoriah.Waterland@Sun.COM 		c = getc(fp);
279*9781SMoriah.Waterland@Sun.COM 		if (c == '=') {
280*9781SMoriah.Waterland@Sun.COM 			/* local path */
281*9781SMoriah.Waterland@Sun.COM 			if (getstr(fp, NULL, PATH_MAX, mylocal)) {
282*9781SMoriah.Waterland@Sun.COM 				if (ept->ftype == 's' || ept->ftype == 'l') {
283*9781SMoriah.Waterland@Sun.COM 					setErrstr(pkg_gt(ERR_READLINK));
284*9781SMoriah.Waterland@Sun.COM 				} else {
285*9781SMoriah.Waterland@Sun.COM 					setErrstr(
286*9781SMoriah.Waterland@Sun.COM 						pkg_gt(ERR_CANT_READ_LCLPATH));
287*9781SMoriah.Waterland@Sun.COM 				}
288*9781SMoriah.Waterland@Sun.COM 				goto error;
289*9781SMoriah.Waterland@Sun.COM 			}
290*9781SMoriah.Waterland@Sun.COM 			ept->ainfo.local = mylocal;
291*9781SMoriah.Waterland@Sun.COM 		} else if (strchr("sl", ept->ftype)) {
292*9781SMoriah.Waterland@Sun.COM 			if ((c != EOF) && (c != '\n'))
293*9781SMoriah.Waterland@Sun.COM 				(void) getend(fp);
294*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_BAD_LINK_SPEC));
295*9781SMoriah.Waterland@Sun.COM 			return (-1);
296*9781SMoriah.Waterland@Sun.COM 		} else
297*9781SMoriah.Waterland@Sun.COM 			(void) ungetc(c, fp);
298*9781SMoriah.Waterland@Sun.COM 		break;
299*9781SMoriah.Waterland@Sun.COM 
300*9781SMoriah.Waterland@Sun.COM 	    default:
301*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_UNKNOWN_FTYPE));
302*9781SMoriah.Waterland@Sun.COM error:
303*9781SMoriah.Waterland@Sun.COM 		(void) getend(fp);
304*9781SMoriah.Waterland@Sun.COM 		return (-1);
305*9781SMoriah.Waterland@Sun.COM 	}
306*9781SMoriah.Waterland@Sun.COM 
307*9781SMoriah.Waterland@Sun.COM 	if (strchr("sl", ept->ftype) && (ept->ainfo.local == NULL)) {
308*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_NO_LINKSOURCE));
309*9781SMoriah.Waterland@Sun.COM 		goto error;
310*9781SMoriah.Waterland@Sun.COM 	}
311*9781SMoriah.Waterland@Sun.COM 
312*9781SMoriah.Waterland@Sun.COM 	if (strchr("cb", ept->ftype)) {
313*9781SMoriah.Waterland@Sun.COM #ifdef SUNOS41
314*9781SMoriah.Waterland@Sun.COM 		ept->ainfo.xmajor = BADMAJOR;
315*9781SMoriah.Waterland@Sun.COM 		ept->ainfo.xminor = BADMINOR;
316*9781SMoriah.Waterland@Sun.COM 		if (getnum(fp, 10, (long *)&ept->ainfo.xmajor, BADMAJOR) ||
317*9781SMoriah.Waterland@Sun.COM 		    getnum(fp, 10, (long *)&ept->ainfo.xminor, BADMINOR))
318*9781SMoriah.Waterland@Sun.COM #else
319*9781SMoriah.Waterland@Sun.COM 		ept->ainfo.major = BADMAJOR;
320*9781SMoriah.Waterland@Sun.COM 		ept->ainfo.minor = BADMINOR;
321*9781SMoriah.Waterland@Sun.COM 		if (getnum(fp, 10, (long *)&ept->ainfo.major, BADMAJOR) ||
322*9781SMoriah.Waterland@Sun.COM 		    getnum(fp, 10, (long *)&ept->ainfo.minor, BADMINOR))
323*9781SMoriah.Waterland@Sun.COM #endif
324*9781SMoriah.Waterland@Sun.COM 		{
325*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_MM_DEVNUMS));
326*9781SMoriah.Waterland@Sun.COM 			goto error;
327*9781SMoriah.Waterland@Sun.COM 		}
328*9781SMoriah.Waterland@Sun.COM 	}
329*9781SMoriah.Waterland@Sun.COM 
330*9781SMoriah.Waterland@Sun.COM 	/*
331*9781SMoriah.Waterland@Sun.COM 	 * Links and information files don't have attributes associated with
332*9781SMoriah.Waterland@Sun.COM 	 * them. The following either resolves potential variables or passes
333*9781SMoriah.Waterland@Sun.COM 	 * them through. Mode is tested for validity to some degree. BAD???
334*9781SMoriah.Waterland@Sun.COM 	 * is returned to indicate that no meaningful mode was provided. A
335*9781SMoriah.Waterland@Sun.COM 	 * higher authority will decide if that's OK or not. CUR??? means that
336*9781SMoriah.Waterland@Sun.COM 	 * the prototype file specifically requires a wildcard ('?') for
337*9781SMoriah.Waterland@Sun.COM 	 * that entry. We issue an error if attributes were entered wrong.
338*9781SMoriah.Waterland@Sun.COM 	 * We just return BAD??? if there was no entry at all.
339*9781SMoriah.Waterland@Sun.COM 	 */
340*9781SMoriah.Waterland@Sun.COM 	if (strchr("cbdxpfve", ept->ftype)) {
341*9781SMoriah.Waterland@Sun.COM 		int retval;
342*9781SMoriah.Waterland@Sun.COM 
343*9781SMoriah.Waterland@Sun.COM 		if ((retval = getvalmode(fp, &(ept->ainfo.mode), CURMODE,
344*9781SMoriah.Waterland@Sun.COM 		    (mapmode != MAPNONE))) == 1)
345*9781SMoriah.Waterland@Sun.COM 			goto end;	/* nothing else on the line */
346*9781SMoriah.Waterland@Sun.COM 		else if (retval == 2)
347*9781SMoriah.Waterland@Sun.COM 			goto error;	/* mode is too no good */
348*9781SMoriah.Waterland@Sun.COM 
349*9781SMoriah.Waterland@Sun.COM 		/* owner & group should be here */
350*9781SMoriah.Waterland@Sun.COM 		if ((retval = getstr(fp, NULL, ATRSIZ,
351*9781SMoriah.Waterland@Sun.COM 		    ept->ainfo.owner)) == 1)
352*9781SMoriah.Waterland@Sun.COM 			goto end;	/* no owner or group - warning */
353*9781SMoriah.Waterland@Sun.COM 		if (retval == -1) {
354*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_OWNTOOLONG));
355*9781SMoriah.Waterland@Sun.COM 			goto error;
356*9781SMoriah.Waterland@Sun.COM 		}
357*9781SMoriah.Waterland@Sun.COM 
358*9781SMoriah.Waterland@Sun.COM 		if ((retval = getstr(fp, NULL, ATRSIZ,
359*9781SMoriah.Waterland@Sun.COM 		    ept->ainfo.group)) == 1)
360*9781SMoriah.Waterland@Sun.COM 			goto end;	/* no group - warning */
361*9781SMoriah.Waterland@Sun.COM 		if (retval == -1) {
362*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_GRPTOOLONG));
363*9781SMoriah.Waterland@Sun.COM 			goto error;
364*9781SMoriah.Waterland@Sun.COM 		}
365*9781SMoriah.Waterland@Sun.COM 
366*9781SMoriah.Waterland@Sun.COM 		/* Resolve the parameters if required. */
367*9781SMoriah.Waterland@Sun.COM 		if (mapmode != MAPNONE) {
368*9781SMoriah.Waterland@Sun.COM 			if (mapvar(mapmode, ept->ainfo.owner)) {
369*9781SMoriah.Waterland@Sun.COM 				(void) snprintf(getErrbufAddr(),
370*9781SMoriah.Waterland@Sun.COM 					getErrbufSize(),
371*9781SMoriah.Waterland@Sun.COM 					pkg_gt(ERR_NOVAR),
372*9781SMoriah.Waterland@Sun.COM 					maptype, ept->ainfo.owner);
373*9781SMoriah.Waterland@Sun.COM 				setErrstr(getErrbufAddr());
374*9781SMoriah.Waterland@Sun.COM 				goto error;
375*9781SMoriah.Waterland@Sun.COM 			}
376*9781SMoriah.Waterland@Sun.COM 			if (mapvar(mapmode, ept->ainfo.group)) {
377*9781SMoriah.Waterland@Sun.COM 				(void) snprintf(getErrbufAddr(),
378*9781SMoriah.Waterland@Sun.COM 					getErrbufSize(), pkg_gt(ERR_NOVAR),
379*9781SMoriah.Waterland@Sun.COM 					maptype, ept->ainfo.group);
380*9781SMoriah.Waterland@Sun.COM 				setErrstr(getErrbufAddr());
381*9781SMoriah.Waterland@Sun.COM 				goto error;
382*9781SMoriah.Waterland@Sun.COM 			}
383*9781SMoriah.Waterland@Sun.COM 		}
384*9781SMoriah.Waterland@Sun.COM 	}
385*9781SMoriah.Waterland@Sun.COM 
386*9781SMoriah.Waterland@Sun.COM 	if (strchr("ifve", ept->ftype)) {
387*9781SMoriah.Waterland@Sun.COM 		/* look for content description */
388*9781SMoriah.Waterland@Sun.COM 		if (!getlnum(fp, 10, (fsblkcnt_t *)&ept->cinfo.size, BADCONT) &&
389*9781SMoriah.Waterland@Sun.COM 		(getnum(fp, 10, (long *)&ept->cinfo.cksum, BADCONT) ||
390*9781SMoriah.Waterland@Sun.COM 		getnum(fp, 10, (long *)&ept->cinfo.modtime, BADCONT))) {
391*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO));
392*9781SMoriah.Waterland@Sun.COM 			goto error;
393*9781SMoriah.Waterland@Sun.COM 		}
394*9781SMoriah.Waterland@Sun.COM 	}
395*9781SMoriah.Waterland@Sun.COM 
396*9781SMoriah.Waterland@Sun.COM 	if (ept->ftype == 'i')
397*9781SMoriah.Waterland@Sun.COM 		goto end;
398*9781SMoriah.Waterland@Sun.COM 
399*9781SMoriah.Waterland@Sun.COM end:
400*9781SMoriah.Waterland@Sun.COM 	if (getend(fp) && ept->pinfo) {
401*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT));
402*9781SMoriah.Waterland@Sun.COM 		return (-1);
403*9781SMoriah.Waterland@Sun.COM 	}
404*9781SMoriah.Waterland@Sun.COM 
405*9781SMoriah.Waterland@Sun.COM done:
406*9781SMoriah.Waterland@Sun.COM 	return (1);
407*9781SMoriah.Waterland@Sun.COM }
408*9781SMoriah.Waterland@Sun.COM 
409*9781SMoriah.Waterland@Sun.COM /*
410*9781SMoriah.Waterland@Sun.COM  * Get and validate the mode attribute. This returns an error if
411*9781SMoriah.Waterland@Sun.COM  *	1. the mode string is too long
412*9781SMoriah.Waterland@Sun.COM  *	2. the mode string includes alpha characters
413*9781SMoriah.Waterland@Sun.COM  *	3. the mode string is not octal
414*9781SMoriah.Waterland@Sun.COM  *	4. mode string is an install parameter
415*9781SMoriah.Waterland@Sun.COM  *	5. mode is an unresolved build parameter and MAPBUILD is
416*9781SMoriah.Waterland@Sun.COM  *	   in effect.
417*9781SMoriah.Waterland@Sun.COM  * If the mode is a build parameter, it is
418*9781SMoriah.Waterland@Sun.COM  *	1. returned as is if MAPNONE is in effect
419*9781SMoriah.Waterland@Sun.COM  *	2. evaluated if MAPBUILD is in effect
420*9781SMoriah.Waterland@Sun.COM  *
421*9781SMoriah.Waterland@Sun.COM  * NOTE : We use "mapmode!=MAPBUILD" to gather that it is install
422*9781SMoriah.Waterland@Sun.COM  * time. At install time we just fix a mode with bad bits set by
423*9781SMoriah.Waterland@Sun.COM  * setting it to CURMODE. This should be an error in a few releases
424*9781SMoriah.Waterland@Sun.COM  * (2.8 maybe) but faulty modes are so common in existing packages
425*9781SMoriah.Waterland@Sun.COM  * that this is a reasonable exception. -- JST 1994-11-9
426*9781SMoriah.Waterland@Sun.COM  *
427*9781SMoriah.Waterland@Sun.COM  * RETURNS
428*9781SMoriah.Waterland@Sun.COM  *	0 if mode is being returned as a valid value
429*9781SMoriah.Waterland@Sun.COM  *	1 if no attributes are present on the line
430*9781SMoriah.Waterland@Sun.COM  *	2 if there was a fundamental error
431*9781SMoriah.Waterland@Sun.COM  */
432*9781SMoriah.Waterland@Sun.COM static int
getvalmode(FILE * fp,mode_t * d,long bad,int map)433*9781SMoriah.Waterland@Sun.COM getvalmode(FILE *fp, mode_t *d, long bad, int map)
434*9781SMoriah.Waterland@Sun.COM {
435*9781SMoriah.Waterland@Sun.COM 	char tempmode[20];
436*9781SMoriah.Waterland@Sun.COM 	mode_t tempmode_t;
437*9781SMoriah.Waterland@Sun.COM 	int retval;
438*9781SMoriah.Waterland@Sun.COM 
439*9781SMoriah.Waterland@Sun.COM 	if ((retval = getstr(fp, NULL, ATRSIZ, tempmode)) == 1)
440*9781SMoriah.Waterland@Sun.COM 		return (1);
441*9781SMoriah.Waterland@Sun.COM 	else if (retval == -1) {
442*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_MODELONG));
443*9781SMoriah.Waterland@Sun.COM 		return (2);
444*9781SMoriah.Waterland@Sun.COM 	} else {
445*9781SMoriah.Waterland@Sun.COM 		/*
446*9781SMoriah.Waterland@Sun.COM 		 * If it isn't a '?' (meaning go with whatever mode is
447*9781SMoriah.Waterland@Sun.COM 		 * there), validate the mode and convert it to a mode_t. The
448*9781SMoriah.Waterland@Sun.COM 		 * "bad" variable here is a misnomer. It doesn't necessarily
449*9781SMoriah.Waterland@Sun.COM 		 * mean bad.
450*9781SMoriah.Waterland@Sun.COM 		 */
451*9781SMoriah.Waterland@Sun.COM 		if (tempmode[0] == '?') {
452*9781SMoriah.Waterland@Sun.COM 			*d = WILDCARD;
453*9781SMoriah.Waterland@Sun.COM 		} else {
454*9781SMoriah.Waterland@Sun.COM 			/*
455*9781SMoriah.Waterland@Sun.COM 			 * Mode may not be an install parameter or a
456*9781SMoriah.Waterland@Sun.COM 			 * non-build parameter.
457*9781SMoriah.Waterland@Sun.COM 			 */
458*9781SMoriah.Waterland@Sun.COM 			if (tempmode[0] == '$' &&
459*9781SMoriah.Waterland@Sun.COM 			    (isupper(tempmode[1]) || !islower(tempmode[1]))) {
460*9781SMoriah.Waterland@Sun.COM 				setErrstr(pkg_gt(ERR_IMODE));
461*9781SMoriah.Waterland@Sun.COM 				return (2);
462*9781SMoriah.Waterland@Sun.COM 			}
463*9781SMoriah.Waterland@Sun.COM 
464*9781SMoriah.Waterland@Sun.COM 			if ((map) && (mapvar(mapmode, tempmode))) {
465*9781SMoriah.Waterland@Sun.COM 				(void) snprintf(getErrbufAddr(),
466*9781SMoriah.Waterland@Sun.COM 						getErrbufSize(),
467*9781SMoriah.Waterland@Sun.COM 						pkg_gt(ERR_NOVAR),
468*9781SMoriah.Waterland@Sun.COM 						maptype, tempmode);
469*9781SMoriah.Waterland@Sun.COM 				setErrstr(getErrbufAddr());
470*9781SMoriah.Waterland@Sun.COM 				return (2);
471*9781SMoriah.Waterland@Sun.COM 			}
472*9781SMoriah.Waterland@Sun.COM 
473*9781SMoriah.Waterland@Sun.COM 
474*9781SMoriah.Waterland@Sun.COM 			if (tempmode[0] == '$') {
475*9781SMoriah.Waterland@Sun.COM 				*d = BADMODE;	/* may be a problem */
476*9781SMoriah.Waterland@Sun.COM 			} else {
477*9781SMoriah.Waterland@Sun.COM 				/*
478*9781SMoriah.Waterland@Sun.COM 				 * At this point it's supposed to be
479*9781SMoriah.Waterland@Sun.COM 				 * something we can convert to a number.
480*9781SMoriah.Waterland@Sun.COM 				 */
481*9781SMoriah.Waterland@Sun.COM 				int n = 0;
482*9781SMoriah.Waterland@Sun.COM 
483*9781SMoriah.Waterland@Sun.COM 				/*
484*9781SMoriah.Waterland@Sun.COM 				 * We reject it if it contains nonnumbers or
485*9781SMoriah.Waterland@Sun.COM 				 * it's not octal.
486*9781SMoriah.Waterland@Sun.COM 				 */
487*9781SMoriah.Waterland@Sun.COM 				while (tempmode[n] && !isspace(tempmode[n])) {
488*9781SMoriah.Waterland@Sun.COM 					if (!isdigit(tempmode[n])) {
489*9781SMoriah.Waterland@Sun.COM 						setErrstr(
490*9781SMoriah.Waterland@Sun.COM 							pkg_gt(ERR_MODEALPHA));
491*9781SMoriah.Waterland@Sun.COM 						return (2);
492*9781SMoriah.Waterland@Sun.COM 					}
493*9781SMoriah.Waterland@Sun.COM 
494*9781SMoriah.Waterland@Sun.COM 					if (strchr("89abcdefABCDEF",
495*9781SMoriah.Waterland@Sun.COM 					    tempmode[n])) {
496*9781SMoriah.Waterland@Sun.COM 						setErrstr(
497*9781SMoriah.Waterland@Sun.COM 							pkg_gt(ERR_BASEINVAL));
498*9781SMoriah.Waterland@Sun.COM 						return (2);
499*9781SMoriah.Waterland@Sun.COM 					}
500*9781SMoriah.Waterland@Sun.COM 					n++;
501*9781SMoriah.Waterland@Sun.COM 				}
502*9781SMoriah.Waterland@Sun.COM 
503*9781SMoriah.Waterland@Sun.COM 				tempmode_t = strtol(tempmode, NULL, 8);
504*9781SMoriah.Waterland@Sun.COM 
505*9781SMoriah.Waterland@Sun.COM 				/*
506*9781SMoriah.Waterland@Sun.COM 				 * We reject it if it contains inappropriate
507*9781SMoriah.Waterland@Sun.COM 				 * bits.
508*9781SMoriah.Waterland@Sun.COM 				 */
509*9781SMoriah.Waterland@Sun.COM 				if (tempmode_t & ~(S_IAMB |
510*9781SMoriah.Waterland@Sun.COM 				    S_ISUID | S_ISGID | S_ISVTX)) {
511*9781SMoriah.Waterland@Sun.COM 					if (mapmode != MAPBUILD) {
512*9781SMoriah.Waterland@Sun.COM 						tempmode_t = bad;
513*9781SMoriah.Waterland@Sun.COM 					} else {
514*9781SMoriah.Waterland@Sun.COM 						setErrstr(pkg_gt(ERR_MODEBITS));
515*9781SMoriah.Waterland@Sun.COM 						return (2);
516*9781SMoriah.Waterland@Sun.COM 					}
517*9781SMoriah.Waterland@Sun.COM 				}
518*9781SMoriah.Waterland@Sun.COM 				*d = tempmode_t;
519*9781SMoriah.Waterland@Sun.COM 			}
520*9781SMoriah.Waterland@Sun.COM 		}
521*9781SMoriah.Waterland@Sun.COM 		return (0);
522*9781SMoriah.Waterland@Sun.COM 	}
523*9781SMoriah.Waterland@Sun.COM }
524*9781SMoriah.Waterland@Sun.COM 
525*9781SMoriah.Waterland@Sun.COM static int
getnum(FILE * fp,int base,long * d,long bad)526*9781SMoriah.Waterland@Sun.COM getnum(FILE *fp, int base, long *d, long bad)
527*9781SMoriah.Waterland@Sun.COM {
528*9781SMoriah.Waterland@Sun.COM 	int c, b;
529*9781SMoriah.Waterland@Sun.COM 
530*9781SMoriah.Waterland@Sun.COM 	/* leading white space ignored */
531*9781SMoriah.Waterland@Sun.COM 	c = eatwhite(fp);
532*9781SMoriah.Waterland@Sun.COM 	if (c == '?') {
533*9781SMoriah.Waterland@Sun.COM 		*d = bad;
534*9781SMoriah.Waterland@Sun.COM 		return (0);
535*9781SMoriah.Waterland@Sun.COM 	}
536*9781SMoriah.Waterland@Sun.COM 
537*9781SMoriah.Waterland@Sun.COM 	if ((c == EOF) || (c == '\n') || !isdigit(c)) {
538*9781SMoriah.Waterland@Sun.COM 		(void) ungetc(c, fp);
539*9781SMoriah.Waterland@Sun.COM 		return (1);
540*9781SMoriah.Waterland@Sun.COM 	}
541*9781SMoriah.Waterland@Sun.COM 
542*9781SMoriah.Waterland@Sun.COM 	*d = 0;
543*9781SMoriah.Waterland@Sun.COM 	while (isdigit(c)) {
544*9781SMoriah.Waterland@Sun.COM 		b = (c & 017);
545*9781SMoriah.Waterland@Sun.COM 		if (b >= base)
546*9781SMoriah.Waterland@Sun.COM 			return (2);
547*9781SMoriah.Waterland@Sun.COM 		*d = (*d * base) + b;
548*9781SMoriah.Waterland@Sun.COM 		c = getc(fp);
549*9781SMoriah.Waterland@Sun.COM 	}
550*9781SMoriah.Waterland@Sun.COM 	(void) ungetc(c, fp);
551*9781SMoriah.Waterland@Sun.COM 	return (0);
552*9781SMoriah.Waterland@Sun.COM }
553*9781SMoriah.Waterland@Sun.COM 
554*9781SMoriah.Waterland@Sun.COM static int
getlnum(FILE * fp,int base,fsblkcnt_t * d,long bad)555*9781SMoriah.Waterland@Sun.COM getlnum(FILE *fp, int base, fsblkcnt_t *d, long bad)
556*9781SMoriah.Waterland@Sun.COM {
557*9781SMoriah.Waterland@Sun.COM 	int c, b;
558*9781SMoriah.Waterland@Sun.COM 
559*9781SMoriah.Waterland@Sun.COM 	/* leading white space ignored */
560*9781SMoriah.Waterland@Sun.COM 	c = eatwhite(fp);
561*9781SMoriah.Waterland@Sun.COM 	if (c == '?') {
562*9781SMoriah.Waterland@Sun.COM 		*d = bad;
563*9781SMoriah.Waterland@Sun.COM 		return (0);
564*9781SMoriah.Waterland@Sun.COM 	}
565*9781SMoriah.Waterland@Sun.COM 
566*9781SMoriah.Waterland@Sun.COM 	if ((c == EOF) || (c == '\n') || !isdigit(c)) {
567*9781SMoriah.Waterland@Sun.COM 		(void) ungetc(c, fp);
568*9781SMoriah.Waterland@Sun.COM 		return (1);
569*9781SMoriah.Waterland@Sun.COM 	}
570*9781SMoriah.Waterland@Sun.COM 
571*9781SMoriah.Waterland@Sun.COM 	*d = 0;
572*9781SMoriah.Waterland@Sun.COM 	while (isdigit(c)) {
573*9781SMoriah.Waterland@Sun.COM 		b = (c & 017);
574*9781SMoriah.Waterland@Sun.COM 		if (b >= base)
575*9781SMoriah.Waterland@Sun.COM 			return (2);
576*9781SMoriah.Waterland@Sun.COM 		*d = (*d * base) + b;
577*9781SMoriah.Waterland@Sun.COM 		c = getc(fp);
578*9781SMoriah.Waterland@Sun.COM 	}
579*9781SMoriah.Waterland@Sun.COM 	(void) ungetc(c, fp);
580*9781SMoriah.Waterland@Sun.COM 	return (0);
581*9781SMoriah.Waterland@Sun.COM }
582*9781SMoriah.Waterland@Sun.COM 
583*9781SMoriah.Waterland@Sun.COM /*
584*9781SMoriah.Waterland@Sun.COM  *  Get a string from the file. Returns
585*9781SMoriah.Waterland@Sun.COM  *	0 if all OK
586*9781SMoriah.Waterland@Sun.COM  *	1 if nothing there
587*9781SMoriah.Waterland@Sun.COM  *	-1 if string is too long
588*9781SMoriah.Waterland@Sun.COM  */
589*9781SMoriah.Waterland@Sun.COM static int
getstr(FILE * fp,char * sep,int n,char * str)590*9781SMoriah.Waterland@Sun.COM getstr(FILE *fp, char *sep, int n, char *str)
591*9781SMoriah.Waterland@Sun.COM {
592*9781SMoriah.Waterland@Sun.COM 	int c;
593*9781SMoriah.Waterland@Sun.COM 
594*9781SMoriah.Waterland@Sun.COM 	/* leading white space ignored */
595*9781SMoriah.Waterland@Sun.COM 	c = eatwhite(fp);
596*9781SMoriah.Waterland@Sun.COM 	if ((c == EOF) || (c == '\n')) {
597*9781SMoriah.Waterland@Sun.COM 		(void) ungetc(c, fp);
598*9781SMoriah.Waterland@Sun.COM 		return (1); /* nothing there */
599*9781SMoriah.Waterland@Sun.COM 	}
600*9781SMoriah.Waterland@Sun.COM 
601*9781SMoriah.Waterland@Sun.COM 	/* fill up string until space, tab, or separator */
602*9781SMoriah.Waterland@Sun.COM 	while (!strchr(" \t", c) && (!sep || !strchr(sep, c))) {
603*9781SMoriah.Waterland@Sun.COM 		if (n-- < 1) {
604*9781SMoriah.Waterland@Sun.COM 			*str = '\0';
605*9781SMoriah.Waterland@Sun.COM 			return (-1); /* too long */
606*9781SMoriah.Waterland@Sun.COM 		}
607*9781SMoriah.Waterland@Sun.COM 		*str++ = (char)c;
608*9781SMoriah.Waterland@Sun.COM 		c = getc(fp);
609*9781SMoriah.Waterland@Sun.COM 		if ((c == EOF) || (c == '\n'))
610*9781SMoriah.Waterland@Sun.COM 			break; /* no more on this line */
611*9781SMoriah.Waterland@Sun.COM 	}
612*9781SMoriah.Waterland@Sun.COM 	*str = '\0';
613*9781SMoriah.Waterland@Sun.COM 	(void) ungetc(c, fp);
614*9781SMoriah.Waterland@Sun.COM 
615*9781SMoriah.Waterland@Sun.COM 	return (0);
616*9781SMoriah.Waterland@Sun.COM }
617*9781SMoriah.Waterland@Sun.COM 
618*9781SMoriah.Waterland@Sun.COM static int
getend(FILE * fp)619*9781SMoriah.Waterland@Sun.COM getend(FILE *fp)
620*9781SMoriah.Waterland@Sun.COM {
621*9781SMoriah.Waterland@Sun.COM 	int c;
622*9781SMoriah.Waterland@Sun.COM 	int n;
623*9781SMoriah.Waterland@Sun.COM 
624*9781SMoriah.Waterland@Sun.COM 	n = 0;
625*9781SMoriah.Waterland@Sun.COM 	do {
626*9781SMoriah.Waterland@Sun.COM 		if ((c = getc(fp)) == EOF)
627*9781SMoriah.Waterland@Sun.COM 			return (n);
628*9781SMoriah.Waterland@Sun.COM 		if (!isspace(c))
629*9781SMoriah.Waterland@Sun.COM 			n++;
630*9781SMoriah.Waterland@Sun.COM 	} while (c != '\n');
631*9781SMoriah.Waterland@Sun.COM 	return (n);
632*9781SMoriah.Waterland@Sun.COM }
633*9781SMoriah.Waterland@Sun.COM 
634*9781SMoriah.Waterland@Sun.COM static int
eatwhite(FILE * fp)635*9781SMoriah.Waterland@Sun.COM eatwhite(FILE *fp)
636*9781SMoriah.Waterland@Sun.COM {
637*9781SMoriah.Waterland@Sun.COM 	int c;
638*9781SMoriah.Waterland@Sun.COM 
639*9781SMoriah.Waterland@Sun.COM 	/* this test works around a side effect of getc() */
640*9781SMoriah.Waterland@Sun.COM 	if (feof(fp))
641*9781SMoriah.Waterland@Sun.COM 		return (EOF);
642*9781SMoriah.Waterland@Sun.COM 	do
643*9781SMoriah.Waterland@Sun.COM 		c = getc(fp);
644*9781SMoriah.Waterland@Sun.COM 	while ((c == ' ') || (c == '\t'));
645*9781SMoriah.Waterland@Sun.COM 	return (c);
646*9781SMoriah.Waterland@Sun.COM }
647*9781SMoriah.Waterland@Sun.COM 
648*9781SMoriah.Waterland@Sun.COM int
gpkgmapvfp(struct cfent * ept,VFP_T * vfp)649*9781SMoriah.Waterland@Sun.COM gpkgmapvfp(struct cfent *ept, VFP_T *vfp)
650*9781SMoriah.Waterland@Sun.COM {
651*9781SMoriah.Waterland@Sun.COM 	int		c;
652*9781SMoriah.Waterland@Sun.COM 	boolean_t	first_char = B_TRUE;
653*9781SMoriah.Waterland@Sun.COM 	(void) strlcpy(ept->pkg_class, BADCLASS, sizeof (ept->pkg_class));
654*9781SMoriah.Waterland@Sun.COM 	(void) strlcpy(ept->ainfo.owner, d_owner, sizeof (ept->ainfo.owner));
655*9781SMoriah.Waterland@Sun.COM 	(void) strlcpy(ept->ainfo.group, d_group, sizeof (ept->ainfo.group));
656*9781SMoriah.Waterland@Sun.COM 
657*9781SMoriah.Waterland@Sun.COM 	setErrstr(NULL);
658*9781SMoriah.Waterland@Sun.COM 	ept->volno = 0;
659*9781SMoriah.Waterland@Sun.COM 	ept->ftype = BADFTYPE;
660*9781SMoriah.Waterland@Sun.COM 	ept->pkg_class_idx = -1;
661*9781SMoriah.Waterland@Sun.COM 	ept->path = NULL;
662*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.local = NULL;
663*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.mode = d_mode;
664*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.major = BADMAJOR;
665*9781SMoriah.Waterland@Sun.COM 	ept->ainfo.minor = BADMINOR;
666*9781SMoriah.Waterland@Sun.COM 	ept->cinfo.cksum = (-1L);
667*9781SMoriah.Waterland@Sun.COM 	ept->cinfo.modtime = (-1L);
668*9781SMoriah.Waterland@Sun.COM 	ept->cinfo.size = (-1L);
669*9781SMoriah.Waterland@Sun.COM 
670*9781SMoriah.Waterland@Sun.COM 	ept->npkgs = 0;
671*9781SMoriah.Waterland@Sun.COM 
672*9781SMoriah.Waterland@Sun.COM 	/* return error if no vfp specified */
673*9781SMoriah.Waterland@Sun.COM 
674*9781SMoriah.Waterland@Sun.COM 	if (vfp == (VFP_T *)NULL) {
675*9781SMoriah.Waterland@Sun.COM 		return (-1);
676*9781SMoriah.Waterland@Sun.COM 	}
677*9781SMoriah.Waterland@Sun.COM 
678*9781SMoriah.Waterland@Sun.COM readline:
679*9781SMoriah.Waterland@Sun.COM 	while (((c = vfpGetcNoInc(vfp)) != '\0') && (isspace(vfpGetc(vfp))))
680*9781SMoriah.Waterland@Sun.COM 		;
681*9781SMoriah.Waterland@Sun.COM 
682*9781SMoriah.Waterland@Sun.COM 	/*
683*9781SMoriah.Waterland@Sun.COM 	 * If the first character is not a digit, we assume that the
684*9781SMoriah.Waterland@Sun.COM 	 * volume number is 1.
685*9781SMoriah.Waterland@Sun.COM 	 */
686*9781SMoriah.Waterland@Sun.COM 	if (first_char && !isdigit(c)) {
687*9781SMoriah.Waterland@Sun.COM 		ept->volno = 1;
688*9781SMoriah.Waterland@Sun.COM 	}
689*9781SMoriah.Waterland@Sun.COM 	first_char = B_FALSE;
690*9781SMoriah.Waterland@Sun.COM 
691*9781SMoriah.Waterland@Sun.COM 	/*
692*9781SMoriah.Waterland@Sun.COM 	 * In case of hsfs the zero-padding of partial pages
693*9781SMoriah.Waterland@Sun.COM 	 * returned by mmap is not done properly. A separate bug has been filed
694*9781SMoriah.Waterland@Sun.COM 	 * on this.
695*9781SMoriah.Waterland@Sun.COM 	 */
696*9781SMoriah.Waterland@Sun.COM 
697*9781SMoriah.Waterland@Sun.COM 	if (vfp->_vfpCurr && (vfp->_vfpCurr > vfp->_vfpEnd)) {
698*9781SMoriah.Waterland@Sun.COM 		return (0);
699*9781SMoriah.Waterland@Sun.COM 	}
700*9781SMoriah.Waterland@Sun.COM 
701*9781SMoriah.Waterland@Sun.COM 	switch (c) {
702*9781SMoriah.Waterland@Sun.COM 	    case '\0':
703*9781SMoriah.Waterland@Sun.COM 		return (0);
704*9781SMoriah.Waterland@Sun.COM 
705*9781SMoriah.Waterland@Sun.COM 	    case '0':
706*9781SMoriah.Waterland@Sun.COM 	    case '1':
707*9781SMoriah.Waterland@Sun.COM 	    case '2':
708*9781SMoriah.Waterland@Sun.COM 	    case '3':
709*9781SMoriah.Waterland@Sun.COM 	    case '4':
710*9781SMoriah.Waterland@Sun.COM 	    case '5':
711*9781SMoriah.Waterland@Sun.COM 	    case '6':
712*9781SMoriah.Waterland@Sun.COM 	    case '7':
713*9781SMoriah.Waterland@Sun.COM 	    case '8':
714*9781SMoriah.Waterland@Sun.COM 	    case '9':
715*9781SMoriah.Waterland@Sun.COM 		if (ept->volno) {
716*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_BAD_VOLUME_NUMBER));
717*9781SMoriah.Waterland@Sun.COM 			goto error;
718*9781SMoriah.Waterland@Sun.COM 		}
719*9781SMoriah.Waterland@Sun.COM 		do {
720*9781SMoriah.Waterland@Sun.COM 			ept->volno = (ept->volno*10)+c-'0';
721*9781SMoriah.Waterland@Sun.COM 			c = vfpGetc(vfp);
722*9781SMoriah.Waterland@Sun.COM 		} while (isdigit(c));
723*9781SMoriah.Waterland@Sun.COM 		if (ept->volno == 0) {
724*9781SMoriah.Waterland@Sun.COM 			ept->volno = 1;
725*9781SMoriah.Waterland@Sun.COM 		}
726*9781SMoriah.Waterland@Sun.COM 
727*9781SMoriah.Waterland@Sun.COM 		goto readline;
728*9781SMoriah.Waterland@Sun.COM 
729*9781SMoriah.Waterland@Sun.COM 	    case ':':
730*9781SMoriah.Waterland@Sun.COM 	    case '#':
731*9781SMoriah.Waterland@Sun.COM 		(void) findendvfp(&vfpGetCurrCharPtr(vfp));
732*9781SMoriah.Waterland@Sun.COM 		/*FALLTHRU*/
733*9781SMoriah.Waterland@Sun.COM 	    case '\n':
734*9781SMoriah.Waterland@Sun.COM 		/*
735*9781SMoriah.Waterland@Sun.COM 		 * Since we are going to scan the next line,
736*9781SMoriah.Waterland@Sun.COM 		 * we need to reset volume number and first_char.
737*9781SMoriah.Waterland@Sun.COM 		 */
738*9781SMoriah.Waterland@Sun.COM 		ept->volno = 0;
739*9781SMoriah.Waterland@Sun.COM 		first_char = B_TRUE;
740*9781SMoriah.Waterland@Sun.COM 		goto readline;
741*9781SMoriah.Waterland@Sun.COM 
742*9781SMoriah.Waterland@Sun.COM 	    case 'i':
743*9781SMoriah.Waterland@Sun.COM 		ept->ftype = (char)c;
744*9781SMoriah.Waterland@Sun.COM 		while (((c = vfpGetcNoInc(vfp)) != '\0') &&
745*9781SMoriah.Waterland@Sun.COM 						(isspace(vfpGetc(vfp))))
746*9781SMoriah.Waterland@Sun.COM 			;
747*9781SMoriah.Waterland@Sun.COM 		/*FALLTHRU*/
748*9781SMoriah.Waterland@Sun.COM 	    case '.':
749*9781SMoriah.Waterland@Sun.COM 	    case '/':
750*9781SMoriah.Waterland@Sun.COM 		vfpDecCurrPtr(vfp);
751*9781SMoriah.Waterland@Sun.COM 
752*9781SMoriah.Waterland@Sun.COM 		if (getstrvfp(&vfpGetCurrCharPtr(vfp), "=", PATH_MAX, mypath)) {
753*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD));
754*9781SMoriah.Waterland@Sun.COM 			goto error;
755*9781SMoriah.Waterland@Sun.COM 		}
756*9781SMoriah.Waterland@Sun.COM 		ept->path = mypath;
757*9781SMoriah.Waterland@Sun.COM 		c = vfpGetc(vfp);
758*9781SMoriah.Waterland@Sun.COM 		if (c == '=') {
759*9781SMoriah.Waterland@Sun.COM 			if (getstrvfp(&vfpGetCurrCharPtr(vfp), NULL, PATH_MAX,
760*9781SMoriah.Waterland@Sun.COM 							mylocal)) {
761*9781SMoriah.Waterland@Sun.COM 				setErrstr(pkg_gt(ERR_CANT_READ_LCLPATH));
762*9781SMoriah.Waterland@Sun.COM 				goto error;
763*9781SMoriah.Waterland@Sun.COM 			}
764*9781SMoriah.Waterland@Sun.COM 			ept->ainfo.local = mylocal;
765*9781SMoriah.Waterland@Sun.COM 		} else {
766*9781SMoriah.Waterland@Sun.COM 			vfpDecCurrPtr(vfp);
767*9781SMoriah.Waterland@Sun.COM 		}
768*9781SMoriah.Waterland@Sun.COM 
769*9781SMoriah.Waterland@Sun.COM 		if (ept->ftype == 'i') {
770*9781SMoriah.Waterland@Sun.COM 			/* content info might exist */
771*9781SMoriah.Waterland@Sun.COM 			if (!getlnumvfp(&vfpGetCurrCharPtr(vfp), 10,
772*9781SMoriah.Waterland@Sun.COM 				(fsblkcnt_t *)&ept->cinfo.size, BADCONT) &&
773*9781SMoriah.Waterland@Sun.COM 			    (getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
774*9781SMoriah.Waterland@Sun.COM 				(long *)&ept->cinfo.cksum, BADCONT) ||
775*9781SMoriah.Waterland@Sun.COM 			    getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
776*9781SMoriah.Waterland@Sun.COM 				(long *)&ept->cinfo.modtime, BADCONT))) {
777*9781SMoriah.Waterland@Sun.COM 				setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO));
778*9781SMoriah.Waterland@Sun.COM 				goto error;
779*9781SMoriah.Waterland@Sun.COM 			}
780*9781SMoriah.Waterland@Sun.COM 		}
781*9781SMoriah.Waterland@Sun.COM 
782*9781SMoriah.Waterland@Sun.COM 		if (getendvfp(&vfpGetCurrCharPtr(vfp))) {
783*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT));
784*9781SMoriah.Waterland@Sun.COM 			return (-1);
785*9781SMoriah.Waterland@Sun.COM 		}
786*9781SMoriah.Waterland@Sun.COM 		return (1);
787*9781SMoriah.Waterland@Sun.COM 
788*9781SMoriah.Waterland@Sun.COM 	    case '?':
789*9781SMoriah.Waterland@Sun.COM 	    case 'f':
790*9781SMoriah.Waterland@Sun.COM 	    case 'v':
791*9781SMoriah.Waterland@Sun.COM 	    case 'e':
792*9781SMoriah.Waterland@Sun.COM 	    case 'l':
793*9781SMoriah.Waterland@Sun.COM 	    case 's':
794*9781SMoriah.Waterland@Sun.COM 	    case 'p':
795*9781SMoriah.Waterland@Sun.COM 	    case 'c':
796*9781SMoriah.Waterland@Sun.COM 	    case 'b':
797*9781SMoriah.Waterland@Sun.COM 	    case 'd':
798*9781SMoriah.Waterland@Sun.COM 	    case 'x':
799*9781SMoriah.Waterland@Sun.COM 		ept->ftype = (char)c;
800*9781SMoriah.Waterland@Sun.COM 		if (getstrvfp(&vfpGetCurrCharPtr(vfp), NULL,
801*9781SMoriah.Waterland@Sun.COM 						CLSSIZ, ept->pkg_class)) {
802*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_CLASS_TOKEN));
803*9781SMoriah.Waterland@Sun.COM 			goto error;
804*9781SMoriah.Waterland@Sun.COM 		}
805*9781SMoriah.Waterland@Sun.COM 		if (getstrvfp(&vfpGetCurrCharPtr(vfp), "=", PATH_MAX, mypath)) {
806*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_PATHNAME_FIELD));
807*9781SMoriah.Waterland@Sun.COM 			goto error;
808*9781SMoriah.Waterland@Sun.COM 		}
809*9781SMoriah.Waterland@Sun.COM 		ept->path = mypath;
810*9781SMoriah.Waterland@Sun.COM 
811*9781SMoriah.Waterland@Sun.COM 		c = vfpGetc(vfp);
812*9781SMoriah.Waterland@Sun.COM 		if (c == '=') {
813*9781SMoriah.Waterland@Sun.COM 			/* local path */
814*9781SMoriah.Waterland@Sun.COM 			if (getstrvfp(&vfpGetCurrCharPtr(vfp), NULL,
815*9781SMoriah.Waterland@Sun.COM 							PATH_MAX, mylocal)) {
816*9781SMoriah.Waterland@Sun.COM 				if (ept->ftype == 's' || ept->ftype == 'l') {
817*9781SMoriah.Waterland@Sun.COM 					setErrstr(pkg_gt(ERR_READLINK));
818*9781SMoriah.Waterland@Sun.COM 				} else {
819*9781SMoriah.Waterland@Sun.COM 					setErrstr(
820*9781SMoriah.Waterland@Sun.COM 						pkg_gt(ERR_CANT_READ_LCLPATH));
821*9781SMoriah.Waterland@Sun.COM 				}
822*9781SMoriah.Waterland@Sun.COM 				goto error;
823*9781SMoriah.Waterland@Sun.COM 			}
824*9781SMoriah.Waterland@Sun.COM 			ept->ainfo.local = mylocal;
825*9781SMoriah.Waterland@Sun.COM 		} else if ((ept->ftype == 's') || (ept->ftype == 'l')) {
826*9781SMoriah.Waterland@Sun.COM 			if ((c != '\0') && (c != '\n'))
827*9781SMoriah.Waterland@Sun.COM 				(void) findendvfp(&vfpGetCurrCharPtr(vfp));
828*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_BAD_LINK_SPEC));
829*9781SMoriah.Waterland@Sun.COM 			return (-1);
830*9781SMoriah.Waterland@Sun.COM 		} else {
831*9781SMoriah.Waterland@Sun.COM 			vfpDecCurrPtr(vfp);
832*9781SMoriah.Waterland@Sun.COM 		}
833*9781SMoriah.Waterland@Sun.COM 		break;
834*9781SMoriah.Waterland@Sun.COM 
835*9781SMoriah.Waterland@Sun.COM 	    default:
836*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_UNKNOWN_FTYPE));
837*9781SMoriah.Waterland@Sun.COM error:
838*9781SMoriah.Waterland@Sun.COM 		(void) findendvfp(&vfpGetCurrCharPtr(vfp));
839*9781SMoriah.Waterland@Sun.COM 		return (-1);
840*9781SMoriah.Waterland@Sun.COM 	}
841*9781SMoriah.Waterland@Sun.COM 
842*9781SMoriah.Waterland@Sun.COM 	if (((ept->ftype == 's') || (ept->ftype == 'l')) &&
843*9781SMoriah.Waterland@Sun.COM 					(ept->ainfo.local == NULL)) {
844*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_NO_LINKSOURCE));
845*9781SMoriah.Waterland@Sun.COM 		goto error;
846*9781SMoriah.Waterland@Sun.COM 	}
847*9781SMoriah.Waterland@Sun.COM 
848*9781SMoriah.Waterland@Sun.COM 	if (((ept->ftype == 'c') || (ept->ftype == 'b'))) {
849*9781SMoriah.Waterland@Sun.COM 		ept->ainfo.major = BADMAJOR;
850*9781SMoriah.Waterland@Sun.COM 		ept->ainfo.minor = BADMINOR;
851*9781SMoriah.Waterland@Sun.COM 
852*9781SMoriah.Waterland@Sun.COM 		if (getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
853*9781SMoriah.Waterland@Sun.COM 				(long *)&ept->ainfo.major, BADMAJOR) ||
854*9781SMoriah.Waterland@Sun.COM 		    getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
855*9781SMoriah.Waterland@Sun.COM 				(long *)&ept->ainfo.minor, BADMINOR)) {
856*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_MM_DEVNUMS));
857*9781SMoriah.Waterland@Sun.COM 			goto error;
858*9781SMoriah.Waterland@Sun.COM 		}
859*9781SMoriah.Waterland@Sun.COM 	}
860*9781SMoriah.Waterland@Sun.COM 
861*9781SMoriah.Waterland@Sun.COM 	/*
862*9781SMoriah.Waterland@Sun.COM 	 * Links and information files don't have attributes associated with
863*9781SMoriah.Waterland@Sun.COM 	 * them. The following either resolves potential variables or passes
864*9781SMoriah.Waterland@Sun.COM 	 * them through. Mode is tested for validity to some degree. BAD???
865*9781SMoriah.Waterland@Sun.COM 	 * is returned to indicate that no meaningful mode was provided. A
866*9781SMoriah.Waterland@Sun.COM 	 * higher authority will decide if that's OK or not. CUR??? means that
867*9781SMoriah.Waterland@Sun.COM 	 * the prototype file specifically requires a wildcard ('?') for
868*9781SMoriah.Waterland@Sun.COM 	 * that entry. We issue an error if attributes were entered wrong.
869*9781SMoriah.Waterland@Sun.COM 	 * We just return BAD??? if there was no entry at all.
870*9781SMoriah.Waterland@Sun.COM 	 */
871*9781SMoriah.Waterland@Sun.COM 	if ((ept->ftype == 'd') || (ept->ftype == 'x') || (ept->ftype == 'c') ||
872*9781SMoriah.Waterland@Sun.COM 		(ept->ftype == 'b') || (ept->ftype == 'p') ||
873*9781SMoriah.Waterland@Sun.COM 		(ept->ftype == 'f') || (ept->ftype == 'v') ||
874*9781SMoriah.Waterland@Sun.COM 		(ept->ftype == 'e')) {
875*9781SMoriah.Waterland@Sun.COM 		int retval;
876*9781SMoriah.Waterland@Sun.COM 
877*9781SMoriah.Waterland@Sun.COM 		retval = getvalmodevfp(&vfpGetCurrCharPtr(vfp),
878*9781SMoriah.Waterland@Sun.COM 				&(ept->ainfo.mode),
879*9781SMoriah.Waterland@Sun.COM 				CURMODE, (mapmode != MAPNONE));
880*9781SMoriah.Waterland@Sun.COM 
881*9781SMoriah.Waterland@Sun.COM 		if (retval == 1) {
882*9781SMoriah.Waterland@Sun.COM 			goto end;	/* nothing else on the line */
883*9781SMoriah.Waterland@Sun.COM 		} else if (retval == 2) {
884*9781SMoriah.Waterland@Sun.COM 			goto error;	/* mode is too no good */
885*9781SMoriah.Waterland@Sun.COM 		}
886*9781SMoriah.Waterland@Sun.COM 
887*9781SMoriah.Waterland@Sun.COM 		/* owner & group should be here */
888*9781SMoriah.Waterland@Sun.COM 		if ((retval = getstrvfp(&vfpGetCurrCharPtr(vfp), NULL, ATRSIZ,
889*9781SMoriah.Waterland@Sun.COM 		    ept->ainfo.owner)) == 1)
890*9781SMoriah.Waterland@Sun.COM 			goto end;	/* no owner or group - warning */
891*9781SMoriah.Waterland@Sun.COM 		if (retval == -1) {
892*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_OWNTOOLONG));
893*9781SMoriah.Waterland@Sun.COM 			goto error;
894*9781SMoriah.Waterland@Sun.COM 		}
895*9781SMoriah.Waterland@Sun.COM 
896*9781SMoriah.Waterland@Sun.COM 		if ((retval = getstrvfp(&vfpGetCurrCharPtr(vfp), NULL, ATRSIZ,
897*9781SMoriah.Waterland@Sun.COM 		    ept->ainfo.group)) == 1)
898*9781SMoriah.Waterland@Sun.COM 			goto end;	/* no group - warning */
899*9781SMoriah.Waterland@Sun.COM 		if (retval == -1) {
900*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_GRPTOOLONG));
901*9781SMoriah.Waterland@Sun.COM 			goto error;
902*9781SMoriah.Waterland@Sun.COM 		}
903*9781SMoriah.Waterland@Sun.COM 
904*9781SMoriah.Waterland@Sun.COM 		/* Resolve the parameters if required. */
905*9781SMoriah.Waterland@Sun.COM 		if (mapmode != MAPNONE) {
906*9781SMoriah.Waterland@Sun.COM 			if (mapvar(mapmode, ept->ainfo.owner)) {
907*9781SMoriah.Waterland@Sun.COM 				(void) snprintf(getErrbufAddr(),
908*9781SMoriah.Waterland@Sun.COM 					getErrbufSize(), pkg_gt(ERR_NOVAR),
909*9781SMoriah.Waterland@Sun.COM 					maptype, ept->ainfo.owner);
910*9781SMoriah.Waterland@Sun.COM 				setErrstr(getErrbufAddr());
911*9781SMoriah.Waterland@Sun.COM 				goto error;
912*9781SMoriah.Waterland@Sun.COM 			}
913*9781SMoriah.Waterland@Sun.COM 			if (mapvar(mapmode, ept->ainfo.group)) {
914*9781SMoriah.Waterland@Sun.COM 				(void) snprintf(getErrbufAddr(),
915*9781SMoriah.Waterland@Sun.COM 					getErrbufSize(), pkg_gt(ERR_NOVAR),
916*9781SMoriah.Waterland@Sun.COM 					maptype, ept->ainfo.group);
917*9781SMoriah.Waterland@Sun.COM 				setErrstr(getErrbufAddr());
918*9781SMoriah.Waterland@Sun.COM 				goto error;
919*9781SMoriah.Waterland@Sun.COM 			}
920*9781SMoriah.Waterland@Sun.COM 		}
921*9781SMoriah.Waterland@Sun.COM 	}
922*9781SMoriah.Waterland@Sun.COM 
923*9781SMoriah.Waterland@Sun.COM 	if ((ept->ftype == 'i') || (ept->ftype == 'f') ||
924*9781SMoriah.Waterland@Sun.COM 			(ept->ftype == 'v') || (ept->ftype == 'e')) {
925*9781SMoriah.Waterland@Sun.COM 		/* look for content description */
926*9781SMoriah.Waterland@Sun.COM 		if (!getlnumvfp(&vfpGetCurrCharPtr(vfp), 10,
927*9781SMoriah.Waterland@Sun.COM 				(fsblkcnt_t *)&ept->cinfo.size, BADCONT) &&
928*9781SMoriah.Waterland@Sun.COM 		(getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
929*9781SMoriah.Waterland@Sun.COM 				(long *)&ept->cinfo.cksum, BADCONT) ||
930*9781SMoriah.Waterland@Sun.COM 		getnumvfp(&vfpGetCurrCharPtr(vfp), 10,
931*9781SMoriah.Waterland@Sun.COM 				(long *)&ept->cinfo.modtime, BADCONT))) {
932*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_CANNOT_READ_CONTENT_INFO));
933*9781SMoriah.Waterland@Sun.COM 			goto error;
934*9781SMoriah.Waterland@Sun.COM 		}
935*9781SMoriah.Waterland@Sun.COM 	}
936*9781SMoriah.Waterland@Sun.COM 
937*9781SMoriah.Waterland@Sun.COM 	if (ept->ftype == 'i')
938*9781SMoriah.Waterland@Sun.COM 		goto end;
939*9781SMoriah.Waterland@Sun.COM 
940*9781SMoriah.Waterland@Sun.COM end:
941*9781SMoriah.Waterland@Sun.COM 	if (getendvfp(&vfpGetCurrCharPtr(vfp)) && ept->pinfo) {
942*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_EXTRA_TOKENS_PRESENT));
943*9781SMoriah.Waterland@Sun.COM 		return (-1);
944*9781SMoriah.Waterland@Sun.COM 	}
945*9781SMoriah.Waterland@Sun.COM 
946*9781SMoriah.Waterland@Sun.COM done:
947*9781SMoriah.Waterland@Sun.COM 	return (1);
948*9781SMoriah.Waterland@Sun.COM }
949*9781SMoriah.Waterland@Sun.COM 
950*9781SMoriah.Waterland@Sun.COM /*
951*9781SMoriah.Waterland@Sun.COM  * Get and validate the mode attribute. This returns an error if
952*9781SMoriah.Waterland@Sun.COM  *	1. the mode string is too long
953*9781SMoriah.Waterland@Sun.COM  *	2. the mode string includes alpha characters
954*9781SMoriah.Waterland@Sun.COM  *	3. the mode string is not octal
955*9781SMoriah.Waterland@Sun.COM  *	4. mode string is an install parameter
956*9781SMoriah.Waterland@Sun.COM  *	5. mode is an unresolved build parameter and MAPBUILD is
957*9781SMoriah.Waterland@Sun.COM  *	   in effect.
958*9781SMoriah.Waterland@Sun.COM  * If the mode is a build parameter, it is
959*9781SMoriah.Waterland@Sun.COM  *	1. returned as is if MAPNONE is in effect
960*9781SMoriah.Waterland@Sun.COM  *	2. evaluated if MAPBUILD is in effect
961*9781SMoriah.Waterland@Sun.COM  *
962*9781SMoriah.Waterland@Sun.COM  * NOTE : We use "mapmode!=MAPBUILD" to gather that it is install
963*9781SMoriah.Waterland@Sun.COM  * time. At install time we just fix a mode with bad bits set by
964*9781SMoriah.Waterland@Sun.COM  * setting it to CURMODE. This should be an error in a few releases
965*9781SMoriah.Waterland@Sun.COM  * (2.8 maybe) but faulty modes are so common in existing packages
966*9781SMoriah.Waterland@Sun.COM  * that this is a reasonable exception. -- JST 1994-11-9
967*9781SMoriah.Waterland@Sun.COM  *
968*9781SMoriah.Waterland@Sun.COM  * RETURNS
969*9781SMoriah.Waterland@Sun.COM  *	0 if mode is being returned as a valid value
970*9781SMoriah.Waterland@Sun.COM  *	1 if no attributes are present on the line
971*9781SMoriah.Waterland@Sun.COM  *	2 if there was a fundamental error
972*9781SMoriah.Waterland@Sun.COM  */
973*9781SMoriah.Waterland@Sun.COM static int
getvalmodevfp(char ** cp,mode_t * d,long bad,int map)974*9781SMoriah.Waterland@Sun.COM getvalmodevfp(char **cp, mode_t *d, long bad, int map)
975*9781SMoriah.Waterland@Sun.COM {
976*9781SMoriah.Waterland@Sun.COM 	char	tempmode[ATRSIZ+1];
977*9781SMoriah.Waterland@Sun.COM 	mode_t	tempmode_t;
978*9781SMoriah.Waterland@Sun.COM 	int	retval;
979*9781SMoriah.Waterland@Sun.COM 	int	n;
980*9781SMoriah.Waterland@Sun.COM 
981*9781SMoriah.Waterland@Sun.COM 	if ((retval = getstrvfp(cp, NULL, sizeof (tempmode), tempmode)) == 1) {
982*9781SMoriah.Waterland@Sun.COM 		return (1);
983*9781SMoriah.Waterland@Sun.COM 	} else if (retval == -1) {
984*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_MODELONG));
985*9781SMoriah.Waterland@Sun.COM 		return (2);
986*9781SMoriah.Waterland@Sun.COM 	}
987*9781SMoriah.Waterland@Sun.COM 
988*9781SMoriah.Waterland@Sun.COM 	/*
989*9781SMoriah.Waterland@Sun.COM 	 * If it isn't a '?' (meaning go with whatever mode is
990*9781SMoriah.Waterland@Sun.COM 	 * there), validate the mode and convert it to a mode_t. The
991*9781SMoriah.Waterland@Sun.COM 	 * "bad" variable here is a misnomer. It doesn't necessarily
992*9781SMoriah.Waterland@Sun.COM 	 * mean bad.
993*9781SMoriah.Waterland@Sun.COM 	 */
994*9781SMoriah.Waterland@Sun.COM 	if (tempmode[0] == '?') {
995*9781SMoriah.Waterland@Sun.COM 		*d = WILDCARD;
996*9781SMoriah.Waterland@Sun.COM 		return (0);
997*9781SMoriah.Waterland@Sun.COM 	}
998*9781SMoriah.Waterland@Sun.COM 
999*9781SMoriah.Waterland@Sun.COM 	/*
1000*9781SMoriah.Waterland@Sun.COM 	 * Mode may not be an install parameter or a
1001*9781SMoriah.Waterland@Sun.COM 	 * non-build parameter.
1002*9781SMoriah.Waterland@Sun.COM 	 */
1003*9781SMoriah.Waterland@Sun.COM 
1004*9781SMoriah.Waterland@Sun.COM 	if (tempmode[0] == '$' &&
1005*9781SMoriah.Waterland@Sun.COM 	    (isupper(tempmode[1]) || !islower(tempmode[1]))) {
1006*9781SMoriah.Waterland@Sun.COM 		setErrstr(pkg_gt(ERR_IMODE));
1007*9781SMoriah.Waterland@Sun.COM 		return (2);
1008*9781SMoriah.Waterland@Sun.COM 	}
1009*9781SMoriah.Waterland@Sun.COM 
1010*9781SMoriah.Waterland@Sun.COM 	if ((map) && (mapvar(mapmode, tempmode))) {
1011*9781SMoriah.Waterland@Sun.COM 		(void) snprintf(getErrbufAddr(), getErrbufSize(),
1012*9781SMoriah.Waterland@Sun.COM 				pkg_gt(ERR_NOVAR), maptype, tempmode);
1013*9781SMoriah.Waterland@Sun.COM 		setErrstr(getErrbufAddr());
1014*9781SMoriah.Waterland@Sun.COM 		return (2);
1015*9781SMoriah.Waterland@Sun.COM 	}
1016*9781SMoriah.Waterland@Sun.COM 
1017*9781SMoriah.Waterland@Sun.COM 	if (tempmode[0] == '$') {
1018*9781SMoriah.Waterland@Sun.COM 		*d = BADMODE;	/* may be a problem */
1019*9781SMoriah.Waterland@Sun.COM 		return (0);
1020*9781SMoriah.Waterland@Sun.COM 	}
1021*9781SMoriah.Waterland@Sun.COM 
1022*9781SMoriah.Waterland@Sun.COM 	/* it's supposed to be something we can convert to a number */
1023*9781SMoriah.Waterland@Sun.COM 
1024*9781SMoriah.Waterland@Sun.COM 	n = 0;
1025*9781SMoriah.Waterland@Sun.COM 
1026*9781SMoriah.Waterland@Sun.COM 	/* reject it if it contains nonnumbers or it's not octal */
1027*9781SMoriah.Waterland@Sun.COM 
1028*9781SMoriah.Waterland@Sun.COM 	while (tempmode[n] && !isspace(tempmode[n])) {
1029*9781SMoriah.Waterland@Sun.COM 		if (!isdigit(tempmode[n])) {
1030*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_MODEALPHA));
1031*9781SMoriah.Waterland@Sun.COM 			return (2);
1032*9781SMoriah.Waterland@Sun.COM 		}
1033*9781SMoriah.Waterland@Sun.COM 
1034*9781SMoriah.Waterland@Sun.COM 		if (strchr("89abcdefABCDEF", tempmode[n])) {
1035*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_BASEINVAL));
1036*9781SMoriah.Waterland@Sun.COM 			return (2);
1037*9781SMoriah.Waterland@Sun.COM 		}
1038*9781SMoriah.Waterland@Sun.COM 		n++;
1039*9781SMoriah.Waterland@Sun.COM 	}
1040*9781SMoriah.Waterland@Sun.COM 
1041*9781SMoriah.Waterland@Sun.COM 	tempmode_t = strtol(tempmode, NULL, 8);
1042*9781SMoriah.Waterland@Sun.COM 
1043*9781SMoriah.Waterland@Sun.COM 	/*
1044*9781SMoriah.Waterland@Sun.COM 	 * We reject it if it contains inappropriate
1045*9781SMoriah.Waterland@Sun.COM 	 * bits.
1046*9781SMoriah.Waterland@Sun.COM 	 */
1047*9781SMoriah.Waterland@Sun.COM 	if (tempmode_t & (~(S_IAMB | S_ISUID | S_ISGID | S_ISVTX))) {
1048*9781SMoriah.Waterland@Sun.COM 		if (mapmode == MAPBUILD) {
1049*9781SMoriah.Waterland@Sun.COM 			setErrstr(pkg_gt(ERR_MODEBITS));
1050*9781SMoriah.Waterland@Sun.COM 			return (2);
1051*9781SMoriah.Waterland@Sun.COM 		}
1052*9781SMoriah.Waterland@Sun.COM 		tempmode_t = bad;
1053*9781SMoriah.Waterland@Sun.COM 	}
1054*9781SMoriah.Waterland@Sun.COM 
1055*9781SMoriah.Waterland@Sun.COM 	*d = tempmode_t;
1056*9781SMoriah.Waterland@Sun.COM 
1057*9781SMoriah.Waterland@Sun.COM 	return (0);
1058*9781SMoriah.Waterland@Sun.COM }
1059*9781SMoriah.Waterland@Sun.COM 
1060*9781SMoriah.Waterland@Sun.COM int
getnumvfp(char ** cp,int base,long * d,long bad)1061*9781SMoriah.Waterland@Sun.COM getnumvfp(char **cp, int base, long *d, long bad)
1062*9781SMoriah.Waterland@Sun.COM {
1063*9781SMoriah.Waterland@Sun.COM 	int c;
1064*9781SMoriah.Waterland@Sun.COM 	char	*p = *cp;
1065*9781SMoriah.Waterland@Sun.COM 
1066*9781SMoriah.Waterland@Sun.COM 	if (*p == '\0') {
1067*9781SMoriah.Waterland@Sun.COM 		return (0);
1068*9781SMoriah.Waterland@Sun.COM 	}
1069*9781SMoriah.Waterland@Sun.COM 
1070*9781SMoriah.Waterland@Sun.COM 	/* leading white space ignored */
1071*9781SMoriah.Waterland@Sun.COM 	while (((c = *p) != '\0') && (isspace(*p++)))
1072*9781SMoriah.Waterland@Sun.COM 		;
1073*9781SMoriah.Waterland@Sun.COM 	if (c == '?') {
1074*9781SMoriah.Waterland@Sun.COM 		*d = bad;
1075*9781SMoriah.Waterland@Sun.COM 		*cp = p;
1076*9781SMoriah.Waterland@Sun.COM 		return (0);
1077*9781SMoriah.Waterland@Sun.COM 	}
1078*9781SMoriah.Waterland@Sun.COM 
1079*9781SMoriah.Waterland@Sun.COM 	if ((c == '\0') || (c == '\n') || !isdigit(c)) {
1080*9781SMoriah.Waterland@Sun.COM 		p--;
1081*9781SMoriah.Waterland@Sun.COM 		*cp = p;
1082*9781SMoriah.Waterland@Sun.COM 		return (1);
1083*9781SMoriah.Waterland@Sun.COM 	}
1084*9781SMoriah.Waterland@Sun.COM 
1085*9781SMoriah.Waterland@Sun.COM 	*d = 0;
1086*9781SMoriah.Waterland@Sun.COM 	while (isdigit(c)) {
1087*9781SMoriah.Waterland@Sun.COM 		*d = (*d * base) + (c & 017);
1088*9781SMoriah.Waterland@Sun.COM 		c = *p++;
1089*9781SMoriah.Waterland@Sun.COM 	}
1090*9781SMoriah.Waterland@Sun.COM 	p--;
1091*9781SMoriah.Waterland@Sun.COM 	*cp = p;
1092*9781SMoriah.Waterland@Sun.COM 	return (0);
1093*9781SMoriah.Waterland@Sun.COM }
1094*9781SMoriah.Waterland@Sun.COM 
1095*9781SMoriah.Waterland@Sun.COM int
getlnumvfp(char ** cp,int base,fsblkcnt_t * d,long bad)1096*9781SMoriah.Waterland@Sun.COM getlnumvfp(char **cp, int base, fsblkcnt_t *d, long bad)
1097*9781SMoriah.Waterland@Sun.COM {
1098*9781SMoriah.Waterland@Sun.COM 	int c;
1099*9781SMoriah.Waterland@Sun.COM 	char	*p = *cp;
1100*9781SMoriah.Waterland@Sun.COM 
1101*9781SMoriah.Waterland@Sun.COM 	if (*p == '\0') {
1102*9781SMoriah.Waterland@Sun.COM 		return (0);
1103*9781SMoriah.Waterland@Sun.COM 	}
1104*9781SMoriah.Waterland@Sun.COM 
1105*9781SMoriah.Waterland@Sun.COM 	/* leading white space ignored */
1106*9781SMoriah.Waterland@Sun.COM 	while (((c = *p) != '\0') && (isspace(*p++)))
1107*9781SMoriah.Waterland@Sun.COM 		;
1108*9781SMoriah.Waterland@Sun.COM 	if (c == '?') {
1109*9781SMoriah.Waterland@Sun.COM 		*d = bad;
1110*9781SMoriah.Waterland@Sun.COM 		*cp = p;
1111*9781SMoriah.Waterland@Sun.COM 		return (0);
1112*9781SMoriah.Waterland@Sun.COM 	}
1113*9781SMoriah.Waterland@Sun.COM 
1114*9781SMoriah.Waterland@Sun.COM 	if ((c == '\0') || (c == '\n') || !isdigit(c)) {
1115*9781SMoriah.Waterland@Sun.COM 		p--;
1116*9781SMoriah.Waterland@Sun.COM 		*cp = p;
1117*9781SMoriah.Waterland@Sun.COM 		return (1);
1118*9781SMoriah.Waterland@Sun.COM 	}
1119*9781SMoriah.Waterland@Sun.COM 
1120*9781SMoriah.Waterland@Sun.COM 	*d = 0;
1121*9781SMoriah.Waterland@Sun.COM 	while (isdigit(c)) {
1122*9781SMoriah.Waterland@Sun.COM 		*d = (*d * base) + (c & 017);
1123*9781SMoriah.Waterland@Sun.COM 		c = *p++;
1124*9781SMoriah.Waterland@Sun.COM 	}
1125*9781SMoriah.Waterland@Sun.COM 	p--;
1126*9781SMoriah.Waterland@Sun.COM 	*cp = p;
1127*9781SMoriah.Waterland@Sun.COM 	return (0);
1128*9781SMoriah.Waterland@Sun.COM }
1129*9781SMoriah.Waterland@Sun.COM 
1130*9781SMoriah.Waterland@Sun.COM static int
getstrvfp(char ** cp,char * sep,int n,char * str)1131*9781SMoriah.Waterland@Sun.COM getstrvfp(char **cp, char *sep, int n, char *str)
1132*9781SMoriah.Waterland@Sun.COM {
1133*9781SMoriah.Waterland@Sun.COM 	char	delims[256];
1134*9781SMoriah.Waterland@Sun.COM 	int	c;
1135*9781SMoriah.Waterland@Sun.COM 	char	*p = *cp;
1136*9781SMoriah.Waterland@Sun.COM 	char	*p1;
1137*9781SMoriah.Waterland@Sun.COM 	size_t	len;
1138*9781SMoriah.Waterland@Sun.COM 
1139*9781SMoriah.Waterland@Sun.COM 	if (*p == '\0') {
1140*9781SMoriah.Waterland@Sun.COM 		return (1);
1141*9781SMoriah.Waterland@Sun.COM 	}
1142*9781SMoriah.Waterland@Sun.COM 
1143*9781SMoriah.Waterland@Sun.COM 	/* leading white space ignored */
1144*9781SMoriah.Waterland@Sun.COM 
1145*9781SMoriah.Waterland@Sun.COM 	while (((c = *p) != '\0') && (isspace(*p++)))
1146*9781SMoriah.Waterland@Sun.COM 		;
1147*9781SMoriah.Waterland@Sun.COM 	if ((c == '\0') || (c == '\n')) {
1148*9781SMoriah.Waterland@Sun.COM 		p--;
1149*9781SMoriah.Waterland@Sun.COM 		*cp = p;
1150*9781SMoriah.Waterland@Sun.COM 		return (1); /* nothing there */
1151*9781SMoriah.Waterland@Sun.COM 	}
1152*9781SMoriah.Waterland@Sun.COM 
1153*9781SMoriah.Waterland@Sun.COM 	p--;
1154*9781SMoriah.Waterland@Sun.COM 
1155*9781SMoriah.Waterland@Sun.COM 	/* generate complete list of delimiters to scan for */
1156*9781SMoriah.Waterland@Sun.COM 
1157*9781SMoriah.Waterland@Sun.COM 	(void) strlcpy(delims, " \t\n", sizeof (delims));
1158*9781SMoriah.Waterland@Sun.COM 	if ((sep != (char *)NULL) && (*sep != '\0')) {
1159*9781SMoriah.Waterland@Sun.COM 		(void) strlcat(delims, sep, sizeof (delims));
1160*9781SMoriah.Waterland@Sun.COM 	}
1161*9781SMoriah.Waterland@Sun.COM 
1162*9781SMoriah.Waterland@Sun.COM 	/* compute length based on delimiter found or not */
1163*9781SMoriah.Waterland@Sun.COM 
1164*9781SMoriah.Waterland@Sun.COM 	p1 = strpbrk(p, delims);
1165*9781SMoriah.Waterland@Sun.COM 	if (p1 == (char *)NULL) {
1166*9781SMoriah.Waterland@Sun.COM 		len = strlen(p);
1167*9781SMoriah.Waterland@Sun.COM 	} else {
1168*9781SMoriah.Waterland@Sun.COM 		len = (ptrdiff_t)p1 - (ptrdiff_t)p;
1169*9781SMoriah.Waterland@Sun.COM 	}
1170*9781SMoriah.Waterland@Sun.COM 
1171*9781SMoriah.Waterland@Sun.COM 	/* if string will fit in result buffer copy string and return success */
1172*9781SMoriah.Waterland@Sun.COM 
1173*9781SMoriah.Waterland@Sun.COM 	if (len < n) {
1174*9781SMoriah.Waterland@Sun.COM 		(void) memcpy(str, p, len);
1175*9781SMoriah.Waterland@Sun.COM 		str[len] = '\0';
1176*9781SMoriah.Waterland@Sun.COM 		p += len;
1177*9781SMoriah.Waterland@Sun.COM 		*cp = p;
1178*9781SMoriah.Waterland@Sun.COM 		return (0);
1179*9781SMoriah.Waterland@Sun.COM 	}
1180*9781SMoriah.Waterland@Sun.COM 
1181*9781SMoriah.Waterland@Sun.COM 	/* result buffer too small; copy partial string, return error */
1182*9781SMoriah.Waterland@Sun.COM 	(void) memcpy(str, p, n-1);
1183*9781SMoriah.Waterland@Sun.COM 	str[n-1] = '\0';
1184*9781SMoriah.Waterland@Sun.COM 	p += n;
1185*9781SMoriah.Waterland@Sun.COM 	*cp = p;
1186*9781SMoriah.Waterland@Sun.COM 	return (-1);
1187*9781SMoriah.Waterland@Sun.COM }
1188*9781SMoriah.Waterland@Sun.COM 
1189*9781SMoriah.Waterland@Sun.COM /*
1190*9781SMoriah.Waterland@Sun.COM  * Name:	getendvfp
1191*9781SMoriah.Waterland@Sun.COM  * Description:	Locate the end of the current line given a pointer into a buffer
1192*9781SMoriah.Waterland@Sun.COM  *		containing characters that is null terminated.
1193*9781SMoriah.Waterland@Sun.COM  * Arguments:	char **cp - pointer to pointer to null-terminated string buffer
1194*9781SMoriah.Waterland@Sun.COM  * Returns:	int == 0 -- no non-space characters preceeded the newline
1195*9781SMoriah.Waterland@Sun.COM  *		    != 0 -- one or more non-space characters preceeded newline
1196*9781SMoriah.Waterland@Sun.COM  * Effects:	cp is updated to point to the first character PAST the first new
1197*9781SMoriah.Waterland@Sun.COM  *		line character found. If no newline character is found, cp is
1198*9781SMoriah.Waterland@Sun.COM  *		updated to point to the '\0' at the end of the buffer.
1199*9781SMoriah.Waterland@Sun.COM  */
1200*9781SMoriah.Waterland@Sun.COM 
1201*9781SMoriah.Waterland@Sun.COM static int
getendvfp(char ** cp)1202*9781SMoriah.Waterland@Sun.COM getendvfp(char **cp)
1203*9781SMoriah.Waterland@Sun.COM {
1204*9781SMoriah.Waterland@Sun.COM 	int	n;
1205*9781SMoriah.Waterland@Sun.COM 	char	*p = *cp;
1206*9781SMoriah.Waterland@Sun.COM 
1207*9781SMoriah.Waterland@Sun.COM 	n = 0;
1208*9781SMoriah.Waterland@Sun.COM 
1209*9781SMoriah.Waterland@Sun.COM 	/* if at end of buffer return no more characters left */
1210*9781SMoriah.Waterland@Sun.COM 
1211*9781SMoriah.Waterland@Sun.COM 	if (*p == '\0') {
1212*9781SMoriah.Waterland@Sun.COM 		return (0);
1213*9781SMoriah.Waterland@Sun.COM 	}
1214*9781SMoriah.Waterland@Sun.COM 
1215*9781SMoriah.Waterland@Sun.COM 	/* find the first null or end of line character */
1216*9781SMoriah.Waterland@Sun.COM 
1217*9781SMoriah.Waterland@Sun.COM 	while ((*p != '\0') && (*p != '\n')) {
1218*9781SMoriah.Waterland@Sun.COM 		if (n == 0) {
1219*9781SMoriah.Waterland@Sun.COM 			if (!isspace(*p)) {
1220*9781SMoriah.Waterland@Sun.COM 				n++;
1221*9781SMoriah.Waterland@Sun.COM 			}
1222*9781SMoriah.Waterland@Sun.COM 		}
1223*9781SMoriah.Waterland@Sun.COM 		p++;
1224*9781SMoriah.Waterland@Sun.COM 	}
1225*9781SMoriah.Waterland@Sun.COM 
1226*9781SMoriah.Waterland@Sun.COM 	/* if at newline, increment pointer to first character past newline */
1227*9781SMoriah.Waterland@Sun.COM 
1228*9781SMoriah.Waterland@Sun.COM 	if (*p == '\n') {
1229*9781SMoriah.Waterland@Sun.COM 		p++;
1230*9781SMoriah.Waterland@Sun.COM 	}
1231*9781SMoriah.Waterland@Sun.COM 
1232*9781SMoriah.Waterland@Sun.COM 	/* set return pointer to null or first character past newline */
1233*9781SMoriah.Waterland@Sun.COM 
1234*9781SMoriah.Waterland@Sun.COM 	*cp = p;
1235*9781SMoriah.Waterland@Sun.COM 
1236*9781SMoriah.Waterland@Sun.COM 	/* return space/nospace indicator */
1237*9781SMoriah.Waterland@Sun.COM 
1238*9781SMoriah.Waterland@Sun.COM 	return (n);
1239*9781SMoriah.Waterland@Sun.COM }
1240*9781SMoriah.Waterland@Sun.COM 
1241*9781SMoriah.Waterland@Sun.COM /*
1242*9781SMoriah.Waterland@Sun.COM  * Name:	findendvfp
1243*9781SMoriah.Waterland@Sun.COM  * Description:	Locate the end of the current line given a pointer into a buffer
1244*9781SMoriah.Waterland@Sun.COM  *		containing characters that is null terminated.
1245*9781SMoriah.Waterland@Sun.COM  * Arguments:	char **cp - pointer to pointer to null-terminated string buffer
1246*9781SMoriah.Waterland@Sun.COM  * Returns:	none
1247*9781SMoriah.Waterland@Sun.COM  * Effects:	cp is updated to point to the first character PAST the first new
1248*9781SMoriah.Waterland@Sun.COM  *		line character found. If no newline character is found, cp is
1249*9781SMoriah.Waterland@Sun.COM  *		updated to point to the '\0' at the end of the buffer.
1250*9781SMoriah.Waterland@Sun.COM  */
1251*9781SMoriah.Waterland@Sun.COM 
1252*9781SMoriah.Waterland@Sun.COM static void
findendvfp(char ** cp)1253*9781SMoriah.Waterland@Sun.COM findendvfp(char **cp)
1254*9781SMoriah.Waterland@Sun.COM {
1255*9781SMoriah.Waterland@Sun.COM 	char	*p1;
1256*9781SMoriah.Waterland@Sun.COM 	char	*p = *cp;
1257*9781SMoriah.Waterland@Sun.COM 
1258*9781SMoriah.Waterland@Sun.COM 	/* if at end of buffer return no more characters left */
1259*9781SMoriah.Waterland@Sun.COM 
1260*9781SMoriah.Waterland@Sun.COM 	if (*p == '\0') {
1261*9781SMoriah.Waterland@Sun.COM 		return;
1262*9781SMoriah.Waterland@Sun.COM 	}
1263*9781SMoriah.Waterland@Sun.COM 
1264*9781SMoriah.Waterland@Sun.COM 	/* find the end of the line */
1265*9781SMoriah.Waterland@Sun.COM 
1266*9781SMoriah.Waterland@Sun.COM 	p1 = strchr(p, '\n');
1267*9781SMoriah.Waterland@Sun.COM 	if (p1 != (char *)NULL) {
1268*9781SMoriah.Waterland@Sun.COM 		*cp = ++p1;
1269*9781SMoriah.Waterland@Sun.COM 		return;
1270*9781SMoriah.Waterland@Sun.COM 	}
1271*9781SMoriah.Waterland@Sun.COM 
1272*9781SMoriah.Waterland@Sun.COM 	/* no newline found - point to null terminator */
1273*9781SMoriah.Waterland@Sun.COM 
1274*9781SMoriah.Waterland@Sun.COM 	*cp = strchr(p, '\0');
1275*9781SMoriah.Waterland@Sun.COM }
1276