#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <unistd.h>
#include <errno.h>
#include <dirent.h>
#include <sys/types.h>
#include <locale.h>
#include <libintl.h>
#include <pkgstrct.h>
#include <pkglocs.h>
#include <assert.h>
#include <instzones_api.h>
#include <pkglib.h>
#include <messages.h>
#include <install.h>
#include <libinst.h>
#include <libadm.h>
extern int npkgs;
extern int ckquit;
extern struct admin adm;
static depckError_t er_ckconflict = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckdepend = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckcfcontent = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckinstance = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckdirs = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckpartinst = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckpartrem = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckpkgdirs = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckpkgfilebad = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckpkgfiles = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckpriv = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckrunlevel = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_cksetuid = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_ckspace = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_newonly = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_prereqinc = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_prereqinst = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_runlevel = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_same = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_overwrite = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_uniq1 = {0, (depckErrorRecord_t *)NULL};
static depckError_t er_attrib = {0, NULL};
static depckError_t er_setuidf = {0, NULL};
static depckError_t er_setgidf = {0, NULL};
static depckError_t er_overwr = {0, NULL};
static char *IMSG_ABADFILE = (char *)NULL;
static char *IMSG_BADFILE = (char *)NULL;
static char *IMSG_CKRUNLVL = (char *)NULL;
static char *IMSG_CNFFAILED = (char *)NULL;
static char *IMSG_DEPEND = (char *)NULL;
static char *IMSG_CFCONTENT = (char *)NULL;
static char *IMSG_INSTANCE = "INSTANCE %s <%s> on %s <%s>";
static char *IMSG_DIRS = (char *)NULL;
static char *IMSG_NEWONLY = (char *)NULL;
static char *IMSG_PARTINST = (char *)NULL;
static char *IMSG_PARTREM = (char *)NULL;
static char *IMSG_PKGDIRS = (char *)NULL;
static char *IMSG_PRENCI = (char *)NULL;
static char *IMSG_PREREQ = (char *)NULL;
static char *IMSG_PRIV = (char *)NULL;
static char *IMSG_RUNLEVEL = (char *)NULL;
static char *IMSG_SAME = (char *)NULL;
static char *IMSG_OVERWRITE = (char *)NULL;
static char *IMSG_UNIQ1 = (char *)NULL;
static char *IMSG_SETUID = (char *)NULL;
static char *IMSG_SPCFAILED = (char *)NULL;
static char *IMSG_ATTRIB;
static char *IMSG_SETUIDF;
static char *IMSG_SETGIDF;
static char *IMSG_OVERWR;
static int ckconflict(char *a_msg, char *a_pkg);
static int ckdepend(char *a_msg, char *a_pkg);
static int ckcfcontent(char *a_msg, char *a_pkg);
static int ckinstance(char *a_msg, char *a_pkg);
static int ckdirs(char *a_msg, char *a_pkg);
static int ckpartinst(char *a_msg, char *a_pkg);
static int ckpartrem(char *a_msg, char *a_pkg);
static int ckpkgfilebad(char *a_msg, char *a_pkg);
static int ckpkgdirs(char *a_msg, char *a_pkg);
static int ckpkgfiles(char *a_msg, char *a_pkg);
static int ckprereqinc(char *a_msg, char *a_pkg);
static int ckprereqinst(char *a_msg, char *a_pkg);
static int ckpriv(char *a_msg, char *a_pkg);
static int ckrunlevel(char *a_msg, char *a_pkg);
static int cksetuid(char *a_msg, char *a_pkg);
static int ckspace(char *a_msg, char *a_pkg);
static int attrib(char *a_msg, char *a_pkg);
static int setuidf(char *a_msg, char *a_pkg);
static int setgidf(char *a_msg, char *a_pkg);
static int overwr(char *a_msg, char *a_pkg);
static depckl_t DEPCKL[] = {
{ "install-same-instance=true", "", &IMSG_SAME,
NULL, &er_same
},
{ "ckpkgfilebad=", NULL, &IMSG_ABADFILE,
&ckpkgfilebad, &er_ckpkgfilebad
},
{ "ckdirs=", NULL, &IMSG_DIRS,
&ckdirs, &er_ckdirs
},
{ "prerequisite-incomplete=", NULL, &IMSG_PRENCI,
&ckprereqinc, &er_prereqinc
},
{ "prerequisite-installed=", NULL, &IMSG_PREREQ,
&ckprereqinst, &er_prereqinst
},
{ "runlevel=", NULL, &IMSG_RUNLEVEL,
NULL, &er_runlevel
},
{ "conflict-contents=", NULL, &IMSG_CFCONTENT,
&ckcfcontent, &er_ckcfcontent
},
{ "ckconflict=", "0", &IMSG_CNFFAILED,
&ckconflict, &er_ckconflict
},
{ "ckdepend=", "0", &IMSG_DEPEND,
&ckdepend, &er_ckdepend
},
{ "ckpartialinstall=", "0", &IMSG_PARTINST,
&ckpartinst, &er_ckpartinst
},
{ "ckpartialremove=", "0", &IMSG_PARTREM,
&ckpartrem, &er_ckpartrem
},
{ "ckpkgdirs=", "0", &IMSG_PKGDIRS,
&ckpkgdirs, &er_ckpkgdirs
},
{ "ckpkgfiles=", "0", &IMSG_BADFILE,
&ckpkgfiles, &er_ckpkgfiles
},
{ "ckpriv=", "0", &IMSG_PRIV,
&ckpriv, &er_ckpriv
},
{ "ckrunlevel=", "0", &IMSG_CKRUNLVL,
&ckrunlevel, &er_ckrunlevel
},
{ "cksetuid=", "0", &IMSG_SETUID,
&cksetuid, &er_cksetuid
},
{ "ckspace=", "0", &IMSG_SPCFAILED,
&ckspace, &er_ckspace
},
{ "install-new-only=true", "", &IMSG_NEWONLY,
NULL, &er_newonly
},
{ "install-ovewrite=true", "", &IMSG_OVERWRITE,
NULL, &er_overwrite
},
{ "install-too-many-instances=true", "", &IMSG_UNIQ1,
NULL, &er_uniq1
},
{ "ckinstance=", "0", &IMSG_INSTANCE,
&ckinstance, &er_ckinstance
},
{ "conflict-attributes=", NULL, &IMSG_ATTRIB,
&attrib, &er_attrib
},
{ "setuid=", NULL, &IMSG_SETUIDF,
&setuidf, &er_setuidf
},
{ "setgid=", NULL, &IMSG_SETGIDF,
&setgidf, &er_setgidf
},
{ "setuid-overwrite=true", "", &IMSG_OVERWR,
&overwr, &er_overwr
},
{ NULL, NULL, NULL,
NULL, NULL }
};
int
preinstall_verify(char **a_pkglist, zoneList_t a_zlst, char *a_zoneTempDir)
{
char *pkginst;
int i;
int savenpkgs = npkgs;
assert(a_pkglist != (char **)NULL);
assert(a_zlst != (zoneList_t)NULL);
assert(a_zoneTempDir != (char *)NULL);
echoDebug(DBG_PREIVFY_ENTRY);
IMSG_ABADFILE = MSG_PKGADDCHK_ABADFILE;
IMSG_BADFILE = MSG_PKGADDCHK_BADFILE;
IMSG_CFCONTENT = MSG_PKGADDCHK_CFCONTENT;
IMSG_CKRUNLVL = MSG_PKGADDCHK_CKRUNLVL;
IMSG_CNFFAILED = MSG_PKGADDCHK_CNFFAILED;
IMSG_DEPEND = MSG_PKGADDCHK_DEPEND;
IMSG_DIRS = MSG_PKGADDCHK_DIRS;
IMSG_NEWONLY = MSG_PKGADDCHK_NEWONLY;
IMSG_OVERWRITE = MSG_PKGADDCHK_OVERWRITE;
IMSG_PARTINST = MSG_PKGADDCHK_PARTINST;
IMSG_PARTREM = MSG_PKGADDCHK_PARTREM;
IMSG_PKGDIRS = MSG_PKGADDCHK_PKGDIRS;
IMSG_PRENCI = MSG_PKGADDCHK_PRENCI;
IMSG_PREREQ = MSG_PKGADDCHK_PREREQ;
IMSG_PRIV = MSG_PKGADDCHK_PRIV;
IMSG_RUNLEVEL = MSG_PKGADDCHK_RUNLEVEL;
IMSG_SAME = MSG_PKGADDCHK_SAME;
IMSG_SETUID = MSG_PKGADDCHK_SETUID;
IMSG_SPCFAILED = MSG_PKGADDCHK_SPCFAILED;
IMSG_UNIQ1 = MSG_PKGADDCHK_UNIQ1;
IMSG_ATTRIB = gettext("\\nattribute change for %s <%s> on %s <%s>\n");
IMSG_SETUIDF = gettext("\\nsetuid %s in %s <%s> on %s <%s>\n");
IMSG_SETGIDF = gettext("\\nsetgid %s in %s <%s> on %s <%s>\n");
IMSG_OVERWR = gettext("\\nFiles that are setuid will be overwritten "
"by installation of %s\n<%s> on %s <%s>.\n");
for (i = 0; (pkginst = a_pkglist[i]) != NULL; i++) {
char *zoneName;
int zoneIndex;
if (pkgPackageIsThisZone(pkginst) == B_TRUE) {
echoDebug(DBG_PREIVFY_SKIP_THISZONE, pkginst);
continue;
}
for (zoneIndex = 0;
(zoneName = z_zlist_get_zonename(a_zlst, zoneIndex)) !=
(char *)NULL; zoneIndex++) {
FILE *fp;
char line[PATH_MAX+1];
char preinstallcheckPath[PATH_MAX+1];
int len;
if (z_zlist_is_zone_runnable(a_zlst,
zoneIndex) == B_FALSE) {
continue;
}
len = snprintf(preinstallcheckPath,
sizeof (preinstallcheckPath),
"%s/%s.%s.preinstallcheck.txt", a_zoneTempDir,
pkginst, zoneName);
if (len > sizeof (preinstallcheckPath)) {
progerr(ERR_CREATE_PATH_3, a_zoneTempDir,
pkginst, zoneName);
continue;
}
if (isfile((char *)NULL, preinstallcheckPath) != 0) {
echoDebug(DBG_PREIVFY_NOFILE,
pkginst, zoneName, preinstallcheckPath,
strerror(errno));
progerr(ERR_PREIVFY_NOFILE,
pkginst, zoneName);
continue;
}
fp = fopen(preinstallcheckPath, "r");
if (fp == (FILE *)NULL) {
progerr(ERR_PREIVFY_OPEN_FILE,
preinstallcheckPath, pkginst, zoneName,
strerror(errno));
continue;
}
while (fgets(line, sizeof (line), fp) != (char *)NULL) {
int j;
int len;
len = strlen(line);
while ((len > 0) && (line[len-1] == '\n')) {
line[--len] = '\0';
}
if (line[0] == '#') {
continue;
}
if (line[0] == '\0') {
continue;
}
for (j = 0;
DEPCKL[j].name != (char *)NULL; j++) {
len = strlen(DEPCKL[j].name);
if (strncmp(line, DEPCKL[j].name,
len) == 0) {
break;
}
}
echoDebug(DBG_PREIVFY_SCAN, line, pkginst,
zoneName);
if (DEPCKL[j].name == (char *)NULL) {
progerr(ERR_PREIVFY_UNKNOWN_LINE, line,
pkginst, zoneName);
continue;
}
if ((DEPCKL[j].ignore_values != (char *)NULL) &&
(*(DEPCKL[j].ignore_values) != '\0') &&
(strchr(DEPCKL[j].ignore_values,
line[len]) != (char *)NULL)) {
continue;
}
depchkRecordError(DEPCKL[j].record, pkginst,
zoneName, &line[len]);
}
(void) fclose(fp);
}
}
i = depchkReportErrors(DEPCKL);
npkgs = savenpkgs;
return (i);
}
static int
getyorn(char *a_msg, char *a_pkg, int a_nocheck, int a_quit,
char *a_helpMsg, char *a_adminMsg)
{
char ans[MAX_INPUT];
char ask_cont[MSG_MAX];
int n;
int saveCkquit;
assert(a_pkg != (char *)NULL);
assert(*a_pkg != '\0');
echoDebug(DBG_PREIVFY_GETYORN_ARGS, a_pkg, a_nocheck, a_quit, a_msg,
a_adminMsg ? a_adminMsg : "");
if (a_nocheck != 0) {
echoDebug(DBG_PREIVFY_GETYORN_NOCHECK, a_pkg);
return (0);
}
if ((a_msg != (char *)NULL) && (*a_msg != '\0')) {
ptext(stderr, "%s", a_msg);
}
if (a_quit != 0) {
if ((a_adminMsg != (char *)NULL) && (*a_adminMsg != '\0')) {
ptext(stderr, a_adminMsg);
}
echoDebug(DBG_PREIVFY_GETYORN_QUIT, a_pkg);
return (4);
}
if (echoGetFlag() == B_FALSE) {
ptext(stderr, MSG_PREIVFY_GETYORN_SUSP, a_pkg);
echoDebug(DBG_PREIVFY_GETYORN_QUIT_USER, a_pkg);
return (5);
}
(void) snprintf(ask_cont, sizeof (ask_cont), gettext(ASK_CONT), a_pkg);
saveCkquit = ckquit;
ckquit = 0;
n = ckyorn(ans, NULL, NULL, a_helpMsg, ask_cont);
ckquit = saveCkquit;
if (n != 0) {
ptext(stderr, MSG_PREIVFY_GETYORN_TERM, a_pkg);
echoDebug(DBG_PREIVFY_GETYORN_CKYORN, a_pkg, n);
return (n);
}
if (strchr("yY", *ans) == NULL) {
ptext(stderr, MSG_PREIVFY_GETYORN_TERM_USER, a_pkg);
echoDebug(DBG_PREIVFY_GETYORN_NOT_Y, a_pkg, ans);
return (3);
}
echoDebug(DBG_PREIVFY_GETYORN_SUCCESS, a_pkg);
return (0);
}
static int
ckprereqinc(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKPRENCI, a_pkg, a_msg);
if (!(ADM(idepend, "nocheck"))) {
ptext(stderr, "%s", a_msg);
}
return (0);
}
static int
ckprereqinst(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKPREREQ, a_pkg, a_msg);
if (!(ADM(idepend, "nocheck"))) {
ptext(stderr, "%s", a_msg);
}
return (0);
}
static int
ckpartinst(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKPARTIALINSTALL, a_pkg, a_msg);
return (getyorn(a_msg, a_pkg, ADM(partial, "nocheck"),
ADM(partial, "quit"), HLP_PKGADDCHK_PARTIAL, NULL));
}
static int
ckpartrem(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKPARTIALREMOVE, a_pkg, a_msg);
return (getyorn(a_msg, a_pkg, ADM(partial, "nocheck"),
ADM(partial, "quit"), HLP_PKGADDCHK_PARTIAL, NULL));
}
static int
ckrunlevel(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKRUNLEVEL, a_pkg, a_msg);
return (0);
}
static int
ckcfcontent(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKCFCONTENT, a_pkg, a_msg);
ptext(stderr, "%s", a_msg);
return (0);
}
static int
ckinstance(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKINSTANCE, a_pkg, a_msg);
return (getyorn(a_msg, a_pkg, ADM(instance, "nocheck"),
ADM(instance, "quit"), HLP_PKGADDCHK_DEPEND,
ERR_PKGADDCHK_DEPFAILED));
}
static int
ckdepend(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKDEPEND, a_pkg, a_msg);
return (getyorn(a_msg, a_pkg, ADM(idepend, "nocheck"),
ADM(idepend, "quit"), HLP_PKGADDCHK_DEPEND,
ERR_PKGADDCHK_DEPFAILED));
}
static int
ckspace(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKSPACE, a_pkg, a_msg);
return (getyorn(a_msg, a_pkg, ADM(space, "nocheck"),
ADM(space, "quit"), HLP_PKGADDCHK_SPACE,
ERR_PKGADDCHK_SPCFAILED));
}
static int
ckpkgdirs(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKPKGDIRS, a_pkg, a_msg);
ptext(stderr, "%s", a_msg);
return (4);
}
static int
ckdirs(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKDIRS, a_pkg, a_msg);
ptext(stderr, "%s", a_msg);
ptext(stderr, ERR_PKGADDCHK_MKPKGDIR);
return (4);
}
static int
ckpkgfilebad(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKPKGFILEBAD, a_pkg, a_msg);
ptext(stderr, "%s", a_msg);
return (0);
}
static int
ckconflict(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKCONFLICT, a_pkg, a_msg);
return (getyorn(a_msg, a_pkg, ADM(conflict, "nocheck"),
ADM(conflict, "quit"), HLP_PKGADDCHK_CONFLICT,
ERR_PKGADDCHK_CNFFAILED));
}
static int
cksetuid(char *a_msg, char *a_pkg)
{
char ans[MAX_INPUT];
char ask_cont[MSG_MAX];
int n;
int saveCkquit;
echoDebug(DBG_PREIVFY_CKSETUID, a_pkg, a_msg);
n = getyorn(a_msg, a_pkg, ADM(setuid, "nocheck"),
ADM(setuid, "quit"), HLP_PKGADDCHK_SETUID, NULL);
if (n != 3) {
return (n);
}
(void) snprintf(ask_cont, sizeof (ask_cont), gettext(ASK_CONT), a_pkg);
saveCkquit = ckquit;
ckquit = 0;
n = ckyorn(ans, NULL, NULL, gettext(HLP_PKGADDCHK_CONT), ask_cont);
ckquit = saveCkquit;
if (n != 0) {
ptext(stderr, MSG_PREIVFY_GETYORN_TERM, a_pkg);
echoDebug(DBG_PREIVFY_GETYORN_CKYORN, a_pkg, n);
return (n);
}
if (strchr("yY", *ans) == NULL) {
ptext(stderr, MSG_PREIVFY_GETYORN_TERM_USER, a_pkg);
echoDebug(DBG_PREIVFY_GETYORN_NOT_Y, a_pkg, ans);
return (3);
}
echoDebug(DBG_PREIVFY_GETYORN_SUCCESS, a_pkg);
return (0);
}
static int
ckpriv(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKPRIV, a_pkg, a_msg);
return (getyorn(a_msg, a_pkg, ADM(action, "nocheck"),
ADM(action, "quit"), HLP_PKGADDCHK_PRIV,
ERR_PKGADDCHK_PRIVFAILED));
}
static int
ckpkgfiles(char *a_msg, char *a_pkg)
{
echoDebug(DBG_PREIVFY_CKPKGFILES, a_pkg, a_msg);
ptext(stderr, "%s", a_msg);
return (4);
}
static int
attrib(char *a_msg, char *a_pkg)
{
return (getyorn(a_msg, a_pkg, ADM(instance, "nocheck"),
ADM(instance, "quit"), HLP_PKGADDCHK_CONT,
ERR_PKGADDCHK_DEPFAILED));
}
static int
setuidf(char *a_msg, char *a_pkg)
{
char *cp;
if ((cp = strchr(a_msg, ':')) != NULL)
*cp = ' ';
return (0);
}
static int
setgidf(char *a_msg, char *a_pkg)
{
char *cp;
if ((cp = strchr(a_msg, ':')) != NULL)
*cp = ' ';
return (0);
}
static int
overwr(char *a_msg, char *a_pkg)
{
return (getyorn(a_msg, a_pkg, ADM(instance, "nocheck"),
ADM(instance, "quit"), HLP_PKGADDCHK_SETUID,
ERR_PKGADDCHK_DEPFAILED));
}