X * sun's chmod(1) won't take litteral 0755 to change setgid bits (ksb)
X * so we have to convert such things into symbolic +- forms (yucko)
X *
X * If we exchange the subscripts of the Add matrix we get a subtraction
X * matrix. See assignments to pcS{Uid,Gid,All} below vs pcA{...}.
X */
static void
SunBotch(pcDo, mFrom, mTo)
char *pcDo;
int mFrom, mTo;
{
X auto char cUid, cGid, cSticky, cSep;
X auto char *pcAUid, *pcAGid, *pcAAll;
X auto char *pcSUid, *pcSGid, *pcSAll;
X
X cUid = (S_ISUID&mFrom) != (S_ISUID&mTo) ?
X ((S_ISUID&mTo) ? '+' : '-') : '\000';
X pcAUid = aaacAdd[(mFrom&0700)>>6][(mTo&0700)>>6];
X pcSUid = aaacAdd[(mTo&0700)>>6][(mFrom&0700)>>6];
X cGid = (S_ISGID&mFrom) != (S_ISGID&mTo) ?
X ((S_ISGID&mTo) ? '+' : '-') : '\000';
X pcAGid = aaacAdd[(mFrom&0070)>>3][(mTo&0070)>>3];
X pcSGid = aaacAdd[(mTo&0070)>>3][(mFrom&0070)>>3];
X cSticky = (S_ISVTX&mFrom) != (S_ISVTX&mTo) ?
X ((S_ISVTX&mTo) ? '+' : '-') : '\000';
X pcAAll = aaacAdd[(mFrom&0007)>>0][(mTo&0007)>>0];
X pcSAll = aaacAdd[(mTo&0007)>>0][(mFrom&0007)>>0];
X if ('\000' != cUid) {
X *pcDo++ = 'u';
X if (cUid == cGid) {
X cGid = '\000';
X *pcDo++ = 'g';
X }
X *pcDo++ = cUid;
X *pcDo++ = 's';
X if (cUid == cSticky) {
X *pcDo++ = 't';
X cSticky = '\000';
X }
X cSep = ',';
X } else {
X cSep = '\000';
X }
X if ('\000' != cGid) {
X if ('\000' != cSep)
X *pcDo++ = cSep;
X *pcDo++ = 'g';
X *pcDo++ = cGid;
X *pcDo++ = 's';
X cSep = ',';
X }
X if ('\000' != cSticky) {
X if ('\000' != cSep)
X *pcDo++ = cSep;
X *pcDo++ = cSticky;
X *pcDo++ = 't';
X cSep = ',';
X }
X if ('\000' != pcAUid[0]) {
X if ('\000' != cSep)
X *pcDo++ = cSep;
X *pcDo++ = 'u';
X if (0 == strcmp(pcAGid, pcAUid)) {
X *pcDo++ = 'g';
X pcAGid = "";
X }
X if (0 == strcmp(pcAAll, pcAUid)) {
X *pcDo++ = 'o';
X pcAAll = "";
X }
X *pcDo++ = '+';
X (void)strcpy(pcDo, pcAUid);
X pcDo += strlen(pcDo);
X cSep = ',';
X }
X if ('\000' != pcSUid[0]) {
X if ('\000' != cSep)
X *pcDo++ = cSep;
X *pcDo++ = 'u';
X if (0 == strcmp(pcSGid, pcSUid)) {
X *pcDo++ = 'g';
X pcSGid = "";
X }
X if (0 == strcmp(pcSAll, pcSUid)) {
X *pcDo++ = 'o';
X pcSAll = "";
X }
X *pcDo++ = '-';
X (void)strcpy(pcDo, pcSUid);
X pcDo += strlen(pcDo);
X cSep = ',';
X }
X if ('\000' != pcAGid[0]) {
X if ('\000' != cSep)
X *pcDo++ = cSep;
X *pcDo++ = 'g';
X if (0 == strcmp(pcAAll, pcAGid)) {
X *pcDo++ = 'o';
X pcAAll = "";
X }
X *pcDo++ = '+';
X (void)strcpy(pcDo, pcAGid);
X pcDo += strlen(pcDo);
X cSep = ',';
X }
X if ('\000' != pcSGid[0]) {
X if ('\000' != cSep)
X *pcDo++ = cSep;
X *pcDo++ = 'g';
X if (0 == strcmp(pcSAll, pcSGid)) {
X *pcDo++ = 'o';
X pcSAll = "";
X }
X *pcDo++ = '-';
X (void)strcpy(pcDo, pcSGid);
X pcDo += strlen(pcDo);
X cSep = ',';
X }
X if ('\000' != pcAAll[0]) {
X if ('\000' != cSep)
X *pcDo++ = cSep;
X *pcDo++ = 'o';
X *pcDo++ = '+';
X (void)strcpy(pcDo, pcAAll);
X pcDo += strlen(pcDo);
X cSep = ',';
X }
X if ('\000' != pcSAll[0]) {
X if ('\000' != cSep)
X *pcDo++ = cSep;
X *pcDo++ = 'o';
X *pcDo++ = '-';
X (void)strcpy(pcDo, pcSAll);
X pcDo += strlen(pcDo);
X cSep = ',';
X }
X *pcDo = '\000';
}
#endif /* brain dead chmod(2) */
X
X
/*
X * qwery the user and exec the `fix' program, if he wants to (ksb)
X *
X * We tell RunCmd to be quiet, because we echo the command when
X * we prompt for run/not. Return 1 for `skip the rest of this file'.
X */
static int
QExec(cmd, arg1, arg2, pcWas)
char *cmd, *arg1, *arg2, *pcWas;
{
X auto char **ppc;
X auto char *arg0, *pcTemp;
X auto char acAns[MAXANS+1];
X auto int iSave;
X static char *apcHelp[] = {
X "f\tskip to the next file",
X "h\tprint this help message",
X "n\tdo not run this command",
X "y\trun this command",
X "q\tquit the program",
X (char *)0
X };
X
X arg0 = StrTail(cmd);
X for (;;) {
X (void)fprintf(fpOut, "%s: %s %s", progname, arg0, arg1);
X if ((char *)0 != arg2)
X (void)printf(" %s", arg2);
X if ((char *)0 != pcWas)
X (void)printf(" {was %s}", pcWas);
X fputs(" [nfhqy] ", fpOut);
X
X if ((char *)0 == fgets(acAns, MAXANS, stdin)) {
X (void)clearerr(stdin);
X fputs("[EOF]\n", fpOut);
X return 0;
X }
X pcTemp = acAns;
X while (isspace(*pcTemp) && '\n' != *pcTemp)
X ++pcTemp;
X switch (*pcTemp) {
X default:
X (void)fprintf(stderr, "%s: unknown execute key `%c\'\n", progname, *pcTemp);
X case 'h':
X case 'H':
X case '?':
X for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) {
X (void)fprintf(fpOut, "%s\n", *ppc);
X }
X continue;
X case 'y': /* yeah, run it */
X case 'Y':
X iSave = fTrace;
X fTrace = FALSE;
X (void)RunCmd(cmd, arg1, arg2);
X fTrace = iSave;
#if defined(INST_FACILITY)
X if (bHaveRoot) {
X if ((char *)0 == arg2) {
X if ((char *)0 == pcWas)
X syslog(LOG_INFO, "%s %s by %s", arg0, arg1, pcGuilty);
X else
X syslog(LOG_INFO, "%s %s {was %s} by %s", arg0, arg1, pcWas, pcGuilty);
X } else if ((char *)0 == pcWas) {
X syslog(LOG_INFO, "%s %s %s by %s", arg0, arg1, arg2, pcGuilty);
X } else {
X syslog(LOG_INFO, "%s %s %s {was %s} by %s", arg0, arg1, arg2, pcWas, pcGuilty);
X }
X }
#endif
X break;
X
X case 'q': /* quit this */
X case 'Q':
X exit(0);
X
X case '\n':
X case 'n': /* no thanks */
X case 'N':
X break;
X
X case 'f': /* next file */
X case 'F':
X return 1;
X }
X break;
X }
X return 0;
X
}
X
CHLIST CLCheck;
static COMPONENT *pCMRoot;
int iMatches;
X
/*
X * we are passed a filename that exists and matches the recorded
X * install.cf line our parrent is currently working one. We should
X * look in the list of examined files to see if we have already
X * matched this file, if so we can ignore this match. Else check to
X * see if it would pass the current line.
X * Report bugs to stdout as install(1l) would, or close.
X */
int
DoCk(pcFile, pstThis)
char *pcFile;
struct stat *pstThis;
{
X register PATH_DATA *pPD;
X auto int fdFile;
X auto int fChGroup, fChOwner, fChMode;
X auto char acOOwner[128], acOGroup[128], acOMode[128];
X auto char acNMode[128];
X auto int mMode, mNew;
X
X pPD = AddPath(& pCMRoot, pcFile);
X if (0 != pPD->fseen) {
X return 0;
X }
X pPD->fseen = 1;
X ++iMatches;
X
X if ('~' == CLCheck.acmode[0]) {
X (void)fprintf(fpOut, "%s: `%s\' should not be installed\n", progname, pcFile);
X } else if ('!' == CLCheck.acmode[0]) {
X (void)fprintf(fpOut, "%s: `%s\' should not exist\n", progname, pcFile);
X if (fInteract) {
X if (QExec(BINRM, "-f", pcFile, (char *)0 != CLCheck.pcmesg && '\000' != CLCheck.pcmesg[0] ? CLCheck.pcmesg : NodeType(pstThis->st_mode, (char *)0))) {
X return 0;
X }
X /* if the user didn't remove it, check it
X */
X if (-1 == access(pcFile, 0)) {
X return 0;
X }
X } else {
X return 0;
X }
X }
X if ('*' == CLCheck.acmode[0]) {
X /* nothing */;
X } else if (CLCheck.mtype != (pstThis->st_mode & S_IFMT)) {
X (void)fprintf(fpOut, "%s: `%s\' should be a %s, not a %s\n", progname, pcFile, NodeType(CLCheck.mtype, (char *)0), NodeType(pstThis->st_mode, (char *)0));
X return 0;
X }
X
X /* time to check the group, owner, mode against our check list...
X * We buffer all the info up for one big informative printf at the end
X */
X fChOwner = fChGroup = fChMode = FALSE;
X
X if ('*' == CLCheck.acowner[0] || (CLCheck.fbangowner ? (fChOwner = pstThis->st_uid == CLCheck.uid) : (fChOwner = pstThis->st_uid != CLCheck.uid))) {
X register struct passwd *pwdTemp;
X
X pwdTemp = getpwuid(pstThis->st_uid);
X if ((struct passwd *)0 != pwdTemp) {
X (void)strcpy(acOOwner, pwdTemp->pw_name);
X } else {
X (void)sprintf(acOOwner, "%d", pstThis->st_uid);
X }
X } else {
X (void)strcpy(acOOwner, CLCheck.acowner);
X }
X
X if ('*' == CLCheck.acgroup[0] || (CLCheck.fbanggroup ? (fChGroup = pstThis->st_gid == CLCheck.gid) : (fChGroup = pstThis->st_gid != CLCheck.gid))) {
X register struct group *grpTemp;
X
X grpTemp = getgrgid(pstThis->st_gid);
X if ((struct group *)0 != grpTemp) {
X (void)strcpy(acOGroup, grpTemp->gr_name);
X } else {
X (void)sprintf(acOGroup, "%d", pstThis->st_gid);
X }
X } else {
X (void)strcpy(acOGroup, CLCheck.acgroup);
X }
X
X mMode = PERM_BITS(pstThis->st_mode);
X (void)sprintf(acOMode, "%04o", mMode);
X if ('*' != CLCheck.acmode[0]) {
X if (CLCheck.mmust != (mMode & CLCheck.mmust)) {
X fChMode = 1;
X } else if (0 != (mMode &~ (CLCheck.mmust|CLCheck.moptional))) {
X fChMode = 1;
X }
X mNew = CLCheck.mmust | (mMode & CLCheck.moptional);
X if (0 != (S_ISUID & mMode) ? 0 == (S_ISUID & (CLCheck.mmust|CLCheck.moptional)) : 0 != (S_ISUID & CLCheck.mmust)) {
X if (fVerbose) {
X (void)fprintf(fpOut, "%s: `%s\' setuid bit must be %s\n", progname, pcFile, apcOO[0 == (S_ISUID & mMode)]);
X }
X mNew |= (S_ISUID & (CLCheck.mmust|CLCheck.moptional));
X fChMode = 1;
X }
X if (0 != (S_ISGID & mMode) ? 0 == (S_ISGID & (CLCheck.mmust|CLCheck.moptional)) : 0 != (S_ISGID & CLCheck.mmust)) {
X if (fVerbose) {
X (void)fprintf(fpOut, "%s: `%s\' setgid bit must be %s\n", progname, pcFile, apcOO[0 == (S_ISGID & mMode)]);
X }
X mNew |= (S_ISGID & (CLCheck.mmust|CLCheck.moptional));
X fChMode = 1;
X }
X if (0 != (S_ISVTX & mMode) ? 0 == (S_ISVTX & (CLCheck.mmust|CLCheck.moptional)) : 0 != (S_ISVTX & CLCheck.mmust)) {
X if (fVerbose) {
X (void)fprintf(fpOut, "%s: `%s\' sticky bit must be %s\n", progname, pcFile, apcOO[0 == (S_ISVTX & mMode)]);
X }
X mNew |= (S_ISVTX & (CLCheck.mmust|CLCheck.moptional));
X fChMode = 1;
X }
#if BROKEN_CHMOD
X if (fChMode) {
X SunBotch(acNMode, mMode, mNew);
X } else {
X (void)sprintf(acNMode, "%04o", mNew);
X }
#else
X (void)sprintf(acNMode, "%04o", mNew);
#endif
X } else {
X (void)strcpy(acNMode, CLCheck.acmode);
X }
X
X /* tell the user of their sins, ask if they want to repent
X */
X if (fChOwner || fChGroup || fChMode) {
X fprintf(fpOut, "%s: `%s\' is %s.%s(%s) should be %s%s.%s%s(%s)\n", progname, pcFile, acOOwner, acOGroup, acOMode, CLCheck.fbangowner ? "!" : "", CLCheck.acowner, CLCheck.fbanggroup ? "!" : "", CLCheck.acgroup, acNMode);
X }
X if (fInteract) {
X if (fChOwner && !CLCheck.fbangowner && QExec(BINCHOWN, CLCheck.acowner, pcFile, acOOwner)) {
X return 0;
X }
X if (fChGroup && !CLCheck.fbanggroup && QExec(BINCHGRP, CLCheck.acgroup, pcFile, acOGroup)) {
X return 0;
X }
X if (fChMode && QExec(BINCHMOD, acNMode, pcFile, acOMode)) {
X return 0;
X }
X mMode = mNew; /* guess that the user did change mode LLL */
X }
X
X /* if we don't have to check strip/ranlib, don't open the file
X * if opening the file might activate a device, avoid it.
X */
X if ('*' == CLCheck.chstrip && 0 == ((S_ISUID|S_ISGID)&mMode)) {
X return 0;
X }
X if (S_IFREG != (pstThis->st_mode & S_IFMT)) {
X if (!CF_IS_NONE(CLCheck)) {
X (void)fprintf(stderr, "%s: %s: will not open %s\n", progname, pcFile, NodeType(pstThis->st_mode, (char *)0));
X }
X return 0;
X }
X
X if (0 > (fdFile = open(pcFile, 0, 0000))) {
X if (errno != EACCES) {
X (void)fprintf(stderr, "%s: open: %s: %s\n", progname, pcFile, strerror(errno));
X fprintf(fpOut, "%s: `%s\' unchecked %s\n", progname, pcFile, pcType);
X }
X return 0;
}
X
/*
X * sep the dirs and the files, dirCk the dirs, fileck file files (ksb)
X */
void
InstCk(argc, argv, pcLSpecial, pCLCheck)
int argc;
char **argv, *pcLSpecial;
CHLIST *pCLCheck; /* the checklist buffer DoCk uses */
{
X register int i, j, fSave;
X auto struct stat statb_me;
X
X fSave = fVerbose;
X fVerbose = 0;
X for (j = i = 0; i< argc; ++i) {
X if (-1 == stat(argv[i], &statb_me)) {
X fprintf(stderr, "%s: stat: %s: %s\n", progname, argv[i], strerror(errno));
X continue;
X }
X Special(argv[i], pcLSpecial, pCLCheck);
X if (S_IFDIR == (statb_me.st_mode & S_IFMT)) {
X argv[j++] = argv[i];
X if (pCLCheck->ffound)
X DoCk(argv[i], & statb_me);
X continue;
X }
X if (pCLCheck->ffound)
X DoCk(argv[i], & statb_me);
X else
X printf("%s: `%s\' not in checklist %s\n", progname, argv[i], pcLSpecial);
X }
X fVerbose = fSave;
X
X if (!fDirs)
X return;
X DirCk(j, argv, pcLSpecial, pCLCheck);
X OldCk(j, argv, pCLCheck);
X for (i = 0; i < j; ++i) {
X FileMatch("*", argv[i], LeftCk);
X }
}
X
X
/*
X * find all the links in a binary dir to a given file in an OLD dir (ksb)
X */
void
FixLinks(pcDir, pcOld, pcBackFile, pST)
char *pcDir, *pcOld, *pcBackFile;
struct stat *pST;
{
X register DIR *pDI;
X register struct direct *pDE;
X register int i, j, fLoop, iCount;
X register char ch;
X register struct fstab *pFS;
X auto struct stat statb_inst, statb_of;
X auto char acLoop[MAXPATHLEN+1];
X auto char acRelink[MAXPATHLEN+1];
X
X (void)sprintf(acLoop, "../%s", pcBackFile);
X /* strip off the mktemp suffix?
X */
X i = strlen(acLoop);
X j = i - 7;
X if (j < 4)
X j = 4;
X for (ch = '\000'; i > j; acLoop[i] = ch, --i, ch = acLoop[i], acLoop[i] = '\000') {
X if ('\000' !=ch && !isdigit(ch) &&
X (! isalpha(ch) && !isdigit(acLoop[i+1]))) {
X acLoop[i] = ch;
X i = j;
X break;
X }
X if (-1 == stat(acLoop, & statb_of)) {
X if (ENOENT == errno)
X continue;
X (void)fprintf(stderr, "%s: stat: %s: %s\n", progname, acLoop, strerror(errno));
X i = j;
X break;
X }
X break;
X }
X if (i != j && pST->st_ino == statb_of.st_ino &&
X pST->st_dev == statb_of.st_dev) {
X fLoop = 1;
X (void)fprintf(fpOut, "%s: `%s/%s\' is still linked to backup %s/%s/%s (inode %d)\n", progname, pcDir, acLoop+3, pcDir, pcOld, pcBackFile, pST->st_ino);
X } else {
X fLoop = 0;
X (void)fprintf(fpOut, "%s: `%s/%s/%s\' has too many links (inode %d)\n", progname, pcDir, pcOld, pcBackFile, pST->st_ino);
X }
X iCount = fLoop + 1;
X
X if ((DIR *)0 == (pDI = opendir(".."))) {
X (void)fprintf(stderr, "%s: opendir: ..: %s\n", progname, strerror(errno));
X return;
X }
X while ((struct direct *)0 != (pDE = readdir(pDI))) {
X if ('.' == pDE->d_name[0] && ('\000' == pDE->d_name[1] ||
X ('.' == pDE->d_name[1] && '\000' == pDE->d_name[2])))
X continue;
X if (i != j && 0 == strcmp(acLoop+3, pDE->d_name)) {
X continue;
X }
X (void)sprintf(acRelink, "../%s", pDE->d_name);
X if (-1 == LSTAT(acRelink, &statb_inst)) {
X if (ENOENT == errno)
X continue;
X (void)fprintf(stderr, "%s: lstat: %s: %s\n", progname, acRelink, strerror(errno));
X continue;
X }
X if (pST->st_ino != statb_inst.st_ino ||
X pST->st_dev != statb_inst.st_dev) {
X continue;
X }
X ++iCount;
X if (i == j) {
X if (fInteract) {
X (void)fprintf(fpOut, "%s: removing %s, a bogus link to %s (cwd=%s/%s)\n", progname, acRelink, pcBackFile, pcDir, pcOld);
X (void)QExec(BINRM, "-f", acRelink, "a bogus link");
X } else {
X (void)fprintf(fpOut, "%s: `%s/%s\' is a link to %s/%s/%s\n", progname, pcDir, pDE->d_name, pcDir, pcOld, pcBackFile);
X }
X continue;
X }
X if (fLoop) {
X (void)fprintf(fpOut, "%s: `%s/%s\' is a link to %s/%s/%s\n", progname, pcDir, pDE->d_name, pcDir, pcOld, pcBackFile);
X continue;
X }
X if (fInteract) {
X (void)fprintf(fpOut, "%s: linking %s to %s (cwd=%s/%s)\n", progname, acRelink, acLoop, pcDir, pcOld);
X if (!QExec(BINRM, "-f", acRelink, "link into OLD"))
X (void)QExec(BINLN, acLoop, acRelink, (char *)0);
X continue;
X }
X (void)fprintf(fpOut, "%s: `%s/%s\' should be linked to `%s/%s\'\n", progname, pcDir, pDE->d_name, pcDir, acLoop+3);
X }
X (void)closedir(pDI);
X /* have seen all the links
X */
X if (pST->st_nlink == iCount)
X return;
X
X /* find the mount point for this file system
X */
X (void)setfsent();
X while ((struct fstab *)0 != (pFS = getfsent())) {
X if ('.' == pFS->fs_file[0] && '\000' == pFS->fs_file[1])
X continue; /* ignore me */
X if (-1 == stat(pFS->fs_file, &statb_of))
X continue;
X if (statb_of.st_dev != pST->st_dev)
X continue;
X /* found it */
X (void)fprintf(fpOut, "%s: use `find %s -inum %d -print\' to locate missing links\n", progname, pFS->fs_file, pST->st_ino);
X iCount = pST->st_nlink;
X break;
X }
X (void)endfsent();
X if (pST->st_nlink != iCount) {
X (void)fprintf(fpOut, "%s: %s: count not find mount point\n", progname, pcDir);
X }
}
X
X
static char
X *pcOldOwner = ODIROWNER,
X *pcOldGroup = ODIRGROUP,
X *pcOldMode = ODIRMODE,
X acOld[] = OLDDIR;
X
/*
X * check the OLD dirs for pooly installed files (ksb)
X */
void
OldCk(iCount, ppcDirs, pCLCheck)
int iCount;
char **ppcDirs;
CHLIST *pCLCheck; /* the checklist buffer DoCk uses */
{
X register DIR *pDI;
X register struct direct *pDE;
X register int i, fChMode;
X auto char acMode[64];
X auto char acPwd[MAXPATHLEN+1];
X auto struct stat statb_backup, statb_old, statb_dir;
X auto struct passwd *pwdOldDef;
X auto struct group *grpOldDef;
X auto int mOldMust, mOldQuest;
X
X if ((char *)0 == getwd(acPwd)) {
X (void)fprintf(stderr, "%s: %s\n", progname, acPwd);
X exit(99);
X }
X
X if (!bHaveRoot) {
X pwdOldDef = getpwuid(geteuid());
X if ((struct passwd *)0 == pwdOldDef) {
X fprintf(stderr, "%s: getpwuid: %d: %s\n", progname, geteuid(), strerror(errno));
X exit(10);
X }
X pwdOldDef = savepwent(pwdOldDef);
X pcOldOwner = pwdOldDef->pw_name;
X } else if ((char *)0 != pcOldOwner || '\000' == pcOldOwner[0]) {
X pcOldOwner = (char *)0;
X pwdOldDef = (struct passwd *)0;
X } else {
X pwdOldDef = getpwnam(pcOldOwner);
X if ((struct passwd *)0 == pwdOldDef) {
X fprintf(stderr, "%s: getpwname: %s: %s\n", progname, pcOldOwner, strerror(errno));
X exit(10);
X }
X pwdOldDef = savepwent(pwdOldDef);
X }
X if (!bHaveRoot) {
X grpOldDef = getgrgid(getegid());
X if ((struct group *)0 == grpOldDef) {
X fprintf(stderr, "%s: getgrgid: %d: %s\n", progname, getegid(), strerror(errno));
X exit(10);
X }
X grpOldDef = savegrent(grpOldDef);
X pcOldGroup = grpOldDef->gr_name;
X } else if ((char *)0 == pcOldGroup || '\000' == pcOldGroup[0]) {
X pcOldGroup = (char *)0;
X grpOldDef = (struct group *)0;
X } else {
X grpOldDef = getgrnam(pcOldGroup);
X if ((struct group *)0 == grpOldDef) {
X fprintf(stderr, "%s: getgrname: %s: %s\n", progname, pcOldGroup, strerror(errno));
X exit(10);
X }
X grpOldDef = savegrent(grpOldDef);
X }
X if ((char *)0 == pcOldMode || '\000' == pcOldMode[0]) {
X pcOldMode = (char *)0;
X } else {
X CvtMode(pcOldMode, &mOldMust, &mOldQuest);
X }
X
X for (i = 0; i < iCount; ++i, chdir(acPwd)) {
X auto char acCurOld[MAXPATHLEN+2];
X
X if ('/' == ppcDirs[i][0]) { /* full path to it */
X (void)sprintf(acCurOld, "%s/%s", ppcDirs[i], acOld);
X } else {
X (void)sprintf(acCurOld, "%s/%s/%s", acPwd, ppcDirs[i], acOld);
X }
X if (-1 == stat(ppcDirs[i], & statb_dir)) {
X (void)fprintf(fpOut, "%s: stat: %s: %s\n", progname, ppcDirs[i], strerror(errno));
X continue;
X }
X
X /* check the modes on the OLD directory itself
X */
X if ((char *)0 == pcOldOwner) {
X register struct passwd *pwdTemp;
X
X pCLCheck->uid = statb_dir.st_uid;
X pwdTemp = getpwuid(statb_dir.st_uid);
X if ((struct passwd *)0 != pwdTemp) {
X (void)strcpy(pCLCheck->acowner, pwdTemp->pw_name);
X } else {
X (void)sprintf(pCLCheck->acowner, "%d", statb_dir.st_uid);
X }
X } else { /* yeah, this is an invarient */
X pCLCheck->uid = pwdOldDef->pw_uid;
X (void)strcpy(pCLCheck->acowner, pwdOldDef->pw_name);
X }
X if ((char *)0 == pcOldGroup) {
X register struct group *grpTemp;
X
X pCLCheck->gid = statb_dir.st_gid;
X grpTemp = getgrgid(statb_dir.st_gid);
X if ((struct group *)0 != grpTemp) {
X (void)strcpy(pCLCheck->acgroup, grpTemp->gr_name);
X } else {
X (void)sprintf(pCLCheck->acgroup, "%d", statb_dir.st_gid);
X }
X } else {
X pCLCheck->gid = grpOldDef->gr_gid;
X (void)strcpy(pCLCheck->acgroup, grpOldDef->gr_name);
X }
X
X pCLCheck->mtype = S_IFDIR;
X if ((char *)0 == pcOldMode) {
X pCLCheck->mmust = PERM_BITS(statb_dir.st_mode);
X pCLCheck->moptional = S_ISGID;
X } else {
X pCLCheck->mmust = mOldMust;
X pCLCheck->moptional = mOldQuest;
X }
X pCLCheck->chstrip = CF_NONE;
X (void)NodeType(pCLCheck->mtype, pCLCheck->acmode);
X ModetoStr(pCLCheck->acmode+1, pCLCheck->mmust, pCLCheck->moptional);
X
X if (-1 == stat(acCurOld, & statb_old)) {
X if (ENOENT != errno)
X (void)fprintf(stderr, "%s: stat: %s: %s\n", progname, acCurOld, strerror(errno));
X continue;
X }
X (void)DoCk(acCurOld, &statb_old);
X
X /* goto the directory and seach for poor backups
X */
X if (-1 == chdir(acCurOld)) {
X (void)fprintf(stderr, "%s: chdir: %s: %s\n", progname, acCurOld, strerror(errno));
X continue;
X }
X if ((DIR *)0 == (pDI = opendir("."))) {
X (void)fprintf(stderr, "%s: opendir: %s/%s/.: %s\n", progname, ppcDirs[i], acOld, strerror(errno));
X continue;
X }
X while ((struct direct *)0 != (pDE = readdir(pDI))) {
X if ('.' == pDE->d_name[0] && ('\000' == pDE->d_name[1] ||
X ('.' == pDE->d_name[1] && '\000' == pDE->d_name[2])))