#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include <stdlib.h>
#include <valtools.h>
#include "pkginfo.h"
#include "pkglib.h"
#include "pkglibmsgs.h"
#include "pkgstrct.h"
#include "pkglocale.h"
extern char *pkgdir;
extern CKMENU *allocmenu(char *label, int attr);
extern int ckitem(CKMENU *menup, char *item[], short max, char *defstr,
char *error, char *help, char *prompt);
extern int pkgnmchk(register char *pkg, register char *spec,
int presvr4flg);
extern int fpkginfo(struct pkginfo *info, char *pkginst);
extern char *fpkginst(char *pkg, ...);
extern int setinvis(CKMENU *menup, char *choice);
extern int setitem(CKMENU *menup, char *choice);
#define CMDSIZ 512
#define LSIZE 256
#define MAXSIZE 128
#define MALLOCSIZ 128
#define MAX_CAT_ARGS 64
#define MAX_CAT_LEN 16
static int cont_in_list = 0;
static char cont_keyword[PKGSIZ+1];
static char **
next_n(int *n, char **nwpkg)
{
int loc_n = *n;
if ((++loc_n % MALLOCSIZ) == 0) {
nwpkg = (char **)realloc(nwpkg,
(loc_n+MALLOCSIZ) * sizeof (char **));
if (nwpkg == NULL) {
progerr(pkg_gt(ERR_MEMORY), errno);
errno = ENOMEM;
return (NULL);
}
}
*n = loc_n;
return (nwpkg);
}
void
pkglist_cont(char *keyword)
{
cont_in_list = 1;
(void) strncpy(cont_keyword, keyword, PKGSIZ);
}
char **
gpkglist(char *dir, char **pkg, char **catg)
{
struct _choice_ *chp;
struct pkginfo info;
char *inst;
CKMENU *menup;
char temp[LSIZE];
char *savedir, **nwpkg;
int i, n;
savedir = pkgdir;
pkgdir = dir;
info.pkginst = NULL;
if (pkginfo(&info, "all", NULL, NULL)) {
errno = ENOPKG;
pkgdir = savedir;
return (NULL);
}
if (pkg[0] == NULL && !cont_in_list) {
menup = allocmenu(pkg_gt(HEADER), CKALPHA);
if (setinvis(menup, "all")) {
errno = EFAULT;
return (NULL);
}
do {
if (!info.pkginst || !info.name || !info.arch ||
!info.version)
continue;
(void) snprintf(temp, sizeof (temp),
"%s %s\n(%s) %s", info.pkginst,
info.name, info.arch, info.version);
if (setitem(menup, temp)) {
errno = EFAULT;
return (NULL);
}
} while (pkginfo(&info, "all", NULL, NULL) == 0);
(void) pkginfo(&info, NULL, NULL, NULL);
pkgdir = savedir;
nwpkg = (char **)calloc(MALLOCSIZ, sizeof (char **));
n = ckitem(menup, nwpkg, MALLOCSIZ, "all", NULL,
pkg_gt(HELP), pkg_gt(PROMPT));
if (n) {
free(nwpkg);
errno = ((n == 3) ? EINTR : EFAULT);
pkgdir = savedir;
return (NULL);
}
if (strcmp(nwpkg[0], "all") == 0) {
chp = menup->choice;
for (n = 0; chp; ) {
nwpkg[n] = strdup(chp->token);
nwpkg = next_n(&n, nwpkg);
chp = chp->next;
nwpkg[n] = NULL;
}
} else {
for (n = 0; nwpkg[n]; n++)
nwpkg[n] = strdup(nwpkg[n]);
}
(void) setitem(menup, NULL);
free(menup);
pkgdir = savedir;
return (nwpkg);
}
(void) pkginfo(&info, NULL, NULL, NULL);
nwpkg = (char **)calloc(MALLOCSIZ, sizeof (char **));
i = n = 0;
do {
if (cont_in_list) {
nwpkg[n] = strdup(cont_keyword);
nwpkg = next_n(&n, nwpkg);
nwpkg[n] = NULL;
cont_in_list = 0;
if (pkg[0] == NULL) {
break;
}
} else if (pkgnmchk(pkg[i], "all", 1)) {
(void) fpkginst(NULL);
inst = fpkginst(pkg[i], NULL, NULL);
if (inst == NULL) {
progerr(pkg_gt(ERR_NOPKG), pkg[i]);
free(nwpkg);
nwpkg = NULL;
errno = ESRCH;
break;
}
do {
if (catg != NULL) {
pkginfo(&info, inst, NULL, NULL);
if (!is_same_CATEGORY(catg,
info.catg))
continue;
}
nwpkg[n] = strdup(inst);
nwpkg = next_n(&n, nwpkg);
nwpkg[n] = NULL;
} while (inst = fpkginst(pkg[i], NULL, NULL));
} else {
if (fpkginfo(&info, pkg[i])) {
progerr(pkg_gt(ERR_NOPKG), pkg[i]);
free(nwpkg);
nwpkg = NULL;
errno = ESRCH;
break;
}
nwpkg[n] = strdup(pkg[i]);
nwpkg = next_n(&n, nwpkg);
nwpkg[n] = NULL;
}
} while (pkg[++i]);
(void) fpkginst(NULL);
(void) fpkginfo(&info, NULL);
pkgdir = savedir;
if (catg != NULL) {
if (nwpkg[0] == NULL) {
free(nwpkg);
return (NULL);
}
}
return (nwpkg);
}
int
is_not_valid_category(char **category, char *progname)
{
if (strcasecmp(progname, "pkgrm") == 0) {
if (is_same_CATEGORY(category, "system"))
return (1);
}
return (0);
}
int
is_not_valid_length(char **category)
{
int i;
for (i = 0; category[i] != NULL; i++) {
if (strlen(category[i]) > MAX_CAT_LEN)
return (1);
}
return (0);
}
int
is_same_CATEGORY(char **category, char *persistent_category)
{
int i, j, n = 0;
char *pers_catg, **pers_catgs;
pers_catg = strdup(persistent_category);
pers_catgs = (char **)calloc(MAX_CAT_LEN, sizeof (char **));
pers_catgs[n++] = strtok(pers_catg, " \t\n, ");
while (pers_catgs[n] = strtok(NULL, " \t\n, "))
n++;
for (i = 0; category[i] != NULL; i++) {
for (j = 0; j < n; j++) {
if (strcasecmp(category[i], pers_catgs[j]) == 0) {
return (1);
}
}
}
return (0);
}
char **
get_categories(char *catg_arg)
{
int n = 0;
char *tmp_catg;
char **catgs;
tmp_catg = strdup(catg_arg);
catgs = (char **)calloc(MAX_CAT_LEN, sizeof (char **));
catgs[n++] = strtok(tmp_catg, " \t\n, ");
while (catgs[n] = strtok(NULL, " \t\n, "))
n++;
if (*catgs == NULL)
return (NULL);
else
return (catgs);
}