check.c revision 5c51f1241dbbdf2656d0e10011981411ed0c9673
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#include <stdio.h>
#include <limits.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h> /* mkdir declaration is here? */
#include <unistd.h>
#include <errno.h>
#include <utmpx.h>
#include <dirent.h>
#include <sys/types.h>
#include <locale.h>
#include <libintl.h>
#include <pkgstrct.h>
#include <pkglocs.h>
#include "install.h"
#include <pkglib.h>
#include "libadm.h"
#include "libinst.h"
#include "pkginstall.h"
extern struct admin adm;
extern struct cfextra **extlist;
extern int ckquit, nocnflct, nosetuid, rprcflag;
extern char ilockfile[], rlockfile[], instdir[], savlog[],
tmpdir[], pkgloc[], pkgloc_sav[], pkgbin[], pkgsav[],
*pkginst, *msgtext;
extern char saveSpoolInstallDir[];
static boolean_t preinstallCheck = B_FALSE;
static char *zoneName = (char *)NULL;
static char ask_cont[100];
#define DISPSIZ 20 /* number of items to display on one page */
#define MSG_RUNLEVEL "\\nThe current run-level of this machine is <%s>, " \
"which is not a run-level suggested for installation " \
"of this package. Suggested run-levels (in order of " \
"preference) include:"
#define HLP_RUNLEVEL "If this package is not installed in a run-level " \
"which has been suggested, it is possible that the " \
"package may not install or operate properly. If " \
"you wish to follow the run-level suggestions, " \
"answer 'n' to stop installation of the package."
#define MSG_STATECHG "\\nTo change states, execute\\n\\tshutdown -y " \
"-i%s -g0\\nafter exiting the installation process. " \
"Please note that after changing states you " \
"may have to mount appropriate filesystem(s) " \
"in order to install this package."
#define ASK_CONFLICT "Do you want to install these conflicting files"
#define MSG_CONFLICT "\\nThe following files are already installed on the " \
"system and are being used by another package:"
#define MSG_ROGUE "\\n* - conflict with a file which does not " \
"belong to any package."
#define HLP_CONFLICT "If you choose to install conflicting files, the " \
"files listed above will be overwritten and/or have " \
"their access permissions changed. If you choose " \
"not to install these files, installation will " \
"proceed but these specific files will not be " \
"installed. Note that sane operation of the " \
"software being installed may require these files " \
"be installed; thus choosing to not to do so may " \
"cause inapropriate operation. If you wish to stop " \
"installation of this package, enter 'q' to quit."
#define ASK_SETUID "Do you want to install these as setuid/setgid files"
#define MSG_SETUID "\\nThe following files are being installed with " \
"setuid and/or setgid permissions:"
#define MSG_OVERWR "\\n* - overwriting a file which is also " \
"setuid/setgid."
#define HLP_SETUID "The package being installed appears to contain " \
"processes which will have their effective user or " \
"group ids set upon execution. History has shown " \
"that these types of processes can be a source of " \
"security problems on your system. If you choose " \
"not to install these as setuid files, installation " \
"will proceed but these specific files will be " \
"installed as regular files with setuid and/or " \
"setgid permissions reset. Note that sane " \
"operation of the software being installed may " \
"require that these files be installed with setuid " \
"or setgid permissions as delivered; thus choosing " \
"to install them as regular files may cause " \
"inapropriate operation. If you wish to stop " \
"installation of this package, enter 'q' to quit."
#define MSG_PARTINST "\\nThe installation of this package was previously " \
"terminated and installation was never successfully " \
"completed."
#define MSG_PARTREM "\\nThe removal of this package was terminated at " \
"some point in time, and package removal was only " \
"partially completed."
#define HLP_PARTIAL "Installation of partially installed packages is " \
"normally allowable, but some packages providers " \
"may suggest that a partially installed package be " \
"completely removed before re-attempting " \
"installation. Check the documentation provided " \
"with this package, and then answer 'y' if you feel " \
"it is advisable to continue the installation process."
#define HLP_SPACE "It appears that there is not enough free space on " \
"your system in which to install this package. It " \
"is possible that one or more filesystems are not " \
"properly mounted. Neither installation of the " \
"package nor its operation can be guaranteed under " \
"these conditions. If you choose to disregard this " \
"warning, enter 'y' to continue the installation " \
"process."
#define HLP_DEPEND "The package being installed has indicated a " \
"dependency on the existence (or non-existence) " \
"of another software package. If this dependency is " \
"not met before continuing, the package may not " \
"install or operate properly. If you wish to " \
"disregard this dependency, answer 'y' to continue " \
"the installation process."
#define MSG_PRIV "\\nThis package contains scripts which will be " \
"executed with super-user permission during the " \
"process of installing this package."
#define HLP_PRIV "During the installation of this package, certain " \
"scripts provided with the package will execute with " \
"super-user permission. These scripts may modify or " \
"otherwise change your system without your " \
"knowledge. If you are certain of the origin and " \
"trustworthiness of the package being installed, " \
"answer 'y' to continue the installation process."
#define ASK_CONT "Do you want to continue with the installation of <%s>"
#define HLP_CONT "If you choose 'y', installation of this package " \
"will continue. If you want to stop installation " \
"of this package, choose 'n'."
#define MSG_MKPKGDIR "unable to make packaging directory <%s>"
#define MSG_CKCONFL_GZ "## Checking for conflicts with packages already " \
"installed."
#define MSG_CKCONFL_LZ "## Checking for conflicts with packages already " \
"installed in zone <%s>."
#define MSG_CKDEPEND_GZ "## Verifying package dependencies."
#define MSG_CKDEPEND_LZ "## Verifying package dependencies in zone <%s>."
#define MSG_CKSPACE_GZ "## Verifying disk space requirements."
#define MSG_CKSPACE_LZ "## Verifying disk space requirements in zone <%s>."
#define MSG_CKUID_GZ "## Checking for setuid/setgid programs."
#define MSG_CKUID_LZ "## Checking for setuid/setgid programs in zone <%s>."
#define MSG_SCRFND "Package scripts were found."
#define MSG_UIDFND "Setuid/setgid processes detected."
#define MSG_ATTRONLY "!%s %s <attribute change only>"
#define MSG_CONTDISP "[Hit <RETURN> to continue display]"
#define ERR_NO_RUNST "unable to determine current run-state"
#define ERR_DEPFAILED "Dependency checking failed."
#define ERR_SPCFAILED "Space checking failed."
#define ERR_CNFFAILED "Conflict checking failed."
#define ERR_BADFILE "packaging file <%s> is corrupt"
/*
* Return value: int
* 0 - success
* 1 - end of file
* 2 - undefined error
* 3 - answer was not "y"/was "q"
* 4 - quit action taken
* 5 - interactive mode required
* If "preinstallcheck" is set to B_TRUE:
* 8 - partial install detected
* 9 - partial removal detected
*/
int
ckpartial(void)
{
char ans[MAX_INPUT];
int n;
if (ADM(partial, "nocheck")) {
return (0);
}
if (access(ilockfile, F_OK) == 0) {
if (preinstallCheck == B_TRUE) {
return (8); /* partial install detected */
}
(void) snprintf(ask_cont, sizeof (ask_cont),
gettext(ASK_CONT), pkginst);
msgtext = gettext(MSG_PARTINST);
ptext(stderr, msgtext);
if (ADM(partial, "quit")) {
return (4);
}
if (echoGetFlag() == B_FALSE) {
return (5);
}
msgtext = NULL;
ckquit = 0;
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_PARTIAL),
ask_cont)) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
return (3);
}
ckquit = 1;
}
if (access(rlockfile, F_OK) == 0) {
if (preinstallCheck == B_TRUE) {
return (9); /* partial removal detected */
}
(void) snprintf(ask_cont, sizeof (ask_cont),
gettext(ASK_CONT), pkginst);
msgtext = gettext(MSG_PARTREM);
ptext(stderr, msgtext);
if (ADM(partial, "quit")) {
return (4);
}
if (echoGetFlag() == B_FALSE) {
return (5);
}
msgtext = NULL;
ckquit = 0;
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_PARTIAL),
ask_cont)) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
return (3);
}
ckquit = 1;
}
return (0);
}
/*
* Return value: int
* 0 - success
* 1 - end of file
* 2 - undefined error
* 3 - answer was not "y"/was "q"
* 4 - quit action taken
* 5 - interactive mode required
* 99 - fatal error
*/
int
ckrunlevel(void)
{
struct utmpx utmpx;
struct utmpx *putmpx;
char ans[MAX_INPUT], *pt, *istates, *pstate;
int n;
char *uxstate;
if (ADM(runlevel, "nocheck")) {
return (0);
}
pt = getenv("ISTATES");
if (pt == NULL) {
return (0);
}
utmpx.ut_type = RUN_LVL;
putmpx = getutxid(&utmpx);
if (putmpx == NULL) {
progerr(gettext(ERR_NO_RUNST));
return (99);
}
(void) snprintf(ask_cont, sizeof (ask_cont),
gettext(ASK_CONT), pkginst);
/*
* this cryptic code is trying to pull the run level
* out of the utmpx entry...the level starts in column
* 11 - looks like "run-level %c"
*/
uxstate = strtok(&putmpx->ut_line[10], " \t\n");
istates = qstrdup(pt);
if ((pt = strtok(pt, " \t\n, ")) == NULL) {
return (0); /* no list is no list */
}
pstate = pt;
do {
if (strcmp(pt, uxstate) == 0) {
free(istates);
return (0);
}
} while (pt = strtok(NULL, " \t\n, "));
if (preinstallCheck == B_FALSE) {
msgtext = gettext(MSG_RUNLEVEL);
ptext(stderr, msgtext, uxstate);
} else {
(void) fprintf(stdout, "runlevel=%s", uxstate);
}
pt = strtok(istates, " \t\n, ");
do {
if (preinstallCheck == B_FALSE) {
ptext(stderr, "\\t%s", pt);
} else {
(void) fprintf(stdout, ":%s", pt);
}
} while (pt = strtok(NULL, " \t\n, "));
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "\n");
}
free(istates);
if (preinstallCheck == B_TRUE) {
return (4);
}
if (ADM(runlevel, "quit")) {
return (4);
}
if (echoGetFlag() == B_FALSE) {
return (5);
}
msgtext = NULL;
ckquit = 0;
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_RUNLEVEL),
ask_cont)) {
return (n);
}
ckquit = 1;
if (strchr("yY", *ans) != NULL) {
return (0);
} else {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(MSG_STATECHG), pstate);
}
return (3);
}
}
/*
* Return value: int
* 0 - success
* 1 - end of file
* 2 - undefined error
* 3 - answer was not "y"/was "q"
* 4 - quit action taken
* 5 - interactive mode required
*/
int
ckdepend(void)
{
int n;
char ans[MAX_INPUT];
char path[PATH_MAX];
if (ADM(idepend, "nocheck")) {
return (0);
}
(void) snprintf(path, sizeof (path), "%s/%s", instdir, DEPEND_FILE);
if (access(path, F_OK) != 0) {
return (0); /* no dependency file provided by package */
}
if (zoneName == (char *)NULL) {
echo(gettext(MSG_CKDEPEND_GZ));
} else {
echo(gettext(MSG_CKDEPEND_LZ), zoneName);
}
if (dockdeps(path, 0, preinstallCheck)) {
(void) snprintf(ask_cont, sizeof (ask_cont),
gettext(ASK_CONT), pkginst);
msgtext = gettext(ERR_DEPFAILED);
if (preinstallCheck == B_TRUE) {
return (4);
}
if (ADM(idepend, "quit")) {
return (4);
}
if (echoGetFlag() == B_FALSE) {
return (5);
}
msgtext = NULL;
ckquit = 0;
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_DEPEND),
ask_cont)) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
return (3);
}
ckquit = 1;
}
return (0);
}
void
cksetZoneName(char *a_zoneName)
{
zoneName = a_zoneName;
}
void
cksetPreinstallCheck(boolean_t a_preinstallCheck)
{
preinstallCheck = a_preinstallCheck;
}
/*
* Return value: int
* 0 - success
* 1 - end of file
* 2 - undefined error
* 3 - answer was not "y"/was "q"
* 4 - quit action taken
* 5 - interactive mode required
*/
int
ckspace(void)
{
int n;
char ans[MAX_INPUT];
char path[PATH_MAX];
if (ADM(space, "nocheck")) {
return (0);
}
if (zoneName == (char *)NULL) {
echo(gettext(MSG_CKSPACE_GZ));
} else {
echo(gettext(MSG_CKSPACE_LZ), zoneName);
}
(void) snprintf(path, sizeof (path), "%s/install/space", instdir);
if (access(path, F_OK) == 0) {
n = dockspace(path);
} else {
n = dockspace(NULL);
}
if (n) {
msgtext = gettext(ERR_SPCFAILED);
(void) snprintf(ask_cont, sizeof (ask_cont),
gettext(ASK_CONT), pkginst);
if (preinstallCheck == B_TRUE) {
return (4);
}
if (ADM(space, "quit")) {
return (4);
}
if (echoGetFlag() == B_FALSE) {
return (5);
}
msgtext = NULL;
ckquit = 0;
n = ckyorn(ans, NULL, NULL, gettext(HLP_SPACE), ask_cont);
if (n != 0) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
return (3);
}
ckquit = 1;
}
return (0);
}
void
ckdirs(void)
{
char path[PATH_MAX];
if (mkpath(get_PKGADM())) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", get_PKGADM());
} else {
progerr(gettext(MSG_MKPKGDIR), get_PKGADM());
}
quit(99);
}
(void) snprintf(path, sizeof (path), "%s/admin", get_PKGADM());
if (mkpath(path)) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", path);
} else {
progerr(gettext(MSG_MKPKGDIR), path);
}
quit(99);
}
(void) snprintf(path, sizeof (path), "%s/logs", get_PKGADM());
if (mkpath(path)) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", path);
} else {
progerr(gettext(MSG_MKPKGDIR), path);
}
quit(99);
}
if (mkpath(PKGSCR)) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", PKGSCR);
} else {
progerr(gettext(MSG_MKPKGDIR), PKGSCR);
}
quit(99);
}
if (mkpath(get_PKGLOC())) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", get_PKGLOC());
} else {
progerr(gettext(MSG_MKPKGDIR), get_PKGLOC());
}
quit(99);
}
}
/*
* Return value: int
* 0 - success
* 99 - failure
*/
int
ckpkgdirs(void)
{
boolean_t nonExistentPkgloc = B_FALSE;
/*
* If pkgloc doesn't exist make sure it gets removed after creating
* it if this is a preinstall check. All dryrun and preinstallation
* checks must not modify the file system.
*/
if (access(pkgloc, F_OK) != 0) {
nonExistentPkgloc = B_TRUE;
}
if (mkpath(pkgloc)) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", pkgloc);
} else {
progerr(gettext(MSG_MKPKGDIR), pkgloc);
}
return (99);
}
if (mkpath(pkgbin)) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", pkgbin);
} else {
progerr(gettext(MSG_MKPKGDIR), pkgbin);
}
return (99);
}
if (mkpath(pkgsav)) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", pkgsav);
} else {
progerr(gettext(MSG_MKPKGDIR), pkgsav);
}
return (99);
}
if (!is_spool_create() && mkpath(saveSpoolInstallDir)) {
if (preinstallCheck == B_TRUE) {
(void) fprintf(stdout, "ckdirs=%s\n", pkgsav);
} else {
progerr(gettext(MSG_MKPKGDIR), pkgsav);
}
return (99);
}
if (preinstallCheck && nonExistentPkgloc) {
rrmdir(pkgloc);
}
return (0);
}
/*
* Return value: int
* 0 - success
* 1 - end of file
* 2 - undefined error
* 3 - answer was not "y"/was "q"
* 4 - quit action taken
* 5 - interactive mode required
*/
int
ckconflct(void)
{
int i, n, count, has_a_rogue = 0;
char ans[MAX_INPUT];
if (ADM(conflict, "nochange")) {
nocnflct++;
return (0);
}
if (ADM(conflict, "nocheck")) {
return (0);
}
if (zoneName == (char *)NULL) {
echo(gettext(MSG_CKCONFL_GZ));
} else {
echo(gettext(MSG_CKCONFL_LZ), zoneName);
}
count = 0;
for (i = 0; extlist[i]; i++) {
struct cfent *ept;
struct mergstat *mstat;
if (extlist[i]->cf_ent.ftype == 'i') {
continue;
}
ept = &(extlist[i]->cf_ent);
mstat = &(extlist[i]->mstat);
if (is_remote_fs(ept->path, &(extlist[i]->fsys_value)) &&
!is_fs_writeable(ept->path,
&(extlist[i]->fsys_value))) {
continue;
}
/*
* If no other package claims it or it's from a continuation
* file, skip it.
*/
if (!mstat->shared || mstat->preloaded) {
continue;
}
if (ept->ftype == 'e') {
continue;
}
if (mstat->rogue) {
has_a_rogue = 1;
}
if (mstat->contchg) {
if (!count++) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(MSG_CONFLICT));
}
} else if ((echoGetFlag() == B_TRUE) &&
((count % DISPSIZ) == 0)) {
echo(gettext(MSG_CONTDISP));
(void) getc(stdin);
}
/*
* NOTE : The leading "!" in this string forces
* puttext() to print leading white space.
*/
if (preinstallCheck == B_FALSE) {
ptext(stderr, "!%s %s",
(mstat->rogue) ? "*" : " ", ept->path);
} else {
(void) fprintf(stdout,
"conflict-contents=%s\n", ept->path);
}
} else if (mstat->attrchg) {
if (!count++) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(MSG_CONFLICT));
}
} else if ((echoGetFlag() == B_TRUE) &&
((count % DISPSIZ) == 0)) {
echo(gettext(MSG_CONTDISP));
(void) getc(stdin);
}
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(MSG_ATTRONLY),
(mstat->rogue) ? "*" : " ", ept->path);
} else {
(void) fprintf(stdout,
"conflict-attributes=%s\n", ept->path);
}
}
}
if (count) {
if (has_a_rogue) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(MSG_ROGUE));
}
}
msgtext = gettext(ERR_CNFFAILED);
if (preinstallCheck == B_TRUE) {
return (4);
}
if (ADM(conflict, "quit")) {
return (4);
}
if (echoGetFlag() == B_FALSE) {
return (5);
}
msgtext = NULL;
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_CONFLICT),
gettext(ASK_CONFLICT))) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
ckquit = 0;
(void) snprintf(ask_cont, sizeof (ask_cont),
gettext(ASK_CONT), pkginst);
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_CONT),
ask_cont)) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
return (3);
}
ckquit = 1;
nocnflct++;
rprcflag++;
}
}
return (0);
}
/*
* Return value: int
* 0 - success
* 1 - end of file
* 2 - undefined error
* 3 - answer was not "y"/was "q"
* 4 - quit action taken
* 5 - interactive mode required
*/
int
cksetuid(void)
{
int i, n, count, overwriting = 0;
char ans[MAX_INPUT];
/* See if the administrative defaults already resolve this check. */
if (ADM(setuid, "nocheck")) {
return (0);
}
if (ADM(setuid, "nochange")) {
nosetuid++; /* Do not install processes as setuid/gid. */
return (0);
}
/* The administrative defaults require review of the package. */
if (zoneName == (char *)NULL) {
echo(gettext(MSG_CKUID_GZ));
} else {
echo(gettext(MSG_CKUID_LZ), zoneName);
}
count = 0;
for (i = 0; extlist[i]; i++) {
int overwr;
struct mergstat *mstat = &(extlist[i]->mstat);
/*
* Provide the administrator with info as to whether there is
* already a setuid process in place. This is only necessary
* to help the administrator decide whether or not to lay
* down the process, it doesn't have anything to do with the
* administrative defaults.
*/
if (mstat->osetuid || mstat->osetgid) {
overwr = 1;
overwriting = 1;
} else
overwr = 0;
if (mstat->setuid || mstat->setgid) {
if (!count++) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(MSG_SETUID));
}
} else if ((echoGetFlag() == B_TRUE) &&
((count % DISPSIZ) == 0)) {
echo(gettext(MSG_CONTDISP));
(void) getc(stdin);
}
/*
* NOTE : The leading "!" in these strings forces
* puttext() to print leading white space.
*/
if (mstat->setuid && mstat->setgid) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(
"!%s %s <setuid %s setgid %s>"),
(overwr) ? "*" : " ",
extlist[i]->cf_ent.path,
extlist[i]->cf_ent.ainfo.owner,
extlist[i]->cf_ent.ainfo.group);
} else {
(void) fprintf(stdout, "setuid=%s:%s\n",
extlist[i]->cf_ent.path,
extlist[i]->cf_ent.ainfo.owner);
(void) fprintf(stdout, "setgid=%s:%s\n",
extlist[i]->cf_ent.path,
extlist[i]->cf_ent.ainfo.group);
}
} else if (mstat->setuid) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(
"!%s %s <setuid %s>"),
(overwr) ? "*" : " ",
extlist[i]->cf_ent.path,
extlist[i]->cf_ent.ainfo.owner);
} else {
(void) fprintf(stdout, "setuid=%s:%s\n",
extlist[i]->cf_ent.path,
extlist[i]->cf_ent.ainfo.owner);
}
} else if (mstat->setgid) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(
"!%s%s <setgid %s>"),
(overwr) ? "*" : " ",
extlist[i]->cf_ent.path,
extlist[i]->cf_ent.ainfo.group);
} else {
(void) fprintf(stdout, "setgid=%s:%s\n",
extlist[i]->cf_ent.path,
extlist[i]->cf_ent.ainfo.group);
}
}
}
}
if (count) {
if (overwriting) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(MSG_OVERWR));
} else {
(void) fprintf(stdout,
"setuid-overwrite=true\n");
}
}
msgtext = gettext(MSG_UIDFND);
if (preinstallCheck == B_TRUE) {
return (4);
}
if (ADM(setuid, "quit")) {
return (4);
}
if (echoGetFlag() == B_FALSE) {
return (5);
}
msgtext = NULL;
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_SETUID),
gettext(ASK_SETUID))) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
ckquit = 0;
(void) snprintf(ask_cont, sizeof (ask_cont),
gettext(ASK_CONT), pkginst);
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_CONT),
ask_cont)) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
return (3);
}
ckquit = 1;
nosetuid++;
rprcflag++;
}
}
return (0);
}
/*
* Return value: int
* 0 - success
* 1 - end of file
* 2 - undefined error
* 3 - answer was not "y"/was "q"
* 4 - quit action taken
* 5 - interactive mode required
*/
int
ckpriv(void)
{
struct dirent *dp;
DIR *dirfp;
int n, found;
char ans[MAX_INPUT], path[PATH_MAX];
if (ADM(action, "nocheck")) {
return (0);
}
(void) snprintf(path, sizeof (path), "%s/install", instdir);
if ((dirfp = opendir(path)) == NULL) {
return (0);
}
found = 0;
while ((dp = readdir(dirfp)) != NULL) {
if (strcmp(dp->d_name, "preinstall") == 0 ||
strcmp(dp->d_name, "postinstall") == 0 ||
strncmp(dp->d_name, "i.", 2) == 0) {
found++;
break;
}
}
(void) closedir(dirfp);
if (found) {
if (preinstallCheck == B_FALSE) {
ptext(stderr, gettext(MSG_PRIV));
msgtext = gettext(MSG_SCRFND);
}
(void) snprintf(ask_cont, sizeof (ask_cont),
gettext(ASK_CONT), pkginst);
if (preinstallCheck == B_TRUE) {
return (4);
}
if (ADM(action, "quit")) {
return (4);
}
if (echoGetFlag() == B_FALSE) {
return (5);
}
msgtext = NULL;
ckquit = 0;
if (n = ckyorn(ans, NULL, NULL, gettext(HLP_PRIV),
ask_cont)) {
return (n);
}
if (strchr("yY", *ans) == NULL) {
return (3);
}
ckquit = 1;
}
return (0);
}
/*
* Return value: int
* 0 - success
* 99 - failure
*/
int
ckpkgfiles(void)
{
register int i;
struct cfent *ept;
int errflg;
char source[PATH_MAX];
errflg = 0;
for (i = 0; extlist[i]; i++) {
ept = &(extlist[i]->cf_ent);
if (ept->ftype != 'i') {
continue;
}
if (ept->ainfo.local) {
(void) snprintf(source, sizeof (source),
"%s/%s", instdir, ept->ainfo.local);
} else if (strcmp(ept->path, PKGINFO) == 0) {
(void) snprintf(source, sizeof (source),
"%s/%s", instdir, ept->path);
} else {
(void) snprintf(source, sizeof (source),
"%s/install/%s", instdir, ept->path);
}
if (cverify(0, &ept->ftype, source, &ept->cinfo, 1)) {
errflg++;
if (preinstallCheck == B_FALSE) {
progerr(gettext(ERR_BADFILE), source);
logerr(getErrbufAddr());
} else {
(void) fprintf(stdout, "ckpkgfilebad=%s",
source);
}
}
}
if (errflg) {
return (99);
} else {
return (0);
}
}