xref: /titanic_44/usr/src/cmd/svr4pkg/pkginfo/pkginfo.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 2009 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 #define	__EXTENTIONS__
32*5c51f124SMoriah Waterland 
33*5c51f124SMoriah Waterland #include <stdio.h>
34*5c51f124SMoriah Waterland #include <limits.h>
35*5c51f124SMoriah Waterland #include <unistd.h>
36*5c51f124SMoriah Waterland #include <stdlib.h>
37*5c51f124SMoriah Waterland #include <locale.h>
38*5c51f124SMoriah Waterland #include <libintl.h>
39*5c51f124SMoriah Waterland #include <strings.h>
40*5c51f124SMoriah Waterland #include <string.h>
41*5c51f124SMoriah Waterland #include <dirent.h>
42*5c51f124SMoriah Waterland #include <sys/param.h>
43*5c51f124SMoriah Waterland #include <sys/stat.h>
44*5c51f124SMoriah Waterland #include <pkginfo.h>
45*5c51f124SMoriah Waterland #include <fcntl.h>
46*5c51f124SMoriah Waterland #include <sys/types.h>
47*5c51f124SMoriah Waterland #include <sys/stat.h>
48*5c51f124SMoriah Waterland #include <sys/param.h>
49*5c51f124SMoriah Waterland #include <sys/mman.h>
50*5c51f124SMoriah Waterland #include <pkgstrct.h>
51*5c51f124SMoriah Waterland #include <pkglocs.h>
52*5c51f124SMoriah Waterland #include <errno.h>
53*5c51f124SMoriah Waterland #include <ctype.h>
54*5c51f124SMoriah Waterland 
55*5c51f124SMoriah Waterland #include <pkglib.h>
56*5c51f124SMoriah Waterland #include <instzones_api.h>
57*5c51f124SMoriah Waterland #include <libadm.h>
58*5c51f124SMoriah Waterland #include <libinst.h>
59*5c51f124SMoriah Waterland 
60*5c51f124SMoriah Waterland extern char	*pkgdir;
61*5c51f124SMoriah Waterland extern int	pkginfofind(char *path, char *pkg_dir, char *pkginst);
62*5c51f124SMoriah Waterland 
63*5c51f124SMoriah Waterland #define	ERR_USAGE	"usage:\n" \
64*5c51f124SMoriah Waterland 			"%s [-q] [-pi] [-x|l] [options] [pkg ...]\n" \
65*5c51f124SMoriah Waterland 			"%s -d device [-q] [-x|l] [options] [pkg ...]\n" \
66*5c51f124SMoriah Waterland 			"where\n" \
67*5c51f124SMoriah Waterland 			"  -q #quiet mode\n" \
68*5c51f124SMoriah Waterland 			"  -p #select partially installed packages\n" \
69*5c51f124SMoriah Waterland 			"  -i #select completely installed packages\n" \
70*5c51f124SMoriah Waterland 			"  -x #extracted listing\n" \
71*5c51f124SMoriah Waterland 			"  -l #long listing\n" \
72*5c51f124SMoriah Waterland 			"  -r #relocation base \n" \
73*5c51f124SMoriah Waterland 			"and options may include:\n" \
74*5c51f124SMoriah Waterland 			"  -c category, [category...]\n" \
75*5c51f124SMoriah Waterland 			"  -a architecture\n" \
76*5c51f124SMoriah Waterland 			"  -v version\n"
77*5c51f124SMoriah Waterland 
78*5c51f124SMoriah Waterland #define	ERR_INCOMP0	"-L and -l/-x/-r flags are incompatible"
79*5c51f124SMoriah Waterland #define	ERR_INCOMP1	"-l and -x/-r flags are not compatible"
80*5c51f124SMoriah Waterland #define	ERR_INCOMP2	"-x and -l/-r flags are not compatible"
81*5c51f124SMoriah Waterland #define	ERR_INCOMP3	"-r and -x/-x flags are not compatible"
82*5c51f124SMoriah Waterland #define	ERR_NOINFO	"ERROR: information for \"%s\" was not found"
83*5c51f124SMoriah Waterland #define	ERR_NOPINFO	"ERROR: No partial information for \"%s\" was found"
84*5c51f124SMoriah Waterland #define	ERR_BADINFO	"pkginfo file is corrupt or missing"
85*5c51f124SMoriah Waterland #define	ERR_ROOT_SET	"Could not set install root from the environment."
86*5c51f124SMoriah Waterland #define	ERR_ROOT_CMD	"Command line install root contends with environment."
87*5c51f124SMoriah Waterland 
88*5c51f124SMoriah Waterland /* Format for dumping package attributes in dumpinfo() */
89*5c51f124SMoriah Waterland #define	FMT	"%10s:  %s\n"
90*5c51f124SMoriah Waterland #define	SFMT	"%-11.11s %-*.*s %s\n"
91*5c51f124SMoriah Waterland #define	CFMT	"%*.*s  "
92*5c51f124SMoriah Waterland #define	XFMT	"%-*.*s  %s\n"
93*5c51f124SMoriah Waterland 
94*5c51f124SMoriah Waterland #define	nblock(size)	((size + (DEV_BSIZE - 1)) / DEV_BSIZE)
95*5c51f124SMoriah Waterland #define	MAXCATG	64
96*5c51f124SMoriah Waterland 
97*5c51f124SMoriah Waterland static char	*device = NULL;
98*5c51f124SMoriah Waterland static char	*parmlst[] = {
99*5c51f124SMoriah Waterland 	"DESC", "PSTAMP", "INSTDATE", "VSTOCK", "SERIALNUM", "HOTLINE",
100*5c51f124SMoriah Waterland 	"EMAIL", NULL
101*5c51f124SMoriah Waterland };
102*5c51f124SMoriah Waterland 
103*5c51f124SMoriah Waterland static char	contents[PATH_MAX];
104*5c51f124SMoriah Waterland static int	errflg = 0;
105*5c51f124SMoriah Waterland static int	qflag = 0;
106*5c51f124SMoriah Waterland static int	iflag = -1;
107*5c51f124SMoriah Waterland static int	pflag = -1;
108*5c51f124SMoriah Waterland static int	lflag = 0;
109*5c51f124SMoriah Waterland static int	Lflag = 0;
110*5c51f124SMoriah Waterland static int	Nflag = 0;
111*5c51f124SMoriah Waterland static int	xflag = 0;
112*5c51f124SMoriah Waterland static int	rflag = 0; 		/* bug # 1081606 */
113*5c51f124SMoriah Waterland static struct cfent	entry;
114*5c51f124SMoriah Waterland static char	**pkg = NULL;
115*5c51f124SMoriah Waterland static int	pkgcnt = 0;
116*5c51f124SMoriah Waterland static char	*ckcatg[MAXCATG] = {NULL};
117*5c51f124SMoriah Waterland static int	ncatg = 0;
118*5c51f124SMoriah Waterland static char	*ckvers = NULL;
119*5c51f124SMoriah Waterland static char	*ckarch = NULL;
120*5c51f124SMoriah Waterland 
121*5c51f124SMoriah Waterland static struct cfstat {
122*5c51f124SMoriah Waterland 	char	pkginst[32];
123*5c51f124SMoriah Waterland 	short	exec;
124*5c51f124SMoriah Waterland 	short	dirs;
125*5c51f124SMoriah Waterland 	short	link;
126*5c51f124SMoriah Waterland 	short	partial;
127*5c51f124SMoriah Waterland 	long	spooled;
128*5c51f124SMoriah Waterland 	long	installed;
129*5c51f124SMoriah Waterland 	short	info;
130*5c51f124SMoriah Waterland 	short	shared;
131*5c51f124SMoriah Waterland 	short	setuid;
132*5c51f124SMoriah Waterland 	long	tblks;
133*5c51f124SMoriah Waterland 	struct cfstat *next;
134*5c51f124SMoriah Waterland } *data;
135*5c51f124SMoriah Waterland static struct pkginfo info;
136*5c51f124SMoriah Waterland 
137*5c51f124SMoriah Waterland static struct	cfstat *fpkg(char *pkginst);
138*5c51f124SMoriah Waterland static int	iscatg(char *list);
139*5c51f124SMoriah Waterland static int	selectp(char *p);
140*5c51f124SMoriah Waterland static void	usage(void), look_for_installed(void),
141*5c51f124SMoriah Waterland 		report(void), rdcontents(void);
142*5c51f124SMoriah Waterland static void	pkgusage(struct cfstat *dp, struct cfent *pentry);
143*5c51f124SMoriah Waterland static void	getinfo(struct cfstat *dp);
144*5c51f124SMoriah Waterland static void	dumpinfo(struct cfstat *dp, int pkgLngth);
145*5c51f124SMoriah Waterland 
146*5c51f124SMoriah Waterland int
147*5c51f124SMoriah Waterland main(int argc, char **argv)
148*5c51f124SMoriah Waterland {
149*5c51f124SMoriah Waterland 	int	c;
150*5c51f124SMoriah Waterland 
151*5c51f124SMoriah Waterland 	pkgdir = NULL;
152*5c51f124SMoriah Waterland 	setErrstr(NULL);
153*5c51f124SMoriah Waterland 
154*5c51f124SMoriah Waterland 	/* initialize locale mechanism */
155*5c51f124SMoriah Waterland 
156*5c51f124SMoriah Waterland 	(void) setlocale(LC_ALL, "");
157*5c51f124SMoriah Waterland 
158*5c51f124SMoriah Waterland #if !defined(TEXT_DOMAIN)	/* Should be defined by cc -D */
159*5c51f124SMoriah Waterland #define	TEXT_DOMAIN "SYS_TEST"
160*5c51f124SMoriah Waterland #endif
161*5c51f124SMoriah Waterland 	(void) textdomain(TEXT_DOMAIN);
162*5c51f124SMoriah Waterland 
163*5c51f124SMoriah Waterland 	/* determine program name */
164*5c51f124SMoriah Waterland 
165*5c51f124SMoriah Waterland 	(void) set_prog_name(argv[0]);
166*5c51f124SMoriah Waterland 
167*5c51f124SMoriah Waterland 	/* tell spmi zones interface how to access package output functions */
168*5c51f124SMoriah Waterland 
169*5c51f124SMoriah Waterland 	z_set_output_functions(echo, echoDebug, progerr);
170*5c51f124SMoriah Waterland 
171*5c51f124SMoriah Waterland 	/* establish installation root directory */
172*5c51f124SMoriah Waterland 
173*5c51f124SMoriah Waterland 	if (!set_inst_root(getenv("PKG_INSTALL_ROOT"))) {
174*5c51f124SMoriah Waterland 		progerr(gettext(ERR_ROOT_SET));
175*5c51f124SMoriah Waterland 		exit(1);
176*5c51f124SMoriah Waterland 	}
177*5c51f124SMoriah Waterland 
178*5c51f124SMoriah Waterland 	while ((c = getopt(argc, argv, "LNR:xv:a:d:qrpilc:?")) != EOF) {
179*5c51f124SMoriah Waterland 		switch (c) {
180*5c51f124SMoriah Waterland 		    case 'v':
181*5c51f124SMoriah Waterland 			ckvers = optarg;
182*5c51f124SMoriah Waterland 			break;
183*5c51f124SMoriah Waterland 
184*5c51f124SMoriah Waterland 		    case 'a':
185*5c51f124SMoriah Waterland 			ckarch = optarg;
186*5c51f124SMoriah Waterland 			break;
187*5c51f124SMoriah Waterland 
188*5c51f124SMoriah Waterland 		    case 'd':
189*5c51f124SMoriah Waterland 			/* -d could specify stream or mountable device */
190*5c51f124SMoriah Waterland 			device = flex_device(optarg, 1);
191*5c51f124SMoriah Waterland 			break;
192*5c51f124SMoriah Waterland 
193*5c51f124SMoriah Waterland 		    case 'q':
194*5c51f124SMoriah Waterland 			qflag++;
195*5c51f124SMoriah Waterland 			break;
196*5c51f124SMoriah Waterland 
197*5c51f124SMoriah Waterland 		    case 'i':
198*5c51f124SMoriah Waterland 			iflag = 1;
199*5c51f124SMoriah Waterland 			if (pflag > 0)
200*5c51f124SMoriah Waterland 				usage();
201*5c51f124SMoriah Waterland 			pflag = 0;
202*5c51f124SMoriah Waterland 			break;
203*5c51f124SMoriah Waterland 
204*5c51f124SMoriah Waterland 		    case 'p':
205*5c51f124SMoriah Waterland 			pflag = 1;
206*5c51f124SMoriah Waterland 			if (iflag > 0)
207*5c51f124SMoriah Waterland 				usage();
208*5c51f124SMoriah Waterland 			iflag = 0;
209*5c51f124SMoriah Waterland 			break;
210*5c51f124SMoriah Waterland 
211*5c51f124SMoriah Waterland 		    case 'N':
212*5c51f124SMoriah Waterland 			Nflag++;
213*5c51f124SMoriah Waterland 			break;
214*5c51f124SMoriah Waterland 
215*5c51f124SMoriah Waterland 		    case 'L':
216*5c51f124SMoriah Waterland 			if (xflag || lflag || rflag) {
217*5c51f124SMoriah Waterland 				progerr(gettext(ERR_INCOMP0));
218*5c51f124SMoriah Waterland 				usage();
219*5c51f124SMoriah Waterland 			}
220*5c51f124SMoriah Waterland 			Lflag++;
221*5c51f124SMoriah Waterland 			break;
222*5c51f124SMoriah Waterland 
223*5c51f124SMoriah Waterland 		    case 'l':
224*5c51f124SMoriah Waterland 			if (xflag || rflag) {
225*5c51f124SMoriah Waterland 				progerr(gettext(ERR_INCOMP1));
226*5c51f124SMoriah Waterland 				usage();
227*5c51f124SMoriah Waterland 			}
228*5c51f124SMoriah Waterland 			lflag++;
229*5c51f124SMoriah Waterland 			break;
230*5c51f124SMoriah Waterland 
231*5c51f124SMoriah Waterland 		    case 'x':
232*5c51f124SMoriah Waterland 			/* bug # 1081606 */
233*5c51f124SMoriah Waterland 			if (lflag || rflag) {
234*5c51f124SMoriah Waterland 				progerr(gettext(ERR_INCOMP2));
235*5c51f124SMoriah Waterland 				usage();
236*5c51f124SMoriah Waterland 			}
237*5c51f124SMoriah Waterland 			xflag++;
238*5c51f124SMoriah Waterland 			break;
239*5c51f124SMoriah Waterland 
240*5c51f124SMoriah Waterland 		    case 'r':
241*5c51f124SMoriah Waterland 			if (lflag || xflag || Lflag) {
242*5c51f124SMoriah Waterland 				progerr(gettext(ERR_INCOMP0));
243*5c51f124SMoriah Waterland 				usage();
244*5c51f124SMoriah Waterland 			}
245*5c51f124SMoriah Waterland 			rflag++;
246*5c51f124SMoriah Waterland 			break;
247*5c51f124SMoriah Waterland 
248*5c51f124SMoriah Waterland 		    case 'c':
249*5c51f124SMoriah Waterland 			ckcatg[ncatg++] = strtok(optarg, " \t\n, ");
250*5c51f124SMoriah Waterland 			while (ckcatg[ncatg] = strtok(NULL, " \t\n, "))
251*5c51f124SMoriah Waterland 				ncatg++;
252*5c51f124SMoriah Waterland 			break;
253*5c51f124SMoriah Waterland 
254*5c51f124SMoriah Waterland 		/* added for newroot functions */
255*5c51f124SMoriah Waterland 		    case 'R':
256*5c51f124SMoriah Waterland 			if (!set_inst_root(optarg)) {
257*5c51f124SMoriah Waterland 				progerr(gettext(ERR_ROOT_CMD));
258*5c51f124SMoriah Waterland 				exit(1);
259*5c51f124SMoriah Waterland 			}
260*5c51f124SMoriah Waterland 			break;
261*5c51f124SMoriah Waterland 
262*5c51f124SMoriah Waterland 		    default:
263*5c51f124SMoriah Waterland 			usage();
264*5c51f124SMoriah Waterland 		}
265*5c51f124SMoriah Waterland 	}
266*5c51f124SMoriah Waterland 
267*5c51f124SMoriah Waterland 	/*
268*5c51f124SMoriah Waterland 	 * implement the newroot option
269*5c51f124SMoriah Waterland 	 */
270*5c51f124SMoriah Waterland 	set_PKGpaths(get_inst_root());	/* set up /var... directories */
271*5c51f124SMoriah Waterland 
272*5c51f124SMoriah Waterland 	/*
273*5c51f124SMoriah Waterland 	 * Open the install DB, if one exists.
274*5c51f124SMoriah Waterland 	 */
275*5c51f124SMoriah Waterland 
276*5c51f124SMoriah Waterland 	pkg = &argv[optind];
277*5c51f124SMoriah Waterland 	pkgcnt = (argc - optind);
278*5c51f124SMoriah Waterland 
279*5c51f124SMoriah Waterland 	if (pkg[0] && strcmp(pkg[0], "all") == NULL) {
280*5c51f124SMoriah Waterland 		pkgcnt = 0;
281*5c51f124SMoriah Waterland 		pkg[0] = NULL;
282*5c51f124SMoriah Waterland 	}
283*5c51f124SMoriah Waterland 
284*5c51f124SMoriah Waterland 	if (pkgdir == NULL)
285*5c51f124SMoriah Waterland 		pkgdir = get_PKGLOC(); 	/* we need this later */
286*5c51f124SMoriah Waterland 
287*5c51f124SMoriah Waterland 	/* convert device appropriately */
288*5c51f124SMoriah Waterland 	if (pkghead(device))
289*5c51f124SMoriah Waterland 		exit(1);
290*5c51f124SMoriah Waterland 
291*5c51f124SMoriah Waterland 	/*
292*5c51f124SMoriah Waterland 	 * If we are to inspect a spooled package we are only interested in
293*5c51f124SMoriah Waterland 	 * the pkginfo file in the spooled pkg so we skip any Reg 4 DB
294*5c51f124SMoriah Waterland 	 * lookups and use the old algorithm. We have a spooled pkg if
295*5c51f124SMoriah Waterland 	 * device is not NULL.
296*5c51f124SMoriah Waterland 	 */
297*5c51f124SMoriah Waterland 
298*5c51f124SMoriah Waterland 
299*5c51f124SMoriah Waterland 	look_for_installed();
300*5c51f124SMoriah Waterland 
301*5c51f124SMoriah Waterland 	if (lflag && strcmp(pkgdir, get_PKGLOC()) == NULL) {
302*5c51f124SMoriah Waterland 		/* look at contents file */
303*5c51f124SMoriah Waterland 		(void) snprintf(contents, sizeof (contents),
304*5c51f124SMoriah Waterland 		    "%s/contents", get_PKGADM());
305*5c51f124SMoriah Waterland 		rdcontents();
306*5c51f124SMoriah Waterland 
307*5c51f124SMoriah Waterland 	}
308*5c51f124SMoriah Waterland 
309*5c51f124SMoriah Waterland 	/*
310*5c51f124SMoriah Waterland 	 * If we are to inspect a spooled package we are only interested in
311*5c51f124SMoriah Waterland 	 * the pkginfo file in the spooled pkg so we skip any Reg 4 DB
312*5c51f124SMoriah Waterland 	 * lookups and use the old algorithm. We have a spooled pkg if
313*5c51f124SMoriah Waterland 	 * device is not NULL.
314*5c51f124SMoriah Waterland 	 */
315*5c51f124SMoriah Waterland 
316*5c51f124SMoriah Waterland 	report();
317*5c51f124SMoriah Waterland 
318*5c51f124SMoriah Waterland 	(void) pkghead(NULL);
319*5c51f124SMoriah Waterland 
320*5c51f124SMoriah Waterland 	return (errflg ? 1 : 0);
321*5c51f124SMoriah Waterland }
322*5c51f124SMoriah Waterland 
323*5c51f124SMoriah Waterland static void
324*5c51f124SMoriah Waterland report(void)
325*5c51f124SMoriah Waterland {
326*5c51f124SMoriah Waterland 	struct cfstat *dp, *choice;
327*5c51f124SMoriah Waterland 	int	i;
328*5c51f124SMoriah Waterland 	int	pkgLgth = 0;
329*5c51f124SMoriah Waterland 	int	longestPkg = 0;
330*5c51f124SMoriah Waterland 	boolean_t output = B_FALSE;
331*5c51f124SMoriah Waterland 
332*5c51f124SMoriah Waterland 	for (;;) {
333*5c51f124SMoriah Waterland 		choice = (struct cfstat *)0;
334*5c51f124SMoriah Waterland 		for (dp = data; dp; dp = dp->next) {
335*5c51f124SMoriah Waterland 			pkgLgth = strlen(dp->pkginst);
336*5c51f124SMoriah Waterland 			if (pkgLgth > longestPkg)
337*5c51f124SMoriah Waterland 				longestPkg = pkgLgth;
338*5c51f124SMoriah Waterland 		}
339*5c51f124SMoriah Waterland 		for (dp = data; dp; dp = dp->next) {
340*5c51f124SMoriah Waterland 			/* get information about this package */
341*5c51f124SMoriah Waterland 			if (dp->installed < 0)
342*5c51f124SMoriah Waterland 				continue; /* already used */
343*5c51f124SMoriah Waterland 			if (Lflag && pkgcnt) {
344*5c51f124SMoriah Waterland 				choice = dp;
345*5c51f124SMoriah Waterland 				break;
346*5c51f124SMoriah Waterland 			} else if (!choice ||
347*5c51f124SMoriah Waterland 			    (strcmp(choice->pkginst, dp->pkginst) > 0))
348*5c51f124SMoriah Waterland 				choice = dp;
349*5c51f124SMoriah Waterland 		}
350*5c51f124SMoriah Waterland 		if (!choice)
351*5c51f124SMoriah Waterland 			break; /* no more packages */
352*5c51f124SMoriah Waterland 
353*5c51f124SMoriah Waterland 		if (pkginfo(&info, choice->pkginst, ckarch, ckvers)) {
354*5c51f124SMoriah Waterland 			choice->installed = (-1);
355*5c51f124SMoriah Waterland 			continue;
356*5c51f124SMoriah Waterland 		}
357*5c51f124SMoriah Waterland 
358*5c51f124SMoriah Waterland 		/*
359*5c51f124SMoriah Waterland 		 * Confirm that the pkginfo file contains the
360*5c51f124SMoriah Waterland 		 * required information.
361*5c51f124SMoriah Waterland 		 */
362*5c51f124SMoriah Waterland 		if (info.name == NULL || *(info.name) == NULL ||
363*5c51f124SMoriah Waterland 		    info.arch == NULL || *(info.arch) == NULL ||
364*5c51f124SMoriah Waterland 		    info.version == NULL || *(info.version) == NULL ||
365*5c51f124SMoriah Waterland 		    info.catg == NULL || *(info.catg) == NULL) {
366*5c51f124SMoriah Waterland 			progerr(gettext(ERR_BADINFO));
367*5c51f124SMoriah Waterland 			errflg++;
368*5c51f124SMoriah Waterland 			return;
369*5c51f124SMoriah Waterland 		}
370*5c51f124SMoriah Waterland 
371*5c51f124SMoriah Waterland 		/* is it in an appropriate catgory? */
372*5c51f124SMoriah Waterland 		if (iscatg(info.catg)) {
373*5c51f124SMoriah Waterland 			choice->installed = (-1);
374*5c51f124SMoriah Waterland 			continue;
375*5c51f124SMoriah Waterland 		}
376*5c51f124SMoriah Waterland 
377*5c51f124SMoriah Waterland 		if (!pflag &&
378*5c51f124SMoriah Waterland 			/* don't include partially installed packages */
379*5c51f124SMoriah Waterland 			(choice->partial || (info.status == PI_PARTIAL) ||
380*5c51f124SMoriah Waterland 				(info.status == PI_UNKNOWN))) {
381*5c51f124SMoriah Waterland 			choice->installed = (-1);
382*5c51f124SMoriah Waterland 			continue;
383*5c51f124SMoriah Waterland 		}
384*5c51f124SMoriah Waterland 
385*5c51f124SMoriah Waterland 		if (Nflag && (info.status == PI_PRESVR4)) {
386*5c51f124SMoriah Waterland 			/* don't include preSVR4 packages */
387*5c51f124SMoriah Waterland 			choice->installed = (-1);
388*5c51f124SMoriah Waterland 			continue;
389*5c51f124SMoriah Waterland 		}
390*5c51f124SMoriah Waterland 
391*5c51f124SMoriah Waterland 		if (!iflag && ((info.status == PI_INSTALLED) ||
392*5c51f124SMoriah Waterland 		    (info.status == PI_PRESVR4))) {
393*5c51f124SMoriah Waterland 			/* don't include completely installed packages */
394*5c51f124SMoriah Waterland 			choice->installed = (-1);
395*5c51f124SMoriah Waterland 			continue;
396*5c51f124SMoriah Waterland 		}
397*5c51f124SMoriah Waterland 
398*5c51f124SMoriah Waterland 		output = B_TRUE;
399*5c51f124SMoriah Waterland 		dumpinfo(choice, longestPkg);
400*5c51f124SMoriah Waterland 		choice->installed = (-1);
401*5c51f124SMoriah Waterland 		if (pkgcnt) {
402*5c51f124SMoriah Waterland 			i = selectp(choice->pkginst);
403*5c51f124SMoriah Waterland 			if (i >= 0)
404*5c51f124SMoriah Waterland 				pkg[i] = NULL;
405*5c51f124SMoriah Waterland 			else {
406*5c51f124SMoriah Waterland 				if (qflag) {
407*5c51f124SMoriah Waterland 					errflg++;
408*5c51f124SMoriah Waterland 					return;
409*5c51f124SMoriah Waterland 				}
410*5c51f124SMoriah Waterland 			}
411*5c51f124SMoriah Waterland 		}
412*5c51f124SMoriah Waterland 	}
413*5c51f124SMoriah Waterland 
414*5c51f124SMoriah Waterland 	/* If no package matched and no output produced set error flag */
415*5c51f124SMoriah Waterland 	if (!output)
416*5c51f124SMoriah Waterland 		errflg++;
417*5c51f124SMoriah Waterland 
418*5c51f124SMoriah Waterland 	/* verify that each package listed on command line was output */
419*5c51f124SMoriah Waterland 	for (i = 0; i < pkgcnt; ++i) {
420*5c51f124SMoriah Waterland 		if (pkg[i]) {
421*5c51f124SMoriah Waterland 			errflg++;
422*5c51f124SMoriah Waterland 			if (!qflag) {
423*5c51f124SMoriah Waterland 				if (pflag == 1)
424*5c51f124SMoriah Waterland 					logerr(gettext(ERR_NOPINFO), pkg[i]);
425*5c51f124SMoriah Waterland 				else
426*5c51f124SMoriah Waterland 					logerr(gettext(ERR_NOINFO), pkg[i]);
427*5c51f124SMoriah Waterland 			} else
428*5c51f124SMoriah Waterland 				return;
429*5c51f124SMoriah Waterland 		}
430*5c51f124SMoriah Waterland 	}
431*5c51f124SMoriah Waterland 	(void) pkginfo(&info, NULL); /* free up all memory and open fds */
432*5c51f124SMoriah Waterland }
433*5c51f124SMoriah Waterland 
434*5c51f124SMoriah Waterland static void
435*5c51f124SMoriah Waterland dumpinfo(struct cfstat *dp, int pkgLngth)
436*5c51f124SMoriah Waterland {
437*5c51f124SMoriah Waterland 	register int i;
438*5c51f124SMoriah Waterland 	char	*pt;
439*5c51f124SMoriah Waterland 	char	category[128];
440*5c51f124SMoriah Waterland 
441*5c51f124SMoriah Waterland 	if (qflag) {
442*5c51f124SMoriah Waterland 		return; /* print nothing */
443*5c51f124SMoriah Waterland 	}
444*5c51f124SMoriah Waterland 
445*5c51f124SMoriah Waterland 	if (rflag) {
446*5c51f124SMoriah Waterland 		(void) puts((info.basedir) ? info.basedir : "none");
447*5c51f124SMoriah Waterland 		return;
448*5c51f124SMoriah Waterland 	}
449*5c51f124SMoriah Waterland 
450*5c51f124SMoriah Waterland 	if (Lflag) {
451*5c51f124SMoriah Waterland 		(void) puts(info.pkginst);
452*5c51f124SMoriah Waterland 		return;
453*5c51f124SMoriah Waterland 	} else if (xflag) {
454*5c51f124SMoriah Waterland 		(void) printf(XFMT, pkgLngth, pkgLngth, info.pkginst,
455*5c51f124SMoriah Waterland 		    info.name);
456*5c51f124SMoriah Waterland 
457*5c51f124SMoriah Waterland 		if (info.arch || info.version) {
458*5c51f124SMoriah Waterland 			(void) printf(CFMT, pkgLngth, pkgLngth, "");
459*5c51f124SMoriah Waterland 			if (info.arch)
460*5c51f124SMoriah Waterland 				(void) printf("(%s) ", info.arch);
461*5c51f124SMoriah Waterland 			if (info.version)
462*5c51f124SMoriah Waterland 				(void) printf("%s", info.version);
463*5c51f124SMoriah Waterland 			(void) printf("\n");
464*5c51f124SMoriah Waterland 		}
465*5c51f124SMoriah Waterland 		return;
466*5c51f124SMoriah Waterland 	} else if (!lflag) {
467*5c51f124SMoriah Waterland 		if (info.catg) {
468*5c51f124SMoriah Waterland 			(void) sscanf(info.catg, "%[^, \t\n]", category);
469*5c51f124SMoriah Waterland 		} else if (info.status == PI_PRESVR4) {
470*5c51f124SMoriah Waterland 			(void) strcpy(category, "preSVR4");
471*5c51f124SMoriah Waterland 		} else {
472*5c51f124SMoriah Waterland 			(void) strcpy(category, "(unknown)");
473*5c51f124SMoriah Waterland 		}
474*5c51f124SMoriah Waterland 		(void) printf(SFMT, category, pkgLngth, pkgLngth, info.pkginst,
475*5c51f124SMoriah Waterland 		    info.name);
476*5c51f124SMoriah Waterland 		return;
477*5c51f124SMoriah Waterland 	}
478*5c51f124SMoriah Waterland 	if (info.pkginst)
479*5c51f124SMoriah Waterland 		(void) printf(FMT, "PKGINST", info.pkginst);
480*5c51f124SMoriah Waterland 	if (info.name)
481*5c51f124SMoriah Waterland 		(void) printf(FMT, "NAME", info.name);
482*5c51f124SMoriah Waterland 	if (lflag && info.catg)
483*5c51f124SMoriah Waterland 		(void) printf(FMT, "CATEGORY", info.catg);
484*5c51f124SMoriah Waterland 	if (lflag && info.arch)
485*5c51f124SMoriah Waterland 		(void) printf(FMT, "ARCH", info.arch);
486*5c51f124SMoriah Waterland 	if (info.version)
487*5c51f124SMoriah Waterland 		(void) printf(FMT, "VERSION", info.version);
488*5c51f124SMoriah Waterland 	if (info.basedir)
489*5c51f124SMoriah Waterland 		(void) printf(FMT, "BASEDIR", info.basedir);
490*5c51f124SMoriah Waterland 	if (info.vendor)
491*5c51f124SMoriah Waterland 		(void) printf(FMT, "VENDOR", info.vendor);
492*5c51f124SMoriah Waterland 
493*5c51f124SMoriah Waterland 	if (info.status == PI_PRESVR4)
494*5c51f124SMoriah Waterland 		(void) printf(FMT, "STATUS", "preSVR4");
495*5c51f124SMoriah Waterland 	else {
496*5c51f124SMoriah Waterland 		for (i = 0; parmlst[i]; ++i) {
497*5c51f124SMoriah Waterland 			if ((pt = pkgparam(info.pkginst, parmlst[i])) != NULL &&
498*5c51f124SMoriah Waterland 			    *pt)
499*5c51f124SMoriah Waterland 				(void) printf(FMT, parmlst[i], pt);
500*5c51f124SMoriah Waterland 		}
501*5c51f124SMoriah Waterland 		if (info.status == PI_SPOOLED)
502*5c51f124SMoriah Waterland 			(void) printf(FMT, "STATUS", gettext("spooled"));
503*5c51f124SMoriah Waterland 		else if (info.status == PI_PARTIAL)
504*5c51f124SMoriah Waterland 			(void) printf(FMT, "STATUS",
505*5c51f124SMoriah Waterland 			    gettext("partially installed"));
506*5c51f124SMoriah Waterland 		else if (info.status == PI_INSTALLED)
507*5c51f124SMoriah Waterland 			(void) printf(FMT, "STATUS",
508*5c51f124SMoriah Waterland 			    gettext("completely installed"));
509*5c51f124SMoriah Waterland 		else
510*5c51f124SMoriah Waterland 			(void) printf(FMT, "STATUS", gettext("(unknown)"));
511*5c51f124SMoriah Waterland 	}
512*5c51f124SMoriah Waterland 	(void) pkgparam(NULL, NULL);
513*5c51f124SMoriah Waterland 
514*5c51f124SMoriah Waterland 	if (!lflag) {
515*5c51f124SMoriah Waterland 		(void) putchar('\n');
516*5c51f124SMoriah Waterland 		return;
517*5c51f124SMoriah Waterland 	}
518*5c51f124SMoriah Waterland 
519*5c51f124SMoriah Waterland 	if (info.status != PI_PRESVR4) {
520*5c51f124SMoriah Waterland 		if (strcmp(pkgdir, get_PKGLOC()))
521*5c51f124SMoriah Waterland 			getinfo(dp);
522*5c51f124SMoriah Waterland 
523*5c51f124SMoriah Waterland 		if (dp->spooled)
524*5c51f124SMoriah Waterland 			(void) printf(
525*5c51f124SMoriah Waterland 			    gettext("%10s:  %7ld spooled pathnames\n"),
526*5c51f124SMoriah Waterland 			    "FILES", dp->spooled);
527*5c51f124SMoriah Waterland 		if (dp->installed)
528*5c51f124SMoriah Waterland 			(void) printf(
529*5c51f124SMoriah Waterland 			    gettext("%10s:  %7ld installed pathnames\n"),
530*5c51f124SMoriah Waterland 			    "FILES", dp->installed);
531*5c51f124SMoriah Waterland 		if (dp->partial)
532*5c51f124SMoriah Waterland 			(void) printf(
533*5c51f124SMoriah Waterland 			    gettext("%20d partially installed pathnames\n"),
534*5c51f124SMoriah Waterland 			    dp->partial);
535*5c51f124SMoriah Waterland 		if (dp->shared)
536*5c51f124SMoriah Waterland 			(void) printf(gettext("%20d shared pathnames\n"),
537*5c51f124SMoriah Waterland 				dp->shared);
538*5c51f124SMoriah Waterland 		if (dp->link)
539*5c51f124SMoriah Waterland 			(void) printf(gettext("%20d linked files\n"), dp->link);
540*5c51f124SMoriah Waterland 		if (dp->dirs)
541*5c51f124SMoriah Waterland 			(void) printf(gettext("%20d directories\n"), dp->dirs);
542*5c51f124SMoriah Waterland 		if (dp->exec)
543*5c51f124SMoriah Waterland 			(void) printf(gettext("%20d executables\n"), dp->exec);
544*5c51f124SMoriah Waterland 		if (dp->setuid)
545*5c51f124SMoriah Waterland 			(void) printf(
546*5c51f124SMoriah Waterland 			    gettext("%20d setuid/setgid executables\n"),
547*5c51f124SMoriah Waterland 			    dp->setuid);
548*5c51f124SMoriah Waterland 		if (dp->info)
549*5c51f124SMoriah Waterland 			(void) printf(
550*5c51f124SMoriah Waterland 			    gettext("%20d package information files\n"),
551*5c51f124SMoriah Waterland 			    dp->info+1); /* pkgmap counts! */
552*5c51f124SMoriah Waterland 
553*5c51f124SMoriah Waterland 		if (dp->tblks)
554*5c51f124SMoriah Waterland 			(void) printf(gettext("%20ld blocks used (approx)\n"),
555*5c51f124SMoriah Waterland 				dp->tblks);
556*5c51f124SMoriah Waterland 	}
557*5c51f124SMoriah Waterland 	(void) putchar('\n');
558*5c51f124SMoriah Waterland }
559*5c51f124SMoriah Waterland 
560*5c51f124SMoriah Waterland static struct cfstat *
561*5c51f124SMoriah Waterland fpkg(char *pkginst)
562*5c51f124SMoriah Waterland {
563*5c51f124SMoriah Waterland 	struct cfstat *dp, *last;
564*5c51f124SMoriah Waterland 
565*5c51f124SMoriah Waterland 	dp = data;
566*5c51f124SMoriah Waterland 	last = (struct cfstat *)0;
567*5c51f124SMoriah Waterland 	while (dp) {
568*5c51f124SMoriah Waterland 		if (strcmp(dp->pkginst, pkginst) == NULL)
569*5c51f124SMoriah Waterland 			return (dp);
570*5c51f124SMoriah Waterland 		last = dp;
571*5c51f124SMoriah Waterland 		dp = dp->next;
572*5c51f124SMoriah Waterland 	}
573*5c51f124SMoriah Waterland 	dp = (struct cfstat *)calloc(1, sizeof (struct cfstat));
574*5c51f124SMoriah Waterland 	if (!dp) {
575*5c51f124SMoriah Waterland 		progerr(gettext("no memory, malloc() failed"));
576*5c51f124SMoriah Waterland 		exit(1);
577*5c51f124SMoriah Waterland 	}
578*5c51f124SMoriah Waterland 	if (!last)
579*5c51f124SMoriah Waterland 		data = dp;
580*5c51f124SMoriah Waterland 	else
581*5c51f124SMoriah Waterland 		last->next = dp; /* link list */
582*5c51f124SMoriah Waterland 	(void) strcpy(dp->pkginst, pkginst);
583*5c51f124SMoriah Waterland 	return (dp);
584*5c51f124SMoriah Waterland }
585*5c51f124SMoriah Waterland 
586*5c51f124SMoriah Waterland #define	SEPAR	','
587*5c51f124SMoriah Waterland 
588*5c51f124SMoriah Waterland static int
589*5c51f124SMoriah Waterland iscatg(char *list)
590*5c51f124SMoriah Waterland {
591*5c51f124SMoriah Waterland 	register int i;
592*5c51f124SMoriah Waterland 	register char *pt;
593*5c51f124SMoriah Waterland 	int	match;
594*5c51f124SMoriah Waterland 
595*5c51f124SMoriah Waterland 	if (!ckcatg[0])
596*5c51f124SMoriah Waterland 		return (0); /* no specification implies all packages */
597*5c51f124SMoriah Waterland 	if (info.status == PI_PRESVR4) {
598*5c51f124SMoriah Waterland 		for (i = 0; ckcatg[i]; /* void */) {
599*5c51f124SMoriah Waterland 			if (strcmp(ckcatg[i++], "preSVR4") == NULL)
600*5c51f124SMoriah Waterland 				return (0);
601*5c51f124SMoriah Waterland 		}
602*5c51f124SMoriah Waterland 		return (1);
603*5c51f124SMoriah Waterland 	}
604*5c51f124SMoriah Waterland 	if (!list)
605*5c51f124SMoriah Waterland 		return (1); /* no category specified in pkginfo is a bug */
606*5c51f124SMoriah Waterland 
607*5c51f124SMoriah Waterland 	match = 0;
608*5c51f124SMoriah Waterland 	do {
609*5c51f124SMoriah Waterland 		if (pt = strchr(list, ','))
610*5c51f124SMoriah Waterland 			*pt = '\0';
611*5c51f124SMoriah Waterland 
612*5c51f124SMoriah Waterland 		for (i = 0; ckcatg[i]; /* void */) {
613*5c51f124SMoriah Waterland 			/* bug id 1081607 */
614*5c51f124SMoriah Waterland 			if (!strcasecmp(list, ckcatg[i++])) {
615*5c51f124SMoriah Waterland 				match++;
616*5c51f124SMoriah Waterland 				break;
617*5c51f124SMoriah Waterland 			}
618*5c51f124SMoriah Waterland 		}
619*5c51f124SMoriah Waterland 
620*5c51f124SMoriah Waterland 		if (pt)
621*5c51f124SMoriah Waterland 			*pt++ = ',';
622*5c51f124SMoriah Waterland 		if (match)
623*5c51f124SMoriah Waterland 			return (0);
624*5c51f124SMoriah Waterland 		list = pt; /* points to next one */
625*5c51f124SMoriah Waterland 	} while (pt);
626*5c51f124SMoriah Waterland 	return (1);
627*5c51f124SMoriah Waterland }
628*5c51f124SMoriah Waterland 
629*5c51f124SMoriah Waterland static void
630*5c51f124SMoriah Waterland look_for_installed(void)
631*5c51f124SMoriah Waterland {
632*5c51f124SMoriah Waterland 	struct dirent *drp;
633*5c51f124SMoriah Waterland 	struct stat	status;
634*5c51f124SMoriah Waterland 	DIR	*dirfp;
635*5c51f124SMoriah Waterland 	char	path[PATH_MAX];
636*5c51f124SMoriah Waterland 	int	n;
637*5c51f124SMoriah Waterland 
638*5c51f124SMoriah Waterland 	if (strcmp(pkgdir, get_PKGLOC()) == NULL &&
639*5c51f124SMoriah Waterland 	    (dirfp = opendir(get_PKGOLD()))) {
640*5c51f124SMoriah Waterland 		while (drp = readdir(dirfp)) {
641*5c51f124SMoriah Waterland 			if (drp->d_name[0] == '.')
642*5c51f124SMoriah Waterland 				continue;
643*5c51f124SMoriah Waterland 			n = strlen(drp->d_name);
644*5c51f124SMoriah Waterland 			if ((n > 5) &&
645*5c51f124SMoriah Waterland 			    strcmp(&drp->d_name[n-5], ".name") == NULL) {
646*5c51f124SMoriah Waterland 				(void) snprintf(path, sizeof (path),
647*5c51f124SMoriah Waterland 				    "%s/%s", get_PKGOLD(), drp->d_name);
648*5c51f124SMoriah Waterland 				if (lstat(path, &status))
649*5c51f124SMoriah Waterland 					continue;
650*5c51f124SMoriah Waterland 				if ((status.st_mode & S_IFMT) != S_IFREG)
651*5c51f124SMoriah Waterland 					continue;
652*5c51f124SMoriah Waterland 				drp->d_name[n-5] = '\0';
653*5c51f124SMoriah Waterland 				if (!pkgcnt || (selectp(drp->d_name) >= 0))
654*5c51f124SMoriah Waterland 					(void) fpkg(drp->d_name);
655*5c51f124SMoriah Waterland 			}
656*5c51f124SMoriah Waterland 		}
657*5c51f124SMoriah Waterland 		(void) closedir(dirfp);
658*5c51f124SMoriah Waterland 	}
659*5c51f124SMoriah Waterland 
660*5c51f124SMoriah Waterland 	if ((dirfp = opendir(pkgdir)) == NULL)
661*5c51f124SMoriah Waterland 		return;
662*5c51f124SMoriah Waterland 
663*5c51f124SMoriah Waterland 	while (drp = readdir(dirfp)) {
664*5c51f124SMoriah Waterland 		if (drp->d_name[0] == '.')
665*5c51f124SMoriah Waterland 			continue;
666*5c51f124SMoriah Waterland 
667*5c51f124SMoriah Waterland 		if (pkgcnt && (selectp(drp->d_name) < 0))
668*5c51f124SMoriah Waterland 			continue;
669*5c51f124SMoriah Waterland 
670*5c51f124SMoriah Waterland 		if (!pkginfofind(path, pkgdir, drp->d_name))
671*5c51f124SMoriah Waterland 			continue; /* doesn't appear to be a package */
672*5c51f124SMoriah Waterland 
673*5c51f124SMoriah Waterland 		(void) fpkg(drp->d_name);
674*5c51f124SMoriah Waterland 	}
675*5c51f124SMoriah Waterland 	(void) closedir(dirfp);
676*5c51f124SMoriah Waterland }
677*5c51f124SMoriah Waterland 
678*5c51f124SMoriah Waterland static int
679*5c51f124SMoriah Waterland selectp(char *p)
680*5c51f124SMoriah Waterland {
681*5c51f124SMoriah Waterland 	register int i;
682*5c51f124SMoriah Waterland 
683*5c51f124SMoriah Waterland 	for (i = 0; i < pkgcnt; ++i) {
684*5c51f124SMoriah Waterland 		if (pkg[i] && pkgnmchk(p, pkg[i], 1) == 0)
685*5c51f124SMoriah Waterland 			return (i);
686*5c51f124SMoriah Waterland 	}
687*5c51f124SMoriah Waterland 	return (-1);
688*5c51f124SMoriah Waterland }
689*5c51f124SMoriah Waterland 
690*5c51f124SMoriah Waterland static void
691*5c51f124SMoriah Waterland rdcontents(void)
692*5c51f124SMoriah Waterland {
693*5c51f124SMoriah Waterland 	VFP_T		*vfp;
694*5c51f124SMoriah Waterland 	struct cfstat	*dp;
695*5c51f124SMoriah Waterland 	struct pinfo	*pinfo;
696*5c51f124SMoriah Waterland 	int		n;
697*5c51f124SMoriah Waterland 
698*5c51f124SMoriah Waterland 	if (vfpOpen(&vfp, contents, "r", VFP_NEEDNOW) != 0) {
699*5c51f124SMoriah Waterland 		progerr(gettext("unable to open \"%s\" for reading"), contents);
700*5c51f124SMoriah Waterland 		exit(1);
701*5c51f124SMoriah Waterland 	}
702*5c51f124SMoriah Waterland 
703*5c51f124SMoriah Waterland 	/* check the contents file to look for referenced packages */
704*5c51f124SMoriah Waterland 	while ((n = srchcfile(&entry, "*", vfp, (VFP_T *)NULL)) > 0) {
705*5c51f124SMoriah Waterland 		for (pinfo = entry.pinfo; pinfo; pinfo = pinfo->next) {
706*5c51f124SMoriah Waterland 			/* see if entry is used by indicated packaged */
707*5c51f124SMoriah Waterland 			if (pkgcnt && (selectp(pinfo->pkg) < 0))
708*5c51f124SMoriah Waterland 				continue;
709*5c51f124SMoriah Waterland 
710*5c51f124SMoriah Waterland 			dp = fpkg(pinfo->pkg);
711*5c51f124SMoriah Waterland 			pkgusage(dp, &entry);
712*5c51f124SMoriah Waterland 
713*5c51f124SMoriah Waterland 			if (entry.npkgs > 1)
714*5c51f124SMoriah Waterland 				dp->shared++;
715*5c51f124SMoriah Waterland 
716*5c51f124SMoriah Waterland 			/*
717*5c51f124SMoriah Waterland 			 * Only objects specifically tagged with '!' event
718*5c51f124SMoriah Waterland 			 * character are considered "partial", everything
719*5c51f124SMoriah Waterland 			 * else is considered "installed" (even server
720*5c51f124SMoriah Waterland 			 * objects).
721*5c51f124SMoriah Waterland 			 */
722*5c51f124SMoriah Waterland 			switch (pinfo->status) {
723*5c51f124SMoriah Waterland 			case '!' :
724*5c51f124SMoriah Waterland 				dp->partial++;
725*5c51f124SMoriah Waterland 				break;
726*5c51f124SMoriah Waterland 			default :
727*5c51f124SMoriah Waterland 				dp->installed++;
728*5c51f124SMoriah Waterland 				break;
729*5c51f124SMoriah Waterland 			}
730*5c51f124SMoriah Waterland 		}
731*5c51f124SMoriah Waterland 	}
732*5c51f124SMoriah Waterland 	if (n < 0) {
733*5c51f124SMoriah Waterland 		char	*errstr = getErrstr();
734*5c51f124SMoriah Waterland 		progerr(gettext("bad entry read in contents file"));
735*5c51f124SMoriah Waterland 		logerr(gettext("pathname: %s"),
736*5c51f124SMoriah Waterland 		    (entry.path && *entry.path) ? entry.path : "Unknown");
737*5c51f124SMoriah Waterland 		logerr(gettext("problem: %s"),
738*5c51f124SMoriah Waterland 		    (errstr && *errstr) ? errstr : "Unknown");
739*5c51f124SMoriah Waterland 		exit(1);
740*5c51f124SMoriah Waterland 	}
741*5c51f124SMoriah Waterland 
742*5c51f124SMoriah Waterland 	(void) vfpClose(&vfp);
743*5c51f124SMoriah Waterland }
744*5c51f124SMoriah Waterland 
745*5c51f124SMoriah Waterland static void
746*5c51f124SMoriah Waterland getinfo(struct cfstat *dp)
747*5c51f124SMoriah Waterland {
748*5c51f124SMoriah Waterland 	int		n;
749*5c51f124SMoriah Waterland 	char		pkgmap[MAXPATHLEN];
750*5c51f124SMoriah Waterland 	VFP_T		*vfp;
751*5c51f124SMoriah Waterland 
752*5c51f124SMoriah Waterland 	(void) snprintf(pkgmap, sizeof (pkgmap),
753*5c51f124SMoriah Waterland 			"%s/%s/pkgmap", pkgdir, dp->pkginst);
754*5c51f124SMoriah Waterland 
755*5c51f124SMoriah Waterland 	if (vfpOpen(&vfp, pkgmap, "r", VFP_NEEDNOW) != 0) {
756*5c51f124SMoriah Waterland 		progerr(gettext("unable open \"%s\" for reading"), pkgmap);
757*5c51f124SMoriah Waterland 		exit(1);
758*5c51f124SMoriah Waterland 	}
759*5c51f124SMoriah Waterland 
760*5c51f124SMoriah Waterland 	dp->spooled = 1; /* pkgmap counts! */
761*5c51f124SMoriah Waterland 
762*5c51f124SMoriah Waterland 	while ((n = gpkgmapvfp(&entry, vfp)) > 0) {
763*5c51f124SMoriah Waterland 		dp->spooled++;
764*5c51f124SMoriah Waterland 		pkgusage(dp, &entry);
765*5c51f124SMoriah Waterland 	}
766*5c51f124SMoriah Waterland 
767*5c51f124SMoriah Waterland 	if (n < 0) {
768*5c51f124SMoriah Waterland 		char	*errstr = getErrstr();
769*5c51f124SMoriah Waterland 		progerr(gettext("bad entry read in pkgmap file"));
770*5c51f124SMoriah Waterland 		logerr(gettext("pathname: %s"),
771*5c51f124SMoriah Waterland 		    (entry.path && *entry.path) ? entry.path : "Unknown");
772*5c51f124SMoriah Waterland 		logerr(gettext("problem: %s"),
773*5c51f124SMoriah Waterland 		    (errstr && *errstr) ? errstr : "Unknown");
774*5c51f124SMoriah Waterland 		exit(1);
775*5c51f124SMoriah Waterland 	}
776*5c51f124SMoriah Waterland 
777*5c51f124SMoriah Waterland 	(void) vfpClose(&vfp);
778*5c51f124SMoriah Waterland }
779*5c51f124SMoriah Waterland 
780*5c51f124SMoriah Waterland static void
781*5c51f124SMoriah Waterland pkgusage(struct cfstat *dp, struct cfent *pentry)
782*5c51f124SMoriah Waterland {
783*5c51f124SMoriah Waterland 	if (pentry->ftype == 'i') {
784*5c51f124SMoriah Waterland 		dp->info++;
785*5c51f124SMoriah Waterland 		return;
786*5c51f124SMoriah Waterland 	} else if (pentry->ftype == 'l') {
787*5c51f124SMoriah Waterland 		dp->link++;
788*5c51f124SMoriah Waterland 	} else {
789*5c51f124SMoriah Waterland 		if ((pentry->ftype == 'd') || (pentry->ftype == 'x'))
790*5c51f124SMoriah Waterland 			dp->dirs++;
791*5c51f124SMoriah Waterland 
792*5c51f124SMoriah Waterland 		/* Only collect mode stats if they would be meaningful. */
793*5c51f124SMoriah Waterland 		if (pentry->ainfo.mode != BADMODE) {
794*5c51f124SMoriah Waterland 			if (pentry->ainfo.mode & 06000)
795*5c51f124SMoriah Waterland 				dp->setuid++;
796*5c51f124SMoriah Waterland 			if (!strchr("dxcbp", pentry->ftype) &&
797*5c51f124SMoriah Waterland 			(pentry->ainfo.mode & 0111))
798*5c51f124SMoriah Waterland 				dp->exec++;
799*5c51f124SMoriah Waterland 		}
800*5c51f124SMoriah Waterland 	}
801*5c51f124SMoriah Waterland 
802*5c51f124SMoriah Waterland 	if (strchr("ifve", pentry->ftype))
803*5c51f124SMoriah Waterland 		dp->tblks += nblock(pentry->cinfo.size);
804*5c51f124SMoriah Waterland }
805*5c51f124SMoriah Waterland 
806*5c51f124SMoriah Waterland static void
807*5c51f124SMoriah Waterland usage(void)
808*5c51f124SMoriah Waterland {
809*5c51f124SMoriah Waterland 	char *prog = get_prog_name();
810*5c51f124SMoriah Waterland 
811*5c51f124SMoriah Waterland 	/* bug # 1081606 */
812*5c51f124SMoriah Waterland 	(void) fprintf(stderr, gettext(ERR_USAGE), prog, prog);
813*5c51f124SMoriah Waterland 
814*5c51f124SMoriah Waterland 	exit(1);
815*5c51f124SMoriah Waterland }
816*5c51f124SMoriah Waterland 
817*5c51f124SMoriah Waterland void
818*5c51f124SMoriah Waterland quit(int retval)
819*5c51f124SMoriah Waterland {
820*5c51f124SMoriah Waterland 	exit(retval);
821*5c51f124SMoriah Waterland }
822