xref: /onnv-gate/usr/src/cmd/svr4pkg/pkgchk/main.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 #include <stdio.h>
32*9781SMoriah.Waterland@Sun.COM #include <limits.h>
33*9781SMoriah.Waterland@Sun.COM #include <unistd.h>
34*9781SMoriah.Waterland@Sun.COM #include <stdlib.h>
35*9781SMoriah.Waterland@Sun.COM #include <string.h>
36*9781SMoriah.Waterland@Sun.COM #include <ctype.h>
37*9781SMoriah.Waterland@Sun.COM #include <dirent.h>
38*9781SMoriah.Waterland@Sun.COM #include <sys/stat.h>
39*9781SMoriah.Waterland@Sun.COM #include <pkginfo.h>
40*9781SMoriah.Waterland@Sun.COM #include <pkglocs.h>
41*9781SMoriah.Waterland@Sun.COM #include <sys/types.h>
42*9781SMoriah.Waterland@Sun.COM #include <pkgstrct.h>
43*9781SMoriah.Waterland@Sun.COM #include <pkgtrans.h>
44*9781SMoriah.Waterland@Sun.COM #include <locale.h>
45*9781SMoriah.Waterland@Sun.COM #include <libintl.h>
46*9781SMoriah.Waterland@Sun.COM #include <pkglib.h>
47*9781SMoriah.Waterland@Sun.COM #include <libadm.h>
48*9781SMoriah.Waterland@Sun.COM #include <libinst.h>
49*9781SMoriah.Waterland@Sun.COM 
50*9781SMoriah.Waterland@Sun.COM #define	MAXPATHS	1024
51*9781SMoriah.Waterland@Sun.COM 
52*9781SMoriah.Waterland@Sun.COM #define	MSG_CHK_STRM	"Checking uninstalled stream format package " \
53*9781SMoriah.Waterland@Sun.COM 				"<%s> from <%s>\n"
54*9781SMoriah.Waterland@Sun.COM #define	MSG_CHK_DIR	"Checking uninstalled directory format package " \
55*9781SMoriah.Waterland@Sun.COM 				"<%s> from <%s>\n"
56*9781SMoriah.Waterland@Sun.COM #define	MSG_NOTROOT	"NOTE: \"root\" permission may be required to " \
57*9781SMoriah.Waterland@Sun.COM 				"validate all objects in the client filesystem."
58*9781SMoriah.Waterland@Sun.COM #define	MSG_CONT	"Continuing."
59*9781SMoriah.Waterland@Sun.COM 
60*9781SMoriah.Waterland@Sun.COM #define	WRN_F_SPOOL	"WARNING: %s is spooled. Ignoring \"f\" argument"
61*9781SMoriah.Waterland@Sun.COM 
62*9781SMoriah.Waterland@Sun.COM #define	ERR_ROOT_SET	"Could not set install root from the environment."
63*9781SMoriah.Waterland@Sun.COM #define	ERR_ROOT_CMD	"Command line install root contends with environment."
64*9781SMoriah.Waterland@Sun.COM #define	ERR_IOPEN	"unable to open input file <%s>"
65*9781SMoriah.Waterland@Sun.COM #define	ERR_IEMPTY	"no pathnames in file specified by -i option"
66*9781SMoriah.Waterland@Sun.COM #define	ERR_POPTION	"no pathname included with -p option"
67*9781SMoriah.Waterland@Sun.COM #define	ERR_PARTIAL_POPTION	"no pathname included with -P option"
68*9781SMoriah.Waterland@Sun.COM #define	ERR_MAXPATHS	"too many pathnames in option list (limit is %d)"
69*9781SMoriah.Waterland@Sun.COM #define	ERR_NOTROOT	"You must be \"root\" for \"%s -f\" to" \
70*9781SMoriah.Waterland@Sun.COM 					"execute properly."
71*9781SMoriah.Waterland@Sun.COM #define	ERR_SEL_PKG "No packages selected for verification."
72*9781SMoriah.Waterland@Sun.COM #define	ERR_CAT_LNGTH "The category argument exceeds the SVr4 ABI\n" \
73*9781SMoriah.Waterland@Sun.COM 		"        defined maximum supported length of 16 characters."
74*9781SMoriah.Waterland@Sun.COM #define	ERR_CAT_FND "Category argument <%s> cannot be found."
75*9781SMoriah.Waterland@Sun.COM #define	ERR_CAT_INV "Category argument <%s> is invalid."
76*9781SMoriah.Waterland@Sun.COM #define	ERR_TOO_MANY "too many pathnames in list, limit is %d"
77*9781SMoriah.Waterland@Sun.COM #define	ERR_PATHS_INVALID "Pathnames in %s are not valid."
78*9781SMoriah.Waterland@Sun.COM #define	ERR_MKDIR "unable to make directory <%s>"
79*9781SMoriah.Waterland@Sun.COM #define	ERR_USAGE	"usage:\n" \
80*9781SMoriah.Waterland@Sun.COM 		"\t%s [-l|vqacnxf] [-R rootdir] [-p path[, ...] | " \
81*9781SMoriah.Waterland@Sun.COM 		"-P path[, ...]]\n" \
82*9781SMoriah.Waterland@Sun.COM 		"\t\t[-i file] [options]\n" \
83*9781SMoriah.Waterland@Sun.COM 		"\t%s -d device [-f][-l|v] [-p path[, ...] | " \
84*9781SMoriah.Waterland@Sun.COM 		"-P path[, ...]]\n" \
85*9781SMoriah.Waterland@Sun.COM 		"\t\t[-V ...] [-M] [-i file] [-Y category[, ...] | " \
86*9781SMoriah.Waterland@Sun.COM 		"pkginst [...]]\n" \
87*9781SMoriah.Waterland@Sun.COM 		"\twhere options may include ONE of the " \
88*9781SMoriah.Waterland@Sun.COM 		"following:\n " \
89*9781SMoriah.Waterland@Sun.COM 		"\t\t-m pkgmap [-e envfile]\n" \
90*9781SMoriah.Waterland@Sun.COM 		"\t\tpkginst [...]\n" \
91*9781SMoriah.Waterland@Sun.COM 		"\t\t-Y category[, ...]\n"
92*9781SMoriah.Waterland@Sun.COM 
93*9781SMoriah.Waterland@Sun.COM #define	LINK	1
94*9781SMoriah.Waterland@Sun.COM 
95*9781SMoriah.Waterland@Sun.COM char	**pkg = NULL;
96*9781SMoriah.Waterland@Sun.COM int	pkgcnt = 0;
97*9781SMoriah.Waterland@Sun.COM char	*basedir;
98*9781SMoriah.Waterland@Sun.COM char	*pathlist[MAXPATHS], *ppathlist[MAXPATHS], pkgspool[PATH_MAX];
99*9781SMoriah.Waterland@Sun.COM short	used[MAXPATHS];
100*9781SMoriah.Waterland@Sun.COM short	npaths;
101*9781SMoriah.Waterland@Sun.COM struct cfent **eptlist;
102*9781SMoriah.Waterland@Sun.COM 
103*9781SMoriah.Waterland@Sun.COM int	aflag = (-1);
104*9781SMoriah.Waterland@Sun.COM int	cflag = (-1);
105*9781SMoriah.Waterland@Sun.COM int	vflag = 0;
106*9781SMoriah.Waterland@Sun.COM int	nflag = 0;
107*9781SMoriah.Waterland@Sun.COM int	lflag = 0;
108*9781SMoriah.Waterland@Sun.COM int	Lflag = 0;
109*9781SMoriah.Waterland@Sun.COM int	fflag = 0;
110*9781SMoriah.Waterland@Sun.COM int	xflag = 0;
111*9781SMoriah.Waterland@Sun.COM int	qflag = 0;
112*9781SMoriah.Waterland@Sun.COM int	Rflag = 0;
113*9781SMoriah.Waterland@Sun.COM int	dflag = 0;
114*9781SMoriah.Waterland@Sun.COM char 	*device;
115*9781SMoriah.Waterland@Sun.COM 
116*9781SMoriah.Waterland@Sun.COM char	*uniTmp;
117*9781SMoriah.Waterland@Sun.COM 
118*9781SMoriah.Waterland@Sun.COM static char	*mapfile,
119*9781SMoriah.Waterland@Sun.COM 		*spooldir,
120*9781SMoriah.Waterland@Sun.COM 		*tmpdir,
121*9781SMoriah.Waterland@Sun.COM 		*envfile;
122*9781SMoriah.Waterland@Sun.COM static int	errflg = 0;
123*9781SMoriah.Waterland@Sun.COM static int	map_client = 1;
124*9781SMoriah.Waterland@Sun.COM 
125*9781SMoriah.Waterland@Sun.COM void	quit(int);
126*9781SMoriah.Waterland@Sun.COM static void	setpathlist(char *);
127*9781SMoriah.Waterland@Sun.COM static void	usage(void);
128*9781SMoriah.Waterland@Sun.COM 
129*9781SMoriah.Waterland@Sun.COM extern	char	**environ;
130*9781SMoriah.Waterland@Sun.COM extern	char	*pkgdir;
131*9781SMoriah.Waterland@Sun.COM 
132*9781SMoriah.Waterland@Sun.COM /* checkmap.c */
133*9781SMoriah.Waterland@Sun.COM extern int	checkmap(int, int, char *, char *, char *, char *, int);
134*9781SMoriah.Waterland@Sun.COM /* scriptvfy.c */
135*9781SMoriah.Waterland@Sun.COM extern int	checkscripts(char *inst_dir, int silent);
136*9781SMoriah.Waterland@Sun.COM 
137*9781SMoriah.Waterland@Sun.COM int
138*9781SMoriah.Waterland@Sun.COM main(int argc, char *argv[])
139*9781SMoriah.Waterland@Sun.COM {
140*9781SMoriah.Waterland@Sun.COM 	int	pkgfmt = 0;	/* Makes more sense as a pointer, but */
141*9781SMoriah.Waterland@Sun.COM 				/*	18N is compromised. */
142*9781SMoriah.Waterland@Sun.COM 	char	file[PATH_MAX+1],
143*9781SMoriah.Waterland@Sun.COM 		*abi_sym_ptr,
144*9781SMoriah.Waterland@Sun.COM 		*vfstab_file = NULL;
145*9781SMoriah.Waterland@Sun.COM 	char *all_pkgs[4] = {"all", NULL};
146*9781SMoriah.Waterland@Sun.COM 	char **category = NULL;
147*9781SMoriah.Waterland@Sun.COM 	char *catg_arg = NULL;
148*9781SMoriah.Waterland@Sun.COM 	int	c;
149*9781SMoriah.Waterland@Sun.COM 	int	n = 0;
150*9781SMoriah.Waterland@Sun.COM 	char	*prog,
151*9781SMoriah.Waterland@Sun.COM 		*Rvalue,
152*9781SMoriah.Waterland@Sun.COM 		*dvalue;
153*9781SMoriah.Waterland@Sun.COM 	int dbcreate = 0;
154*9781SMoriah.Waterland@Sun.COM 	int pathtype;
155*9781SMoriah.Waterland@Sun.COM 
156*9781SMoriah.Waterland@Sun.COM 	/* initialize locale mechanism */
157*9781SMoriah.Waterland@Sun.COM 
158*9781SMoriah.Waterland@Sun.COM 	(void) setlocale(LC_ALL, "");
159*9781SMoriah.Waterland@Sun.COM 
160*9781SMoriah.Waterland@Sun.COM #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
161*9781SMoriah.Waterland@Sun.COM #define	TEXT_DOMAIN "SYS_TEST"
162*9781SMoriah.Waterland@Sun.COM #endif
163*9781SMoriah.Waterland@Sun.COM 	(void) textdomain(TEXT_DOMAIN);
164*9781SMoriah.Waterland@Sun.COM 
165*9781SMoriah.Waterland@Sun.COM 	/* determine program name */
166*9781SMoriah.Waterland@Sun.COM 
167*9781SMoriah.Waterland@Sun.COM 	prog = set_prog_name(argv[0]);
168*9781SMoriah.Waterland@Sun.COM 
169*9781SMoriah.Waterland@Sun.COM 	/* establish installation root directory */
170*9781SMoriah.Waterland@Sun.COM 
171*9781SMoriah.Waterland@Sun.COM 	if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
172*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_ROOT_SET));
173*9781SMoriah.Waterland@Sun.COM 		quit(1);
174*9781SMoriah.Waterland@Sun.COM 	}
175*9781SMoriah.Waterland@Sun.COM 
176*9781SMoriah.Waterland@Sun.COM 	/* check if not ABI compliant mode */
177*9781SMoriah.Waterland@Sun.COM 	abi_sym_ptr = getenv("PKG_NONABI_SYMLINKS");
178*9781SMoriah.Waterland@Sun.COM 	if (abi_sym_ptr && strncasecmp(abi_sym_ptr, "TRUE", 4) == 0) {
179*9781SMoriah.Waterland@Sun.COM 		set_nonABI_symlinks();
180*9781SMoriah.Waterland@Sun.COM 	}
181*9781SMoriah.Waterland@Sun.COM 
182*9781SMoriah.Waterland@Sun.COM 	/* bugId 4012147 */
183*9781SMoriah.Waterland@Sun.COM 	if ((uniTmp = getenv("PKG_NO_UNIFIED")) != NULL)
184*9781SMoriah.Waterland@Sun.COM 		map_client = 0;
185*9781SMoriah.Waterland@Sun.COM 
186*9781SMoriah.Waterland@Sun.COM 	while ((c = getopt(argc, argv, "Y:R:e:p:d:nLli:vaV:Mm:cqxfQP:?"))
187*9781SMoriah.Waterland@Sun.COM 			!= EOF) {
188*9781SMoriah.Waterland@Sun.COM 		switch (c) {
189*9781SMoriah.Waterland@Sun.COM 		case 'p':
190*9781SMoriah.Waterland@Sun.COM 			pathlist[npaths] = strtok(optarg, " , ");
191*9781SMoriah.Waterland@Sun.COM 			if (pathlist[npaths++] == NULL) {
192*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_POPTION));
193*9781SMoriah.Waterland@Sun.COM 				quit(1);
194*9781SMoriah.Waterland@Sun.COM 			}
195*9781SMoriah.Waterland@Sun.COM 			while (pathlist[npaths] = strtok(NULL, " , ")) {
196*9781SMoriah.Waterland@Sun.COM 				if (npaths++ >= MAXPATHS) {
197*9781SMoriah.Waterland@Sun.COM 					progerr(gettext(ERR_MAXPATHS),
198*9781SMoriah.Waterland@Sun.COM 						MAXPATHS);
199*9781SMoriah.Waterland@Sun.COM 					quit(1);
200*9781SMoriah.Waterland@Sun.COM 				}
201*9781SMoriah.Waterland@Sun.COM 			}
202*9781SMoriah.Waterland@Sun.COM 			break;
203*9781SMoriah.Waterland@Sun.COM 
204*9781SMoriah.Waterland@Sun.COM 		case 'd':
205*9781SMoriah.Waterland@Sun.COM 			dvalue = optarg;
206*9781SMoriah.Waterland@Sun.COM 			dflag = 1;
207*9781SMoriah.Waterland@Sun.COM 			break;
208*9781SMoriah.Waterland@Sun.COM 
209*9781SMoriah.Waterland@Sun.COM 		case 'n':
210*9781SMoriah.Waterland@Sun.COM 			nflag++;
211*9781SMoriah.Waterland@Sun.COM 			break;
212*9781SMoriah.Waterland@Sun.COM 
213*9781SMoriah.Waterland@Sun.COM 		case 'M':
214*9781SMoriah.Waterland@Sun.COM 			map_client = 0;
215*9781SMoriah.Waterland@Sun.COM 			break;
216*9781SMoriah.Waterland@Sun.COM 
217*9781SMoriah.Waterland@Sun.COM 		/*
218*9781SMoriah.Waterland@Sun.COM 		 * Allow admin to establish the client filesystem using a
219*9781SMoriah.Waterland@Sun.COM 		 * vfstab-like file of stable format.
220*9781SMoriah.Waterland@Sun.COM 		 */
221*9781SMoriah.Waterland@Sun.COM 		case 'V':
222*9781SMoriah.Waterland@Sun.COM 			vfstab_file = flex_device(optarg, 2);
223*9781SMoriah.Waterland@Sun.COM 			map_client = 1;
224*9781SMoriah.Waterland@Sun.COM 			break;
225*9781SMoriah.Waterland@Sun.COM 
226*9781SMoriah.Waterland@Sun.COM 		case 'f':
227*9781SMoriah.Waterland@Sun.COM 			if (getuid()) {
228*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_NOTROOT), prog);
229*9781SMoriah.Waterland@Sun.COM 				quit(1);
230*9781SMoriah.Waterland@Sun.COM 			}
231*9781SMoriah.Waterland@Sun.COM 			fflag++;
232*9781SMoriah.Waterland@Sun.COM 			break;
233*9781SMoriah.Waterland@Sun.COM 
234*9781SMoriah.Waterland@Sun.COM 		case 'i':
235*9781SMoriah.Waterland@Sun.COM 			setpathlist(optarg);
236*9781SMoriah.Waterland@Sun.COM 			break;
237*9781SMoriah.Waterland@Sun.COM 
238*9781SMoriah.Waterland@Sun.COM 		case 'v':
239*9781SMoriah.Waterland@Sun.COM 			vflag++;
240*9781SMoriah.Waterland@Sun.COM 			break;
241*9781SMoriah.Waterland@Sun.COM 
242*9781SMoriah.Waterland@Sun.COM 		case 'l':
243*9781SMoriah.Waterland@Sun.COM 			lflag++;
244*9781SMoriah.Waterland@Sun.COM 			break;
245*9781SMoriah.Waterland@Sun.COM 
246*9781SMoriah.Waterland@Sun.COM 		case 'L':
247*9781SMoriah.Waterland@Sun.COM 			Lflag++;
248*9781SMoriah.Waterland@Sun.COM 			break;
249*9781SMoriah.Waterland@Sun.COM 
250*9781SMoriah.Waterland@Sun.COM 		case 'x':
251*9781SMoriah.Waterland@Sun.COM 			if (aflag < 0)
252*9781SMoriah.Waterland@Sun.COM 				aflag = 0;
253*9781SMoriah.Waterland@Sun.COM 			if (cflag < 0)
254*9781SMoriah.Waterland@Sun.COM 				cflag = 0;
255*9781SMoriah.Waterland@Sun.COM 			xflag++;
256*9781SMoriah.Waterland@Sun.COM 			break;
257*9781SMoriah.Waterland@Sun.COM 
258*9781SMoriah.Waterland@Sun.COM 		case 'q':
259*9781SMoriah.Waterland@Sun.COM 			qflag++;
260*9781SMoriah.Waterland@Sun.COM 			break;
261*9781SMoriah.Waterland@Sun.COM 
262*9781SMoriah.Waterland@Sun.COM 		case 'a':
263*9781SMoriah.Waterland@Sun.COM 			if (cflag < 0)
264*9781SMoriah.Waterland@Sun.COM 				cflag = 0;
265*9781SMoriah.Waterland@Sun.COM 			aflag = 1;
266*9781SMoriah.Waterland@Sun.COM 			break;
267*9781SMoriah.Waterland@Sun.COM 
268*9781SMoriah.Waterland@Sun.COM 		case 'c':
269*9781SMoriah.Waterland@Sun.COM 			if (aflag < 0)
270*9781SMoriah.Waterland@Sun.COM 				aflag = 0;
271*9781SMoriah.Waterland@Sun.COM 			cflag = 1;
272*9781SMoriah.Waterland@Sun.COM 			break;
273*9781SMoriah.Waterland@Sun.COM 
274*9781SMoriah.Waterland@Sun.COM 		case 'e':
275*9781SMoriah.Waterland@Sun.COM 			envfile = optarg;
276*9781SMoriah.Waterland@Sun.COM 			break;
277*9781SMoriah.Waterland@Sun.COM 
278*9781SMoriah.Waterland@Sun.COM 		case 'm':
279*9781SMoriah.Waterland@Sun.COM 			mapfile = optarg;
280*9781SMoriah.Waterland@Sun.COM 			break;
281*9781SMoriah.Waterland@Sun.COM 
282*9781SMoriah.Waterland@Sun.COM 		case 'R':
283*9781SMoriah.Waterland@Sun.COM 			Rvalue = optarg;
284*9781SMoriah.Waterland@Sun.COM 			Rflag = 1;
285*9781SMoriah.Waterland@Sun.COM 			break;
286*9781SMoriah.Waterland@Sun.COM 
287*9781SMoriah.Waterland@Sun.COM 		case 'Y':
288*9781SMoriah.Waterland@Sun.COM 			catg_arg = strdup(optarg);
289*9781SMoriah.Waterland@Sun.COM 
290*9781SMoriah.Waterland@Sun.COM 			if ((category = get_categories(catg_arg)) == NULL) {
291*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_CAT_INV), catg_arg);
292*9781SMoriah.Waterland@Sun.COM 				quit(1);
293*9781SMoriah.Waterland@Sun.COM 			} else if (is_not_valid_length(category)) {
294*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_CAT_LNGTH));
295*9781SMoriah.Waterland@Sun.COM 				quit(1);
296*9781SMoriah.Waterland@Sun.COM 			}
297*9781SMoriah.Waterland@Sun.COM 			break;
298*9781SMoriah.Waterland@Sun.COM 
299*9781SMoriah.Waterland@Sun.COM 		case 'Q':
300*9781SMoriah.Waterland@Sun.COM 			dbcreate++;
301*9781SMoriah.Waterland@Sun.COM 			break;
302*9781SMoriah.Waterland@Sun.COM 
303*9781SMoriah.Waterland@Sun.COM 		case 'P':
304*9781SMoriah.Waterland@Sun.COM 			ppathlist[npaths] = strtok(optarg, " , ");
305*9781SMoriah.Waterland@Sun.COM 			if ((ppathlist[npaths] == NULL) ||
306*9781SMoriah.Waterland@Sun.COM 			    (ppathlist[npaths][0] == '-')) {
307*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_PARTIAL_POPTION));
308*9781SMoriah.Waterland@Sun.COM 				quit(1);
309*9781SMoriah.Waterland@Sun.COM 			}
310*9781SMoriah.Waterland@Sun.COM 			npaths++;
311*9781SMoriah.Waterland@Sun.COM 			while (ppathlist[npaths] = strtok(NULL, " , ")) {
312*9781SMoriah.Waterland@Sun.COM 				if (npaths++ >= MAXPATHS) {
313*9781SMoriah.Waterland@Sun.COM 					progerr(gettext(ERR_MAXPATHS),
314*9781SMoriah.Waterland@Sun.COM 						MAXPATHS);
315*9781SMoriah.Waterland@Sun.COM 					quit(1);
316*9781SMoriah.Waterland@Sun.COM 				}
317*9781SMoriah.Waterland@Sun.COM 			}
318*9781SMoriah.Waterland@Sun.COM 			break;
319*9781SMoriah.Waterland@Sun.COM 
320*9781SMoriah.Waterland@Sun.COM 		default:
321*9781SMoriah.Waterland@Sun.COM 			usage();
322*9781SMoriah.Waterland@Sun.COM 			/*NOTREACHED*/
323*9781SMoriah.Waterland@Sun.COM 			/*
324*9781SMoriah.Waterland@Sun.COM 			 * Although usage() calls a noreturn function,
325*9781SMoriah.Waterland@Sun.COM 			 * needed to add return (1);  so that main() would
326*9781SMoriah.Waterland@Sun.COM 			 * pass compilation checks. The statement below
327*9781SMoriah.Waterland@Sun.COM 			 * should never be executed.
328*9781SMoriah.Waterland@Sun.COM 			 */
329*9781SMoriah.Waterland@Sun.COM 			return (1);
330*9781SMoriah.Waterland@Sun.COM 		}
331*9781SMoriah.Waterland@Sun.COM 	}
332*9781SMoriah.Waterland@Sun.COM 
333*9781SMoriah.Waterland@Sun.COM 	/* Check for incompatible options */
334*9781SMoriah.Waterland@Sun.COM 	if (dflag && Rflag)
335*9781SMoriah.Waterland@Sun.COM 		usage();
336*9781SMoriah.Waterland@Sun.COM 
337*9781SMoriah.Waterland@Sun.COM 	/* Check for root dir and device dir if set */
338*9781SMoriah.Waterland@Sun.COM 	if (Rflag) {
339*9781SMoriah.Waterland@Sun.COM 		if (!set_inst_root(Rvalue)) {
340*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_ROOT_CMD));
341*9781SMoriah.Waterland@Sun.COM 			quit(1);
342*9781SMoriah.Waterland@Sun.COM 		}
343*9781SMoriah.Waterland@Sun.COM 	}
344*9781SMoriah.Waterland@Sun.COM 
345*9781SMoriah.Waterland@Sun.COM 	if (dflag)
346*9781SMoriah.Waterland@Sun.COM 		device = flex_device(dvalue, 1);
347*9781SMoriah.Waterland@Sun.COM 
348*9781SMoriah.Waterland@Sun.COM 	if (lflag || Lflag) {
349*9781SMoriah.Waterland@Sun.COM 		/* we're only supposed to list information */
350*9781SMoriah.Waterland@Sun.COM 		if ((cflag >= 0) || (aflag >= 0) ||
351*9781SMoriah.Waterland@Sun.COM 		qflag || xflag || fflag || nflag || vflag)
352*9781SMoriah.Waterland@Sun.COM 			usage();
353*9781SMoriah.Waterland@Sun.COM 	}
354*9781SMoriah.Waterland@Sun.COM 
355*9781SMoriah.Waterland@Sun.COM 	set_PKGpaths(get_inst_root());
356*9781SMoriah.Waterland@Sun.COM 
357*9781SMoriah.Waterland@Sun.COM 	if (catg_arg != NULL && device == NULL) {
358*9781SMoriah.Waterland@Sun.COM 		if (argc - optind) {
359*9781SMoriah.Waterland@Sun.COM 			usage();
360*9781SMoriah.Waterland@Sun.COM 		}
361*9781SMoriah.Waterland@Sun.COM 		pkg = gpkglist(pkgdir, all_pkgs, category);
362*9781SMoriah.Waterland@Sun.COM 		if (pkg == NULL) {
363*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_CAT_FND), catg_arg);
364*9781SMoriah.Waterland@Sun.COM 			quit(1);
365*9781SMoriah.Waterland@Sun.COM 		} else {
366*9781SMoriah.Waterland@Sun.COM 			for (pkgcnt = 0; pkg[pkgcnt] != NULL; pkgcnt++);
367*9781SMoriah.Waterland@Sun.COM 		}
368*9781SMoriah.Waterland@Sun.COM 	} else if (catg_arg != NULL && optind < argc) {
369*9781SMoriah.Waterland@Sun.COM 		usage();
370*9781SMoriah.Waterland@Sun.COM 	} else {
371*9781SMoriah.Waterland@Sun.COM 		pkg = &argv[optind];
372*9781SMoriah.Waterland@Sun.COM 		pkgcnt = (argc - optind);
373*9781SMoriah.Waterland@Sun.COM 	}
374*9781SMoriah.Waterland@Sun.COM 
375*9781SMoriah.Waterland@Sun.COM 	environ = NULL;		/* Sever the parent environment. */
376*9781SMoriah.Waterland@Sun.COM 
377*9781SMoriah.Waterland@Sun.COM 	if (vcfile() == 0) {
378*9781SMoriah.Waterland@Sun.COM 		quit(99);
379*9781SMoriah.Waterland@Sun.COM 	}
380*9781SMoriah.Waterland@Sun.COM 
381*9781SMoriah.Waterland@Sun.COM 	errflg = 0;
382*9781SMoriah.Waterland@Sun.COM 	if (mapfile) {
383*9781SMoriah.Waterland@Sun.COM 		/* check for incompatible options */
384*9781SMoriah.Waterland@Sun.COM 		if (device || pkgcnt)
385*9781SMoriah.Waterland@Sun.COM 			usage();
386*9781SMoriah.Waterland@Sun.COM 		put_path_params();	/* Restore what's needed. */
387*9781SMoriah.Waterland@Sun.COM 
388*9781SMoriah.Waterland@Sun.COM 		/* send pathtype if partial path */
389*9781SMoriah.Waterland@Sun.COM 		pathtype = (ppathlist[0] != NULL) ? 1 : 0;
390*9781SMoriah.Waterland@Sun.COM 		if (checkmap(0, (device != NULL), mapfile, envfile, NULL,
391*9781SMoriah.Waterland@Sun.COM 		    NULL, pathtype))
392*9781SMoriah.Waterland@Sun.COM 			errflg++;
393*9781SMoriah.Waterland@Sun.COM 	} else if (device) {
394*9781SMoriah.Waterland@Sun.COM 		/* check for incompatible options */
395*9781SMoriah.Waterland@Sun.COM 		if ((cflag >= 0) || (aflag >= 0))
396*9781SMoriah.Waterland@Sun.COM 			usage();
397*9781SMoriah.Waterland@Sun.COM 		if (qflag || xflag || nflag || envfile)
398*9781SMoriah.Waterland@Sun.COM 			usage();
399*9781SMoriah.Waterland@Sun.COM 		tmpdir = NULL;
400*9781SMoriah.Waterland@Sun.COM 		if ((spooldir = devattr(device, "pathname")) == NULL)
401*9781SMoriah.Waterland@Sun.COM 			spooldir = device;
402*9781SMoriah.Waterland@Sun.COM 		if (isdir(spooldir)) {
403*9781SMoriah.Waterland@Sun.COM 			tmpdir = spooldir = qstrdup(tmpnam(NULL));
404*9781SMoriah.Waterland@Sun.COM 			if (fflag) {
405*9781SMoriah.Waterland@Sun.COM 				logerr(gettext(WRN_F_SPOOL), *pkg);
406*9781SMoriah.Waterland@Sun.COM 				fflag = 0;
407*9781SMoriah.Waterland@Sun.COM 			}
408*9781SMoriah.Waterland@Sun.COM 			if (mkdir(spooldir, 0755)) {
409*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_MKDIR), spooldir);
410*9781SMoriah.Waterland@Sun.COM 				quit(99);
411*9781SMoriah.Waterland@Sun.COM 			}
412*9781SMoriah.Waterland@Sun.COM 			if (n = pkgtrans(device, spooldir, pkg, PT_SILENT,
413*9781SMoriah.Waterland@Sun.COM 				NULL, NULL))
414*9781SMoriah.Waterland@Sun.COM 				quit(n);
415*9781SMoriah.Waterland@Sun.COM 			if (catg_arg != NULL)
416*9781SMoriah.Waterland@Sun.COM 				pkg = gpkglist(spooldir, all_pkgs, category);
417*9781SMoriah.Waterland@Sun.COM 			else
418*9781SMoriah.Waterland@Sun.COM 				pkg = gpkglist(spooldir, all_pkgs, NULL);
419*9781SMoriah.Waterland@Sun.COM 			pkgfmt = 0;
420*9781SMoriah.Waterland@Sun.COM 		} else {
421*9781SMoriah.Waterland@Sun.COM 			if (catg_arg != NULL)
422*9781SMoriah.Waterland@Sun.COM 				pkg = gpkglist(spooldir,
423*9781SMoriah.Waterland@Sun.COM 					pkgcnt ? pkg : all_pkgs, category);
424*9781SMoriah.Waterland@Sun.COM 			else
425*9781SMoriah.Waterland@Sun.COM 				pkg = gpkglist(spooldir,
426*9781SMoriah.Waterland@Sun.COM 					pkgcnt ? pkg : all_pkgs, NULL);
427*9781SMoriah.Waterland@Sun.COM 			pkgfmt = 1;
428*9781SMoriah.Waterland@Sun.COM 		}
429*9781SMoriah.Waterland@Sun.COM 
430*9781SMoriah.Waterland@Sun.COM 		/*
431*9781SMoriah.Waterland@Sun.COM 		 * At this point pkg[] is the list of packages to check. They
432*9781SMoriah.Waterland@Sun.COM 		 * are in directory format in spooldir.
433*9781SMoriah.Waterland@Sun.COM 		 */
434*9781SMoriah.Waterland@Sun.COM 		if (pkg == NULL) {
435*9781SMoriah.Waterland@Sun.COM 			if (catg_arg != NULL) {
436*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_CAT_FND), catg_arg);
437*9781SMoriah.Waterland@Sun.COM 				quit(1);
438*9781SMoriah.Waterland@Sun.COM 			} else {
439*9781SMoriah.Waterland@Sun.COM 				progerr(gettext(ERR_SEL_PKG));
440*9781SMoriah.Waterland@Sun.COM 				quit(1);
441*9781SMoriah.Waterland@Sun.COM 			}
442*9781SMoriah.Waterland@Sun.COM 		}
443*9781SMoriah.Waterland@Sun.COM 
444*9781SMoriah.Waterland@Sun.COM 		aflag = 0;
445*9781SMoriah.Waterland@Sun.COM 
446*9781SMoriah.Waterland@Sun.COM 		for (n = 0; pkg[n]; n++) {
447*9781SMoriah.Waterland@Sun.COM 			char locenv[PATH_MAX];
448*9781SMoriah.Waterland@Sun.COM 
449*9781SMoriah.Waterland@Sun.COM 	/*
450*9781SMoriah.Waterland@Sun.COM 	 * *********************************************************************
451*9781SMoriah.Waterland@Sun.COM 	 * this feature is removed starting with Solaris 10 - there is no built
452*9781SMoriah.Waterland@Sun.COM 	 * in list of packages that should be run "the old way"
453*9781SMoriah.Waterland@Sun.COM 	 * *********************************************************************
454*9781SMoriah.Waterland@Sun.COM 	 */
455*9781SMoriah.Waterland@Sun.COM #ifdef	ALLOW_EXCEPTION_PKG_LIST
456*9781SMoriah.Waterland@Sun.COM 			/* Until 2.9, set it from the execption list */
457*9781SMoriah.Waterland@Sun.COM 			if (exception_pkg(pkg[n], LINK))
458*9781SMoriah.Waterland@Sun.COM 				set_nonABI_symlinks();
459*9781SMoriah.Waterland@Sun.COM #endif
460*9781SMoriah.Waterland@Sun.COM 
461*9781SMoriah.Waterland@Sun.COM 			if (pkgfmt)
462*9781SMoriah.Waterland@Sun.COM 				(void) printf(
463*9781SMoriah.Waterland@Sun.COM 					gettext(MSG_CHK_DIR), pkg[n], device);
464*9781SMoriah.Waterland@Sun.COM 			else
465*9781SMoriah.Waterland@Sun.COM 				(void) printf(
466*9781SMoriah.Waterland@Sun.COM 					gettext(MSG_CHK_STRM), pkg[n], device);
467*9781SMoriah.Waterland@Sun.COM 
468*9781SMoriah.Waterland@Sun.COM 			(void) snprintf(pkgspool, sizeof (pkgspool),
469*9781SMoriah.Waterland@Sun.COM 				"%s/%s", spooldir, pkg[n]);
470*9781SMoriah.Waterland@Sun.COM 			(void) snprintf(file, sizeof (file),
471*9781SMoriah.Waterland@Sun.COM 				"%s/install", pkgspool);
472*9781SMoriah.Waterland@Sun.COM 			/* Here we check the install scripts. */
473*9781SMoriah.Waterland@Sun.COM 			(void) printf(
474*9781SMoriah.Waterland@Sun.COM 				gettext("## Checking control scripts.\n"));
475*9781SMoriah.Waterland@Sun.COM 			(void) checkscripts(file, 0);
476*9781SMoriah.Waterland@Sun.COM 			/* Verify consistency with the pkgmap. */
477*9781SMoriah.Waterland@Sun.COM 			(void) printf(
478*9781SMoriah.Waterland@Sun.COM 				gettext("## Checking package objects.\n"));
479*9781SMoriah.Waterland@Sun.COM 			(void) snprintf(file, sizeof (file),
480*9781SMoriah.Waterland@Sun.COM 				"%s/pkgmap", pkgspool);
481*9781SMoriah.Waterland@Sun.COM 			(void) snprintf(locenv, sizeof (locenv),
482*9781SMoriah.Waterland@Sun.COM 				"%s/pkginfo", pkgspool);
483*9781SMoriah.Waterland@Sun.COM 			envfile = locenv;
484*9781SMoriah.Waterland@Sun.COM 
485*9781SMoriah.Waterland@Sun.COM 			/*
486*9781SMoriah.Waterland@Sun.COM 			 * NOTE : checkmap() frees the environ data and
487*9781SMoriah.Waterland@Sun.COM 			 * pointer when it's through with them.
488*9781SMoriah.Waterland@Sun.COM 			 */
489*9781SMoriah.Waterland@Sun.COM 			if (checkmap(0, (device != NULL), file, envfile,
490*9781SMoriah.Waterland@Sun.COM 					pkg[n], NULL, 0))
491*9781SMoriah.Waterland@Sun.COM 				errflg++;
492*9781SMoriah.Waterland@Sun.COM 			(void) printf(
493*9781SMoriah.Waterland@Sun.COM 				gettext("## Checking is complete.\n"));
494*9781SMoriah.Waterland@Sun.COM 		}
495*9781SMoriah.Waterland@Sun.COM 	} else {
496*9781SMoriah.Waterland@Sun.COM 		if (envfile)
497*9781SMoriah.Waterland@Sun.COM 			usage();
498*9781SMoriah.Waterland@Sun.COM 
499*9781SMoriah.Waterland@Sun.COM 		put_path_params();	/* Restore what's needed. */
500*9781SMoriah.Waterland@Sun.COM 
501*9781SMoriah.Waterland@Sun.COM 		/*
502*9781SMoriah.Waterland@Sun.COM 		 * If this is a check of a client of some sort, we'll need to
503*9781SMoriah.Waterland@Sun.COM 		 * mount up the client's filesystems. If the caller isn't
504*9781SMoriah.Waterland@Sun.COM 		 * root, this may not be possible.
505*9781SMoriah.Waterland@Sun.COM 		 */
506*9781SMoriah.Waterland@Sun.COM 		if (is_an_inst_root()) {
507*9781SMoriah.Waterland@Sun.COM 			if (getuid()) {
508*9781SMoriah.Waterland@Sun.COM 				logerr(gettext(MSG_NOTROOT));
509*9781SMoriah.Waterland@Sun.COM 				logerr(gettext(MSG_CONT));
510*9781SMoriah.Waterland@Sun.COM 			} else {
511*9781SMoriah.Waterland@Sun.COM 				if (get_mntinfo(map_client, vfstab_file))
512*9781SMoriah.Waterland@Sun.COM 					map_client = 0;
513*9781SMoriah.Waterland@Sun.COM 				if (map_client)
514*9781SMoriah.Waterland@Sun.COM 					mount_client();
515*9781SMoriah.Waterland@Sun.COM 			}
516*9781SMoriah.Waterland@Sun.COM 		}
517*9781SMoriah.Waterland@Sun.COM 
518*9781SMoriah.Waterland@Sun.COM 		(void) snprintf(file, sizeof (file),
519*9781SMoriah.Waterland@Sun.COM 			"%s/contents", get_PKGADM());
520*9781SMoriah.Waterland@Sun.COM 		if (ppathlist[0] != NULL) {
521*9781SMoriah.Waterland@Sun.COM 			for (n = 0; ppathlist[n]; n++) {
522*9781SMoriah.Waterland@Sun.COM 				if (checkmap(1, (device != NULL), file, NULL,
523*9781SMoriah.Waterland@Sun.COM 						NULL, ppathlist[n], 1))
524*9781SMoriah.Waterland@Sun.COM 					errflg++;
525*9781SMoriah.Waterland@Sun.COM 			}
526*9781SMoriah.Waterland@Sun.COM 		} else if (pkg[0] != NULL) {
527*9781SMoriah.Waterland@Sun.COM 				if (checkmap(1, (device != NULL), file, NULL,
528*9781SMoriah.Waterland@Sun.COM 					pkg[0], NULL, 0)) {
529*9781SMoriah.Waterland@Sun.COM 					errflg++;
530*9781SMoriah.Waterland@Sun.COM 				}
531*9781SMoriah.Waterland@Sun.COM 		} else {
532*9781SMoriah.Waterland@Sun.COM 			if (checkmap(1, (device != NULL), file, NULL,
533*9781SMoriah.Waterland@Sun.COM 					NULL, NULL, 0)) {
534*9781SMoriah.Waterland@Sun.COM 				errflg++;
535*9781SMoriah.Waterland@Sun.COM 			}
536*9781SMoriah.Waterland@Sun.COM 		}
537*9781SMoriah.Waterland@Sun.COM 
538*9781SMoriah.Waterland@Sun.COM 		if (map_client) {
539*9781SMoriah.Waterland@Sun.COM 			unmount_client();
540*9781SMoriah.Waterland@Sun.COM 		}
541*9781SMoriah.Waterland@Sun.COM 	}
542*9781SMoriah.Waterland@Sun.COM 	quit(errflg ? 1 : 0);
543*9781SMoriah.Waterland@Sun.COM 	/* LINTED: no return */
544*9781SMoriah.Waterland@Sun.COM }
545*9781SMoriah.Waterland@Sun.COM 
546*9781SMoriah.Waterland@Sun.COM static void
547*9781SMoriah.Waterland@Sun.COM setpathlist(char *file)
548*9781SMoriah.Waterland@Sun.COM {
549*9781SMoriah.Waterland@Sun.COM 	int fd;
550*9781SMoriah.Waterland@Sun.COM 	struct stat st;
551*9781SMoriah.Waterland@Sun.COM 	FILE *fplist;
552*9781SMoriah.Waterland@Sun.COM 	char pathname[PATH_MAX];
553*9781SMoriah.Waterland@Sun.COM 	/*
554*9781SMoriah.Waterland@Sun.COM 	 * This trap laid to catch a mismatch between the declaration above and
555*9781SMoriah.Waterland@Sun.COM 	 * the hard-coded constant in the fscanf below
556*9781SMoriah.Waterland@Sun.COM 	 */
557*9781SMoriah.Waterland@Sun.COM #if PATH_MAX != 1024
558*9781SMoriah.Waterland@Sun.COM #error "PATH_MAX changed, so we have a bug to fix"
559*9781SMoriah.Waterland@Sun.COM #endif
560*9781SMoriah.Waterland@Sun.COM 
561*9781SMoriah.Waterland@Sun.COM 	if (strcmp(file, "-") == 0) {
562*9781SMoriah.Waterland@Sun.COM 		fplist = stdin;
563*9781SMoriah.Waterland@Sun.COM 	} else {
564*9781SMoriah.Waterland@Sun.COM 		if ((fd = open(file, O_RDONLY)) == -1) {
565*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_IOPEN), file);
566*9781SMoriah.Waterland@Sun.COM 			quit(1);
567*9781SMoriah.Waterland@Sun.COM 		}
568*9781SMoriah.Waterland@Sun.COM 		if (fstat(fd, &st) == -1) {
569*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_IOPEN), file);
570*9781SMoriah.Waterland@Sun.COM 			quit(1);
571*9781SMoriah.Waterland@Sun.COM 		}
572*9781SMoriah.Waterland@Sun.COM 		if (S_ISDIR(st.st_mode) || S_ISBLK(st.st_mode)) {
573*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_PATHS_INVALID), file);
574*9781SMoriah.Waterland@Sun.COM 			quit(1);
575*9781SMoriah.Waterland@Sun.COM 		}
576*9781SMoriah.Waterland@Sun.COM 		if ((fplist = fdopen(fd, "r")) == NULL) {
577*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_IOPEN), file);
578*9781SMoriah.Waterland@Sun.COM 			quit(1);
579*9781SMoriah.Waterland@Sun.COM 		}
580*9781SMoriah.Waterland@Sun.COM 	}
581*9781SMoriah.Waterland@Sun.COM 	while (fscanf(fplist, "%1024s", pathname) == 1) {
582*9781SMoriah.Waterland@Sun.COM 		if (*pathname == '\0') {
583*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_PATHS_INVALID), file);
584*9781SMoriah.Waterland@Sun.COM 			quit(1);
585*9781SMoriah.Waterland@Sun.COM 		}
586*9781SMoriah.Waterland@Sun.COM 		pathlist[npaths] = qstrdup(pathname);
587*9781SMoriah.Waterland@Sun.COM 		if (npaths++ > MAXPATHS) {
588*9781SMoriah.Waterland@Sun.COM 			progerr(gettext(ERR_TOO_MANY), MAXPATHS);
589*9781SMoriah.Waterland@Sun.COM 			quit(1);
590*9781SMoriah.Waterland@Sun.COM 		}
591*9781SMoriah.Waterland@Sun.COM 	}
592*9781SMoriah.Waterland@Sun.COM 	if (npaths == 0) {
593*9781SMoriah.Waterland@Sun.COM 		progerr(gettext(ERR_IEMPTY));
594*9781SMoriah.Waterland@Sun.COM 		quit(1);
595*9781SMoriah.Waterland@Sun.COM 	}
596*9781SMoriah.Waterland@Sun.COM 	(void) fclose(fplist);
597*9781SMoriah.Waterland@Sun.COM }
598*9781SMoriah.Waterland@Sun.COM 
599*9781SMoriah.Waterland@Sun.COM void
600*9781SMoriah.Waterland@Sun.COM quit(int n)
601*9781SMoriah.Waterland@Sun.COM {
602*9781SMoriah.Waterland@Sun.COM 	/* cleanup any temporary directories */
603*9781SMoriah.Waterland@Sun.COM 	(void) chdir("/");
604*9781SMoriah.Waterland@Sun.COM 	if (tmpdir != NULL) {
605*9781SMoriah.Waterland@Sun.COM 		(void) rrmdir(tmpdir);
606*9781SMoriah.Waterland@Sun.COM 		free(tmpdir);
607*9781SMoriah.Waterland@Sun.COM 		tmpdir = NULL;
608*9781SMoriah.Waterland@Sun.COM 	}
609*9781SMoriah.Waterland@Sun.COM 	(void) pkghead(NULL);
610*9781SMoriah.Waterland@Sun.COM 	exit(n);
611*9781SMoriah.Waterland@Sun.COM 	/*NOTREACHED*/
612*9781SMoriah.Waterland@Sun.COM }
613*9781SMoriah.Waterland@Sun.COM 
614*9781SMoriah.Waterland@Sun.COM static void
615*9781SMoriah.Waterland@Sun.COM usage(void)
616*9781SMoriah.Waterland@Sun.COM {
617*9781SMoriah.Waterland@Sun.COM 	char *prog = get_prog_name();
618*9781SMoriah.Waterland@Sun.COM 
619*9781SMoriah.Waterland@Sun.COM 	(void) fprintf(stderr, gettext(ERR_USAGE), prog, prog);
620*9781SMoriah.Waterland@Sun.COM 	quit(1);
621*9781SMoriah.Waterland@Sun.COM 	/*NOTREACHED*/
622*9781SMoriah.Waterland@Sun.COM }
623