xref: /titanic_52/usr/src/cmd/svr4pkg/pkgmk/mkpkgmap.c (revision 5c51f1241dbbdf2656d0e10011981411ed0c9673)
1*5c51f124SMoriah Waterland /*
2*5c51f124SMoriah Waterland  * CDDL HEADER START
3*5c51f124SMoriah Waterland  *
4*5c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
5*5c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
6*5c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
7*5c51f124SMoriah Waterland  *
8*5c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
10*5c51f124SMoriah Waterland  * See the License for the specific language governing permissions
11*5c51f124SMoriah Waterland  * and limitations under the License.
12*5c51f124SMoriah Waterland  *
13*5c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
14*5c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
16*5c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
17*5c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5c51f124SMoriah Waterland  *
19*5c51f124SMoriah Waterland  * CDDL HEADER END
20*5c51f124SMoriah Waterland  */
21*5c51f124SMoriah Waterland 
22*5c51f124SMoriah Waterland /*
23*5c51f124SMoriah Waterland  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24*5c51f124SMoriah Waterland  * Use is subject to license terms.
25*5c51f124SMoriah Waterland  */
26*5c51f124SMoriah Waterland 
27*5c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28*5c51f124SMoriah Waterland /* All Rights Reserved */
29*5c51f124SMoriah Waterland 
30*5c51f124SMoriah Waterland 
31*5c51f124SMoriah Waterland #include <stdio.h>
32*5c51f124SMoriah Waterland #include <string.h>
33*5c51f124SMoriah Waterland #include <errno.h>
34*5c51f124SMoriah Waterland #include <ctype.h>
35*5c51f124SMoriah Waterland #include <sys/types.h>
36*5c51f124SMoriah Waterland #include <sys/stat.h>
37*5c51f124SMoriah Waterland #include <limits.h>
38*5c51f124SMoriah Waterland #include <pkgstrct.h>
39*5c51f124SMoriah Waterland #include <pkginfo.h>
40*5c51f124SMoriah Waterland #include <locale.h>
41*5c51f124SMoriah Waterland #include <libintl.h>
42*5c51f124SMoriah Waterland #include <unistd.h>
43*5c51f124SMoriah Waterland #include <stdlib.h>
44*5c51f124SMoriah Waterland #include <pkglib.h>
45*5c51f124SMoriah Waterland #include <install.h>
46*5c51f124SMoriah Waterland #include <libadm.h>
47*5c51f124SMoriah Waterland #include <libinst.h>
48*5c51f124SMoriah Waterland 
49*5c51f124SMoriah Waterland extern char	*basedir, *root, *rootlist[], **environ;
50*5c51f124SMoriah Waterland 
51*5c51f124SMoriah Waterland /*
52*5c51f124SMoriah Waterland  * IMPORTANT NOTE: PLEASE SEE THE DEFINITION OF temp[] BELOW BEFORE
53*5c51f124SMoriah Waterland  * CHANGING THE DEFINITION OF PATH_LGTH!!!!
54*5c51f124SMoriah Waterland  */
55*5c51f124SMoriah Waterland 
56*5c51f124SMoriah Waterland #define	PATH_LGTH 4096
57*5c51f124SMoriah Waterland 
58*5c51f124SMoriah Waterland #define	MAXPARAMS 256
59*5c51f124SMoriah Waterland #define	NRECURS 20
60*5c51f124SMoriah Waterland 
61*5c51f124SMoriah Waterland #define	MSG_BPARAMC	"parametric class specification for <%s> not allowed"
62*5c51f124SMoriah Waterland #define	MSG_SRCHLOC	"no object for <%s> found in local path"
63*5c51f124SMoriah Waterland #define	MSG_SRCHSRCH	"no object for <%s> found in search path"
64*5c51f124SMoriah Waterland #define	MSG_SRCHROOT	"no object for <%s> found in root directory"
65*5c51f124SMoriah Waterland #define	MSG_CONTENTS	"unable to process contents of object <%s>"
66*5c51f124SMoriah Waterland #define	MSG_WRITE	"write of entry failed, errno=%d"
67*5c51f124SMoriah Waterland #define	MSG_GARBDEFLT	"garbled default settings: %s"
68*5c51f124SMoriah Waterland #define	MSG_BANG	"unknown directive: %s"
69*5c51f124SMoriah Waterland #define	MSG_CHDIR	"unable to change directory to <%s>"
70*5c51f124SMoriah Waterland #define	MSG_INCOMPLETE	"processing of <%s> may be incomplete"
71*5c51f124SMoriah Waterland #define	MSG_NRECURS	"too many levels of include (limit is %d)"
72*5c51f124SMoriah Waterland #define	MSG_RDINCLUDE	"unable to process include file <%s>, errno=%d"
73*5c51f124SMoriah Waterland #define	MSG_IGNINCLUDE	"ignoring include file <%s>"
74*5c51f124SMoriah Waterland #define	MSG_NODEVICE	"device numbers cannot be determined for <%s>"
75*5c51f124SMoriah Waterland 
76*5c51f124SMoriah Waterland #define	WRN_BADATTR	"WARNING: attributes set to %04o %s %s for <%s>"
77*5c51f124SMoriah Waterland #define	WRN_BADATTRM	"WARNING: attributes set to %s %s %s for <%s>"
78*5c51f124SMoriah Waterland #define	WRN_FAKEBD	"WARNING: parametric paths may ignore BASEDIR"
79*5c51f124SMoriah Waterland 
80*5c51f124SMoriah Waterland #define	ERR_TEMP	"unable to obtain temporary file resources, errno=%d"
81*5c51f124SMoriah Waterland #define	ERR_ENVBUILD	"unable to build parameter environment, errno=%d"
82*5c51f124SMoriah Waterland #define	ERR_MAXPARAMS	"too many parameter definitions (limit is %d)"
83*5c51f124SMoriah Waterland #define	ERR_GETCWD	"unable to get current directory, errno=%d"
84*5c51f124SMoriah Waterland #define	ERR_PATHVAR	"cannot resolve all build parameters associated with " \
85*5c51f124SMoriah Waterland 			    "path <%s>."
86*5c51f124SMoriah Waterland 
87*5c51f124SMoriah Waterland static struct cfent entry;
88*5c51f124SMoriah Waterland static FILE	*fp,
89*5c51f124SMoriah Waterland 		*sfp[20];
90*5c51f124SMoriah Waterland static char	*dname[NRECURS],
91*5c51f124SMoriah Waterland 		*params[256],
92*5c51f124SMoriah Waterland 		*proto[NRECURS],
93*5c51f124SMoriah Waterland 		*rootp[NRECURS][16],
94*5c51f124SMoriah Waterland 		*srchp[NRECURS][16],
95*5c51f124SMoriah Waterland 		*d_own[NRECURS],
96*5c51f124SMoriah Waterland 		*d_grp[NRECURS],
97*5c51f124SMoriah Waterland 		*rdonly[256];
98*5c51f124SMoriah Waterland static mode_t	d_mod[NRECURS];
99*5c51f124SMoriah Waterland static int	nfp = (-1);
100*5c51f124SMoriah Waterland static int	nrdonly = 0;
101*5c51f124SMoriah Waterland static int	errflg = 0;
102*5c51f124SMoriah Waterland static char	*separ = " \t\n, ";
103*5c51f124SMoriah Waterland 
104*5c51f124SMoriah Waterland /* libpkg/gpkgmap.c */
105*5c51f124SMoriah Waterland extern void	attrpreset(int mode, char *owner, char *group);
106*5c51f124SMoriah Waterland extern void	attrdefault();
107*5c51f124SMoriah Waterland static char	*findfile(char *path, char *local);
108*5c51f124SMoriah Waterland static char	*srchroot(char *path, char *copy);
109*5c51f124SMoriah Waterland 
110*5c51f124SMoriah Waterland static int	popenv(void);
111*5c51f124SMoriah Waterland 
112*5c51f124SMoriah Waterland static int	doattrib(void);
113*5c51f124SMoriah Waterland static void	doinclude(void);
114*5c51f124SMoriah Waterland static void	dorsearch(void);
115*5c51f124SMoriah Waterland static void	dosearch(void);
116*5c51f124SMoriah Waterland static void	error(int flag);
117*5c51f124SMoriah Waterland static void	lputenv(char *s);
118*5c51f124SMoriah Waterland static void	pushenv(char *file);
119*5c51f124SMoriah Waterland static void	translate(register char *pt, register char *copy);
120*5c51f124SMoriah Waterland 
121*5c51f124SMoriah Waterland int
122*5c51f124SMoriah Waterland mkpkgmap(char *outfile, char *protofile, char **envparam)
123*5c51f124SMoriah Waterland {
124*5c51f124SMoriah Waterland 	FILE	*tmpfp;
125*5c51f124SMoriah Waterland 	char	*pt, *path, mybuff[PATH_LGTH];
126*5c51f124SMoriah Waterland 	char	**envsave;
127*5c51f124SMoriah Waterland 	int	c, fakebasedir;
128*5c51f124SMoriah Waterland 	int	i, n;
129*5c51f124SMoriah Waterland 
130*5c51f124SMoriah Waterland 	/*
131*5c51f124SMoriah Waterland 	 * NOTE: THE SIZE OF temp IS HARD CODED INTO CALLS TO fscanf.
132*5c51f124SMoriah Waterland 	 * YOU *MUST* MAKE SURE TO CHANGE THOSE CALLS IF THE SIZE OF temp
133*5c51f124SMoriah Waterland 	 * IS EVER CHANGED!!!!!!
134*5c51f124SMoriah Waterland 	 */
135*5c51f124SMoriah Waterland 	char	temp[PATH_LGTH];
136*5c51f124SMoriah Waterland 
137*5c51f124SMoriah Waterland 	if ((tmpfp = fopen(outfile, "w")) == NULL) {
138*5c51f124SMoriah Waterland 		progerr(gettext(ERR_TEMP), errno);
139*5c51f124SMoriah Waterland 		quit(99);
140*5c51f124SMoriah Waterland 	}
141*5c51f124SMoriah Waterland 	envsave = environ;
142*5c51f124SMoriah Waterland 	environ = params; /* use only local environ */
143*5c51f124SMoriah Waterland 	attrdefault();	/* assume no default attributes */
144*5c51f124SMoriah Waterland 
145*5c51f124SMoriah Waterland 	/*
146*5c51f124SMoriah Waterland 	 * Environment parameters are optional, so variable
147*5c51f124SMoriah Waterland 	 * (envparam[i]) could be NULL.
148*5c51f124SMoriah Waterland 	 */
149*5c51f124SMoriah Waterland 	for (i = 0; (envparam[i] != NULL) &&
150*5c51f124SMoriah Waterland 	    (pt = strchr(envparam[i], '=')); i++) {
151*5c51f124SMoriah Waterland 		*pt = '\0';
152*5c51f124SMoriah Waterland 		rdonly[nrdonly++] = qstrdup(envparam[i]);
153*5c51f124SMoriah Waterland 		*pt = '=';
154*5c51f124SMoriah Waterland 		if (putenv(qstrdup(envparam[i]))) { /* bugid 1090920 */
155*5c51f124SMoriah Waterland 			progerr(gettext(ERR_ENVBUILD), errno);
156*5c51f124SMoriah Waterland 			quit(99);
157*5c51f124SMoriah Waterland 		}
158*5c51f124SMoriah Waterland 		if (nrdonly >= MAXPARAMS) {
159*5c51f124SMoriah Waterland 			progerr(gettext(ERR_MAXPARAMS), MAXPARAMS);
160*5c51f124SMoriah Waterland 			quit(1);
161*5c51f124SMoriah Waterland 		}
162*5c51f124SMoriah Waterland 	}
163*5c51f124SMoriah Waterland 
164*5c51f124SMoriah Waterland 	pushenv(protofile);
165*5c51f124SMoriah Waterland 	errflg = 0;
166*5c51f124SMoriah Waterland again:
167*5c51f124SMoriah Waterland 	fakebasedir = 0;
168*5c51f124SMoriah Waterland 	while (!feof(fp)) {
169*5c51f124SMoriah Waterland 		c = getc(fp);
170*5c51f124SMoriah Waterland 		while (isspace(c))
171*5c51f124SMoriah Waterland 			c = getc(fp);
172*5c51f124SMoriah Waterland 
173*5c51f124SMoriah Waterland 		if (c == '#') {
174*5c51f124SMoriah Waterland 			do c = getc(fp); while ((c != EOF) && (c != '\n'));
175*5c51f124SMoriah Waterland 			continue;
176*5c51f124SMoriah Waterland 		}
177*5c51f124SMoriah Waterland 		if (c == EOF)
178*5c51f124SMoriah Waterland 			break;
179*5c51f124SMoriah Waterland 
180*5c51f124SMoriah Waterland 		if (c == '!') {
181*5c51f124SMoriah Waterland 			/*
182*5c51f124SMoriah Waterland 			 * IMPORTANT NOTE: THE SIZE OF temp IS HARD CODED INTO
183*5c51f124SMoriah Waterland 			 * the FOLLOWING CALL TO fscanf -- YOU MUST CHANGE THIS
184*5c51f124SMoriah Waterland 			 * LINE IF THE SIZE OF fscanf IS EVER CHANGED!!!
185*5c51f124SMoriah Waterland 			 */
186*5c51f124SMoriah Waterland 			(void) fscanf(fp, "%4096s", temp);
187*5c51f124SMoriah Waterland 
188*5c51f124SMoriah Waterland 			if (strcmp(temp, "include") == 0)
189*5c51f124SMoriah Waterland 				doinclude();
190*5c51f124SMoriah Waterland 			else if (strcmp(temp, "rsearch") == 0)
191*5c51f124SMoriah Waterland 				dorsearch();
192*5c51f124SMoriah Waterland 			else if (strcmp(temp, "search") == 0)
193*5c51f124SMoriah Waterland 				dosearch();
194*5c51f124SMoriah Waterland 			else if (strcmp(temp, "default") == 0) {
195*5c51f124SMoriah Waterland 				if (doattrib())
196*5c51f124SMoriah Waterland 					break;
197*5c51f124SMoriah Waterland 			} else if (strchr(temp, '=')) {
198*5c51f124SMoriah Waterland 				translate(temp, mybuff);
199*5c51f124SMoriah Waterland 				/* put this into the local environment */
200*5c51f124SMoriah Waterland 				lputenv(mybuff);
201*5c51f124SMoriah Waterland 				(void) fscanf(fp, "%*[^\n]"); /* rest of line */
202*5c51f124SMoriah Waterland 				(void) fscanf(fp, "\n"); /* rest of line */
203*5c51f124SMoriah Waterland 			} else {
204*5c51f124SMoriah Waterland 				error(1);
205*5c51f124SMoriah Waterland 				logerr(gettext(MSG_BANG), temp);
206*5c51f124SMoriah Waterland 				(void) fscanf(fp, "%*[^\n]"); /* read of line */
207*5c51f124SMoriah Waterland 				(void) fscanf(fp, "\n"); /* read of line */
208*5c51f124SMoriah Waterland 			}
209*5c51f124SMoriah Waterland 			continue;
210*5c51f124SMoriah Waterland 		}
211*5c51f124SMoriah Waterland 		(void) ungetc(c, fp);
212*5c51f124SMoriah Waterland 
213*5c51f124SMoriah Waterland 		if ((n = gpkgmap(&entry, fp)) < 0) {
214*5c51f124SMoriah Waterland 			char	*errstr;
215*5c51f124SMoriah Waterland 
216*5c51f124SMoriah Waterland 			error(1);
217*5c51f124SMoriah Waterland 			errstr = getErrstr();
218*5c51f124SMoriah Waterland 			logerr(gettext("garbled entry"));
219*5c51f124SMoriah Waterland 			logerr(gettext("- pathname: %s"),
220*5c51f124SMoriah Waterland 			    (entry.path && *entry.path) ? entry.path :
221*5c51f124SMoriah Waterland 			    "Unknown");
222*5c51f124SMoriah Waterland 			logerr(gettext("- problem: %s"),
223*5c51f124SMoriah Waterland 			    (errstr && *errstr) ? errstr : "Unknown");
224*5c51f124SMoriah Waterland 			break;
225*5c51f124SMoriah Waterland 		}
226*5c51f124SMoriah Waterland 		if (n == 0)
227*5c51f124SMoriah Waterland 			break; /* done with file */
228*5c51f124SMoriah Waterland 
229*5c51f124SMoriah Waterland 		/* don't allow classname to be parametric */
230*5c51f124SMoriah Waterland 		if (entry.ftype != 'i') {
231*5c51f124SMoriah Waterland 			if (entry.pkg_class[0] == '$') {
232*5c51f124SMoriah Waterland 				error(1);
233*5c51f124SMoriah Waterland 				logerr(gettext(MSG_BPARAMC), entry.path);
234*5c51f124SMoriah Waterland 			}
235*5c51f124SMoriah Waterland 		}
236*5c51f124SMoriah Waterland 
237*5c51f124SMoriah Waterland 		if (strchr("dxlscbp", entry.ftype)) {
238*5c51f124SMoriah Waterland 			/*
239*5c51f124SMoriah Waterland 			 * We don't need to search for things without any
240*5c51f124SMoriah Waterland 			 * contents in them.
241*5c51f124SMoriah Waterland 			 */
242*5c51f124SMoriah Waterland 			if (strchr("cb", entry.ftype)) {
243*5c51f124SMoriah Waterland 				if (entry.ainfo.major == BADMAJOR ||
244*5c51f124SMoriah Waterland 				    entry.ainfo.minor == BADMINOR) {
245*5c51f124SMoriah Waterland 					error(1);
246*5c51f124SMoriah Waterland 					logerr(gettext(MSG_NODEVICE),
247*5c51f124SMoriah Waterland 					    entry.path);
248*5c51f124SMoriah Waterland 				}
249*5c51f124SMoriah Waterland 			}
250*5c51f124SMoriah Waterland 			path = NULL;
251*5c51f124SMoriah Waterland 		} else {
252*5c51f124SMoriah Waterland 			path = findfile(entry.path, entry.ainfo.local);
253*5c51f124SMoriah Waterland 			if (!path)
254*5c51f124SMoriah Waterland 				continue;
255*5c51f124SMoriah Waterland 
256*5c51f124SMoriah Waterland 			entry.ainfo.local = path;
257*5c51f124SMoriah Waterland 			if (strchr("fevin?", entry.ftype)) {
258*5c51f124SMoriah Waterland 				if (cverify(0, &entry.ftype, path,
259*5c51f124SMoriah Waterland 				    &entry.cinfo, 1)) {
260*5c51f124SMoriah Waterland 					error(1);
261*5c51f124SMoriah Waterland 					logerr(gettext(MSG_CONTENTS), path);
262*5c51f124SMoriah Waterland 				}
263*5c51f124SMoriah Waterland 			}
264*5c51f124SMoriah Waterland 		}
265*5c51f124SMoriah Waterland 
266*5c51f124SMoriah Waterland 		/* Warn if attributes are not set correctly. */
267*5c51f124SMoriah Waterland 		if (!strchr("isl", entry.ftype)) {
268*5c51f124SMoriah Waterland 			int dowarning = 0;
269*5c51f124SMoriah Waterland 			int hasbadmode = 0;
270*5c51f124SMoriah Waterland 
271*5c51f124SMoriah Waterland 			if (entry.ainfo.mode == NOMODE) {
272*5c51f124SMoriah Waterland 				entry.ainfo.mode = CURMODE;
273*5c51f124SMoriah Waterland 				dowarning = 1;
274*5c51f124SMoriah Waterland 				hasbadmode = 1;
275*5c51f124SMoriah Waterland 			}
276*5c51f124SMoriah Waterland 
277*5c51f124SMoriah Waterland 			if (strcmp(entry.ainfo.owner, NOOWNER) == 0) {
278*5c51f124SMoriah Waterland 				(void) strlcpy(entry.ainfo.owner, CUROWNER,
279*5c51f124SMoriah Waterland 						sizeof (entry.ainfo.owner));
280*5c51f124SMoriah Waterland 				dowarning = 1;
281*5c51f124SMoriah Waterland 			}
282*5c51f124SMoriah Waterland 
283*5c51f124SMoriah Waterland 			if (strcmp(entry.ainfo.group, NOGROUP) == 0) {
284*5c51f124SMoriah Waterland 				(void) strlcpy(entry.ainfo.group, CURGROUP,
285*5c51f124SMoriah Waterland 						sizeof (entry.ainfo.group));
286*5c51f124SMoriah Waterland 				dowarning = 1;
287*5c51f124SMoriah Waterland 			}
288*5c51f124SMoriah Waterland 
289*5c51f124SMoriah Waterland 
290*5c51f124SMoriah Waterland 			if (dowarning) {
291*5c51f124SMoriah Waterland 				if (hasbadmode)
292*5c51f124SMoriah Waterland 					logerr(gettext(WRN_BADATTRM),
293*5c51f124SMoriah Waterland 						"?",
294*5c51f124SMoriah Waterland 					    entry.ainfo.owner,
295*5c51f124SMoriah Waterland 					    entry.ainfo.group,
296*5c51f124SMoriah Waterland 					    entry.path);
297*5c51f124SMoriah Waterland 				else
298*5c51f124SMoriah Waterland 					logerr(gettext(WRN_BADATTR),
299*5c51f124SMoriah Waterland 						(int)entry.ainfo.mode,
300*5c51f124SMoriah Waterland 						entry.ainfo.owner,
301*5c51f124SMoriah Waterland 						entry.ainfo.group,
302*5c51f124SMoriah Waterland 						entry.path);
303*5c51f124SMoriah Waterland 			}
304*5c51f124SMoriah Waterland 		}
305*5c51f124SMoriah Waterland 
306*5c51f124SMoriah Waterland 		/*
307*5c51f124SMoriah Waterland 		 * Resolve build parameters (initial lower case) in
308*5c51f124SMoriah Waterland 		 * the link and target paths.
309*5c51f124SMoriah Waterland 		 */
310*5c51f124SMoriah Waterland 		if (strchr("ls", entry.ftype)) {
311*5c51f124SMoriah Waterland 			if (!RELATIVE(entry.ainfo.local) ||
312*5c51f124SMoriah Waterland 					PARAMETRIC(entry.ainfo.local)) {
313*5c51f124SMoriah Waterland 				if (mappath(1, entry.ainfo.local)) {
314*5c51f124SMoriah Waterland 					error(1);
315*5c51f124SMoriah Waterland 					logerr(gettext(ERR_PATHVAR),
316*5c51f124SMoriah Waterland 					    entry.ainfo.local);
317*5c51f124SMoriah Waterland 					break;
318*5c51f124SMoriah Waterland 				}
319*5c51f124SMoriah Waterland 
320*5c51f124SMoriah Waterland 				canonize(entry.ainfo.local);
321*5c51f124SMoriah Waterland 			}
322*5c51f124SMoriah Waterland 		}
323*5c51f124SMoriah Waterland 
324*5c51f124SMoriah Waterland 		/*
325*5c51f124SMoriah Waterland 		 * Warn if top level file or directory is an install
326*5c51f124SMoriah Waterland 		 * parameter
327*5c51f124SMoriah Waterland 		 */
328*5c51f124SMoriah Waterland 		if (entry.ftype != 'i') {
329*5c51f124SMoriah Waterland 			if (entry.path[0] == '$' && isupper(entry.path[1]))
330*5c51f124SMoriah Waterland 				fakebasedir = 1;
331*5c51f124SMoriah Waterland 		}
332*5c51f124SMoriah Waterland 
333*5c51f124SMoriah Waterland 		if (mappath(1, entry.path)) {
334*5c51f124SMoriah Waterland 			error(1);
335*5c51f124SMoriah Waterland 			logerr(gettext(ERR_PATHVAR), entry.path);
336*5c51f124SMoriah Waterland 			break;
337*5c51f124SMoriah Waterland 		}
338*5c51f124SMoriah Waterland 
339*5c51f124SMoriah Waterland 		canonize(entry.path);
340*5c51f124SMoriah Waterland 		if (ppkgmap(&entry, tmpfp)) {
341*5c51f124SMoriah Waterland 			error(1);
342*5c51f124SMoriah Waterland 			logerr(gettext(MSG_WRITE), errno);
343*5c51f124SMoriah Waterland 			break;
344*5c51f124SMoriah Waterland 		}
345*5c51f124SMoriah Waterland 	}
346*5c51f124SMoriah Waterland 
347*5c51f124SMoriah Waterland 	if (fakebasedir) {
348*5c51f124SMoriah Waterland 		logerr(gettext(WRN_FAKEBD));
349*5c51f124SMoriah Waterland 		fakebasedir = 0;
350*5c51f124SMoriah Waterland 	}
351*5c51f124SMoriah Waterland 
352*5c51f124SMoriah Waterland 	if (popenv())
353*5c51f124SMoriah Waterland 		goto again;
354*5c51f124SMoriah Waterland 
355*5c51f124SMoriah Waterland 	(void) fclose(tmpfp);
356*5c51f124SMoriah Waterland 	environ = envsave; /* restore environment */
357*5c51f124SMoriah Waterland 
358*5c51f124SMoriah Waterland 	return (errflg ? 1 : 0);
359*5c51f124SMoriah Waterland }
360*5c51f124SMoriah Waterland 
361*5c51f124SMoriah Waterland static char *
362*5c51f124SMoriah Waterland findfile(char *path, char *local)
363*5c51f124SMoriah Waterland {
364*5c51f124SMoriah Waterland 	struct stat statbuf;
365*5c51f124SMoriah Waterland 	static char host[PATH_MAX];
366*5c51f124SMoriah Waterland 	register char *pt;
367*5c51f124SMoriah Waterland 	char	temp[PATH_MAX], *basename;
368*5c51f124SMoriah Waterland 	int	i;
369*5c51f124SMoriah Waterland 
370*5c51f124SMoriah Waterland 	/*
371*5c51f124SMoriah Waterland 	 * map any parameters specified in path to their corresponding values
372*5c51f124SMoriah Waterland 	 * and make sure the path is in its canonical form; any parmeters for
373*5c51f124SMoriah Waterland 	 * which a value is not defined will be left unexpanded. Since this
374*5c51f124SMoriah Waterland 	 * is an actual search for a real file (which will not end up in the
375*5c51f124SMoriah Waterland 	 * package) - we map ALL variables (both build and Install).
376*5c51f124SMoriah Waterland 	 */
377*5c51f124SMoriah Waterland 	(void) strlcpy(temp, (local && local[0] ? local : path), sizeof (temp));
378*5c51f124SMoriah Waterland 	mappath(0, temp);
379*5c51f124SMoriah Waterland 	canonize(temp);
380*5c51f124SMoriah Waterland 
381*5c51f124SMoriah Waterland 	*host = '\0';
382*5c51f124SMoriah Waterland 	if (rootlist[0] || (basedir && (*temp != '/'))) {
383*5c51f124SMoriah Waterland 		/*
384*5c51f124SMoriah Waterland 		 * search for path in the pseudo-root/basedir directory; note
385*5c51f124SMoriah Waterland 		 * that package information files should NOT be included in
386*5c51f124SMoriah Waterland 		 * this list
387*5c51f124SMoriah Waterland 		 */
388*5c51f124SMoriah Waterland 		if (entry.ftype != 'i')
389*5c51f124SMoriah Waterland 			return (srchroot(temp, host));
390*5c51f124SMoriah Waterland 	}
391*5c51f124SMoriah Waterland 
392*5c51f124SMoriah Waterland 	/* looking for local object file  */
393*5c51f124SMoriah Waterland 	if (local && *local) {
394*5c51f124SMoriah Waterland 		basepath(temp, dname[nfp], NULL);
395*5c51f124SMoriah Waterland 		/*
396*5c51f124SMoriah Waterland 		 * If it equals "/dev/null", that just means it's an empty
397*5c51f124SMoriah Waterland 		 * file. Otherwise, we'll really be writing stuff, so we need
398*5c51f124SMoriah Waterland 		 * to verify the source.
399*5c51f124SMoriah Waterland 		 */
400*5c51f124SMoriah Waterland 		if (strcmp(temp, "/dev/null") != 0) {
401*5c51f124SMoriah Waterland 			if (stat(temp, &statbuf) ||
402*5c51f124SMoriah Waterland 			    !(statbuf.st_mode & S_IFREG)) {
403*5c51f124SMoriah Waterland 				error(1);
404*5c51f124SMoriah Waterland 				logerr(gettext(MSG_SRCHLOC), path);
405*5c51f124SMoriah Waterland 				return (NULL);
406*5c51f124SMoriah Waterland 			}
407*5c51f124SMoriah Waterland 		}
408*5c51f124SMoriah Waterland 		(void) strlcpy(host, temp, sizeof (host));
409*5c51f124SMoriah Waterland 		return (host);
410*5c51f124SMoriah Waterland 	}
411*5c51f124SMoriah Waterland 
412*5c51f124SMoriah Waterland 	for (i = 0; rootp[nfp][i]; i++) {
413*5c51f124SMoriah Waterland 		(void) snprintf(host, sizeof (host), "%s/%s", rootp[nfp][i],
414*5c51f124SMoriah Waterland 		    temp + (*temp == '/' ? 1 : 0));
415*5c51f124SMoriah Waterland 		if ((stat(host, &statbuf) == 0) &&
416*5c51f124SMoriah Waterland 		    (statbuf.st_mode & S_IFREG)) {
417*5c51f124SMoriah Waterland 			return (host);
418*5c51f124SMoriah Waterland 		}
419*5c51f124SMoriah Waterland 	}
420*5c51f124SMoriah Waterland 
421*5c51f124SMoriah Waterland 	pt = strrchr(temp, '/');
422*5c51f124SMoriah Waterland 	if (!pt++)
423*5c51f124SMoriah Waterland 		pt = temp;
424*5c51f124SMoriah Waterland 
425*5c51f124SMoriah Waterland 	basename = pt;
426*5c51f124SMoriah Waterland 
427*5c51f124SMoriah Waterland 	for (i = 0; srchp[nfp][i]; i++) {
428*5c51f124SMoriah Waterland 		(void) snprintf(host, sizeof (host), "%s/%s",
429*5c51f124SMoriah Waterland 			srchp[nfp][i], basename);
430*5c51f124SMoriah Waterland 		if ((stat(host, &statbuf) == 0) &&
431*5c51f124SMoriah Waterland 		    (statbuf.st_mode & S_IFREG)) {
432*5c51f124SMoriah Waterland 			return (host);
433*5c51f124SMoriah Waterland 		}
434*5c51f124SMoriah Waterland 	}
435*5c51f124SMoriah Waterland 
436*5c51f124SMoriah Waterland 	/* check current directory as a last resort */
437*5c51f124SMoriah Waterland 	(void) snprintf(host, sizeof (host), "%s/%s", dname[nfp], basename);
438*5c51f124SMoriah Waterland 	if ((stat(host, &statbuf) == 0) && (statbuf.st_mode & S_IFREG))
439*5c51f124SMoriah Waterland 		return (host);
440*5c51f124SMoriah Waterland 
441*5c51f124SMoriah Waterland 	error(1);
442*5c51f124SMoriah Waterland 	logerr(gettext(MSG_SRCHSRCH), path);
443*5c51f124SMoriah Waterland 	return (NULL);
444*5c51f124SMoriah Waterland }
445*5c51f124SMoriah Waterland 
446*5c51f124SMoriah Waterland static void
447*5c51f124SMoriah Waterland dosearch(void)
448*5c51f124SMoriah Waterland {
449*5c51f124SMoriah Waterland 	char temp[PATH_MAX], lookpath[PATH_MAX], *pt;
450*5c51f124SMoriah Waterland 	int n;
451*5c51f124SMoriah Waterland 
452*5c51f124SMoriah Waterland 	(void) fgets(temp, PATH_MAX, fp);
453*5c51f124SMoriah Waterland 	translate(temp, lookpath);
454*5c51f124SMoriah Waterland 
455*5c51f124SMoriah Waterland 	for (n = 0; srchp[nfp][n]; n++)
456*5c51f124SMoriah Waterland 		free(srchp[nfp][n]);
457*5c51f124SMoriah Waterland 
458*5c51f124SMoriah Waterland 	n = 0;
459*5c51f124SMoriah Waterland 	pt = strtok(lookpath, separ);
460*5c51f124SMoriah Waterland 	if (pt && *pt) {
461*5c51f124SMoriah Waterland 		do {
462*5c51f124SMoriah Waterland 			if (*pt != '/') {
463*5c51f124SMoriah Waterland 				/* make relative path an absolute directory */
464*5c51f124SMoriah Waterland 				(void) snprintf(temp, sizeof (temp),
465*5c51f124SMoriah Waterland 						"%s/%s", dname[nfp], pt);
466*5c51f124SMoriah Waterland 				pt = temp;
467*5c51f124SMoriah Waterland 			}
468*5c51f124SMoriah Waterland 			canonize(pt);
469*5c51f124SMoriah Waterland 			srchp[nfp][n++] = qstrdup(pt);
470*5c51f124SMoriah Waterland 		} while (pt = strtok(NULL, separ));
471*5c51f124SMoriah Waterland 		srchp[nfp][n] = NULL;
472*5c51f124SMoriah Waterland 	}
473*5c51f124SMoriah Waterland }
474*5c51f124SMoriah Waterland 
475*5c51f124SMoriah Waterland static void
476*5c51f124SMoriah Waterland dorsearch(void)
477*5c51f124SMoriah Waterland {
478*5c51f124SMoriah Waterland 	char temp[PATH_MAX], lookpath[PATH_MAX], *pt;
479*5c51f124SMoriah Waterland 	int n;
480*5c51f124SMoriah Waterland 
481*5c51f124SMoriah Waterland 	(void) fgets(temp, PATH_MAX, fp);
482*5c51f124SMoriah Waterland 	translate(temp, lookpath);
483*5c51f124SMoriah Waterland 
484*5c51f124SMoriah Waterland 	for (n = 0; rootp[nfp][n]; n++)
485*5c51f124SMoriah Waterland 		free(rootp[nfp][n]);
486*5c51f124SMoriah Waterland 
487*5c51f124SMoriah Waterland 	n = 0;
488*5c51f124SMoriah Waterland 	pt = strtok(lookpath, separ);
489*5c51f124SMoriah Waterland 	do {
490*5c51f124SMoriah Waterland 		if (*pt != '/') {
491*5c51f124SMoriah Waterland 			/* make relative path an absolute directory */
492*5c51f124SMoriah Waterland 			(void) snprintf(temp, sizeof (temp),
493*5c51f124SMoriah Waterland 					"%s/%s", dname[nfp], pt);
494*5c51f124SMoriah Waterland 			pt = temp;
495*5c51f124SMoriah Waterland 		}
496*5c51f124SMoriah Waterland 		canonize(pt);
497*5c51f124SMoriah Waterland 		rootp[nfp][n++] = qstrdup(pt);
498*5c51f124SMoriah Waterland 	} while (pt = strtok(NULL, separ));
499*5c51f124SMoriah Waterland 	rootp[nfp][n] = NULL;
500*5c51f124SMoriah Waterland }
501*5c51f124SMoriah Waterland 
502*5c51f124SMoriah Waterland /*
503*5c51f124SMoriah Waterland  * This function reads the default mode, owner and group from the prototype
504*5c51f124SMoriah Waterland  * file and makes that available.
505*5c51f124SMoriah Waterland  */
506*5c51f124SMoriah Waterland static int
507*5c51f124SMoriah Waterland doattrib(void)
508*5c51f124SMoriah Waterland {
509*5c51f124SMoriah Waterland 	char *pt, attrib[PATH_MAX], *mode_ptr, *owner_ptr, *group_ptr, *eol;
510*5c51f124SMoriah Waterland 	int mode;
511*5c51f124SMoriah Waterland 	char owner[ATRSIZ+1], group[ATRSIZ+1], attrib_save[(4*ATRSIZ)];
512*5c51f124SMoriah Waterland 
513*5c51f124SMoriah Waterland 	(void) fgets(attrib, PATH_MAX, fp);
514*5c51f124SMoriah Waterland 
515*5c51f124SMoriah Waterland 	(void) strlcpy(attrib_save, attrib, sizeof (attrib_save));
516*5c51f124SMoriah Waterland 
517*5c51f124SMoriah Waterland 	/*
518*5c51f124SMoriah Waterland 	 * Now resolve any variables that may be present. Start on group and
519*5c51f124SMoriah Waterland 	 * move backward since that keeps the resolved string from
520*5c51f124SMoriah Waterland 	 * overwriting any of the other entries. This is required since
521*5c51f124SMoriah Waterland 	 * mapvar() writes the resolved string over the string provided.
522*5c51f124SMoriah Waterland 	 */
523*5c51f124SMoriah Waterland 	mode_ptr = strtok(attrib, " \t");
524*5c51f124SMoriah Waterland 	owner_ptr = strtok(NULL, " \t");
525*5c51f124SMoriah Waterland 	group_ptr = strtok(NULL, " \t\n");
526*5c51f124SMoriah Waterland 	eol = strtok(NULL, " \t\n");
527*5c51f124SMoriah Waterland 	if (strtok(NULL, " \t\n")) {
528*5c51f124SMoriah Waterland 		/* extra tokens on the line */
529*5c51f124SMoriah Waterland 		error(1);
530*5c51f124SMoriah Waterland 		logerr(gettext(MSG_GARBDEFLT), (eol) ? eol :
531*5c51f124SMoriah Waterland 		    gettext("unreadable at end of line"));
532*5c51f124SMoriah Waterland 		return (1);
533*5c51f124SMoriah Waterland 	}
534*5c51f124SMoriah Waterland 
535*5c51f124SMoriah Waterland 	if (group_ptr && mapvar(1, group_ptr) == 0)
536*5c51f124SMoriah Waterland 		(void) strncpy(group, group_ptr, ATRSIZ);
537*5c51f124SMoriah Waterland 	else {
538*5c51f124SMoriah Waterland 		error(1);
539*5c51f124SMoriah Waterland 		logerr(gettext(MSG_GARBDEFLT), (attrib_save) ?
540*5c51f124SMoriah Waterland 		    ((attrib_save[0]) ? attrib_save : gettext("none")) :
541*5c51f124SMoriah Waterland 		    gettext("unreadable at group"));
542*5c51f124SMoriah Waterland 		return (1);
543*5c51f124SMoriah Waterland 	}
544*5c51f124SMoriah Waterland 
545*5c51f124SMoriah Waterland 	if (owner_ptr && mapvar(1, owner_ptr) == 0)
546*5c51f124SMoriah Waterland 		(void) strncpy(owner, owner_ptr, ATRSIZ);
547*5c51f124SMoriah Waterland 	else {
548*5c51f124SMoriah Waterland 		error(1);
549*5c51f124SMoriah Waterland 		logerr(gettext(MSG_GARBDEFLT), (attrib_save) ?
550*5c51f124SMoriah Waterland 		    ((attrib_save[0]) ? attrib_save : gettext("none")) :
551*5c51f124SMoriah Waterland 		    gettext("unreadable at owner"));
552*5c51f124SMoriah Waterland 		return (1);
553*5c51f124SMoriah Waterland 	}
554*5c51f124SMoriah Waterland 
555*5c51f124SMoriah Waterland 	/*
556*5c51f124SMoriah Waterland 	 * For mode, don't use scanf, since we want to force an octal
557*5c51f124SMoriah Waterland 	 * interpretation and need to limit the length of the owner and group
558*5c51f124SMoriah Waterland 	 * specifications.
559*5c51f124SMoriah Waterland 	 */
560*5c51f124SMoriah Waterland 	if (mode_ptr && mapvar(1, mode_ptr) == 0)
561*5c51f124SMoriah Waterland 		mode = strtol(mode_ptr, &pt, 8);
562*5c51f124SMoriah Waterland 	else {
563*5c51f124SMoriah Waterland 		error(1);
564*5c51f124SMoriah Waterland 		logerr(gettext(MSG_GARBDEFLT), (attrib_save) ?
565*5c51f124SMoriah Waterland 		    ((attrib_save[0]) ? attrib_save : gettext("none")) :
566*5c51f124SMoriah Waterland 		    gettext("unreadable at mode"));
567*5c51f124SMoriah Waterland 		return (1);
568*5c51f124SMoriah Waterland 	}
569*5c51f124SMoriah Waterland 
570*5c51f124SMoriah Waterland 	/* free any previous memory from qstrdup */
571*5c51f124SMoriah Waterland 	if (d_own[nfp])
572*5c51f124SMoriah Waterland 		free(d_own[nfp]);
573*5c51f124SMoriah Waterland 	if (d_grp[nfp])
574*5c51f124SMoriah Waterland 		free(d_grp[nfp]);
575*5c51f124SMoriah Waterland 
576*5c51f124SMoriah Waterland 	d_mod[nfp] = mode;
577*5c51f124SMoriah Waterland 	d_own[nfp] = qstrdup(owner);
578*5c51f124SMoriah Waterland 	d_grp[nfp] = qstrdup(group);
579*5c51f124SMoriah Waterland 
580*5c51f124SMoriah Waterland 	attrpreset(d_mod[nfp], d_own[nfp], d_grp[nfp]);
581*5c51f124SMoriah Waterland 
582*5c51f124SMoriah Waterland 	return (0);
583*5c51f124SMoriah Waterland }
584*5c51f124SMoriah Waterland 
585*5c51f124SMoriah Waterland static void
586*5c51f124SMoriah Waterland doinclude(void)
587*5c51f124SMoriah Waterland {
588*5c51f124SMoriah Waterland 	char	file[PATH_MAX];
589*5c51f124SMoriah Waterland 	char	temp[PATH_MAX];
590*5c51f124SMoriah Waterland 
591*5c51f124SMoriah Waterland 	(void) fgets(temp, PATH_MAX, fp);
592*5c51f124SMoriah Waterland 
593*5c51f124SMoriah Waterland 	/*
594*5c51f124SMoriah Waterland 	 * IMPORTANT NOTE: THE SIZE OF temp IS HARD CODED INTO THE
595*5c51f124SMoriah Waterland 	 * FOLLOWING CALL TO fscanf -- YOU MUST CHANGE THIS LINE IF
596*5c51f124SMoriah Waterland 	 * THE SIZE OF fscanf IS EVER CHANGED!!!
597*5c51f124SMoriah Waterland 	 */
598*5c51f124SMoriah Waterland 	(void) sscanf(temp, "%1024s", file);
599*5c51f124SMoriah Waterland 
600*5c51f124SMoriah Waterland 	translate(file, temp);
601*5c51f124SMoriah Waterland 	canonize(temp);
602*5c51f124SMoriah Waterland 
603*5c51f124SMoriah Waterland 	if (*temp == NULL)
604*5c51f124SMoriah Waterland 		return;
605*5c51f124SMoriah Waterland 	else if (*temp != '/')
606*5c51f124SMoriah Waterland 		(void) snprintf(file, sizeof (file), "%s/%s", dname[nfp], temp);
607*5c51f124SMoriah Waterland 	else
608*5c51f124SMoriah Waterland 		(void) strlcpy(file, temp, sizeof (file));
609*5c51f124SMoriah Waterland 
610*5c51f124SMoriah Waterland 	canonize(file);
611*5c51f124SMoriah Waterland 	pushenv(file);
612*5c51f124SMoriah Waterland }
613*5c51f124SMoriah Waterland 
614*5c51f124SMoriah Waterland /*
615*5c51f124SMoriah Waterland  * This does what mappath() does except that it does it for ALL variables
616*5c51f124SMoriah Waterland  * using whitespace as a token separator. This is used to resolve search
617*5c51f124SMoriah Waterland  * paths and assignment statements. It doesn't effect the build versus
618*5c51f124SMoriah Waterland  * install decision made for pkgmap variables.
619*5c51f124SMoriah Waterland  */
620*5c51f124SMoriah Waterland static void
621*5c51f124SMoriah Waterland translate(register char *pt, register char *copy)
622*5c51f124SMoriah Waterland {
623*5c51f124SMoriah Waterland 	char *pt2, varname[MAX_PKG_PARAM_LENGTH];
624*5c51f124SMoriah Waterland 
625*5c51f124SMoriah Waterland token:
626*5c51f124SMoriah Waterland 	/* eat white space */
627*5c51f124SMoriah Waterland 	while (isspace(*pt))
628*5c51f124SMoriah Waterland 		pt++;
629*5c51f124SMoriah Waterland 	while (*pt && !isspace(*pt)) {
630*5c51f124SMoriah Waterland 		if (*pt == '$') {
631*5c51f124SMoriah Waterland 			pt2 = varname;
632*5c51f124SMoriah Waterland 			while (*++pt && !strchr("/= \t\n\r", *pt))
633*5c51f124SMoriah Waterland 				*pt2++ = *pt;
634*5c51f124SMoriah Waterland 			*pt2 = '\0';
635*5c51f124SMoriah Waterland 			if (pt2 = getenv(varname)) {
636*5c51f124SMoriah Waterland 				while (*pt2)
637*5c51f124SMoriah Waterland 					*copy++ = *pt2++;
638*5c51f124SMoriah Waterland 			}
639*5c51f124SMoriah Waterland 		} else
640*5c51f124SMoriah Waterland 			*copy++ = *pt++;
641*5c51f124SMoriah Waterland 	}
642*5c51f124SMoriah Waterland 	if (*pt) {
643*5c51f124SMoriah Waterland 		*copy++ = ' ';
644*5c51f124SMoriah Waterland 		goto token;
645*5c51f124SMoriah Waterland 	}
646*5c51f124SMoriah Waterland 	*copy = '\0';
647*5c51f124SMoriah Waterland }
648*5c51f124SMoriah Waterland 
649*5c51f124SMoriah Waterland static void
650*5c51f124SMoriah Waterland error(int flag)
651*5c51f124SMoriah Waterland {
652*5c51f124SMoriah Waterland 	static char *lasterr = NULL;
653*5c51f124SMoriah Waterland 
654*5c51f124SMoriah Waterland 	if (lasterr != proto[nfp]) {
655*5c51f124SMoriah Waterland 		lasterr = proto[nfp];
656*5c51f124SMoriah Waterland 		(void) fprintf(stderr, gettext("ERROR in %s:\n"), lasterr);
657*5c51f124SMoriah Waterland 	}
658*5c51f124SMoriah Waterland 	if (flag)
659*5c51f124SMoriah Waterland 		errflg++;
660*5c51f124SMoriah Waterland }
661*5c51f124SMoriah Waterland 
662*5c51f124SMoriah Waterland /* Set up defaults and change to the build directory. */
663*5c51f124SMoriah Waterland static void
664*5c51f124SMoriah Waterland pushenv(char *file)
665*5c51f124SMoriah Waterland {
666*5c51f124SMoriah Waterland 	register char *pt;
667*5c51f124SMoriah Waterland 	static char	topdir[PATH_MAX];
668*5c51f124SMoriah Waterland 
669*5c51f124SMoriah Waterland 	if ((nfp+1) >= NRECURS) {
670*5c51f124SMoriah Waterland 		error(1);
671*5c51f124SMoriah Waterland 		logerr(gettext(MSG_NRECURS), NRECURS);
672*5c51f124SMoriah Waterland 		logerr(gettext(MSG_IGNINCLUDE), file);
673*5c51f124SMoriah Waterland 		return;
674*5c51f124SMoriah Waterland 	}
675*5c51f124SMoriah Waterland 
676*5c51f124SMoriah Waterland 	if (strcmp(file, "-") == 0) {
677*5c51f124SMoriah Waterland 		fp = stdin;
678*5c51f124SMoriah Waterland 	} else if ((fp = fopen(file, "r")) == NULL) {
679*5c51f124SMoriah Waterland 		error(1);
680*5c51f124SMoriah Waterland 		logerr(gettext(MSG_RDINCLUDE), file, errno);
681*5c51f124SMoriah Waterland 		if (nfp >= 0) {
682*5c51f124SMoriah Waterland 			logerr(gettext(MSG_IGNINCLUDE), file);
683*5c51f124SMoriah Waterland 			fp = sfp[nfp];
684*5c51f124SMoriah Waterland 			return;
685*5c51f124SMoriah Waterland 		} else
686*5c51f124SMoriah Waterland 			quit(1);
687*5c51f124SMoriah Waterland 	}
688*5c51f124SMoriah Waterland 	sfp[++nfp] = fp;
689*5c51f124SMoriah Waterland 	srchp[nfp][0] = NULL;
690*5c51f124SMoriah Waterland 	rootp[nfp][0] = NULL;
691*5c51f124SMoriah Waterland 	d_mod[nfp] = (mode_t)(-1);
692*5c51f124SMoriah Waterland 	d_own[nfp] = NULL;
693*5c51f124SMoriah Waterland 	d_grp[nfp] = NULL;
694*5c51f124SMoriah Waterland 
695*5c51f124SMoriah Waterland 	if (!nfp) {
696*5c51f124SMoriah Waterland 		/* upper level proto file */
697*5c51f124SMoriah Waterland 		proto[nfp] = file;
698*5c51f124SMoriah Waterland 		if (file[0] == '/')
699*5c51f124SMoriah Waterland 			pt = strcpy(topdir, file);
700*5c51f124SMoriah Waterland 		else {
701*5c51f124SMoriah Waterland 			/* path is relative to the prototype file specified */
702*5c51f124SMoriah Waterland 			pt = getcwd(NULL, PATH_MAX);
703*5c51f124SMoriah Waterland 			if (pt == NULL) {
704*5c51f124SMoriah Waterland 				progerr(gettext(ERR_GETCWD), errno);
705*5c51f124SMoriah Waterland 				quit(99);
706*5c51f124SMoriah Waterland 			}
707*5c51f124SMoriah Waterland 			(void) snprintf(topdir, sizeof (topdir),
708*5c51f124SMoriah Waterland 						"%s/%s", pt, file);
709*5c51f124SMoriah Waterland 		}
710*5c51f124SMoriah Waterland 		if (pt = strrchr(topdir, '/'))
711*5c51f124SMoriah Waterland 			*pt = '\0'; /* should always happen */
712*5c51f124SMoriah Waterland 		if (topdir[0] == '\0')
713*5c51f124SMoriah Waterland 			(void) strlcpy(topdir, "/", sizeof (topdir));
714*5c51f124SMoriah Waterland 		dname[nfp] = topdir;
715*5c51f124SMoriah Waterland 	} else {
716*5c51f124SMoriah Waterland 		proto[nfp] = qstrdup(file);
717*5c51f124SMoriah Waterland 		dname[nfp] = qstrdup(file);
718*5c51f124SMoriah Waterland 		if (pt = strrchr(dname[nfp], '/'))
719*5c51f124SMoriah Waterland 			*pt = '\0';
720*5c51f124SMoriah Waterland 		else {
721*5c51f124SMoriah Waterland 			/* same directory as the last prototype */
722*5c51f124SMoriah Waterland 			free(dname[nfp]);
723*5c51f124SMoriah Waterland 			dname[nfp] = qstrdup(dname[nfp-1]);
724*5c51f124SMoriah Waterland 			return; /* no need to canonize() or chdir() */
725*5c51f124SMoriah Waterland 		}
726*5c51f124SMoriah Waterland 	}
727*5c51f124SMoriah Waterland 
728*5c51f124SMoriah Waterland 	canonize(dname[nfp]);
729*5c51f124SMoriah Waterland 
730*5c51f124SMoriah Waterland 	if (chdir(dname[nfp])) {
731*5c51f124SMoriah Waterland 		error(1);
732*5c51f124SMoriah Waterland 		logerr(gettext(MSG_CHDIR), dname[nfp]);
733*5c51f124SMoriah Waterland 		if (!nfp)
734*5c51f124SMoriah Waterland 			quit(1); /* must be able to cd to upper level */
735*5c51f124SMoriah Waterland 		logerr(gettext(MSG_IGNINCLUDE), proto[nfp]);
736*5c51f124SMoriah Waterland 		(void) popenv();
737*5c51f124SMoriah Waterland 	}
738*5c51f124SMoriah Waterland }
739*5c51f124SMoriah Waterland 
740*5c51f124SMoriah Waterland /* Restore defaults and return to the prior directory. */
741*5c51f124SMoriah Waterland static int
742*5c51f124SMoriah Waterland popenv(void)
743*5c51f124SMoriah Waterland {
744*5c51f124SMoriah Waterland 	int i;
745*5c51f124SMoriah Waterland 
746*5c51f124SMoriah Waterland 	(void) fclose(fp);
747*5c51f124SMoriah Waterland 	if (nfp) {
748*5c51f124SMoriah Waterland 		if (proto[nfp])
749*5c51f124SMoriah Waterland 			free(proto[nfp]);
750*5c51f124SMoriah Waterland 		if (dname[nfp])
751*5c51f124SMoriah Waterland 			free(dname[nfp]);
752*5c51f124SMoriah Waterland 		for (i = 0; srchp[nfp][i]; i++)
753*5c51f124SMoriah Waterland 			free(srchp[nfp][i]);
754*5c51f124SMoriah Waterland 		for (i = 0; rootp[nfp][i]; i++)
755*5c51f124SMoriah Waterland 			free(rootp[nfp][i]);
756*5c51f124SMoriah Waterland 		if (d_own[nfp])
757*5c51f124SMoriah Waterland 			free(d_own[nfp]);
758*5c51f124SMoriah Waterland 		if (d_grp[nfp])
759*5c51f124SMoriah Waterland 			free(d_grp[nfp]);
760*5c51f124SMoriah Waterland 
761*5c51f124SMoriah Waterland 		fp = sfp[--nfp];
762*5c51f124SMoriah Waterland 
763*5c51f124SMoriah Waterland 		if (chdir(dname[nfp])) {
764*5c51f124SMoriah Waterland 			error(1);
765*5c51f124SMoriah Waterland 			logerr(gettext(MSG_CHDIR), dname[nfp]);
766*5c51f124SMoriah Waterland 			logerr(gettext(MSG_INCOMPLETE), proto[nfp]);
767*5c51f124SMoriah Waterland 			return (popenv());
768*5c51f124SMoriah Waterland 		}
769*5c51f124SMoriah Waterland 		return (1);
770*5c51f124SMoriah Waterland 	}
771*5c51f124SMoriah Waterland 	return (0);
772*5c51f124SMoriah Waterland }
773*5c51f124SMoriah Waterland 
774*5c51f124SMoriah Waterland /*
775*5c51f124SMoriah Waterland  * If this parameter isn't already in place, put it into the local
776*5c51f124SMoriah Waterland  * environment. This means that command line directives override prototype
777*5c51f124SMoriah Waterland  * file directives.
778*5c51f124SMoriah Waterland  */
779*5c51f124SMoriah Waterland static void
780*5c51f124SMoriah Waterland lputenv(char *s)
781*5c51f124SMoriah Waterland {
782*5c51f124SMoriah Waterland 	char *pt;
783*5c51f124SMoriah Waterland 	int i;
784*5c51f124SMoriah Waterland 
785*5c51f124SMoriah Waterland 	pt = strchr(s, '=');
786*5c51f124SMoriah Waterland 	if (!pt)
787*5c51f124SMoriah Waterland 		return;
788*5c51f124SMoriah Waterland 
789*5c51f124SMoriah Waterland 	*pt = '\0';
790*5c51f124SMoriah Waterland 	for (i = 0; i < nrdonly; i++) {
791*5c51f124SMoriah Waterland 		if (strcmp(rdonly[i], s) == 0) {
792*5c51f124SMoriah Waterland 			*pt = '=';
793*5c51f124SMoriah Waterland 			return;
794*5c51f124SMoriah Waterland 		}
795*5c51f124SMoriah Waterland 	}
796*5c51f124SMoriah Waterland 	*pt = '=';
797*5c51f124SMoriah Waterland 
798*5c51f124SMoriah Waterland 	if (putenv(qstrdup(s))) {
799*5c51f124SMoriah Waterland 		progerr(gettext(ERR_ENVBUILD), errno);
800*5c51f124SMoriah Waterland 		quit(99);
801*5c51f124SMoriah Waterland 	}
802*5c51f124SMoriah Waterland }
803*5c51f124SMoriah Waterland 
804*5c51f124SMoriah Waterland static char *
805*5c51f124SMoriah Waterland srchroot(char *path, char *copy)
806*5c51f124SMoriah Waterland {
807*5c51f124SMoriah Waterland 	struct stat statbuf;
808*5c51f124SMoriah Waterland 	int i;
809*5c51f124SMoriah Waterland 
810*5c51f124SMoriah Waterland 	i = 0;
811*5c51f124SMoriah Waterland 	root = rootlist[i++];
812*5c51f124SMoriah Waterland 	do {
813*5c51f124SMoriah Waterland 		/* convert with root & basedir info */
814*5c51f124SMoriah Waterland 		cvtpath(path, copy);
815*5c51f124SMoriah Waterland 		/* make it pretty again */
816*5c51f124SMoriah Waterland 		canonize(copy);
817*5c51f124SMoriah Waterland 
818*5c51f124SMoriah Waterland 		if (stat(copy, &statbuf) || !(statbuf.st_mode & S_IFREG)) {
819*5c51f124SMoriah Waterland 			root = rootlist[i++];
820*5c51f124SMoriah Waterland 			continue; /* host source must be a regular file */
821*5c51f124SMoriah Waterland 		}
822*5c51f124SMoriah Waterland 		return (copy);
823*5c51f124SMoriah Waterland 	} while (root != NULL);
824*5c51f124SMoriah Waterland 	error(1);
825*5c51f124SMoriah Waterland 	logerr(gettext(MSG_SRCHROOT), path);
826*5c51f124SMoriah Waterland 	return (NULL);
827*5c51f124SMoriah Waterland }
828