home *** CD-ROM | disk | FTP | other *** search
- Subject: v24i065: Purdue software product installation system, Part03/07
- Newsgroups: comp.sources.unix
- Approved: rsalz@uunet.UU.NET
- X-Checksum-Snefru: 0d6c1fc0 72ec59c9 f3e3e0bb 98f91467
-
- Submitted-by: Kevin Braunsdorf <ksb@nostromo.cc.purdue.edu>
- Posting-number: Volume 24, Issue 65
- Archive-name: pucc-install/part03
-
- Submitted-by: ksb@cc.purdue.edu (Kevin Braunsdorf)
- Archive-name: pucc-1b/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...
-