15c51f124SMoriah Waterland /*
25c51f124SMoriah Waterland  * CDDL HEADER START
35c51f124SMoriah Waterland  *
45c51f124SMoriah Waterland  * The contents of this file are subject to the terms of the
55c51f124SMoriah Waterland  * Common Development and Distribution License (the "License").
65c51f124SMoriah Waterland  * You may not use this file except in compliance with the License.
75c51f124SMoriah Waterland  *
85c51f124SMoriah Waterland  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95c51f124SMoriah Waterland  * or http://www.opensolaris.org/os/licensing.
105c51f124SMoriah Waterland  * See the License for the specific language governing permissions
115c51f124SMoriah Waterland  * and limitations under the License.
125c51f124SMoriah Waterland  *
135c51f124SMoriah Waterland  * When distributing Covered Code, include this CDDL HEADER in each
145c51f124SMoriah Waterland  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155c51f124SMoriah Waterland  * If applicable, add the following below this CDDL HEADER, with the
165c51f124SMoriah Waterland  * fields enclosed by brackets "[]" replaced with your own identifying
175c51f124SMoriah Waterland  * information: Portions Copyright [yyyy] [name of copyright owner]
185c51f124SMoriah Waterland  *
195c51f124SMoriah Waterland  * CDDL HEADER END
205c51f124SMoriah Waterland  */
215c51f124SMoriah Waterland 
225c51f124SMoriah Waterland /*
235c51f124SMoriah Waterland  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
245c51f124SMoriah Waterland  * Use is subject to license terms.
255c51f124SMoriah Waterland  */
265c51f124SMoriah Waterland 
275c51f124SMoriah Waterland /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
285c51f124SMoriah Waterland /* All Rights Reserved */
295c51f124SMoriah Waterland 
305c51f124SMoriah Waterland 
315c51f124SMoriah Waterland 
325c51f124SMoriah Waterland #include <stdio.h>
335c51f124SMoriah Waterland #include <ctype.h>
345c51f124SMoriah Waterland #include <string.h>
355c51f124SMoriah Waterland #include <signal.h>
365c51f124SMoriah Waterland #include <errno.h>
375c51f124SMoriah Waterland #include <stdlib.h>
385c51f124SMoriah Waterland #include <valtools.h>
395c51f124SMoriah Waterland #include "pkginfo.h"
405c51f124SMoriah Waterland #include "pkglib.h"
415c51f124SMoriah Waterland #include "pkglibmsgs.h"
425c51f124SMoriah Waterland #include "pkgstrct.h"
435c51f124SMoriah Waterland #include "pkglocale.h"
445c51f124SMoriah Waterland 
455c51f124SMoriah Waterland extern char	*pkgdir; 		/* WHERE? */
465c51f124SMoriah Waterland 
475c51f124SMoriah Waterland /* libadm.a */
485c51f124SMoriah Waterland extern CKMENU	*allocmenu(char *label, int attr);
495c51f124SMoriah Waterland extern int	ckitem(CKMENU *menup, char *item[], short max, char *defstr,
505c51f124SMoriah Waterland 				char *error, char *help, char *prompt);
515c51f124SMoriah Waterland extern int	pkgnmchk(register char *pkg, register char *spec,
525c51f124SMoriah Waterland 				int presvr4flg);
535c51f124SMoriah Waterland extern int	fpkginfo(struct pkginfo *info, char *pkginst);
545c51f124SMoriah Waterland extern char	*fpkginst(char *pkg, ...);
555c51f124SMoriah Waterland extern int	setinvis(CKMENU *menup, char *choice);
565c51f124SMoriah Waterland extern int	setitem(CKMENU *menup, char *choice);
575c51f124SMoriah Waterland 
585c51f124SMoriah Waterland #define	CMDSIZ			512
595c51f124SMoriah Waterland #define	LSIZE			256
605c51f124SMoriah Waterland #define	MAXSIZE			128
615c51f124SMoriah Waterland #define	MALLOCSIZ		128
625c51f124SMoriah Waterland #define	MAX_CAT_ARGS	64
635c51f124SMoriah Waterland #define	MAX_CAT_LEN		16
645c51f124SMoriah Waterland 
655c51f124SMoriah Waterland static int	cont_in_list = 0;	/* live continuation */
665c51f124SMoriah Waterland static char	cont_keyword[PKGSIZ+1];	/* the continuation keyword */
675c51f124SMoriah Waterland 
685c51f124SMoriah Waterland /*
695c51f124SMoriah Waterland  * Allocate memory for the next package name. This function attempts the
705c51f124SMoriah Waterland  * allocation and if that succeeds, returns a pointer to the new memory
715c51f124SMoriah Waterland  * location and increments "n". Otherwise, it returens NULL and n is
725c51f124SMoriah Waterland  * unchanged.
735c51f124SMoriah Waterland  */
745c51f124SMoriah Waterland static char **
next_n(int * n,char ** nwpkg)755c51f124SMoriah Waterland next_n(int *n, char **nwpkg)
765c51f124SMoriah Waterland {
775c51f124SMoriah Waterland 	int loc_n = *n;
785c51f124SMoriah Waterland 
795c51f124SMoriah Waterland 	if ((++loc_n % MALLOCSIZ) == 0) {
805c51f124SMoriah Waterland 		nwpkg = (char **)realloc(nwpkg,
815c51f124SMoriah Waterland 			(loc_n+MALLOCSIZ) * sizeof (char **));
825c51f124SMoriah Waterland 		if (nwpkg == NULL) {
835c51f124SMoriah Waterland 			progerr(pkg_gt(ERR_MEMORY), errno);
845c51f124SMoriah Waterland 			errno = ENOMEM;
855c51f124SMoriah Waterland 			return (NULL);
865c51f124SMoriah Waterland 		}
875c51f124SMoriah Waterland 	}
885c51f124SMoriah Waterland 
895c51f124SMoriah Waterland 	*n = loc_n;
905c51f124SMoriah Waterland 	return (nwpkg);
915c51f124SMoriah Waterland }
925c51f124SMoriah Waterland 
935c51f124SMoriah Waterland /*
945c51f124SMoriah Waterland  * This informs gpkglist() to put a keyword at the head of the pkglist. This
955c51f124SMoriah Waterland  * was originally intended for live continue, but it may have other
965c51f124SMoriah Waterland  * applications as well.
975c51f124SMoriah Waterland  */
985c51f124SMoriah Waterland void
pkglist_cont(char * keyword)995c51f124SMoriah Waterland pkglist_cont(char *keyword)
1005c51f124SMoriah Waterland {
1015c51f124SMoriah Waterland 	cont_in_list = 1;
1025c51f124SMoriah Waterland 	(void) strncpy(cont_keyword, keyword, PKGSIZ);
1035c51f124SMoriah Waterland }
1045c51f124SMoriah Waterland 
1055c51f124SMoriah Waterland /*
1065c51f124SMoriah Waterland  * This function constructs the list of packages that the user wants managed.
1075c51f124SMoriah Waterland  * It may be a list on the command line, it may be some or all of the
1085c51f124SMoriah Waterland  * packages in a directory or it may be a continuation from a previous
1095c51f124SMoriah Waterland  * dryrun. It may also be a list of pkgs gathered from the CATEGORY parameter
1105c51f124SMoriah Waterland  * in a spooled or installed pkginfo file.
1115c51f124SMoriah Waterland  */
1125c51f124SMoriah Waterland char **
gpkglist(char * dir,char ** pkg,char ** catg)1135c51f124SMoriah Waterland gpkglist(char *dir, char **pkg, char **catg)
1145c51f124SMoriah Waterland {
1155c51f124SMoriah Waterland 	struct _choice_ *chp;
1165c51f124SMoriah Waterland 	struct pkginfo info;
1175c51f124SMoriah Waterland 	char	*inst;
1185c51f124SMoriah Waterland 	CKMENU	*menup;
1195c51f124SMoriah Waterland 	char	temp[LSIZE];
1205c51f124SMoriah Waterland 	char	*savedir, **nwpkg;
1215c51f124SMoriah Waterland 	int	i, n;
1225c51f124SMoriah Waterland 
1235c51f124SMoriah Waterland 	savedir = pkgdir;
1245c51f124SMoriah Waterland 	pkgdir = dir;
1255c51f124SMoriah Waterland 
1265c51f124SMoriah Waterland 	info.pkginst = NULL; /* initialize for memory handling */
1275c51f124SMoriah Waterland 	if (pkginfo(&info, "all", NULL, NULL)) {
1285c51f124SMoriah Waterland 		errno = ENOPKG; /* contains no valid packages */
1295c51f124SMoriah Waterland 		pkgdir = savedir;
1305c51f124SMoriah Waterland 		return (NULL);
1315c51f124SMoriah Waterland 	}
1325c51f124SMoriah Waterland 
1335c51f124SMoriah Waterland 	/*
1345c51f124SMoriah Waterland 	 * If no explicit list was provided and this is not a continuation
1355c51f124SMoriah Waterland 	 * (implying a certain level of direction on the caller's part)
1365c51f124SMoriah Waterland 	 * present a menu of available packages for installation.
1375c51f124SMoriah Waterland 	 */
1385c51f124SMoriah Waterland 	if (pkg[0] == NULL && !cont_in_list) {
1395c51f124SMoriah Waterland 		menup = allocmenu(pkg_gt(HEADER), CKALPHA);
1405c51f124SMoriah Waterland 		if (setinvis(menup, "all")) {
1415c51f124SMoriah Waterland 			errno = EFAULT;
1425c51f124SMoriah Waterland 			return (NULL);
1435c51f124SMoriah Waterland 		}
1445c51f124SMoriah Waterland 		do {
1455c51f124SMoriah Waterland 			/* bug id 1087404 */
1465c51f124SMoriah Waterland 			if (!info.pkginst || !info.name || !info.arch ||
1475c51f124SMoriah Waterland 			    !info.version)
1485c51f124SMoriah Waterland 				continue;
149*4656d474SGarrett D'Amore 			(void) snprintf(temp, sizeof (temp),
150*4656d474SGarrett D'Amore 			    "%s %s\n(%s) %s", info.pkginst,
151*4656d474SGarrett D'Amore 			    info.name, info.arch, info.version);
1525c51f124SMoriah Waterland 			if (setitem(menup, temp)) {
1535c51f124SMoriah Waterland 				errno = EFAULT;
1545c51f124SMoriah Waterland 				return (NULL);
1555c51f124SMoriah Waterland 			}
1565c51f124SMoriah Waterland 		} while (pkginfo(&info, "all", NULL, NULL) == 0);
1575c51f124SMoriah Waterland 		/* clear memory usage by pkginfo */
1585c51f124SMoriah Waterland 		(void) pkginfo(&info, NULL, NULL, NULL);
1595c51f124SMoriah Waterland 		pkgdir = savedir; 	/* restore pkgdir to orig value */
1605c51f124SMoriah Waterland 
1615c51f124SMoriah Waterland 		nwpkg = (char **)calloc(MALLOCSIZ, sizeof (char **));
1625c51f124SMoriah Waterland 		n = ckitem(menup, nwpkg, MALLOCSIZ, "all", NULL,
1635c51f124SMoriah Waterland 		    pkg_gt(HELP), pkg_gt(PROMPT));
1645c51f124SMoriah Waterland 		if (n) {
1655c51f124SMoriah Waterland 			free(nwpkg);
1665c51f124SMoriah Waterland 			errno = ((n == 3) ? EINTR : EFAULT);
1675c51f124SMoriah Waterland 			pkgdir = savedir;
1685c51f124SMoriah Waterland 			return (NULL);
1695c51f124SMoriah Waterland 		}
1705c51f124SMoriah Waterland 		if (strcmp(nwpkg[0], "all") == 0) {
1715c51f124SMoriah Waterland 			chp = menup->choice;
1725c51f124SMoriah Waterland 			for (n = 0; chp; /* void */) {
1735c51f124SMoriah Waterland 				nwpkg[n] = strdup(chp->token);
1745c51f124SMoriah Waterland 				nwpkg = next_n(&n, nwpkg);
1755c51f124SMoriah Waterland 				chp = chp->next;
1765c51f124SMoriah Waterland 				nwpkg[n] = NULL;
1775c51f124SMoriah Waterland 			}
1785c51f124SMoriah Waterland 		} else {
1795c51f124SMoriah Waterland 			for (n = 0; nwpkg[n]; n++)
1805c51f124SMoriah Waterland 				nwpkg[n] = strdup(nwpkg[n]);
1815c51f124SMoriah Waterland 		}
1825c51f124SMoriah Waterland 		(void) setitem(menup, NULL); /* free resources */
1835c51f124SMoriah Waterland 		free(menup);
1845c51f124SMoriah Waterland 		pkgdir = savedir;
1855c51f124SMoriah Waterland 		return (nwpkg);
1865c51f124SMoriah Waterland 	}
1875c51f124SMoriah Waterland 
1885c51f124SMoriah Waterland 	/* clear memory usage by pkginfo */
1895c51f124SMoriah Waterland 	(void) pkginfo(&info, NULL, NULL, NULL);
1905c51f124SMoriah Waterland 
1915c51f124SMoriah Waterland 	nwpkg = (char **)calloc(MALLOCSIZ, sizeof (char **));
1925c51f124SMoriah Waterland 
1935c51f124SMoriah Waterland 	/*
1945c51f124SMoriah Waterland 	 * pkg array contains the instance identifiers to
1955c51f124SMoriah Waterland 	 * be selected, or possibly wildcard definitions
1965c51f124SMoriah Waterland 	 */
1975c51f124SMoriah Waterland 	i = n = 0;
1985c51f124SMoriah Waterland 	do {
1995c51f124SMoriah Waterland 		if (cont_in_list) {	/* This is a live continuation. */
2005c51f124SMoriah Waterland 			nwpkg[n] = strdup(cont_keyword);
2015c51f124SMoriah Waterland 			nwpkg = next_n(&n, nwpkg);
2025c51f124SMoriah Waterland 			nwpkg[n] = NULL;
2035c51f124SMoriah Waterland 			cont_in_list = 0;	/* handled */
2045c51f124SMoriah Waterland 
2055c51f124SMoriah Waterland 			if (pkg[0] == NULL) {	/* It's just a continuation. */
2065c51f124SMoriah Waterland 				break;
2075c51f124SMoriah Waterland 			}
2085c51f124SMoriah Waterland 		} else if (pkgnmchk(pkg[i], "all", 1)) {
2095c51f124SMoriah Waterland 			/* wildcard specification */
2105c51f124SMoriah Waterland 			(void) fpkginst(NULL);
2115c51f124SMoriah Waterland 			inst = fpkginst(pkg[i], NULL, NULL);
2125c51f124SMoriah Waterland 			if (inst == NULL) {
2135c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_NOPKG), pkg[i]);
2145c51f124SMoriah Waterland 				free(nwpkg);
2155c51f124SMoriah Waterland 				nwpkg = NULL;
2165c51f124SMoriah Waterland 				errno = ESRCH;
2175c51f124SMoriah Waterland 				break;
2185c51f124SMoriah Waterland 			}
2195c51f124SMoriah Waterland 			do {
2205c51f124SMoriah Waterland 				if (catg != NULL) {
2215c51f124SMoriah Waterland 					pkginfo(&info, inst, NULL, NULL);
2225c51f124SMoriah Waterland 					if (!is_same_CATEGORY(catg,
2235c51f124SMoriah Waterland 							info.catg))
2245c51f124SMoriah Waterland 						continue;
2255c51f124SMoriah Waterland 				}
2265c51f124SMoriah Waterland 				nwpkg[n] = strdup(inst);
2275c51f124SMoriah Waterland 				nwpkg = next_n(&n, nwpkg);
2285c51f124SMoriah Waterland 				nwpkg[n] = NULL;
2295c51f124SMoriah Waterland 			} while (inst = fpkginst(pkg[i], NULL, NULL));
2305c51f124SMoriah Waterland 		} else {
2315c51f124SMoriah Waterland 			if (fpkginfo(&info, pkg[i])) {
2325c51f124SMoriah Waterland 				progerr(pkg_gt(ERR_NOPKG), pkg[i]);
2335c51f124SMoriah Waterland 				free(nwpkg);
2345c51f124SMoriah Waterland 				nwpkg = NULL;
2355c51f124SMoriah Waterland 				errno = ESRCH;
2365c51f124SMoriah Waterland 				break;
2375c51f124SMoriah Waterland 			}
2385c51f124SMoriah Waterland 			nwpkg[n] = strdup(pkg[i]);
2395c51f124SMoriah Waterland 			nwpkg = next_n(&n, nwpkg);
2405c51f124SMoriah Waterland 			nwpkg[n] = NULL;
2415c51f124SMoriah Waterland 		}
2425c51f124SMoriah Waterland 	} while (pkg[++i]);
2435c51f124SMoriah Waterland 
2445c51f124SMoriah Waterland 	(void) fpkginst(NULL);
2455c51f124SMoriah Waterland 	(void) fpkginfo(&info, NULL);
2465c51f124SMoriah Waterland 	pkgdir = savedir; 	/* restore pkgdir to orig value */
2475c51f124SMoriah Waterland 
2485c51f124SMoriah Waterland 	if (catg != NULL) {
2495c51f124SMoriah Waterland 		if (nwpkg[0] == NULL) {
2505c51f124SMoriah Waterland 
2515c51f124SMoriah Waterland 			/*
2525c51f124SMoriah Waterland 			 * No pkgs in the spooled directory matched the
2535c51f124SMoriah Waterland 			 * category specified by the user.
2545c51f124SMoriah Waterland 			 */
2555c51f124SMoriah Waterland 
2565c51f124SMoriah Waterland 			free(nwpkg);
2575c51f124SMoriah Waterland 			return (NULL);
2585c51f124SMoriah Waterland 		}
2595c51f124SMoriah Waterland 	}
2605c51f124SMoriah Waterland 	return (nwpkg);
2615c51f124SMoriah Waterland }
2625c51f124SMoriah Waterland 
2635c51f124SMoriah Waterland /*
2645c51f124SMoriah Waterland  * Check category passed in on the command line to see if it is valid.
2655c51f124SMoriah Waterland  *
2665c51f124SMoriah Waterland  * returns 0 if the category is valid
2675c51f124SMoriah Waterland  * returns 1 if the category is invalid
2685c51f124SMoriah Waterland  */
2695c51f124SMoriah Waterland 
2705c51f124SMoriah Waterland int
is_not_valid_category(char ** category,char * progname)2715c51f124SMoriah Waterland is_not_valid_category(char **category, char *progname)
2725c51f124SMoriah Waterland {
2735c51f124SMoriah Waterland 	if (strcasecmp(progname, "pkgrm") == 0) {
2745c51f124SMoriah Waterland 		if (is_same_CATEGORY(category, "system"))
2755c51f124SMoriah Waterland 			return (1);
2765c51f124SMoriah Waterland 	}
2775c51f124SMoriah Waterland 
2785c51f124SMoriah Waterland 	return (0);
2795c51f124SMoriah Waterland }
2805c51f124SMoriah Waterland 
2815c51f124SMoriah Waterland /*
2825c51f124SMoriah Waterland  * Check category length
2835c51f124SMoriah Waterland  *
2845c51f124SMoriah Waterland  * returns 0 if the category length is valid
2855c51f124SMoriah Waterland  * returns 1 if a category has length > 16 chars as defined by the SVr4 ABI
2865c51f124SMoriah Waterland  */
2875c51f124SMoriah Waterland 
2885c51f124SMoriah Waterland int
is_not_valid_length(char ** category)2895c51f124SMoriah Waterland is_not_valid_length(char **category)
2905c51f124SMoriah Waterland {
2915c51f124SMoriah Waterland 	int i;
2925c51f124SMoriah Waterland 
2935c51f124SMoriah Waterland 	for (i = 0; category[i] != NULL; i++) {
2945c51f124SMoriah Waterland 		if (strlen(category[i]) > MAX_CAT_LEN)
2955c51f124SMoriah Waterland 			return (1);
2965c51f124SMoriah Waterland 	}
2975c51f124SMoriah Waterland 
2985c51f124SMoriah Waterland 	return (0);
2995c51f124SMoriah Waterland }
3005c51f124SMoriah Waterland 
3015c51f124SMoriah Waterland /*
3025c51f124SMoriah Waterland  * Check category passed in on the command line against the CATEGORY in the
3035c51f124SMoriah Waterland  * spooled or installed packages pkginfo file.
3045c51f124SMoriah Waterland  *
3055c51f124SMoriah Waterland  * returns 0 if categories match
3065c51f124SMoriah Waterland  * returns 1 if categories don't match
3075c51f124SMoriah Waterland  */
3085c51f124SMoriah Waterland 
3095c51f124SMoriah Waterland int
is_same_CATEGORY(char ** category,char * persistent_category)3105c51f124SMoriah Waterland is_same_CATEGORY(char **category, char *persistent_category)
3115c51f124SMoriah Waterland {
3125c51f124SMoriah Waterland 	int i, j, n = 0;
3135c51f124SMoriah Waterland 	char *pers_catg, **pers_catgs;
3145c51f124SMoriah Waterland 
3155c51f124SMoriah Waterland 	pers_catg = strdup(persistent_category);
3165c51f124SMoriah Waterland 
3175c51f124SMoriah Waterland 	pers_catgs = (char **)calloc(MAX_CAT_LEN, sizeof (char **));
3185c51f124SMoriah Waterland 
3195c51f124SMoriah Waterland 	pers_catgs[n++] = strtok(pers_catg, " \t\n, ");
3205c51f124SMoriah Waterland 	while (pers_catgs[n] = strtok(NULL, " \t\n, "))
3215c51f124SMoriah Waterland 		n++;
3225c51f124SMoriah Waterland 
3235c51f124SMoriah Waterland 	for (i = 0; category[i] != NULL; i++) {
3245c51f124SMoriah Waterland 		for (j = 0; j < n; j++) {
3255c51f124SMoriah Waterland 			if (strcasecmp(category[i], pers_catgs[j]) == 0) {
3265c51f124SMoriah Waterland 				return (1);
3275c51f124SMoriah Waterland 			}
3285c51f124SMoriah Waterland 		}
3295c51f124SMoriah Waterland 	}
3305c51f124SMoriah Waterland 
3315c51f124SMoriah Waterland 	return (0);
3325c51f124SMoriah Waterland }
3335c51f124SMoriah Waterland 
3345c51f124SMoriah Waterland /*
3355c51f124SMoriah Waterland  * Given a string of categories, construct a null-terminated array of
3365c51f124SMoriah Waterland  * categories.
3375c51f124SMoriah Waterland  *
3385c51f124SMoriah Waterland  * returns the array of categories or NULL
3395c51f124SMoriah Waterland  */
3405c51f124SMoriah Waterland 
3415c51f124SMoriah Waterland char **
get_categories(char * catg_arg)3425c51f124SMoriah Waterland get_categories(char *catg_arg)
3435c51f124SMoriah Waterland {
3445c51f124SMoriah Waterland 	int n = 0;
3455c51f124SMoriah Waterland 	char *tmp_catg;
3465c51f124SMoriah Waterland 	char **catgs;
3475c51f124SMoriah Waterland 
3485c51f124SMoriah Waterland 	tmp_catg = strdup(catg_arg);
3495c51f124SMoriah Waterland 
3505c51f124SMoriah Waterland 	catgs = (char **)calloc(MAX_CAT_LEN, sizeof (char **));
3515c51f124SMoriah Waterland 
3525c51f124SMoriah Waterland 	catgs[n++] = strtok(tmp_catg, " \t\n, ");
3535c51f124SMoriah Waterland 	while (catgs[n] = strtok(NULL, " \t\n, "))
3545c51f124SMoriah Waterland 		n++;
3555c51f124SMoriah Waterland 
3565c51f124SMoriah Waterland 	if (*catgs == NULL)
3575c51f124SMoriah Waterland 		return (NULL);
3585c51f124SMoriah Waterland 	else
3595c51f124SMoriah Waterland 		return (catgs);
3605c51f124SMoriah Waterland }