rsalz@uunet.uu.net (Rich Salz) (03/21/91)
Submitted-by: Kevin Braunsdorf <ksb@cc.purdue.edu> Posting-number: Volume 24, Issue 65 Archive-name: pucc-install/part03 #!/bin/sh # This is part 03 of pucc-1b # ============= install.d/main.c ============== if test ! -d 'install.d'; then echo 'x - creating directory install.d' mkdir 'install.d' fi if test -f 'install.d/main.c' -a X"$1" != X"-c"; then echo 'x - skipping install.d/main.c (File already exists)' else echo 'x - extracting install.d/main.c (Text)' sed 's/^X//' << 'Purdue' > 'install.d/main.c' && /* X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana X * 47907. All rights reserved. X * X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb X * X * This software is not subject to any license of the American Telephone X * and Telegraph Company or the Regents of the University of California. X * X * Permission is granted to anyone to use this software for any purpose on X * any computer system, and to alter it and redistribute it freely, subject X * to the following restrictions: X * X * 1. Neither the authors nor Purdue University are responsible for any X * consequences of the use of this software. X * X * 2. The origin of this software must not be misrepresented, either by X * explicit claim or by omission. Credit to the authors and Purdue X * University must appear in documentation and sources. X * X * 3. Altered versions must be plainly marked as such, and must not be X * misrepresented as being the original software. X * X * 4. This notice may not be removed or altered. X */ X /* X * install X * Install a <file> and back up the existing file to a standard X * location (normally a sub-directory named "OLD"). The name is always X * "OLD/<file>". Name clashes in OLD are resolved by renaming an existing X * OLD/<file> to OLD/<file><pid>. The OLD files should be cleaned X * up with a script that removes aged files (see purge(1l)). X * X * Authors: X * Jeff Smith (jms) & Kevin Braunsdorf (ksb) X * Purdue University Computing Center X * Math Building, Purdue, West Lafayette, IN, 47906 X * X * 15 Nov 1985 to 01 June 1990 X * X * Usage X * install [options] file [files] destination X * install -d [options] directory X * install -R [options] file X * install -[Vh] X * X * file(s): an absolute or relative path. If > 1 file to X * install is specified, destination must be a directory. X * X * destination: a pathname ending in either the destination X * directory or a filename which may be the same as or different X * than the tail of file(s). X * X * mk(1l) stuff: X * $Compile: make all X * $Compile: SYS=bsd make all X * $Compile: SYS=SYSV make all X * X * Environment: X * Set the environment variable INSTALL to any of the options to get the X * same effect as using them on the command line (e.g., INSTALL="-c"). X * Command line options silently override environental variables. X * X * N.B. X * + "OLD" directories may *not* be mount points! X * + the TMPINST macro file may be removed by purge after only few hours X * X * BUGS: X * + competing installs can (still) loose data :-{! X * if two users are installing the same file at the same time X * we can loose one of the two updates, use the flock(1) X * command on the destination directory to avoid this in the shell. X * (using flock(2) we *could* avoid this, see notes in main) X * flock ${BIN} install -vs ${PROG} ${BIN} X */ X #if !defined(lint) static char *rcsid = "$Id: main.c,v 7.0 90/09/17 09:41:57 ksb Exp $"; #endif /* !lint */ X #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <stdio.h> #include <pwd.h> #include <grp.h> X #include "configure.h" #include "install.h" #include "syscalls.h" #include "special.h" #include "file.h" #include "dir.h" #include "main.h" X #if STRINGS #include <strings.h> #else #include <string.h> #endif X extern char *realloc(), *malloc(); X #include "getopt.h" /* char *optarg; int optind; */ #if !defined(BADCH) /* char getopt returns for illegal options */ #define BADCH ((int) '\?') #endif /* !BADCH */ X X /* global variables for options X */ char *progname; /* tail of argv[0] */ char *Group = (char *)0; /* given group ownership */ char *Owner = (char *)0; /* given owner */ char *Mode = (char *)0; /* given mode */ char *HardLinks = (char *)0; /* hard links to installed file */ char *SoftLinks = (char *)0; /* symlinks to installed file */ int Copy = FALSE; /* we're copying */ int Destroy = FALSE; /* user doesn't want an OLD */ int BuildDir = FALSE; /* we're installing a directory */ int KeepTimeStamp = FALSE; /* if preserving timestamp */ int fQuiet = FALSE; /* suppress some errors, be quiet */ int Ranlib = FALSE; /* if we're running ranlib(1) */ int Strip = FALSE; /* if we're running strip(1) */ int fDelete = FALSE; /* uninstall the given file/dir */ int fRecurse = FALSE; /* Sun-like recursive dir install */ int fTrace = FALSE; /* if just tracing */ int fVerbose = FALSE; /* if verbose */ int f1Copy = FALSE; /* only keep one copy */ #if defined(CONFIG) struct passwd *pwdDef; /* aux default owner for config file */ struct group *grpDef; /* aux default group for config file */ char *pcSpecial = CONFIG; /* file contains ckecked paths */ #endif /* have a -C option? */ X /* X * global variables, but not option flags X */ int bHaveRoot; /* we have root permissions */ char *pcGuilty; /* the name logged as the installer */ static char copyright[] = X "@(#) Copyright 1990 Purdue Research Foundation. All rights reserved.\n"; X X /* X * Print detailed usage info X */ static char *apcHelp[] = { X "1 keep exactly one backup of the installed file", #if defined(CONFIG) X "C config use <config> to check for special files", #endif /* no -C option to list */ X "D destroy <destination> (no backup)", X "H links hard links to update (colon separated)", X "R remove the given target", #if HAVE_SLINKS X "S links symbolic links to update (colon separated)", #endif /* no symbolic links to worry about */ X "V explain compiled in default modes", X "c copy <file> instead of renaming it", X "d install a directory (mkdir with specified mode/group/owner)", X "g group install <file|directory> with group <group>", X "h help (print this)", X "l run ranlib(1) on <file>", X "m mode install <file|directory> with mode <mode>", X "n trace execution but do not do anything", X "o owner install <file|directory> with owner <owner>", X "p preserve timestamp of file being installed", X "q if install can recover from the error be quiet", X "r build all intervening directories", X "s run strip(1) on <file>", X "v run ls(1) on installed files and backups", X (char *)0 }; X #if defined(CONFIG) char acVArgs[] = X "[-C config]"; char acDArgs[] = X "[-nqrv] [-C config] [-g group] [-m mode] [-o owner]"; #if HAVE_SLINKS char acOArgs[] = X "[-1Dclnpqsv] [-C config] [-H links] [-S links] [-g group] [-m mode] [-o owner]"; #else char acOArgs[] = X "[-1Dclnpqsv] [-C config] [-H links] [-g group] [-m mode] [-o owner]"; #endif X #else /* change usage messgae, reflect CONFIG */ char acVArgs[] = X ""; char acDArgs[] = X "[-nqrv] [-g group] [-m mode] [-o owner]"; #if HAVE_SLINKS char acOArgs[] = X "[-1Dclnpqsv] [-H links] [-S links] [-g group] [-m mode] [-o owner]"; #else char acOArgs[] = X "[-1Dclnpqsv] [-H links] [-g group] [-m mode] [-o owner]"; #endif #endif /* no -C option to list */ X /* X * Output a useful, std usage message. Maybe a longer one if requested (ksb) X */ static void Usage(fp, bVerbose) FILE *fp; /* file to output to */ int bVerbose; /* should we explain options more */ { X register char **ppc; X X (void)fprintf(fp, "%s: usage %s files destination\n", progname, acOArgs); X (void)fprintf(fp, "%s: usage -d %s directory\n", progname, acDArgs); X (void)fprintf(fp, "%s: usage -h\n", progname); X (void)fprintf(fp, "%s: usage -R [options] target\n", progname); X (void)fprintf(fp, "%s: usage -V %s\n", progname, acVArgs); X if (bVerbose) { X for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) { X (void)fprintf(fp, *ppc, OLDDIR); X (void)fputc('\n', fp); X } X fprintf(fp, "%s", copyright); X } } X X /* X * first non-nil argument (ksb) X */ static char * nonnil(pc1, pc2) char *pc1, *pc2; { X if ((char *)0 != pc1) X return pc1; X if ((char *)0 != pc2) X return pc2; #if defined(DEBUG) X Die("nil pointer in nonnil"); #endif X return (char *)0; } X /* X * explain to the poor user what install will use as modes here (ksb) X */ static void Explain(fp) FILE *fp; { X static char acDMsg[] = "inherited"; X auto struct passwd *pwd; /* owner of this dir. */ X auto struct group *grp; /* group of this directory */ X X (void)fprintf(fp, "%s: version: %s\n", progname, "$Id: main.c,v 7.0 90/09/17 09:41:57 ksb Exp $"); #if defined(CONFIG) X (void)fprintf(fp, "%s: configuration file: %s, owner = %s, group = %s\n", progname, ((char *)0 == pcSpecial || '\000' == *pcSpecial) ? "(none)" : pcSpecial, (struct passwd *)0 != pwdDef ? pwdDef->pw_name : acDMsg, (struct group *)0 != grpDef ? grpDef->gr_name : acDMsg); #endif #if defined(INST_FACILITY) X (void)fprintf(fp, "%s: syslog facility: %d\n", progname, INST_FACILITY); #endif X (void)fprintf(fp, "%s: superuser (%s) defaults:\n", progname, pcGuilty); X (void)fprintf(fp, "%s: owner is file=%-10s dir=%-10s %s=%s\n", progname, X nonnil(DEFOWNER, acDMsg), X nonnil(DEFDIROWNER, acDMsg), X OLDDIR, X nonnil(ODIROWNER, acDMsg) X ); X (void)fprintf(fp, "%s: group is file=%-10s dir=%-10s %s=%s\n", progname, X nonnil(DEFGROUP, acDMsg), X nonnil(DEFDIRGROUP, acDMsg), X OLDDIR, X nonnil(ODIRGROUP, acDMsg) X ); X (void)fprintf(fp, "%s: mode is file=%-10s dir=%-10s %s=%s\n", progname, X nonnil(DEFMODE, acDMsg), X nonnil(DEFDIRMODE, acDMsg), X OLDDIR, X nonnil(ODIRMODE, acDMsg) X ); X X if (bHaveRoot) { X /* we assume the super user doesn't care about Joe User */ X return; X } X X (void)setpwent(); X if ((struct passwd *)0 == (pwd = getpwuid((int) geteuid()))) { X (void)fprintf(stderr, "%s: getpwuid: %d (effective uid) not found\n", progname, geteuid()); X exit(1); X } X (void)endpwent(); X X (void)setgrent(); X if ((struct group *)0 == (grp = getgrgid((int) getegid()))) { X (void)fprintf(stderr, "%s: getgrgid: %d (effective gid) not found\n", progname, getegid()); X exit(1); X } X (void)endgrent(); X (void)fprintf(fp, "%s: user defaults:\n", progname); X (void)fprintf(fp, "%s: owner is file=%-10s dir=%-10s %s=%s\n", progname, X pwd->pw_name, X pwd->pw_name, X OLDDIR, X pwd->pw_name X ); X (void)fprintf(fp, "%s: group is file=%-10s dir=%-10s %s=%s\n", progname, X grp->gr_name, X grp->gr_name, X OLDDIR, X grp->gr_name X ); X (void)fprintf(fp, "%s: mode is file=%-10s dir=%-10s %s=%s\n", progname, X nonnil(DEFMODE, acDMsg), X nonnil(DEFDIRMODE, acDMsg), X OLDDIR, X nonnil(ODIRMODE, acDMsg) X ); } X X static char acOutMem[] = "%s: out of memory\n"; /* X * OptAccum X * Accumulate a string, for string options that "append with a sep" (ksb) X * note: arg must start out as either "(char *)0" or a malloc'd string X */ static char * OptAccum(pcOld, pcArg, pcSep) char *pcOld, *pcArg, *pcSep; { X register int len; X register char *pcNew; X X /* Do not add null strings X */ X len = strlen(pcArg); X if (0 == len) { X return pcOld; X } X X if ((char *)0 == pcOld) { X pcNew = malloc(len+1); X if ((char *)0 == pcNew) { X (void)fprintf(stderr, acOutMem, progname); X exit(1); X } X pcNew[0] = '\000'; X } else { X len += strlen(pcOld)+strlen(pcSep)+1; X if ((char *)0 == (pcNew = realloc(pcOld, len))) { X (void)fprintf(stderr, acOutMem, progname); X exit(1); X } X (void)strcat(pcNew, pcSep); X } X pcOld = strcat(pcNew, pcArg); X return pcOld; } X X /* X * parse options with getopt and install files X */ int main(argc, argv) int argc; char **argv; { X extern char *getenv(); /* we want an env var */ X extern char *getlogin(); X static char Opts[] = /* valid options */ X "1cC:dDg:hH:lm:no:pqrRsS:vV"; X auto char *pcEnv; /* options passed through env */ X auto char *Dest; /* destination dir or filename */ X auto int iOption; /* argument pointer */ X auto int iFailed; /* installs that failed */ X auto int iArgs; /* args left after option processing */ X auto int fExplain; /* tell the user about our defaults */ X X (void)umask(022); X X /* Figure out our name and fix argv[0] for getopt() if necessary. X */ X progname = StrTail(argv[0]); X if (NULL == progname || '\000' == *progname) X progname = "install"; X /* here we become deinstall, or deinstallp X * a little gem for those who like to pick through source code... X */ X if ('d' == progname[0] && 'e' == progname[1]) { X fDelete = TRUE; X } X iFailed = 0; X X /* Check for environtment options X */ X if ((char *)0 != (pcEnv = getenv("INSTALL"))) { X envopt(pcEnv); X } X X /* See if we have root permissions, this changes default modes/owners X */ X bHaveRoot = 0 == geteuid(); X X /* Parse command line options, set flags, etc. X */ X fExplain = FALSE; X while (EOF != (iOption = getopt(argc, argv, Opts))) { X switch (iOption) { X case '1': X f1Copy = TRUE; X break; X case 'c': /* copy */ X Copy = TRUE; X break; X case 'C': /* check list */ #if defined(CONFIG) X pcSpecial = optarg; X break; #else /* give them an error */ X (void)fprintf(stderr, "%s: check list option not installed\n", progname); X exit(EXIT_OPT); #endif /* set check flags from config file */ X case 'S': /* soft links */ #if HAVE_SLINKS X SoftLinks = OptAccum(SoftLinks, optarg, ":"); X break; #else /* no symlink, warn and use hard ones */ X (void)fprintf(stderr, "%s: no symbolic links here, trying hard links\n", progname); X /*fall through*/ #endif /* handle -S based on OS */ X case 'H': /* hard links */ X HardLinks = OptAccum(HardLinks, optarg, ":"); X break; X case 'd': /* directory */ X BuildDir = TRUE; X break; X case 'D': /* destroy */ X Destroy = TRUE; X break; X case 'g': /* change group */ X Group = optarg; X break; X case 'h': /* help */ X Usage(stdout, 1); X exit(0); X break; X case 'l': /* ranlib */ X Ranlib = TRUE; X break; X case 'm': /* change mode */ X Mode = optarg; X break; X case 'n': /* execution trace */ X fTrace = TRUE; X break; X case 'o': /* change owner */ X Owner = optarg; X break; X case 'p': /* preserve time */ X KeepTimeStamp = TRUE; X break; X case 'q': /* be quiet */ X fQuiet = TRUE; X break; X case 'r': /* install -d -r /a/b build /a and /a/b */ X fRecurse = TRUE; X break; X case 'R': /* deintstall */ X fDelete = TRUE; X break; X case 's': /* strip(1) */ X Strip = TRUE; X break; X case 'v': /* run ls(1) */ X fVerbose = TRUE; X break; X case 'V': X fExplain = TRUE; X break; X case BADCH: /* illegal option */ X Usage(stderr, 0); X exit(EXIT_OPT); X break; X /* Since getopt should have caught all problems, this has X * to be an error X */ X default: X Die("command line parsing bug"); X } X } X X /* Usage checks. If installing > 1 file, the destination X * must be a directory which already exists. X */ X if (FALSE != Strip && FALSE != Ranlib) { X (void)fprintf(stderr, "%s: options `-l\' and `-s\' are incompatible\n", progname); X exit(EXIT_OPT); X } X if (FALSE != Ranlib && FALSE != KeepTimeStamp) { X (void)fprintf(stderr, "%s: option `-l\' suppresses `-p\'\n", progname); X } X if ((char *)0 != Mode) { X auto char *pcMsg; /* error, build a b,c,s,l,p message */ X auto int mMust; /* bits in mode to build */ X auto int m_Opt; /* discard optional bits */ X auto char chType; X auto char *pcUse; X auto char acShow[20]; X X CvtMode(Mode, & mMust, & m_Opt); X pcMsg = NodeType(mMust, &chType); X switch (chType) { X case 'd': X BuildDir = TRUE; X break; X case '-': X break; X case 's': X for (;;) { X pcUse = "a server"; X break; X case 'l': X pcUse = "ln -s"; X break; X case 'p': X case 'b': X case 'c': X (void)sprintf(acShow, "mknod %c", chType); X pcUse = acShow; X break; X } X default: X (void)fprintf(stderr, "%s: to build a %s use %s\n", progname, pcMsg, pcUse); X exit(1); X } X } X #if defined(INST_FACILITY) X if (bHaveRoot && FALSE == fTrace) { X openlog(progname, 0, INST_FACILITY); X } #endif /* we need to start syslog */ X pcGuilty = getlogin(); X if ((char *)0 == pcGuilty || '\000' == *pcGuilty) { X pcGuilty = getenv("USER"); X if ((char *)0 == pcGuilty || '\000' == *pcGuilty) X pcGuilty = "root\?"; X } X #if defined(CONFIG) X InitCfg((char *)0, (char *)0); #endif X X iArgs = argc - optind; X if (FALSE != fExplain) { X Explain(stdout); X } else if (FALSE != BuildDir) { X auto char *pcSlash, *pcDir; X X /* this check keeps Joe Bogus from having X * INSTALL=-vd X * in the environment break every program that uses install. X */ X if (1 != iArgs) { X (void)fprintf(stderr, "%s: only a single directory name may be given with -d\n", progname); X Usage(stderr, 0); X exit(EXIT_OPT); X } X if ((char *)0 != HardLinks) { X (void)fprintf(stderr, "%s: directories cannot have mulitple hard links, use -S\n", progname); X exit(EXIT_OPT); X } X if ((FALSE != Destroy || FALSE != f1Copy) && FALSE == fQuiet) { X (void)fprintf(stderr, "%s: -d ignores -D and -1\n", progname); X } X if ((FALSE != Strip || FALSE != Ranlib) && FALSE != fQuiet) { X (void)fprintf(stderr, "%s: -d cannot strip or ranlib a directory\n", progname); X } X X /* StrTail cuts trailing '/'s X * If we are building an OLD dir do it correctly X */ X pcDir = argv[argc-1]; X if (0 == strcmp(OLDDIR, StrTail(pcDir))) { X pcSlash = strrchr(pcDir, '/'); X if ((char *)0 == pcSlash) { X /* nothing to do, in `pwd` */; X } else if (pcSlash == pcDir) { X /* build "/", sure... done */; X } else if (FALSE != fRecurse) { X *pcSlash = '\000'; X if (!fDelete && FAIL == DirInstall(pcDir, Owner, Group, Mode, DEFDIROWNER, DEFDIRGROUP, DEFDIRMODE, (char *)0, 0)) { X exit(1); X } X *pcSlash = '/'; X /* yeah, odd... but -n look right this way */ X fRecurse = FALSE; X } X /* letting the user symlink to an OLD dir is very X * bogus, we do it only because I cannot think X * of a good error message.... (ksb) X */ X if (FAIL == DirInstall(pcDir, FALSE == bHaveRoot ? (char *)0 : ODIROWNER, FALSE == bHaveRoot ? (char *)0 : ODIRGROUP, ODIRMODE, (char *)0, (char *)0, (char *)0, SoftLinks, fDelete)) { X exit(1); X } X } else if (FAIL == DirInstall(pcDir, Owner, Group, Mode, DEFDIROWNER, DEFDIRGROUP, DEFDIRMODE, SoftLinks, fDelete)) { X exit(1); X } X } else if (fDelete) { X if (iArgs != 1) { X (void)fprintf(stderr, "%s: just give one target to remove\n", progname); X Usage(stderr, 0); X exit(EXIT_OPT); X } X if (FALSE != Destroy) { X (void)fprintf(stderr, "%s: -D changed to -1 to preserve last copy of target\n", progname); X Destroy = FALSE; X f1Copy = TRUE; X } X if (FAIL == Install("-", argv[optind], HardLinks, SoftLinks)) { X ++iFailed; X } X } else { X if (iArgs < 2) { X (void)fprintf(stderr, "%s: need both source and destination\n", progname); X Usage(stderr, 0); X exit(EXIT_OPT); X } X X Dest = argv[argc - 1]; X if (iArgs > 2 && IsDir(Dest) == FALSE) { X (void)fprintf(stderr, "%s: `%s\' must be an existing directory to install multiple files or directories\n", progname, Dest); X Usage(stderr, 0); X exit(EXIT_OPT); X } X X if (iArgs > 2 && ((char *)0 != HardLinks || (char *)0 != SoftLinks)) { X (void)fprintf(stderr, "%s: -H or -S option ambiguous with multiple source files\n", progname); X exit(EXIT_OPT); X } X X /* install the files X */ X for (--argc; optind < argc; optind++) { X if (FAIL == Install(argv[optind], Dest, HardLinks, SoftLinks)) { X (void)fprintf(stderr, "%s: installation of `%s\' failed\n", progname, argv[optind]); X ++iFailed; X } X } X } X #if defined(INST_FACILITY) X if (bHaveRoot && FALSE == fTrace) { X closelog(); X } #endif /* close-m up for now */ X X exit(iFailed); } Purdue chmod 0444 install.d/main.c || echo 'restore of install.d/main.c failed' Wc_c="`wc -c < 'install.d/main.c'`" test 19085 -eq "$Wc_c" || echo 'install.d/main.c: original size 19085, current size' "$Wc_c" fi # ============= install.d/syscalls.c ============== if test -f 'install.d/syscalls.c' -a X"$1" != X"-c"; then echo 'x - skipping install.d/syscalls.c (File already exists)' else echo 'x - extracting install.d/syscalls.c (Text)' sed 's/^X//' << 'Purdue' > 'install.d/syscalls.c' && /* X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana X * 47907. All rights reserved. X * X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb X * X * This software is not subject to any license of the American Telephone X * and Telegraph Company or the Regents of the University of California. X * X * Permission is granted to anyone to use this software for any purpose on X * any computer system, and to alter it and redistribute it freely, subject X * to the following restrictions: X * X * 1. Neither the authors nor Purdue University are responsible for any X * consequences of the use of this software. X * X * 2. The origin of this software must not be misrepresented, either by X * explicit claim or by omission. Credit to the authors and Purdue X * University must appear in documentation and sources. X * X * 3. Altered versions must be plainly marked as such, and must not be X * misrepresented as being the original software. X * X * 4. This notice may not be removed or altered. X */ X /* X * filer the unix system calls so they are more verbose or ineffective (ksb) X * under some options X */ #if !defined(lint) static char *rcsid = "$Id: syscalls.c,v 7.2 90/10/23 11:01:40 ksb Exp $"; #endif /* !lint */ X #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include <sys/time.h> #include <stdio.h> #include <ctype.h> #include <errno.h> #include <pwd.h> #include <grp.h> X #include "configure.h" #include "install.h" #include "main.h" X #if STRINGS #include <strings.h> #else #include <string.h> #endif X extern char *malloc(); X X #if !defined(BINCHGRP) #define BINCHGRP "/bin/chgrp" #endif X static char acChgrp[] = /* full path name to chgrp */ X BINCHGRP; X X static int iSigsBlocked = 0; /* count nested calls */ X #if defined(pdp11) || defined(SYSV) || defined(HPUX7) #else /* BSD */ static int OldSigMask; /* old signal mask */ #endif /* mask singals old way */ /* X * Mask all maskable signals (jsmith) X * is we mask CHLD ranlib breaks (actually the shell does) X */ void BlockSigs() { X if (0 == iSigsBlocked++) { #if defined(pdp11) || defined(SYSV) || defined(HPUX7) X register int i; X for (i = 0; i < NSIG; i++) { X signal(i, SIG_IGN); X } #else /* BSD */ X register int Mask; X Mask = sigmask(SIGHUP)|sigmask(SIGTERM)| X sigmask(SIGINT)|sigmask(SIGTSTP)|sigmask(SIGQUIT); X OldSigMask = sigsetmask(Mask); #endif /* do signal stuff */ X } } X X /* X * Return the signal mask to what it was in before BlockSigs() (jsmith) X */ void UnBlockSigs() { X if (0 == --iSigsBlocked) { #if defined(pdp11) || defined(SYSV) || defined(HPUX7) X register int i; X X for (i = 0; i < NSIG; i++) { X signal(i, SIG_DFL); X } #else /* BSD */ X (void)sigsetmask(OldSigMask); #endif /* more signal stuff */ X } } X X /* X * install suffers an internal error and exits abruptly (ksb) X * (really just a good break point for dbx/gdb/sdb) X */ void Die(pcError) char *pcError; /* error message, last gasp as we croak */ { X (void)fprintf(stderr, "%s: internal error: %s\n", progname, pcError); X exit(EXIT_INTER); } X X #define safecopy(Mdst, Msrc, Mfield, Mpc) \ X if ((char *)0 != Msrc->Mfield) { \ X Mdst->Mfield = Mpc; \ X (void)strcpy(pc, Msrc->Mfield); \ X Mpc = strchr(Mpc, '\000')+1; \ X } else { \ X Mdst->Mfield = (char *)0;\ X } X X /* X * this routine saves a group entry in malloced memory (ksb) X * simply free it when you are done with it X */ struct group * savegrent(pGR) struct group *pGR; { X register struct group *pGRNew; X register int size, i; X register char *pc; X auto char **ppc; X X if ((struct group *)0 == pGR) { X return (struct group *)0; X } X X size = sizeof(struct group); X if ((char *)0 != pGR->gr_name) X size += strlen(pGR->gr_name)+1; X if ((char *)0 != pGR->gr_passwd) X size += strlen(pGR->gr_passwd)+1; X for (i = 0; (char *)0 != pGR->gr_mem[i]; ++i) { X size += sizeof(char *) + strlen(pGR->gr_mem[i]) + 1; X } X size += sizeof(char *); X X if ((char *)0 == (pc = malloc(size))) { X return (struct group *)0; X } X X pGRNew = (struct group *)pc; X pc += sizeof(struct group); X X ppc = (char **) pc; X pc += (1+i) * sizeof(char *); X X safecopy(pGRNew, pGR, gr_name, pc); X safecopy(pGRNew, pGR, gr_passwd, pc); X X pGRNew->gr_gid = pGR->gr_gid; X X pGRNew->gr_mem = ppc; X for (i = 0; (char *)0 != pGR->gr_mem[i]; ++i) { X *ppc++ = pc; X (void)strcpy(pc, pGR->gr_mem[i]); X pc = strchr(pc, '\000')+1; X } X *ppc = (char *)0; X X return pGRNew; } X X /* X * this routine saves a passwd entry in malloced memory (ksb) X * simply free it when you are done with it X */ struct passwd * savepwent(pPW) struct passwd *pPW; { X register struct passwd *pPWNew; X register int size; X register char *pc; X X if ((struct passwd *)0 == pPW) { X return (struct passwd *)0; X } X size = sizeof(struct passwd); X if ((char *)0 != pPW->pw_name) X size += strlen(pPW->pw_name) +1; X if ((char *)0 != pPW->pw_passwd) X size += strlen(pPW->pw_passwd) +1; X if ((char *)0 != pPW->pw_comment) X size += strlen(pPW->pw_comment) +1; X if ((char *)0 != pPW->pw_gecos) X size += strlen(pPW->pw_gecos) +1; X if ((char *)0 != pPW->pw_dir) X size += strlen(pPW->pw_dir) +1; X if ((char *)0 != pPW->pw_shell) X size += strlen(pPW->pw_shell) +1; X X if ((char *)0 == (pc = malloc(size))) { X return (struct passwd *)0; X } X pPWNew = (struct passwd *)pc; X pc += sizeof(struct passwd); X safecopy(pPWNew, pPW, pw_name, pc); X safecopy(pPWNew, pPW, pw_passwd, pc); X pPWNew->pw_uid = pPW->pw_uid; X pPWNew->pw_gid = pPW->pw_gid; #if HAVE_QUOTA X pPWNew->pw_quota = pPW->pw_quota; #endif X X safecopy(pPWNew, pPW, pw_comment, pc); X safecopy(pPWNew, pPW, pw_gecos, pc); X safecopy(pPWNew, pPW, pw_dir, pc); X safecopy(pPWNew, pPW, pw_shell, pc); X X return pPWNew; } X #undef safecopy X X X /* X * ChMode() X * run chmod(2) on file, or trace doing so X */ void ChMode(pcFile, mMode) char *pcFile; /* pathname of file to change */ int mMode; /* mode to change to */ { X mMode = PERM_BITS(mMode); X if (FALSE != fTrace) { X (void)printf("%s: chmod %o %s\n", progname, mMode, pcFile); X } else if (-1 == chmod(pcFile, mMode)) { X (void)fprintf(stderr, "%s: chmod (%04o): %s: %s\n", progname, mMode, pcFile, strerror(errno)); X } } X X /* X * ChGroup() X * run chgrp(1) on file (for when we are NOT root) X * X * Globals: X * Group - character string specifying the group owner X */ void ChGroup(pcFile, pgroup) char *pcFile; /* pathname of file to change group of */ struct group *pgroup; /* info on group */ { X if (RunCmd(acChgrp, pgroup->gr_name, pcFile) != 0) { X (void)fprintf(stderr, "%s: `%s %s %s\' failed\n", progname, acChgrp, pgroup->gr_name, pcFile); X } } X X /* X * ChOwnGrp() X * Change the ownership and group of a file (must be root) X */ void ChOwnGrp(pcFile, powner, pgroup) char *pcFile; /* the pathname of the file to change */ struct passwd *powner; /* info for owner of file */ struct group *pgroup; /* info for group of file */ { X if (FALSE != fTrace) { X (void)printf("%s: chown %s %s\n", progname, powner->pw_name, pcFile); X (void)printf("%s: chgrp %s %s\n", progname, pgroup->gr_name, pcFile); X } else if (-1 == chown(pcFile, powner->pw_uid, pgroup->gr_gid)) { X (void)fprintf(stderr, "%s: chown: %s: %s\n", progname, pcFile, strerror(errno)); X /*return anyway*/ X } } X X /* X * ChTimeStamp() X * Change the time stamp of an installed file to match the original X * timestamp of the file to install X */ void ChTimeStamp(pcFile, pSTTimes) char *pcFile; /* the pathname of the file to change */ struct stat *pSTTimes; /* stat buffer containing timestamp of exemplar */ { #if defined(SYSV) || defined(HPUX7) X auto time_t tv[2]; X X tv[0] = pSTTimes->st_atime; X tv[1] = pSTTimes->st_mtime; X if (-1 == utime(pcFile, tv)) { X (void)fprintf(stderr, "%s: utime: %s: %s\n", progname, pcFile, strerror(errno)); X } #else /* BSD */ X auto struct timeval tv[2]; X X tv[0].tv_sec = pSTTimes->st_atime; X tv[1].tv_sec = pSTTimes->st_mtime; X tv[0].tv_usec = tv[1].tv_usec = 0; X if (-1 == utimes(pcFile, tv)) { X (void)fprintf(stderr, "%s: utimes: %s: %s\n", progname, pcFile, strerror(errno)); X } #endif /* BSD */ } X /* X * DoCopy() X * Copy the file "File" to file "Dest" X */ int DoCopy(File, Dest) char *File; /* the file to copy */ char *Dest; /* the target (destination) file */ { X register int fdSrc; /* file descriptors */ X register int fdDest; /* file to dopy to */ X register int n; /* number of chars read */ X register int fStdin; /* are we doing stdin */ X auto char acBlock[BLKSIZ]; X auto struct stat statb_File; X X X fStdin = '-' == File[0] && '\000' == File[1]; X X if (FALSE != fTrace) { X if (fStdin) X (void)printf("%s: cat - >%s\n", progname, Dest); X else X (void)printf("%s: cp %s %s\n", progname, File, Dest); X return SUCCEED; X } X X if (fStdin) X fdSrc = fileno(stdin); X else #if defined(pdp11) || defined(SYSV) X if (-1 == (fdSrc = open(File, O_RDONLY))) { X (void)fprintf(stderr, "%s: open: %s: %s\n", progname, File, strerror(errno)); X } #else /* BSD */ X if (-1 == (fdSrc = open(File, O_RDONLY, 0400))) { X (void)fprintf(stderr, "%s: open: %s: %s\n", progname, File, strerror(errno)); X } #endif /* do an open */ X X if (fstat(fdSrc, &statb_File) < 0) { X (void)fprintf(stderr, "%s: fstat: %s: %s\n", progname, File, strerror(errno)); X if (!fStdin) X (void)close(fdSrc); X return FAIL; X } X X /* we have to have rw- on the file to strip it later (ksb) X */ X if (-1 == (fdDest = creat(Dest, (int)statb_File.st_mode|0600))) { X (void)fprintf(stderr, "%s: create: %s: %s\n", progname, Dest, strerror(errno)); X if (!fStdin) X (void)close(fdSrc); X return FAIL; X } X X /* Do the copy here X */ X while (0 != (n = read(fdSrc, acBlock, BLKSIZ))) { X if (-1 == n) { X (void)fprintf(stderr, "%s: read: %s: %s\n", progname, File, strerror(errno)); X if (!fStdin) X (void)close(fdSrc); X (void)close(fdDest); X (void)unlink(Dest); X return FAIL; X } X if (write(fdDest, acBlock, n) != n) { X (void)fprintf(stderr, "%s: write: %s: %s\n", progname, Dest, strerror(errno)); X if (!fStdin) X (void)close(fdSrc); X (void)close(fdDest); X (void)unlink(Dest); X return FAIL; X } X } X X if (!fStdin) X (void)close(fdSrc); X (void)close(fdDest); X X return SUCCEED; } X X /* X * StrTail() X * return last element of a pathname X */ char * StrTail(pcPath) register char *pcPath; /* pathname to get tail of */ { X register char *pcTemp; X X /* don't hand strlen() or strrchr() a null pointer X */ X if ((char *) NULL == pcPath) { X return (char *)NULL; X } X X /* make sure we weren't handed something like "/a/b/" or "/a/b//". X * If we were we don't want to return ++pcTemp X */ X while ('/' == *(pcTemp = (pcPath + strlen(pcPath)) - 1)) { X if (pcTemp == pcPath) X break; X *pcTemp = '\000'; X } X X /* return last element X */ X if ((char *) NULL == (pcTemp = strrchr(pcPath, '/'))) X return pcPath; X return ++pcTemp; } X X /* X * call mktemp is fTrace is not set, else replace XXXX... with $$ (ksb) X */ char * Mytemp(pcFile) char *pcFile; { X register char *pcRet; X extern char *mktemp(); X X if (FALSE != fTrace) { X if ((char *)0 == (pcRet = strchr(pcFile, '\000'))) { X Die("strchr: nil pointer"); X } X while (pcRet > pcFile && 'X' == pcRet[-1]) X --pcRet; X (void)strcpy(pcRet, "$$"); X pcRet = pcFile; X } else if ((char *)0 == (pcRet = mktemp(pcFile))) { X Die("mktemp: nil pointer"); X } X return pcRet; } X X /* X * MungName() X * Mangle a pathname to make it unique (we hope) X * (note that the pathname passed must be in a large buffer) X */ void MungName(pcName) char *pcName; /* the name of the file we want to change */ { X register char *pcPat = PATMKTEMP; X #if defined(pdp11) || defined(SYSV) #if defined(SYSV) #define MAXNAMLEN 14 #endif /* max path component length */ X register char *pcTemp; X register int iPatLen; X X /* Pathname components must be no longer than 14 chars on 2.9bsd X * systems. If necessary truncate the filename after the first X * 8 chars so we can append "XXXXXX" for Mytemp() X */ X if ((pcTemp = strrchr(pcName, '/')) != (char *) 0) { X pcName = ++pcTemp; X } X X iPatLen = strlen(pcPat); X if (strlen(pcName) + iPatLen > MAXNAMLEN) { X *(pcName + (MAXNAMLEN - iPatLen)) = '\000'; X } X #endif /* path name limits */ X X if (MAXPATHLEN < (strlen(pcName) + strlen(pcPat))) { /* sanity */ X (void)fprintf(stderr, "%s: unreasonably long pathname `%s\'\n", progname, pcName); X exit(EXIT_OPT); X } X X /* This is real simple on reasonable operating systems X */ X (void)strcat(pcName, pcPat); X (void)Mytemp(pcName); } X X #if HAVE_SLINKS /* X * CopySLink() X * Copy a symbolic link; here we know that pcLink is a symbolic link, X * and pcCopy needs to be clone of it. X * X * Side Effects X * We might MungName our second argument, if we have to. X */ int CopySLink(pcLink, pcCopy) char *pcLink, *pcCopy; { X auto char acUcb[MAXPATHLEN+1]; X auto int iUcbLen; #if defined(DYNIX) X auto char acAtt[MAXPATHLEN+1]; X auto int iAttLen; #endif /* conditional symbolic links */ X #if defined(DYNIX) X if ((iAttLen = readclink(pcLink, acAtt, MAXPATHLEN, U_ATT)) <= 0) { X goto std_link; X } else if ((iUcbLen = readclink(pcLink, acUcb, MAXPATHLEN, U_UCB)) < 0) { X (void)fprintf(stderr, "%s: readclink(ucb): %s: %s\n", progname, pcLink, strerror(errno)); X return FAIL; X } X acAtt[iAttLen] = '\000'; X acUcb[iUcbLen] = '\000'; X if ('/' != acAtt[0]) { X if ('/' != acUcb[0]) { X (void)fprintf(stderr, "%s: neither branch of `%s\' is a full path, link will not point the correct place in OLD\n", progname, pcLink); X } else { X (void)fprintf(stderr, "%s: att branch of `%s\' is not a full path, it will not point the correct place in OLD\n", progname, pcLink); X } X } else if ('/' != acUcb[0]) { X (void)fprintf(stderr, "%s: ucb branch of `%s\' is not a full path, it will not point the correct place in OLD\n", progname, pcLink); X } X if (FALSE != fTrace) { X (void)printf("%s: ln -c att=%s ucb=%s %s\n", progname, acAtt, acUcb, pcCopy); X return SUCCEED; X } X if (0 == csymlink(acUcb, acAtt, pcCopy)) { X return SUCCEED; X } X if (errno != EEXIST) { X (void)fprintf(stderr, "%s: csymlink: %s: %s\n", progname, pcCopy, strerror(errno)); X return FAIL; X } X MungName(pcCopy); X if (0 != csymlink(acUcb, acAtt, pcCopy)) { X (void)fprintf(stderr, "%s: csymlink: %s: %s\n", progname, pcCopy, strerror(errno)); X return FAIL; X } X return SUCCEED; X std_link: X /* dynix link code finds a nornal ucb link to copy -- fall into */; #endif /* might have to copy a csymlink */ X X if ((iUcbLen = readlink(pcLink, acUcb, MAXPATHLEN)) < 0) { X (void)fprintf(stderr, "%s: readlink: %s: %s\n", progname, pcLink, strerror(errno)); X return FAIL; X } X X acUcb[iUcbLen] = '\000'; X if ('/' != acUcb[0]) { X (void)fprintf(stderr, "%s: link `%s\' is not a full path, it will not point the correct place in OLD\n", progname, pcLink); X } X if (FALSE != fTrace) { X (void)printf("%s: ln -s %s %s\n", progname, acUcb, pcCopy); X return SUCCEED; X } X if (0 == symlink(acUcb, pcCopy)) { X return SUCCEED; X } X if (errno != EEXIST) { X (void)fprintf(stderr, "%s: symlink: %s: %s\n", progname, pcCopy, strerror(errno)); X return FAIL; X } X MungName(pcCopy); X if (0 != symlink(acUcb, pcCopy)) { X (void)fprintf(stderr, "%s: symlink: %s: %s\n", progname, pcCopy, strerror(errno)); X return FAIL; X } X return SUCCEED; } #endif /* don't handle links at all */ X X /* X * Rename() X * Simulate the vax rename() syscall using link/unlink, or fTrace X */ int Rename(pcOrig, pcNew, pcNote) char *pcOrig; /* the original file name */ char *pcNew; /* the name file will have after the rename */ char *pcNote; /* tell the user always? */ { X register int fRet; X X BlockSigs(); X X if ((char *)0 != pcNote) { X (void)printf("%s: %s %s to %s\n", progname, pcNote, pcOrig, pcNew); X } X X fRet = SUCCEED; X if (FALSE != fTrace) { X (void)printf("%s: mv %s %s\n", progname, pcOrig, pcNew); X } else { #if defined(pdp11) || defined(SYSV) X (void)unlink(pcNew); X if (-1 == link(pcOrig, pcNew)) { X (void)fprintf(stderr, "%s: link: %s to %s: %s\n", progname, pcOrig, pcNew, strerror(errno)); X fRet = FAIL; X } else if (-1 == unlink(pcOrig)) { X (void)fprintf(stderr, "%s: unlink: %s: %s\n", progname, pcOrig, strerror(errno)); X fRet = FAIL; X } #else /* have rename to call */ X if (-1 == rename(pcOrig, pcNew)) { X (void)fprintf(stderr, "%s: rename: %s to %s: %s\n", progname, pcOrig, pcNew, strerror(errno)); X fRet = FAIL; X } #endif /* need to invent rename */ X } X X UnBlockSigs(); X X return fRet; } X /* X * IsDir() X * find out if a file is a directory, or a symlink to a directory X */ int IsDir(dest) char *dest; { X auto struct stat statb; X X if (-1 == stat(dest, &statb)) { X return FALSE; X } X X if (S_IFDIR == (statb.st_mode & S_IFMT)) { X return TRUE; X } X return FALSE; } X X /* X * MyWait() X * loop waiting until given child exits, return the childs status X */ int MyWait(pid) int pid; /* process id to wait for */ { X auto int wpid; #if defined(pdp11) || defined(SYSV) || defined(HPUX7) X auto int status; #else /* BSD */ X auto union wait status; #endif /* set up for a wait */ X X while ((wpid = wait(&status)) != pid) { X if (wpid == -1) X break; X } X X if (wpid == -1) { X /* this happens on the ETA, where did the kid go? X */ X if (ECHILD == errno) X return 0; X (void)fprintf(stderr, "%s: wait: %s\n", progname, strerror(errno)); X return 1; X } X #if defined(pdp11) || defined(SYSV) || defined(HPUX7) X return status; #else /* BSD */ X return status.w_status; #endif /* return value from wait */ } X X /* X * RunCmd() X * Vfork's & exec's a command and wait's for it to finish X * we return 1 for FAIL here, not FAIL, caller compares to 0 X * (as this is the sh(1) convention). X */ int RunCmd(cmd, arg1, arg2) char *cmd; /* full pathname of the command */ char *arg1; /* first argument to cmd */ char *arg2; /* second argument to cmd (can be nil) */ { X auto char *arg0; /* basename of cmd */ X register int pid; X X arg0 = StrTail(cmd); X if (FALSE != fTrace) { X (void)printf("%s: %s %s", progname, arg0, arg1); X if ((char *)0 != arg2) X (void)printf(" %s", arg2); X (void)fputc('\n', stdout); X return 0; X } X X (void)fflush(stdout); X (void)fflush(stderr); X switch ((pid = vfork())) { X case 0: /* child */ X execl(cmd, arg0, arg1, arg2, (char *)0); X (void)fprintf(stderr, "%s: execl: `%s\': %s\n", progname, cmd, strerror(errno)); X exit(1); X case -1: /* error */ X (void)fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno)); X exit(EXIT_FSYS); X default: /* parent */ X break; X } X X return MyWait(pid); } Purdue chmod 0444 install.d/syscalls.c || echo 'restore of install.d/syscalls.c failed' Wc_c="`wc -c < 'install.d/syscalls.c'`" test 18260 -eq "$Wc_c" || echo 'install.d/syscalls.c: original size 18260, current size' "$Wc_c" fi # ============= instck/main.c ============== if test ! -d 'instck'; then echo 'x - creating directory instck' mkdir 'instck' fi if test -f 'instck/main.c' -a X"$1" != X"-c"; then echo 'x - skipping instck/main.c (File already exists)' else echo 'x - extracting instck/main.c (Text)' sed 's/^X//' << 'Purdue' > 'instck/main.c' && /* X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana X * 47907. All rights reserved. X * X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb X * X * This software is not subject to any license of the American Telephone X * and Telegraph Company or the Regents of the University of California. X * X * Permission is granted to anyone to use this software for any purpose on X * any computer system, and to alter it and redistribute it freely, subject X * to the following restrictions: X * X * 1. Neither the authors nor Purdue University are responsible for any X * consequences of the use of this software. X * X * 2. The origin of this software must not be misrepresented, either by X * explicit claim or by omission. Credit to the authors and Purdue X * University must appear in documentation and sources. X * X * 3. Altered versions must be plainly marked as such, and must not be X * misrepresented as being the original software. X * X * 4. This notice may not be removed or altered. X */ static char copyright[] = X "@(#) Copyright 1990 Purdue Research Foundation.\nAll rights reserved.\n"; X /* X * instck - check for improperly installed files (ksb) X * X * Usage X * instck -h X * instck -G [-Ldv] [-g group] [-o owner] [-m mode] [dirs] >check.cf X * instck [-dlvS] [-C check] [dirs] >errors.log X * X * dirs(s): an absolute or relative paths to check-in or gen-for X * X * mk(1l) stuff: X * $Compile: make all X * $Compile: SYS=bsd make all X * $Compile: SYS=SYSV make all X * X * Environment: X * Set the environment variable INSTCK to any of the options to get the X * same effect as using them on the command line (e.g., INSTCK="-v"). X * Command line options silently override environental variables. X * X * N.B. X * See the main.c file in the source for install(1L). X */ X #if !defined(lint) static char *rcsid = "$Id: main.c,v 7.0 90/09/17 10:09:23 ksb Exp $"; #endif /* !lint */ X #include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/file.h> #include <sys/time.h> #include <sys/dir.h> #include <a.out.h> #include <ar.h> X X #include "configure.h" #include "install.h" #include "main.h" #include "special.h" #include "syscalls.h" #include "instck.h" X #include <stdio.h> #include <ctype.h> #include <errno.h> #include <pwd.h> #include <grp.h> X #include "getopt.h" /* char *optarg; int optind; */ #if !defined(BADCH) /* char getopt returns for illegal options */ #define BADCH (int) '\?' #endif /* !BADCH */ X X /* global variables for options X */ char *progname; /* tail of argv[0] */ int fDirs = TRUE; /* scan into dirs while building */ int fLongList = FALSE; /* list long, list leftovers */ int fInteract; /* ask the user if we should fix things */ int fTrace = FALSE; /* keep install part happy */ int fVerbose = FALSE; /* if verbose */ int fGen = FALSE; /* generate a .cf file for dirs */ int bHaveRoot; /* are we the super user */ int fLinks = FALSE; /* record links in link format */ char *pcGuilty; /* who is su'd root */ char *pcSpecial = CONFIG; /* file contains ckecked paths */ char *pcMode = DEFMODE; /* default mode on all files */ char *pcDefMode; /* string mode we need (this dir) */ X X /* X * Print detailed usage info X */ char *apcHelp[] = { X "C config use config to check for special files", X "d do not scan given directories for files", X "g group set the default group for all files", X "G generate a check list for the given dirs on stdout", X "h print this message", X "i interactively repair the installed files", X "l list left over files (those that were not checked)", X "L record all links in link format", X "m mode set the default mode for installed files", X "o owner set the default owner for installed files", X "S run as if we were the superuser", X "v be more verbose", X "V show version information", X (char *)0 }; X char acOArgs[] = X "[-dGhilLvV] [-C config] [-g group] [-m mode] [-o owner]"; X /* X * Usage X * Output a useful, std usage message. Maybe a longer one if requested X */ int Usage(fp, bVerbose) FILE *fp; /* file to output to */ int bVerbose; /* should we explain options more */ { X register char **ppc; X X (void)fprintf(fp, "%s: usage %s [dirs]\n", progname, acOArgs); X if (bVerbose) { X for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) { X (void)fprintf(fp, *ppc, OLDDIR); X (void)fputc('\n', fp); X } X (void)fprintf(fp, "%s", copyright); X } } X X /* X * parse options with getopt and install files X */ int main(argc, argv) int argc; char **argv; { X extern char *getenv(); /* we want an env var */ X static char Opts[] = /* valid options */ X "C:dGg:hilLm:o:SvV"; X auto char *pcEnv; /* options passed through env */ X auto int iOption; /* argument pointer */ X auto char acMBuf[20]; /* mode buffer */ X auto int iM, iO; /* more mode buffers */ X auto int fVersion; /* we should just output version info */ X auto char *pcOwner; /* login name for default owner */ X auto char *pcGroup; /* group name for default group */ X X /* Figure out our name and fix argv[0] for getopt() if necessary. X */ X progname = StrTail(argv[0]); X if (NULL == progname || NULL == *progname) X progname = "instck"; X X /* Check for environtment options X */ X if ((char *)0 != (pcEnv = getenv("INSTCK"))) { X envopt(pcEnv); X } X X /* are we the superuser X */ X bHaveRoot = 0 == geteuid(); X X /* Parse command line options, set flags, etc. X */ X fVersion = FALSE; X pcGroup = pcOwner = (char *)0; X while (EOF != (iOption = getopt(argc, argv, Opts))) { X switch (iOption) { X case 'C': /* check list */ X pcSpecial = optarg; X break; X case 'd': /* don't drop down into given dirs */ X fDirs = FALSE; X break; X case 'g': /* new default group */ X pcGroup = optarg; X break; X case 'G': /* output a new .cf file for dirs */ X fGen = TRUE; X break; X case 'h': /* help */ X Usage(stdout, 1); X exit(0); X break; X case 'i': X fInteract = TRUE; X break; X case 'l': /* long list */ X fLongList = TRUE; X break; X case 'L': /* link format */ X fLinks = TRUE; X break; X case 'm': /* set mode */ X pcMode = optarg; X break; X case 'o': /* set default owner */ X pcOwner = optarg; X break; X case 'S': /* we *are* the superuser */ X bHaveRoot = TRUE; X break; X case 'v': /* run ls(1), and insert comments */ X fVerbose = TRUE; X break; X case 'V': X fVersion = TRUE; X break; X case BADCH: /* illegal option */ X Usage(stderr, 0); X exit(EXIT_OPT); X break; X } X } X X X /* set the files we need, instck the dirs we were asked to, end clean X */ X (void)setpwent(); X (void)setgrent(); X InitCfg(pcOwner, pcGroup); X X pcDefMode = acMBuf; X acMBuf[0] = '-'; X if ((char *)0 == pcMode || '\000' == pcMode[0]) { X pcMode = (char *)0; X } else { X CvtMode(pcMode, & iM, & iO); X ModetoStr(pcDefMode+1, iM, iO); X } X X argc -= optind; X argv += optind; X argc = ElimDups(argc, argv); X X if (fVersion) { X static char acInh[] = "inherited"; X X printf("%s: version: $Id: main.c,v 7.0 90/09/17 10:09:23 ksb Exp $\n", progname); X printf("%s: configuration file: %s\n", progname, pcSpecial); #if defined(INST_FACILITY) X printf("%s: syslog facility: %d\n", progname, INST_FACILITY); #endif X printf("%s: defaults: owner=%-10s group=%-10s mode=%s\n", progname, (struct passwd *)0 != pwdDef ? pwdDef->pw_name : acInh, (struct group *)0 != grpDef ? grpDef->gr_name : acInh, (char *)0 != pcMode ? pcDefMode : acInh); X } else if (fGen) { X GenCk(argc, argv); X } else { #if defined(INST_FACILITY) X if (bHaveRoot && fInteract) { X extern char *getlogin(); X openlog(progname, 0, INST_FACILITY); X pcGuilty = getlogin(); X if ((char *)0 == pcGuilty || '\000' == *pcGuilty) { X pcGuilty = getenv("USER"); X if ((char *)0 == pcGuilty || '\000' == *pcGuilty) X pcGuilty = getenv("LOGNAME"); X if ((char *)0 == pcGuilty || '\000' == *pcGuilty) X pcGuilty = "root\?"; X } X } #endif X argc = FilterOld(argc, argv, & CLCheck); X InstCk(argc, argv, pcSpecial, & CLCheck); #if defined(INST_FACILITY) X if (bHaveRoot && fInteract) { X closelog(); X } #endif X } X X (void)endpwent(); X (void)endgrent(); X X exit(0); } Purdue chmod 0444 instck/main.c || echo 'restore of instck/main.c failed' Wc_c="`wc -c < 'instck/main.c'`" test 8078 -eq "$Wc_c" || echo 'instck/main.c: original size 8078, current size' "$Wc_c" fi # ============= instck/main.h ============== if test -f 'instck/main.h' -a X"$1" != X"-c"; then echo 'x - skipping instck/main.h (File already exists)' else echo 'x - extracting instck/main.h (Text)' sed 's/^X//' << 'Purdue' > 'instck/main.h' && /* X * $Id: main.h,v 7.1 90/09/17 10:25:39 ksb Exp $ X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana X * 47907. All rights reserved. X * X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb X * X * This software is not subject to any license of the American Telephone X * and Telegraph Company or the Regents of the University of California. X * X * Permission is granted to anyone to use this software for any purpose on X * any computer system, and to alter it and redistribute it freely, subject X * to the following restrictions: X * X * 1. Neither the authors nor Purdue University are responsible for any X * consequences of the use of this software. X * X * 2. The origin of this software must not be misrepresented, either by X * explicit claim or by omission. Credit to the authors and Purdue X * University must appear in documentation and sources. X * X * 3. Altered versions must be plainly marked as such, and must not be X * misrepresented as being the original software. X * X * 4. This notice may not be removed or altered. X */ X /* X * paths, names and options of tools we need to fork X */ X /* global variables for options X */ extern char *progname; /* tail of argv[0] */ extern char *pcGuilty; /* who is su'd root? */ extern char *pcMode; /* given mode */ extern char *pcSpecial; /* .cf file for normal mode */ extern int fDirs; /* scan dirs or not */ extern int fInteract; /* ask the user if we should fix things */ extern int fLongList; /* long list, list leftovers */ extern int fTrace; /* keep install part happy */ extern int fVerbose; /* if verbose */ extern int fLinks; /* record links in special link format */ extern int bHaveRoot; /* we are the superuser */ extern char *pcDefMode; /* string mode we need (this dir) */ X #define INSTCK 1 /* we are not install, we are instck */ Purdue chmod 0444 instck/main.h || echo 'restore of instck/main.h failed' Wc_c="`wc -c < 'instck/main.h'`" test 1858 -eq "$Wc_c" || echo 'instck/main.h: original size 1858, current size' "$Wc_c" fi # ============= install.cf/install.cf ============== if test ! -d 'install.cf'; then echo 'x - creating directory install.cf' mkdir 'install.cf' fi if test -f 'install.cf/install.cf' -a X"$1" != X"-c"; then echo 'x - skipping install.cf/install.cf (File already exists)' else echo 'x - extracting install.cf/install.cf (Text)' sed 's/^X//' << 'Purdue' > 'install.cf/install.cf' && # $Id: install.cf,v 7.2 90/11/08 11:00:36 ksb Exp $ # This file tells install(1l) what files to check as special # file modes owner group strip? comment X # protect dirs in the std search path / dr?xr-xr-x root * - /bin " " " " /usr " " " " /etc " " " " /lib " " " " /usr/bin " " " " /usr/lib " " " " /usr/etc " " " " /usr/local/bin " " " " X # protect user file systems /user? dr?xr-xr-x root * - /home " " " " /users " " " " /home/* " " " " X # (unix and variants) /unix -r?-r--r-- root * n new kernel /vmunix " " " " " /dynix " " " " " /hp-ux " " " " " vmunix " " " " new client kernel X # important special binaries /bin/sh -rwx?-x?-x * * ? /bin/su -rws?-x?-? root * ? /bin/init -rwx?--?-- root * ? /etc/init " " * ? X # important data files /etc/shadow drwx------ root * - /etc/shadow/OLD drwx????-? " * - /etc/passwd -r?-r--r-- " " - /etc/shadow/passwd " " " " /etc/group " " " " /etc/shadow/* " " " " X # one might make a directory with install /tmp drwxrwxrwt root system - /usr/tmp " " " - lost+found drwxr-xr-x " " - for fcsk(8) X # new files should be owner by the installer for tickle(8) /usr/new/bin/OLD drwxr-xr-x root * - /usr/new/bin/* -rwxr-x?-?/7000 !root * ? test installation /usr/new/etc/OLD drwxr-xr-x root * - /usr/new/etc/* -rwxr-x?-?/7000 !root * ? test installation X # these cannot be stripped (and must have the world read bit) saved_kcl -rwxr-xr-x * * n X # protect from default execute bit /usr/lib/libg.a -r?-r--r-- * * n not a library *.a -r?-??-??- * * l library *.so.[0-9]* " " " n dynamic library *.o " * * n *.ln " * * n *.[hc] " " " " Purdue chmod 0444 install.cf/install.cf || echo 'restore of install.cf/install.cf failed' Wc_c="`wc -c < 'install.cf/install.cf'`" test 1669 -eq "$Wc_c" || echo 'install.cf/install.cf: original size 1669, current size' "$Wc_c" fi true || echo 'restore of install.d/install.1l failed' echo End of part 3, continue with part 4 exit 0 exit 0 # Just in case... -- Please send comp.sources.unix-related mail to rsalz@uunet.uu.net. Use a domain-based address or give alternate paths, or you may lose out.