home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume24 / pucc-install / part03 < prev    next >
Encoding:
Internet Message Format  |  1991-03-19  |  52.3 KB

  1. Subject:  v24i065:  Purdue software product installation system, Part03/07
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 0d6c1fc0 72ec59c9 f3e3e0bb 98f91467
  5.  
  6. Submitted-by: Kevin Braunsdorf <ksb@nostromo.cc.purdue.edu>
  7. Posting-number: Volume 24, Issue 65
  8. Archive-name: pucc-install/part03
  9.  
  10. Submitted-by: ksb@cc.purdue.edu (Kevin Braunsdorf)
  11. Archive-name: pucc-1b/part03
  12.  
  13. #!/bin/sh
  14. # This is part 03 of pucc-1b
  15. # ============= install.d/main.c ==============
  16. if test ! -d 'install.d'; then
  17.     echo 'x - creating directory install.d'
  18.     mkdir 'install.d'
  19. fi
  20. if test -f 'install.d/main.c' -a X"$1" != X"-c"; then
  21.     echo 'x - skipping install.d/main.c (File already exists)'
  22. else
  23. echo 'x - extracting install.d/main.c (Text)'
  24. sed 's/^X//' << 'Purdue' > 'install.d/main.c' &&
  25. /*
  26. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  27. X * 47907.  All rights reserved.
  28. X *
  29. X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  30. X *
  31. X * This software is not subject to any license of the American Telephone
  32. X * and Telegraph Company or the Regents of the University of California.
  33. X *
  34. X * Permission is granted to anyone to use this software for any purpose on
  35. X * any computer system, and to alter it and redistribute it freely, subject
  36. X * to the following restrictions:
  37. X *
  38. X * 1. Neither the authors nor Purdue University are responsible for any
  39. X *    consequences of the use of this software.
  40. X *
  41. X * 2. The origin of this software must not be misrepresented, either by
  42. X *    explicit claim or by omission.  Credit to the authors and Purdue
  43. X *    University must appear in documentation and sources.
  44. X *
  45. X * 3. Altered versions must be plainly marked as such, and must not be
  46. X *    misrepresented as being the original software.
  47. X *
  48. X * 4. This notice may not be removed or altered.
  49. X */
  50. X
  51. /*
  52. X * install
  53. X *    Install a <file> and back up the existing file to a standard
  54. X *    location (normally a sub-directory named "OLD").  The name is always
  55. X *    "OLD/<file>".  Name clashes in OLD are resolved by renaming an existing
  56. X *    OLD/<file> to OLD/<file><pid>.  The OLD files should be cleaned
  57. X *    up with a script that removes aged files (see purge(1l)).
  58. X *
  59. X * Authors:
  60. X *    Jeff Smith (jms) & Kevin Braunsdorf (ksb)
  61. X *    Purdue University Computing Center
  62. X *    Math Building, Purdue, West Lafayette, IN, 47906
  63. X *
  64. X *    15 Nov 1985    to    01 June 1990
  65. X *
  66. X * Usage
  67. X *    install [options] file [files] destination
  68. X *    install -d [options] directory
  69. X *    install -R [options] file
  70. X *    install -[Vh]
  71. X *
  72. X *     file(s):    an absolute or relative path.  If > 1 file to
  73. X *        install is specified, destination must be a directory.
  74. X *
  75. X *    destination:    a pathname ending in either the destination
  76. X *        directory or a filename which may be the same as or different
  77. X *        than the tail of file(s).
  78. X *
  79. X * mk(1l) stuff:
  80. X * $Compile: make all
  81. X * $Compile: SYS=bsd make all
  82. X * $Compile: SYS=SYSV make all
  83. X *
  84. X * Environment:
  85. X *    Set the environment variable INSTALL to any of the options to get the
  86. X *    same effect as using them on the command line (e.g., INSTALL="-c").
  87. X *    Command line options silently override environental variables.
  88. X *
  89. X * N.B.
  90. X *    + "OLD" directories may *not* be mount points!
  91. X *    + the TMPINST macro file may be removed by purge after only few hours
  92. X *
  93. X * BUGS:
  94. X *    + competing installs can (still) loose data :-{!
  95. X *      if two users are installing the same file at the same time
  96. X *      we can loose one of the two updates, use the flock(1)
  97. X *      command on the destination directory to avoid this in the shell.
  98. X *      (using flock(2) we *could* avoid this, see notes in main)
  99. X *        flock ${BIN} install -vs ${PROG} ${BIN}
  100. X */
  101. X
  102. #if !defined(lint)
  103. static char *rcsid = "$Id: main.c,v 7.0 90/09/17 09:41:57 ksb Exp $";
  104. #endif    /* !lint */
  105. X
  106. #include <sys/param.h>
  107. #include <sys/types.h>
  108. #include <sys/stat.h>
  109. #include <stdio.h>
  110. #include <pwd.h>
  111. #include <grp.h>
  112. X
  113. #include "configure.h"
  114. #include "install.h"
  115. #include "syscalls.h"
  116. #include "special.h"
  117. #include "file.h"
  118. #include "dir.h"
  119. #include "main.h"
  120. X
  121. #if STRINGS
  122. #include <strings.h>
  123. #else
  124. #include <string.h>
  125. #endif
  126. X
  127. extern char *realloc(), *malloc();
  128. X
  129. #include "getopt.h"        /* char *optarg; int optind;        */
  130. #if !defined(BADCH)        /* char getopt returns for illegal options */
  131. #define    BADCH    ((int) '\?')
  132. #endif    /* !BADCH */
  133. X
  134. X
  135. /* global variables for options
  136. X */
  137. char *progname;            /* tail of argv[0]            */
  138. char *Group = (char *)0;    /* given group ownership        */
  139. char *Owner = (char *)0;    /* given owner                */
  140. char *Mode = (char *)0;        /* given mode                */
  141. char *HardLinks = (char *)0;    /* hard links to installed file        */
  142. char *SoftLinks = (char *)0;    /* symlinks to installed file        */
  143. int Copy = FALSE;        /* we're copying            */
  144. int Destroy = FALSE;        /* user doesn't want an OLD        */
  145. int BuildDir = FALSE;        /* we're installing a directory        */
  146. int KeepTimeStamp = FALSE;    /* if preserving timestamp        */
  147. int fQuiet = FALSE;        /* suppress some errors, be quiet    */
  148. int Ranlib = FALSE;        /* if we're running ranlib(1)        */
  149. int Strip = FALSE;        /* if we're running strip(1)        */
  150. int fDelete = FALSE;        /* uninstall the given file/dir        */
  151. int fRecurse = FALSE;        /* Sun-like recursive dir install    */
  152. int fTrace = FALSE;        /* if just tracing            */
  153. int fVerbose = FALSE;        /* if verbose                */
  154. int f1Copy = FALSE;        /* only keep one copy            */
  155. #if defined(CONFIG)
  156. struct passwd *pwdDef;        /* aux default owner for config file    */
  157. struct group *grpDef;        /* aux default group for config file    */
  158. char *pcSpecial = CONFIG;    /* file contains ckecked paths        */
  159. #endif    /* have a -C option?            */
  160. X
  161. /*
  162. X * global variables, but not option flags
  163. X */
  164. int bHaveRoot;            /* we have root permissions        */
  165. char *pcGuilty;            /* the name logged as the installer    */
  166. static char copyright[] =
  167. X   "@(#) Copyright 1990 Purdue Research Foundation. All rights reserved.\n";
  168. X
  169. X
  170. /*
  171. X * Print detailed usage info
  172. X */
  173. static char *apcHelp[] = {
  174. X    "1        keep exactly one backup of the installed file",
  175. #if defined(CONFIG)
  176. X    "C config use <config> to check for special files",
  177. #endif /* no -C option to list            */
  178. X    "D        destroy <destination> (no backup)",
  179. X    "H links  hard links to update (colon separated)",
  180. X    "R        remove the given target",
  181. #if HAVE_SLINKS
  182. X    "S links  symbolic links to update (colon separated)",
  183. #endif    /* no symbolic links to worry about    */
  184. X    "V        explain compiled in default modes",
  185. X    "c        copy <file> instead of renaming it",
  186. X    "d        install a directory (mkdir with specified mode/group/owner)",
  187. X    "g group  install <file|directory> with group <group>",
  188. X    "h        help (print this)",
  189. X    "l        run ranlib(1) on <file>",
  190. X    "m mode   install <file|directory> with mode <mode>",
  191. X    "n        trace execution but do not do anything",
  192. X    "o owner  install <file|directory> with owner <owner>",
  193. X    "p        preserve timestamp of file being installed",
  194. X    "q        if install can recover from the error be quiet",
  195. X    "r        build all intervening directories",
  196. X    "s        run strip(1) on <file>",
  197. X    "v        run ls(1) on installed files and backups",
  198. X    (char *)0
  199. };
  200. X
  201. #if defined(CONFIG)
  202. char acVArgs[] =
  203. X    "[-C config]";
  204. char acDArgs[] =
  205. X    "[-nqrv] [-C config] [-g group] [-m mode] [-o owner]";
  206. #if HAVE_SLINKS
  207. char acOArgs[] =
  208. X    "[-1Dclnpqsv] [-C config] [-H links] [-S links] [-g group] [-m mode] [-o owner]";
  209. #else
  210. char acOArgs[] =
  211. X    "[-1Dclnpqsv] [-C config] [-H links] [-g group] [-m mode] [-o owner]";
  212. #endif
  213. X
  214. #else    /* change usage messgae, reflect CONFIG    */
  215. char acVArgs[] =
  216. X    "";
  217. char acDArgs[] =
  218. X    "[-nqrv] [-g group] [-m mode] [-o owner]";
  219. #if HAVE_SLINKS
  220. char acOArgs[] =
  221. X    "[-1Dclnpqsv] [-H links] [-S links] [-g group] [-m mode] [-o owner]";
  222. #else
  223. char acOArgs[] =
  224. X    "[-1Dclnpqsv] [-H links] [-g group] [-m mode] [-o owner]";
  225. #endif
  226. #endif /* no -C option to list            */
  227. X
  228. /*
  229. X * Output a useful, std usage message. Maybe a longer one if requested    (ksb)
  230. X */
  231. static void
  232. Usage(fp, bVerbose)
  233. FILE *fp;        /* file to output to                */
  234. int bVerbose;        /* should we explain options more        */
  235. {
  236. X    register char **ppc;
  237. X
  238. X    (void)fprintf(fp, "%s: usage %s files destination\n", progname, acOArgs);
  239. X    (void)fprintf(fp, "%s: usage -d %s directory\n", progname, acDArgs);
  240. X    (void)fprintf(fp, "%s: usage -h\n", progname);
  241. X    (void)fprintf(fp, "%s: usage -R [options] target\n", progname);
  242. X    (void)fprintf(fp, "%s: usage -V %s\n", progname, acVArgs);
  243. X    if (bVerbose) {
  244. X        for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) {
  245. X            (void)fprintf(fp, *ppc, OLDDIR);
  246. X            (void)fputc('\n', fp);
  247. X        }
  248. X        fprintf(fp, "%s", copyright);
  249. X    }
  250. }
  251. X
  252. X
  253. /*
  254. X * first non-nil argument                        (ksb)
  255. X */
  256. static char *
  257. nonnil(pc1, pc2)
  258. char *pc1, *pc2;
  259. {
  260. X    if ((char *)0 != pc1)
  261. X        return pc1;
  262. X    if ((char *)0 != pc2)
  263. X        return pc2;
  264. #if defined(DEBUG)
  265. X    Die("nil pointer in nonnil");
  266. #endif
  267. X    return (char *)0;
  268. }
  269. X
  270. /*
  271. X * explain to the poor user what install will use as modes here        (ksb)
  272. X */
  273. static void
  274. Explain(fp)
  275. FILE *fp;
  276. {
  277. X    static char acDMsg[] = "inherited";
  278. X    auto struct passwd *pwd;    /* owner of this dir.        */
  279. X    auto struct group *grp;        /* group of this directory    */
  280. X
  281. X    (void)fprintf(fp, "%s: version: %s\n", progname, "$Id: main.c,v 7.0 90/09/17 09:41:57 ksb Exp $");
  282. #if defined(CONFIG)
  283. 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);
  284. #endif
  285. #if defined(INST_FACILITY)
  286. X    (void)fprintf(fp, "%s: syslog facility: %d\n", progname, INST_FACILITY);
  287. #endif
  288. X    (void)fprintf(fp, "%s: superuser (%s) defaults:\n", progname, pcGuilty);
  289. X    (void)fprintf(fp, "%s: owner is file=%-10s dir=%-10s %s=%s\n", progname,
  290. X        nonnil(DEFOWNER, acDMsg),
  291. X        nonnil(DEFDIROWNER, acDMsg),
  292. X        OLDDIR,
  293. X        nonnil(ODIROWNER, acDMsg)
  294. X    );
  295. X    (void)fprintf(fp, "%s: group is file=%-10s dir=%-10s %s=%s\n", progname,
  296. X        nonnil(DEFGROUP, acDMsg),
  297. X        nonnil(DEFDIRGROUP, acDMsg),
  298. X        OLDDIR,
  299. X        nonnil(ODIRGROUP, acDMsg)
  300. X    );
  301. X    (void)fprintf(fp, "%s: mode is  file=%-10s dir=%-10s %s=%s\n", progname,
  302. X        nonnil(DEFMODE, acDMsg),
  303. X        nonnil(DEFDIRMODE, acDMsg),
  304. X        OLDDIR,
  305. X        nonnil(ODIRMODE, acDMsg)
  306. X    );
  307. X
  308. X    if (bHaveRoot) {
  309. X        /* we assume the super user doesn't care about Joe User */
  310. X        return;
  311. X    }
  312. X
  313. X    (void)setpwent();
  314. X    if ((struct passwd *)0 == (pwd = getpwuid((int) geteuid()))) {
  315. X        (void)fprintf(stderr, "%s: getpwuid: %d (effective uid) not found\n", progname, geteuid());
  316. X        exit(1);
  317. X    }
  318. X    (void)endpwent();
  319. X
  320. X    (void)setgrent();
  321. X    if ((struct group *)0 == (grp = getgrgid((int) getegid()))) {
  322. X        (void)fprintf(stderr, "%s: getgrgid: %d (effective gid) not found\n", progname, getegid());
  323. X        exit(1);
  324. X    }
  325. X    (void)endgrent();
  326. X    (void)fprintf(fp, "%s: user defaults:\n", progname);
  327. X    (void)fprintf(fp, "%s: owner is file=%-10s dir=%-10s %s=%s\n", progname,
  328. X        pwd->pw_name,
  329. X        pwd->pw_name,
  330. X        OLDDIR,
  331. X        pwd->pw_name
  332. X    );
  333. X    (void)fprintf(fp, "%s: group is file=%-10s dir=%-10s %s=%s\n", progname,
  334. X        grp->gr_name,
  335. X        grp->gr_name,
  336. X        OLDDIR,
  337. X        grp->gr_name
  338. X    );
  339. X    (void)fprintf(fp, "%s: mode is  file=%-10s dir=%-10s %s=%s\n", progname,
  340. X        nonnil(DEFMODE, acDMsg),
  341. X        nonnil(DEFDIRMODE, acDMsg),
  342. X        OLDDIR,
  343. X        nonnil(ODIRMODE, acDMsg)
  344. X    );
  345. }
  346. X
  347. X
  348. static char acOutMem[] = "%s: out of memory\n";
  349. /*
  350. X * OptAccum
  351. X * Accumulate a string, for string options that "append with a sep"    (ksb)
  352. X * note: arg must start out as either "(char *)0" or a malloc'd string
  353. X */
  354. static char *
  355. OptAccum(pcOld, pcArg, pcSep)
  356. char *pcOld, *pcArg, *pcSep;
  357. {
  358. X    register int len;
  359. X    register char *pcNew;
  360. X
  361. X    /* Do not add null strings
  362. X     */
  363. X    len = strlen(pcArg);
  364. X    if (0 == len) {
  365. X        return pcOld;
  366. X    }
  367. X
  368. X    if ((char *)0 == pcOld) {
  369. X        pcNew = malloc(len+1);
  370. X        if ((char *)0 == pcNew) {
  371. X            (void)fprintf(stderr, acOutMem, progname);
  372. X            exit(1);
  373. X        }
  374. X        pcNew[0] = '\000';
  375. X    } else {
  376. X        len += strlen(pcOld)+strlen(pcSep)+1;
  377. X        if ((char *)0 == (pcNew = realloc(pcOld, len))) {
  378. X            (void)fprintf(stderr, acOutMem, progname);
  379. X            exit(1);
  380. X        }
  381. X        (void)strcat(pcNew, pcSep);
  382. X    }
  383. X    pcOld = strcat(pcNew, pcArg);
  384. X    return pcOld;
  385. }
  386. X
  387. X
  388. /*
  389. X * parse options with getopt and install files
  390. X */
  391. int
  392. main(argc, argv)
  393. int argc;
  394. char **argv;
  395. {
  396. X    extern char *getenv();    /* we want an env var            */
  397. X    extern char *getlogin();
  398. X    static char Opts[] =    /* valid options            */
  399. X        "1cC:dDg:hH:lm:no:pqrRsS:vV";
  400. X    auto char *pcEnv;    /* options passed through env        */
  401. X    auto char *Dest;    /* destination dir or filename        */
  402. X    auto int iOption;    /* argument pointer            */
  403. X    auto int iFailed;    /* installs that failed            */
  404. X    auto int iArgs;        /* args left after option processing    */
  405. X    auto int fExplain;    /* tell the user about our defaults    */
  406. X
  407. X    (void)umask(022);
  408. X
  409. X    /* Figure out our name and fix argv[0] for getopt() if necessary.
  410. X     */
  411. X    progname = StrTail(argv[0]);
  412. X    if (NULL == progname || '\000' == *progname)
  413. X        progname = "install";
  414. X    /* here we become deinstall, or deinstallp
  415. X     * a little gem for those who like to pick through source code...
  416. X     */
  417. X    if ('d' == progname[0] && 'e' == progname[1]) {
  418. X        fDelete = TRUE;
  419. X    }
  420. X    iFailed = 0;
  421. X
  422. X    /* Check for environtment options
  423. X     */
  424. X    if ((char *)0 != (pcEnv = getenv("INSTALL"))) {
  425. X        envopt(pcEnv);
  426. X    }
  427. X
  428. X    /* See if we have root permissions, this changes default modes/owners
  429. X     */
  430. X    bHaveRoot = 0 == geteuid();
  431. X
  432. X    /* Parse command line options, set flags, etc.
  433. X     */
  434. X    fExplain = FALSE;
  435. X    while (EOF != (iOption = getopt(argc, argv, Opts))) {
  436. X        switch (iOption) {
  437. X        case '1':
  438. X            f1Copy = TRUE;
  439. X            break;
  440. X        case 'c':    /* copy        */
  441. X            Copy = TRUE;
  442. X            break;
  443. X        case 'C':    /* check list    */
  444. #if defined(CONFIG)
  445. X            pcSpecial = optarg;
  446. X            break;
  447. #else /* give them an error */
  448. X            (void)fprintf(stderr, "%s: check list option not installed\n", progname);
  449. X            exit(EXIT_OPT);
  450. #endif    /* set check flags from config file    */
  451. X        case 'S':    /* soft links    */
  452. #if HAVE_SLINKS
  453. X            SoftLinks = OptAccum(SoftLinks, optarg, ":");
  454. X            break;
  455. #else    /* no symlink, warn and use hard ones    */
  456. X            (void)fprintf(stderr, "%s: no symbolic links here, trying hard links\n", progname);
  457. X            /*fall through*/
  458. #endif    /* handle -S based on OS        */
  459. X        case 'H':    /* hard links    */
  460. X            HardLinks = OptAccum(HardLinks, optarg, ":");
  461. X            break;
  462. X        case 'd':    /* directory    */
  463. X            BuildDir = TRUE;
  464. X            break;
  465. X        case 'D':    /* destroy    */
  466. X            Destroy = TRUE;
  467. X            break;
  468. X        case 'g':    /* change group    */
  469. X            Group = optarg;
  470. X            break;
  471. X        case 'h':    /* help        */
  472. X            Usage(stdout, 1);
  473. X            exit(0);
  474. X            break;
  475. X        case 'l':    /* ranlib    */
  476. X            Ranlib = TRUE;
  477. X            break;
  478. X        case 'm':    /* change mode    */
  479. X            Mode = optarg;
  480. X            break;
  481. X        case 'n':    /* execution trace */
  482. X            fTrace = TRUE;
  483. X            break;
  484. X        case 'o':    /* change owner    */
  485. X            Owner = optarg;
  486. X            break;
  487. X        case 'p':    /* preserve time */
  488. X            KeepTimeStamp = TRUE;
  489. X            break;
  490. X        case 'q':    /* be quiet */
  491. X            fQuiet = TRUE;
  492. X            break;
  493. X        case 'r':    /* install -d -r /a/b build /a and /a/b */
  494. X            fRecurse = TRUE;
  495. X            break;
  496. X        case 'R':    /* deintstall    */
  497. X            fDelete = TRUE;
  498. X            break;
  499. X        case 's':    /* strip(1)    */
  500. X            Strip = TRUE;
  501. X            break;
  502. X        case 'v':    /* run ls(1)    */
  503. X            fVerbose = TRUE;
  504. X            break;
  505. X        case 'V':
  506. X            fExplain = TRUE;
  507. X            break;
  508. X        case BADCH:    /* illegal option */
  509. X            Usage(stderr, 0);
  510. X            exit(EXIT_OPT);
  511. X            break;
  512. X        /* Since getopt should have caught all problems, this has
  513. X         * to be an error
  514. X         */
  515. X        default:
  516. X            Die("command line parsing bug");
  517. X        }
  518. X    }
  519. X
  520. X    /* Usage checks.  If installing > 1 file, the destination
  521. X     * must be a directory which already exists.
  522. X     */
  523. X    if (FALSE != Strip && FALSE != Ranlib) {
  524. X        (void)fprintf(stderr, "%s: options `-l\' and `-s\' are incompatible\n", progname);
  525. X        exit(EXIT_OPT);
  526. X    }
  527. X    if (FALSE != Ranlib && FALSE != KeepTimeStamp) {
  528. X        (void)fprintf(stderr, "%s: option `-l\' suppresses `-p\'\n", progname);
  529. X    }
  530. X    if ((char *)0 != Mode) {
  531. X        auto char *pcMsg; /* error, build a b,c,s,l,p message    */
  532. X        auto int mMust;      /* bits in mode to build        */
  533. X        auto int m_Opt;      /* discard optional bits        */
  534. X        auto char chType;
  535. X        auto char *pcUse;
  536. X        auto char acShow[20];
  537. X
  538. X        CvtMode(Mode, & mMust, & m_Opt);
  539. X        pcMsg = NodeType(mMust, &chType);
  540. X        switch (chType) {
  541. X        case 'd':
  542. X            BuildDir = TRUE;
  543. X            break;
  544. X        case '-':
  545. X            break;
  546. X        case 's':
  547. X            for (;;) {
  548. X                pcUse = "a server";
  549. X                break;
  550. X        case 'l':
  551. X                pcUse = "ln -s";
  552. X                break;
  553. X        case 'p':
  554. X        case 'b':
  555. X        case 'c':
  556. X                (void)sprintf(acShow, "mknod %c", chType);
  557. X                pcUse = acShow;
  558. X                break;
  559. X            }
  560. X        default:
  561. X            (void)fprintf(stderr, "%s: to build a %s use %s\n", progname, pcMsg, pcUse);
  562. X            exit(1);
  563. X        }
  564. X    }
  565. X
  566. #if defined(INST_FACILITY)
  567. X    if (bHaveRoot && FALSE == fTrace) {
  568. X        openlog(progname, 0, INST_FACILITY);
  569. X    }
  570. #endif    /* we need to start syslog        */
  571. X    pcGuilty = getlogin();
  572. X    if ((char *)0 == pcGuilty || '\000' == *pcGuilty) {
  573. X        pcGuilty = getenv("USER");
  574. X        if ((char *)0 == pcGuilty || '\000' == *pcGuilty)
  575. X            pcGuilty = "root\?";
  576. X    }
  577. X
  578. #if defined(CONFIG)
  579. X    InitCfg((char *)0, (char *)0);
  580. #endif
  581. X
  582. X    iArgs = argc - optind;
  583. X    if (FALSE != fExplain) {
  584. X        Explain(stdout);
  585. X    } else if (FALSE != BuildDir) {
  586. X        auto char *pcSlash, *pcDir;
  587. X
  588. X        /* this check keeps Joe Bogus from having
  589. X         *  INSTALL=-vd
  590. X         * in the environment break every program that uses install.
  591. X         */
  592. X        if (1 != iArgs) {
  593. X            (void)fprintf(stderr, "%s: only a single directory name may be given with -d\n", progname);
  594. X            Usage(stderr, 0);
  595. X            exit(EXIT_OPT);
  596. X        }
  597. X        if ((char *)0 != HardLinks) {
  598. X            (void)fprintf(stderr, "%s: directories cannot have mulitple hard links, use -S\n", progname);
  599. X            exit(EXIT_OPT);
  600. X        }
  601. X        if ((FALSE != Destroy || FALSE != f1Copy) && FALSE == fQuiet) {
  602. X            (void)fprintf(stderr, "%s: -d ignores -D and -1\n", progname);
  603. X        }
  604. X        if ((FALSE != Strip || FALSE != Ranlib) && FALSE != fQuiet) {
  605. X            (void)fprintf(stderr, "%s: -d cannot strip or ranlib a directory\n", progname);
  606. X        }
  607. X
  608. X        /* StrTail cuts trailing '/'s
  609. X         * If we are building an OLD dir do it correctly
  610. X         */
  611. X        pcDir = argv[argc-1];
  612. X        if (0 == strcmp(OLDDIR, StrTail(pcDir))) {
  613. X            pcSlash = strrchr(pcDir, '/');
  614. X            if ((char *)0 == pcSlash) {
  615. X                /* nothing to do, in `pwd` */;
  616. X            } else if (pcSlash == pcDir) {
  617. X                /* build "/", sure... done */;
  618. X            } else if (FALSE != fRecurse) {
  619. X                *pcSlash = '\000';
  620. X                if (!fDelete && FAIL == DirInstall(pcDir, Owner, Group, Mode, DEFDIROWNER, DEFDIRGROUP, DEFDIRMODE, (char *)0, 0)) {
  621. X                    exit(1);
  622. X                }
  623. X                *pcSlash = '/';
  624. X                /* yeah, odd... but -n look right this way */
  625. X                fRecurse = FALSE;
  626. X            }
  627. X            /* letting the user symlink to an OLD dir is very
  628. X             * bogus, we do it only because I cannot think
  629. X             * of a good error message.... (ksb)
  630. X             */
  631. X            if (FAIL == DirInstall(pcDir, FALSE == bHaveRoot ? (char *)0 : ODIROWNER, FALSE == bHaveRoot ? (char *)0 : ODIRGROUP, ODIRMODE, (char *)0, (char *)0, (char *)0, SoftLinks, fDelete)) {
  632. X                exit(1);
  633. X            }
  634. X        } else if (FAIL == DirInstall(pcDir, Owner, Group, Mode, DEFDIROWNER, DEFDIRGROUP, DEFDIRMODE, SoftLinks, fDelete)) {
  635. X            exit(1);
  636. X        }
  637. X    } else if (fDelete) {
  638. X        if (iArgs != 1) {
  639. X            (void)fprintf(stderr, "%s: just give one target to remove\n", progname);
  640. X            Usage(stderr, 0);
  641. X            exit(EXIT_OPT);
  642. X        }
  643. X        if (FALSE != Destroy) {
  644. X            (void)fprintf(stderr, "%s: -D changed to -1 to preserve last copy of target\n", progname);
  645. X            Destroy = FALSE;
  646. X            f1Copy = TRUE;
  647. X        }
  648. X        if (FAIL == Install("-", argv[optind], HardLinks, SoftLinks)) {
  649. X            ++iFailed;
  650. X        }
  651. X    } else {
  652. X        if (iArgs < 2) {
  653. X            (void)fprintf(stderr, "%s: need both source and destination\n", progname);
  654. X            Usage(stderr, 0);
  655. X            exit(EXIT_OPT);
  656. X        }
  657. X
  658. X        Dest = argv[argc - 1];
  659. X        if (iArgs > 2 && IsDir(Dest) == FALSE) {
  660. X            (void)fprintf(stderr, "%s: `%s\' must be an existing directory to install multiple files or directories\n", progname, Dest);
  661. X            Usage(stderr, 0);
  662. X            exit(EXIT_OPT);
  663. X        }
  664. X
  665. X        if (iArgs > 2 && ((char *)0 != HardLinks || (char *)0 != SoftLinks)) {
  666. X            (void)fprintf(stderr, "%s: -H or -S option ambiguous with multiple source files\n", progname);
  667. X            exit(EXIT_OPT);
  668. X        }
  669. X
  670. X        /* install the files
  671. X         */
  672. X        for (--argc; optind < argc; optind++) {
  673. X            if (FAIL == Install(argv[optind], Dest, HardLinks, SoftLinks)) {
  674. X                (void)fprintf(stderr, "%s: installation of `%s\' failed\n", progname, argv[optind]);
  675. X                ++iFailed;
  676. X            }
  677. X        }
  678. X    }
  679. X
  680. #if defined(INST_FACILITY)
  681. X    if (bHaveRoot && FALSE == fTrace) {
  682. X        closelog();
  683. X    }
  684. #endif    /* close-m up for now            */
  685. X
  686. X    exit(iFailed);
  687. }
  688. Purdue
  689. chmod 0444 install.d/main.c ||
  690. echo 'restore of install.d/main.c failed'
  691. Wc_c="`wc -c < 'install.d/main.c'`"
  692. test 19085 -eq "$Wc_c" ||
  693.     echo 'install.d/main.c: original size 19085, current size' "$Wc_c"
  694. fi
  695. # ============= install.d/syscalls.c ==============
  696. if test -f 'install.d/syscalls.c' -a X"$1" != X"-c"; then
  697.     echo 'x - skipping install.d/syscalls.c (File already exists)'
  698. else
  699. echo 'x - extracting install.d/syscalls.c (Text)'
  700. sed 's/^X//' << 'Purdue' > 'install.d/syscalls.c' &&
  701. /*
  702. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  703. X * 47907.  All rights reserved.
  704. X *
  705. X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  706. X *
  707. X * This software is not subject to any license of the American Telephone
  708. X * and Telegraph Company or the Regents of the University of California.
  709. X *
  710. X * Permission is granted to anyone to use this software for any purpose on
  711. X * any computer system, and to alter it and redistribute it freely, subject
  712. X * to the following restrictions:
  713. X *
  714. X * 1. Neither the authors nor Purdue University are responsible for any
  715. X *    consequences of the use of this software.
  716. X *
  717. X * 2. The origin of this software must not be misrepresented, either by
  718. X *    explicit claim or by omission.  Credit to the authors and Purdue
  719. X *    University must appear in documentation and sources.
  720. X *
  721. X * 3. Altered versions must be plainly marked as such, and must not be
  722. X *    misrepresented as being the original software.
  723. X *
  724. X * 4. This notice may not be removed or altered.
  725. X */
  726. X
  727. /*
  728. X * filer the unix system calls so they are more verbose or ineffective    (ksb)
  729. X * under some options
  730. X */
  731. #if !defined(lint)
  732. static char *rcsid = "$Id: syscalls.c,v 7.2 90/10/23 11:01:40 ksb Exp $";
  733. #endif    /* !lint */
  734. X
  735. #include <sys/param.h>
  736. #include <sys/types.h>
  737. #include <sys/stat.h>
  738. #include <sys/file.h>
  739. #include <sys/time.h>
  740. #include <stdio.h>
  741. #include <ctype.h>
  742. #include <errno.h>
  743. #include <pwd.h>
  744. #include <grp.h>
  745. X
  746. #include "configure.h"
  747. #include "install.h"
  748. #include "main.h"
  749. X
  750. #if STRINGS
  751. #include <strings.h>
  752. #else
  753. #include <string.h>
  754. #endif
  755. X
  756. extern char *malloc();
  757. X
  758. X
  759. #if !defined(BINCHGRP)
  760. #define BINCHGRP    "/bin/chgrp"
  761. #endif
  762. X
  763. static char acChgrp[] =        /* full path name to chgrp        */
  764. X    BINCHGRP;
  765. X
  766. X
  767. static int iSigsBlocked = 0;    /* count nested calls            */
  768. X
  769. #if defined(pdp11) || defined(SYSV) || defined(HPUX7)
  770. #else    /* BSD */
  771. static int OldSigMask;        /* old signal mask            */
  772. #endif    /* mask singals old way */
  773. /*
  774. X * Mask all maskable signals                         (jsmith)
  775. X * is we mask CHLD ranlib breaks (actually the shell does)
  776. X */
  777. void
  778. BlockSigs()
  779. {
  780. X    if (0 == iSigsBlocked++) {
  781. #if defined(pdp11) || defined(SYSV) || defined(HPUX7)
  782. X        register int    i;
  783. X        for (i = 0; i < NSIG; i++) {
  784. X            signal(i, SIG_IGN);
  785. X        }
  786. #else    /* BSD */
  787. X        register int Mask;
  788. X        Mask = sigmask(SIGHUP)|sigmask(SIGTERM)|
  789. X            sigmask(SIGINT)|sigmask(SIGTSTP)|sigmask(SIGQUIT);
  790. X        OldSigMask = sigsetmask(Mask);
  791. #endif    /* do signal stuff */
  792. X    }
  793. }
  794. X
  795. X
  796. /*
  797. X * Return the signal mask to what it was in before BlockSigs()         (jsmith)
  798. X */
  799. void
  800. UnBlockSigs()
  801. {
  802. X    if (0 == --iSigsBlocked) {
  803. #if defined(pdp11) || defined(SYSV) || defined(HPUX7)
  804. X        register int i;
  805. X
  806. X        for (i = 0; i < NSIG; i++) {
  807. X            signal(i, SIG_DFL);
  808. X        }
  809. #else    /* BSD */
  810. X        (void)sigsetmask(OldSigMask);
  811. #endif    /* more signal stuff */
  812. X    }
  813. }
  814. X
  815. X
  816. /*
  817. X * install suffers an internal error and exits abruptly            (ksb)
  818. X * (really just a good break point for dbx/gdb/sdb)
  819. X */
  820. void
  821. Die(pcError)
  822. char *pcError;        /* error message, last gasp as we croak        */
  823. {
  824. X    (void)fprintf(stderr, "%s: internal error: %s\n", progname, pcError);
  825. X    exit(EXIT_INTER);
  826. }
  827. X
  828. X
  829. #define safecopy(Mdst, Msrc, Mfield, Mpc) \
  830. X    if ((char *)0 != Msrc->Mfield) { \
  831. X        Mdst->Mfield = Mpc; \
  832. X        (void)strcpy(pc, Msrc->Mfield); \
  833. X        Mpc = strchr(Mpc, '\000')+1; \
  834. X    } else { \
  835. X        Mdst->Mfield = (char *)0;\
  836. X    }
  837. X
  838. X
  839. /*
  840. X * this routine saves a group entry in malloced memory            (ksb)
  841. X * simply free it when you are done with it
  842. X */
  843. struct group *
  844. savegrent(pGR)
  845. struct group *pGR;
  846. {
  847. X    register struct group *pGRNew;
  848. X    register int size, i;
  849. X    register char *pc;
  850. X    auto char **ppc;
  851. X
  852. X    if ((struct group *)0 == pGR) {
  853. X        return (struct group *)0;
  854. X    }
  855. X
  856. X    size = sizeof(struct group);
  857. X    if ((char *)0 != pGR->gr_name)
  858. X        size += strlen(pGR->gr_name)+1;
  859. X    if ((char *)0 != pGR->gr_passwd)
  860. X        size += strlen(pGR->gr_passwd)+1;
  861. X    for (i = 0; (char *)0 != pGR->gr_mem[i]; ++i) {
  862. X        size += sizeof(char *) + strlen(pGR->gr_mem[i]) + 1;
  863. X    }
  864. X    size += sizeof(char *);
  865. X
  866. X    if ((char *)0 == (pc = malloc(size))) {
  867. X        return (struct group *)0;
  868. X    }
  869. X
  870. X    pGRNew = (struct group *)pc;
  871. X    pc += sizeof(struct group);
  872. X
  873. X    ppc = (char **) pc;
  874. X    pc += (1+i) * sizeof(char *);
  875. X
  876. X    safecopy(pGRNew, pGR, gr_name, pc);
  877. X    safecopy(pGRNew, pGR, gr_passwd, pc);
  878. X
  879. X    pGRNew->gr_gid = pGR->gr_gid;
  880. X
  881. X    pGRNew->gr_mem = ppc;
  882. X    for (i = 0; (char *)0 != pGR->gr_mem[i]; ++i) {
  883. X        *ppc++ = pc;
  884. X        (void)strcpy(pc, pGR->gr_mem[i]);
  885. X        pc = strchr(pc, '\000')+1;
  886. X    }
  887. X    *ppc = (char *)0;
  888. X
  889. X    return pGRNew;
  890. }
  891. X
  892. X
  893. /*
  894. X * this routine saves a passwd entry in malloced memory            (ksb)
  895. X * simply free it when you are done with it
  896. X */
  897. struct passwd *
  898. savepwent(pPW)
  899. struct passwd *pPW;
  900. {
  901. X    register struct passwd *pPWNew;
  902. X    register int size;
  903. X    register char *pc;
  904. X
  905. X    if ((struct passwd *)0 == pPW) {
  906. X        return (struct passwd *)0;
  907. X    }
  908. X    size = sizeof(struct passwd);
  909. X    if ((char *)0 != pPW->pw_name)
  910. X        size += strlen(pPW->pw_name) +1;
  911. X    if ((char *)0 != pPW->pw_passwd)
  912. X        size += strlen(pPW->pw_passwd) +1;
  913. X    if ((char *)0 != pPW->pw_comment)
  914. X        size += strlen(pPW->pw_comment) +1;
  915. X    if ((char *)0 != pPW->pw_gecos)
  916. X        size += strlen(pPW->pw_gecos) +1;
  917. X    if ((char *)0 != pPW->pw_dir)
  918. X        size += strlen(pPW->pw_dir) +1;
  919. X    if ((char *)0 != pPW->pw_shell)
  920. X        size += strlen(pPW->pw_shell) +1;
  921. X
  922. X    if ((char *)0 == (pc = malloc(size))) {
  923. X        return (struct passwd *)0;
  924. X    }
  925. X    pPWNew = (struct passwd *)pc;
  926. X    pc += sizeof(struct passwd);
  927. X    safecopy(pPWNew, pPW, pw_name, pc);
  928. X    safecopy(pPWNew, pPW, pw_passwd, pc);
  929. X    pPWNew->pw_uid = pPW->pw_uid;
  930. X    pPWNew->pw_gid = pPW->pw_gid;
  931. #if HAVE_QUOTA
  932. X    pPWNew->pw_quota = pPW->pw_quota;
  933. #endif
  934. X
  935. X    safecopy(pPWNew, pPW, pw_comment, pc);
  936. X    safecopy(pPWNew, pPW, pw_gecos, pc);
  937. X    safecopy(pPWNew, pPW, pw_dir, pc);
  938. X    safecopy(pPWNew, pPW, pw_shell, pc);
  939. X
  940. X    return pPWNew;
  941. }
  942. X
  943. #undef    safecopy
  944. X
  945. X
  946. X
  947. /*
  948. X * ChMode()
  949. X *    run chmod(2) on file, or trace doing so
  950. X */
  951. void
  952. ChMode(pcFile, mMode)
  953. char *pcFile;        /* pathname of file to change            */
  954. int mMode;        /* mode to change to                */
  955. {
  956. X    mMode = PERM_BITS(mMode);
  957. X    if (FALSE != fTrace) {
  958. X        (void)printf("%s: chmod %o %s\n", progname, mMode, pcFile);
  959. X    } else if (-1 == chmod(pcFile, mMode)) {
  960. X        (void)fprintf(stderr, "%s: chmod (%04o): %s: %s\n", progname, mMode, pcFile, strerror(errno));
  961. X    }
  962. }
  963. X
  964. X
  965. /*
  966. X * ChGroup()
  967. X *    run chgrp(1) on file (for when we are NOT root)
  968. X *
  969. X * Globals:
  970. X *    Group    - character string specifying the group owner
  971. X */
  972. void
  973. ChGroup(pcFile, pgroup)
  974. char *pcFile;        /* pathname of file to change group of        */
  975. struct group *pgroup;    /* info on group                */
  976. {
  977. X    if (RunCmd(acChgrp, pgroup->gr_name, pcFile) != 0) {
  978. X        (void)fprintf(stderr, "%s: `%s %s %s\' failed\n", progname, acChgrp, pgroup->gr_name, pcFile);
  979. X    }
  980. }
  981. X
  982. X
  983. /*
  984. X * ChOwnGrp()
  985. X *    Change the ownership and group of a file (must be root)
  986. X */
  987. void
  988. ChOwnGrp(pcFile, powner, pgroup)
  989. char *pcFile;        /* the pathname of the file to change        */
  990. struct passwd *powner;    /* info for owner of file            */
  991. struct group *pgroup;    /* info for group of file            */
  992. {
  993. X    if (FALSE != fTrace) {
  994. X        (void)printf("%s: chown %s %s\n", progname, powner->pw_name, pcFile);
  995. X        (void)printf("%s: chgrp %s %s\n", progname, pgroup->gr_name, pcFile);
  996. X    } else if (-1 == chown(pcFile, powner->pw_uid, pgroup->gr_gid)) {
  997. X        (void)fprintf(stderr, "%s: chown: %s: %s\n", progname, pcFile, strerror(errno));
  998. X        /*return anyway*/
  999. X    }
  1000. }
  1001. X
  1002. X
  1003. /*
  1004. X * ChTimeStamp()
  1005. X *    Change the time stamp of an installed file to match the original
  1006. X *    timestamp of the file to install
  1007. X */
  1008. void
  1009. ChTimeStamp(pcFile, pSTTimes)
  1010. char *pcFile;         /* the pathname of the file to change        */
  1011. struct stat *pSTTimes;    /* stat buffer containing timestamp of exemplar    */
  1012. {
  1013. #if defined(SYSV) || defined(HPUX7)
  1014. X    auto time_t tv[2];
  1015. X
  1016. X    tv[0] = pSTTimes->st_atime;
  1017. X    tv[1] = pSTTimes->st_mtime;
  1018. X    if (-1 == utime(pcFile, tv)) {
  1019. X        (void)fprintf(stderr, "%s: utime: %s: %s\n", progname, pcFile, strerror(errno));
  1020. X    }
  1021. #else /* BSD */
  1022. X    auto struct timeval tv[2];
  1023. X
  1024. X    tv[0].tv_sec = pSTTimes->st_atime;
  1025. X    tv[1].tv_sec = pSTTimes->st_mtime;
  1026. X    tv[0].tv_usec = tv[1].tv_usec = 0;
  1027. X    if (-1 == utimes(pcFile, tv)) {
  1028. X        (void)fprintf(stderr, "%s: utimes: %s: %s\n", progname, pcFile, strerror(errno));
  1029. X    }
  1030. #endif    /* BSD */
  1031. }
  1032. X
  1033. /*
  1034. X * DoCopy()
  1035. X *    Copy the file "File" to file "Dest"
  1036. X */
  1037. int
  1038. DoCopy(File, Dest)
  1039. char *File;        /* the file to copy                */
  1040. char *Dest;        /* the target (destination) file        */
  1041. {
  1042. X    register int fdSrc;    /* file descriptors            */
  1043. X    register int fdDest;    /* file to dopy to            */
  1044. X    register int n;        /* number of chars read            */
  1045. X    register int fStdin;    /* are we doing stdin            */
  1046. X    auto char acBlock[BLKSIZ];
  1047. X    auto struct stat statb_File;
  1048. X
  1049. X
  1050. X    fStdin = '-' == File[0] && '\000' == File[1];
  1051. X
  1052. X    if (FALSE != fTrace) {
  1053. X        if (fStdin)
  1054. X            (void)printf("%s: cat - >%s\n", progname, Dest);
  1055. X        else
  1056. X            (void)printf("%s: cp %s %s\n", progname, File, Dest);
  1057. X        return SUCCEED;
  1058. X    }
  1059. X
  1060. X    if (fStdin)
  1061. X        fdSrc = fileno(stdin);
  1062. X    else
  1063. #if defined(pdp11) || defined(SYSV)
  1064. X    if (-1 == (fdSrc = open(File, O_RDONLY))) {
  1065. X        (void)fprintf(stderr, "%s: open: %s: %s\n", progname, File, strerror(errno));
  1066. X    }
  1067. #else    /* BSD */
  1068. X    if (-1 == (fdSrc = open(File, O_RDONLY, 0400))) {
  1069. X        (void)fprintf(stderr, "%s: open: %s: %s\n", progname, File, strerror(errno));
  1070. X    }
  1071. #endif    /* do an open */
  1072. X
  1073. X    if (fstat(fdSrc, &statb_File) < 0) {
  1074. X        (void)fprintf(stderr, "%s: fstat: %s: %s\n", progname, File, strerror(errno));
  1075. X        if (!fStdin)
  1076. X            (void)close(fdSrc);
  1077. X        return FAIL;
  1078. X    }
  1079. X
  1080. X    /* we have to have rw- on the file to strip it later        (ksb)
  1081. X     */
  1082. X    if (-1 == (fdDest = creat(Dest, (int)statb_File.st_mode|0600))) {
  1083. X        (void)fprintf(stderr, "%s: create: %s: %s\n", progname, Dest, strerror(errno));
  1084. X        if (!fStdin)
  1085. X            (void)close(fdSrc);
  1086. X        return FAIL;
  1087. X    }
  1088. X
  1089. X    /* Do the copy here
  1090. X     */
  1091. X    while (0 != (n = read(fdSrc, acBlock, BLKSIZ))) {
  1092. X        if (-1 == n) {
  1093. X            (void)fprintf(stderr, "%s: read: %s: %s\n", progname, File, strerror(errno));
  1094. X            if (!fStdin)
  1095. X                (void)close(fdSrc);
  1096. X            (void)close(fdDest);
  1097. X            (void)unlink(Dest);
  1098. X            return FAIL;
  1099. X        }
  1100. X        if (write(fdDest, acBlock, n) != n) {
  1101. X            (void)fprintf(stderr, "%s: write: %s: %s\n", progname, Dest, strerror(errno));
  1102. X            if (!fStdin)
  1103. X                (void)close(fdSrc);
  1104. X            (void)close(fdDest);
  1105. X            (void)unlink(Dest);
  1106. X            return FAIL;
  1107. X        }
  1108. X    }
  1109. X
  1110. X    if (!fStdin)
  1111. X        (void)close(fdSrc);
  1112. X    (void)close(fdDest);
  1113. X
  1114. X    return SUCCEED;
  1115. }
  1116. X
  1117. X
  1118. /*
  1119. X * StrTail()
  1120. X *    return last element of a pathname
  1121. X */
  1122. char *
  1123. StrTail(pcPath)
  1124. register char *pcPath;    /* pathname to get tail of            */
  1125. {
  1126. X    register char *pcTemp;
  1127. X
  1128. X    /* don't hand strlen() or strrchr() a null pointer
  1129. X     */
  1130. X    if ((char *) NULL == pcPath) {
  1131. X        return (char *)NULL;
  1132. X    }
  1133. X
  1134. X    /* make sure we weren't handed something like "/a/b/" or "/a/b//".
  1135. X     * If we were we don't want to return ++pcTemp
  1136. X     */
  1137. X    while ('/' == *(pcTemp = (pcPath + strlen(pcPath)) - 1)) {
  1138. X        if (pcTemp == pcPath)
  1139. X            break;
  1140. X        *pcTemp = '\000';
  1141. X    }
  1142. X
  1143. X    /* return last element
  1144. X     */
  1145. X    if ((char *) NULL == (pcTemp = strrchr(pcPath, '/')))
  1146. X        return pcPath;
  1147. X    return ++pcTemp;
  1148. }
  1149. X
  1150. X
  1151. /*
  1152. X * call mktemp is fTrace is not set, else replace XXXX... with $$    (ksb)
  1153. X */
  1154. char *
  1155. Mytemp(pcFile)
  1156. char *pcFile;
  1157. {
  1158. X    register char *pcRet;
  1159. X    extern char *mktemp();
  1160. X
  1161. X    if (FALSE != fTrace) {
  1162. X        if ((char *)0 == (pcRet = strchr(pcFile, '\000'))) {
  1163. X            Die("strchr: nil pointer");
  1164. X        }
  1165. X        while (pcRet > pcFile && 'X' == pcRet[-1])
  1166. X            --pcRet;
  1167. X        (void)strcpy(pcRet, "$$");
  1168. X        pcRet = pcFile;
  1169. X    } else if ((char *)0 == (pcRet = mktemp(pcFile))) {
  1170. X        Die("mktemp: nil pointer");
  1171. X    }
  1172. X    return pcRet;
  1173. }
  1174. X
  1175. X
  1176. /*
  1177. X * MungName()
  1178. X *    Mangle a pathname to make it unique (we hope)
  1179. X * (note that the pathname passed must be in a large buffer)
  1180. X */
  1181. void
  1182. MungName(pcName)
  1183. char    *pcName;     /* the name of the file we want to change    */
  1184. {
  1185. X    register char    *pcPat = PATMKTEMP;
  1186. X
  1187. #if defined(pdp11) || defined(SYSV)
  1188. #if defined(SYSV)
  1189. #define MAXNAMLEN    14
  1190. #endif    /* max path component length */
  1191. X    register char    *pcTemp;
  1192. X    register int    iPatLen;
  1193. X
  1194. X    /* Pathname components must be no longer than 14 chars on 2.9bsd
  1195. X     * systems.  If necessary truncate the filename after the first
  1196. X     * 8 chars so we can append "XXXXXX" for Mytemp()
  1197. X     */
  1198. X    if ((pcTemp = strrchr(pcName, '/')) != (char *) 0) {
  1199. X        pcName = ++pcTemp;
  1200. X    }
  1201. X
  1202. X    iPatLen = strlen(pcPat);
  1203. X    if (strlen(pcName) + iPatLen > MAXNAMLEN) {
  1204. X        *(pcName + (MAXNAMLEN - iPatLen)) = '\000';
  1205. X    }
  1206. X
  1207. #endif    /* path name limits */
  1208. X
  1209. X    if (MAXPATHLEN < (strlen(pcName) + strlen(pcPat))) {    /* sanity */
  1210. X        (void)fprintf(stderr, "%s: unreasonably long pathname `%s\'\n", progname, pcName);
  1211. X        exit(EXIT_OPT);
  1212. X    }
  1213. X
  1214. X    /* This is real simple on reasonable operating systems
  1215. X     */
  1216. X    (void)strcat(pcName, pcPat);
  1217. X    (void)Mytemp(pcName);
  1218. }
  1219. X
  1220. X
  1221. #if HAVE_SLINKS
  1222. /*
  1223. X * CopySLink()
  1224. X *    Copy a symbolic link; here we know that pcLink is a symbolic link,
  1225. X *    and pcCopy needs to be clone of it.
  1226. X *
  1227. X * Side Effects
  1228. X *    We might MungName our second argument, if we have to.
  1229. X */
  1230. int
  1231. CopySLink(pcLink, pcCopy)
  1232. char *pcLink, *pcCopy;
  1233. {
  1234. X    auto char acUcb[MAXPATHLEN+1];
  1235. X    auto int iUcbLen;
  1236. #if defined(DYNIX)
  1237. X    auto char acAtt[MAXPATHLEN+1];
  1238. X    auto int iAttLen;
  1239. #endif    /* conditional symbolic links            */
  1240. X
  1241. #if defined(DYNIX)
  1242. X    if ((iAttLen = readclink(pcLink, acAtt, MAXPATHLEN, U_ATT)) <= 0) {
  1243. X        goto std_link;
  1244. X    } else if ((iUcbLen = readclink(pcLink, acUcb, MAXPATHLEN, U_UCB)) < 0) {
  1245. X        (void)fprintf(stderr, "%s: readclink(ucb): %s: %s\n", progname, pcLink, strerror(errno));
  1246. X        return FAIL;
  1247. X    }
  1248. X    acAtt[iAttLen] = '\000';
  1249. X    acUcb[iUcbLen] = '\000';
  1250. X    if ('/' != acAtt[0]) {
  1251. X        if ('/' != acUcb[0]) {
  1252. 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);
  1253. X        } else {
  1254. 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);
  1255. X        }
  1256. X    } else if ('/' != acUcb[0]) {
  1257. 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);
  1258. X    }
  1259. X    if (FALSE != fTrace) {
  1260. X        (void)printf("%s: ln -c att=%s ucb=%s %s\n", progname, acAtt, acUcb, pcCopy);
  1261. X        return SUCCEED;
  1262. X    }
  1263. X    if (0 == csymlink(acUcb, acAtt, pcCopy)) {
  1264. X        return SUCCEED;
  1265. X    }
  1266. X    if (errno != EEXIST) {
  1267. X        (void)fprintf(stderr, "%s: csymlink: %s: %s\n", progname, pcCopy, strerror(errno));
  1268. X        return FAIL;
  1269. X    }
  1270. X    MungName(pcCopy);
  1271. X    if (0 != csymlink(acUcb, acAtt, pcCopy)) {
  1272. X        (void)fprintf(stderr, "%s: csymlink: %s: %s\n", progname, pcCopy, strerror(errno));
  1273. X        return FAIL;
  1274. X    }
  1275. X    return SUCCEED;
  1276. X
  1277. std_link:
  1278. X    /* dynix link code finds a nornal ucb link to copy -- fall into */;
  1279. #endif    /* might have to copy a csymlink    */
  1280. X
  1281. X    if ((iUcbLen = readlink(pcLink, acUcb, MAXPATHLEN)) < 0) {
  1282. X        (void)fprintf(stderr, "%s: readlink: %s: %s\n", progname, pcLink, strerror(errno));
  1283. X        return FAIL;
  1284. X    }
  1285. X
  1286. X    acUcb[iUcbLen] = '\000';
  1287. X    if ('/' != acUcb[0]) {
  1288. X        (void)fprintf(stderr, "%s: link `%s\' is not a full path, it will not point the correct place in OLD\n", progname, pcLink);
  1289. X    }
  1290. X    if (FALSE != fTrace) {
  1291. X        (void)printf("%s: ln -s %s %s\n", progname, acUcb, pcCopy);
  1292. X        return SUCCEED;
  1293. X    }
  1294. X    if (0 == symlink(acUcb, pcCopy)) {
  1295. X        return SUCCEED;
  1296. X    }
  1297. X    if (errno != EEXIST) {
  1298. X        (void)fprintf(stderr, "%s: symlink: %s: %s\n", progname, pcCopy, strerror(errno));
  1299. X        return FAIL;
  1300. X    }
  1301. X    MungName(pcCopy);
  1302. X    if (0 != symlink(acUcb, pcCopy)) {
  1303. X        (void)fprintf(stderr, "%s: symlink: %s: %s\n", progname, pcCopy, strerror(errno));
  1304. X        return FAIL;
  1305. X    }
  1306. X    return SUCCEED;
  1307. }
  1308. #endif    /* don't handle links at all */
  1309. X
  1310. X
  1311. /*
  1312. X * Rename()
  1313. X *    Simulate the vax rename() syscall using link/unlink, or fTrace
  1314. X */
  1315. int
  1316. Rename(pcOrig, pcNew, pcNote)
  1317. char *pcOrig;        /* the original file name            */
  1318. char *pcNew;        /* the name file will have after the rename    */
  1319. char *pcNote;        /* tell the user always?            */
  1320. {
  1321. X    register int fRet;
  1322. X
  1323. X    BlockSigs();
  1324. X
  1325. X    if ((char *)0 != pcNote) {
  1326. X        (void)printf("%s: %s %s to %s\n", progname, pcNote, pcOrig, pcNew);
  1327. X    }
  1328. X
  1329. X    fRet = SUCCEED;
  1330. X    if (FALSE != fTrace) {
  1331. X        (void)printf("%s: mv %s %s\n", progname, pcOrig, pcNew);
  1332. X    } else {
  1333. #if defined(pdp11) || defined(SYSV)
  1334. X        (void)unlink(pcNew);
  1335. X        if (-1 == link(pcOrig, pcNew)) {
  1336. X            (void)fprintf(stderr, "%s: link: %s to %s: %s\n", progname, pcOrig, pcNew, strerror(errno));
  1337. X            fRet = FAIL;
  1338. X        } else if (-1 == unlink(pcOrig)) {
  1339. X            (void)fprintf(stderr, "%s: unlink: %s: %s\n", progname, pcOrig, strerror(errno));
  1340. X            fRet = FAIL;
  1341. X        }
  1342. #else    /* have rename to call        */
  1343. X        if (-1 == rename(pcOrig, pcNew)) {
  1344. X            (void)fprintf(stderr, "%s: rename: %s to %s: %s\n", progname, pcOrig, pcNew, strerror(errno));
  1345. X            fRet = FAIL;
  1346. X        }
  1347. #endif    /* need to invent rename    */
  1348. X    }
  1349. X
  1350. X    UnBlockSigs();
  1351. X
  1352. X    return fRet;
  1353. }
  1354. X
  1355. /*
  1356. X * IsDir()
  1357. X *    find out if a file is a directory, or a symlink to a directory
  1358. X */
  1359. int
  1360. IsDir(dest)
  1361. char *dest;
  1362. {
  1363. X    auto struct stat statb;
  1364. X
  1365. X    if (-1 == stat(dest, &statb)) {
  1366. X        return FALSE;
  1367. X    }
  1368. X
  1369. X    if (S_IFDIR == (statb.st_mode & S_IFMT)) {
  1370. X        return TRUE;
  1371. X    }
  1372. X    return FALSE;
  1373. }
  1374. X
  1375. X
  1376. /*
  1377. X * MyWait()
  1378. X *    loop waiting until given child exits, return the childs status
  1379. X */
  1380. int
  1381. MyWait(pid)
  1382. int pid;        /* process id to wait for            */
  1383. {
  1384. X    auto int wpid;
  1385. #if defined(pdp11) || defined(SYSV) || defined(HPUX7)
  1386. X    auto int status;
  1387. #else    /* BSD */
  1388. X    auto union wait    status;
  1389. #endif    /* set up for a wait */
  1390. X
  1391. X    while ((wpid = wait(&status)) != pid) {
  1392. X        if (wpid == -1)
  1393. X            break;
  1394. X    }
  1395. X
  1396. X    if (wpid == -1) {
  1397. X        /* this happens on the ETA, where did the kid go?
  1398. X         */
  1399. X        if (ECHILD == errno)
  1400. X            return 0;
  1401. X        (void)fprintf(stderr, "%s: wait: %s\n", progname, strerror(errno));
  1402. X        return 1;
  1403. X    }
  1404. X
  1405. #if defined(pdp11) || defined(SYSV) || defined(HPUX7)
  1406. X    return status;
  1407. #else    /* BSD */
  1408. X    return status.w_status;
  1409. #endif    /* return value from wait */
  1410. }
  1411. X
  1412. X
  1413. /*
  1414. X * RunCmd()
  1415. X *    Vfork's & exec's a command and wait's for it to finish
  1416. X *    we return 1 for FAIL here, not FAIL, caller compares to 0
  1417. X *    (as this is the sh(1) convention).
  1418. X */
  1419. int
  1420. RunCmd(cmd, arg1, arg2)
  1421. char *cmd;        /* full pathname of the command            */
  1422. char *arg1;        /* first argument to cmd            */
  1423. char *arg2;        /* second argument to cmd (can be nil)        */
  1424. {
  1425. X    auto char *arg0;    /* basename of cmd            */
  1426. X    register int pid;
  1427. X
  1428. X    arg0 = StrTail(cmd);
  1429. X    if (FALSE != fTrace) {
  1430. X        (void)printf("%s: %s %s", progname, arg0, arg1);
  1431. X        if ((char *)0 != arg2)
  1432. X            (void)printf(" %s", arg2);
  1433. X        (void)fputc('\n', stdout);
  1434. X        return 0;
  1435. X    }
  1436. X
  1437. X    (void)fflush(stdout);
  1438. X    (void)fflush(stderr);
  1439. X    switch ((pid = vfork())) {
  1440. X    case 0:        /* child                    */
  1441. X        execl(cmd, arg0, arg1, arg2, (char *)0);
  1442. X        (void)fprintf(stderr, "%s: execl: `%s\': %s\n", progname, cmd, strerror(errno));
  1443. X        exit(1);
  1444. X    case -1:    /* error                    */
  1445. X        (void)fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
  1446. X        exit(EXIT_FSYS);
  1447. X    default:    /* parent                    */
  1448. X        break;
  1449. X    }
  1450. X
  1451. X    return MyWait(pid);
  1452. }
  1453. Purdue
  1454. chmod 0444 install.d/syscalls.c ||
  1455. echo 'restore of install.d/syscalls.c failed'
  1456. Wc_c="`wc -c < 'install.d/syscalls.c'`"
  1457. test 18260 -eq "$Wc_c" ||
  1458.     echo 'install.d/syscalls.c: original size 18260, current size' "$Wc_c"
  1459. fi
  1460. # ============= instck/main.c ==============
  1461. if test ! -d 'instck'; then
  1462.     echo 'x - creating directory instck'
  1463.     mkdir 'instck'
  1464. fi
  1465. if test -f 'instck/main.c' -a X"$1" != X"-c"; then
  1466.     echo 'x - skipping instck/main.c (File already exists)'
  1467. else
  1468. echo 'x - extracting instck/main.c (Text)'
  1469. sed 's/^X//' << 'Purdue' > 'instck/main.c' &&
  1470. /*
  1471. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  1472. X * 47907.  All rights reserved.
  1473. X *
  1474. X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  1475. X *
  1476. X * This software is not subject to any license of the American Telephone
  1477. X * and Telegraph Company or the Regents of the University of California.
  1478. X *
  1479. X * Permission is granted to anyone to use this software for any purpose on
  1480. X * any computer system, and to alter it and redistribute it freely, subject
  1481. X * to the following restrictions:
  1482. X *
  1483. X * 1. Neither the authors nor Purdue University are responsible for any
  1484. X *    consequences of the use of this software.
  1485. X *
  1486. X * 2. The origin of this software must not be misrepresented, either by
  1487. X *    explicit claim or by omission.  Credit to the authors and Purdue
  1488. X *    University must appear in documentation and sources.
  1489. X *
  1490. X * 3. Altered versions must be plainly marked as such, and must not be
  1491. X *    misrepresented as being the original software.
  1492. X *
  1493. X * 4. This notice may not be removed or altered.
  1494. X */
  1495. static char copyright[] =
  1496. X "@(#) Copyright 1990 Purdue Research Foundation.\nAll rights reserved.\n";
  1497. X
  1498. /*
  1499. X * instck - check for improperly installed files            (ksb)
  1500. X *
  1501. X * Usage
  1502. X *    instck -h
  1503. X *    instck -G [-Ldv] [-g group] [-o owner] [-m mode] [dirs] >check.cf
  1504. X *    instck [-dlvS] [-C check] [dirs] >errors.log
  1505. X *
  1506. X *     dirs(s):    an absolute or relative paths to check-in or gen-for
  1507. X *
  1508. X * mk(1l) stuff:
  1509. X *    $Compile: make all
  1510. X *    $Compile: SYS=bsd make all
  1511. X *    $Compile: SYS=SYSV make all
  1512. X *
  1513. X * Environment:
  1514. X *    Set the environment variable INSTCK to any of the options to get the
  1515. X *    same effect as using them on the command line (e.g., INSTCK="-v").
  1516. X *    Command line options silently override environental variables.
  1517. X *
  1518. X * N.B.
  1519. X *    See the main.c file in the source for install(1L).
  1520. X */
  1521. X
  1522. #if !defined(lint)
  1523. static char *rcsid = "$Id: main.c,v 7.0 90/09/17 10:09:23 ksb Exp $";
  1524. #endif    /* !lint */
  1525. X
  1526. #include <sys/param.h>
  1527. #include <sys/types.h>
  1528. #include <sys/stat.h>
  1529. #include <sys/file.h>
  1530. #include <sys/time.h>
  1531. #include <sys/dir.h>
  1532. #include <a.out.h>
  1533. #include <ar.h>
  1534. X
  1535. X
  1536. #include "configure.h"
  1537. #include "install.h"
  1538. #include "main.h"
  1539. #include "special.h"
  1540. #include "syscalls.h"
  1541. #include "instck.h"
  1542. X
  1543. #include <stdio.h>
  1544. #include <ctype.h>
  1545. #include <errno.h>
  1546. #include <pwd.h>
  1547. #include <grp.h>
  1548. X
  1549. #include "getopt.h"        /* char *optarg; int optind;        */
  1550. #if !defined(BADCH)        /* char getopt returns for illegal options */
  1551. #define    BADCH (int) '\?'
  1552. #endif    /* !BADCH */
  1553. X
  1554. X
  1555. /* global variables for options
  1556. X */
  1557. char *progname;            /* tail of argv[0]            */
  1558. int fDirs = TRUE;        /* scan into dirs while building    */
  1559. int fLongList = FALSE;        /* list long, list leftovers        */
  1560. int fInteract;            /* ask the user if we should fix things    */
  1561. int fTrace = FALSE;        /* keep install part happy        */
  1562. int fVerbose = FALSE;        /* if verbose                */
  1563. int fGen = FALSE;        /* generate a .cf file for dirs        */
  1564. int bHaveRoot;            /* are we the super user        */
  1565. int fLinks = FALSE;        /* record links in link format        */
  1566. char *pcGuilty;            /* who is su'd root            */
  1567. char *pcSpecial = CONFIG;    /* file contains ckecked paths        */
  1568. char *pcMode = DEFMODE;        /* default mode on all files        */
  1569. char *pcDefMode;        /* string mode we need (this dir)    */
  1570. X
  1571. X
  1572. /*
  1573. X * Print detailed usage info
  1574. X */
  1575. char *apcHelp[] = {
  1576. X    "C config use config to check for special files",
  1577. X    "d        do not scan given directories for files",
  1578. X    "g group  set the default group for all files",
  1579. X    "G        generate a check list for the given dirs on stdout",
  1580. X    "h        print this message",
  1581. X    "i        interactively repair the installed files",
  1582. X    "l        list left over files (those that were not checked)",
  1583. X    "L        record all links in link format",
  1584. X    "m mode   set the default mode for installed files",
  1585. X    "o owner  set the default owner for installed files",
  1586. X    "S        run as if we were the superuser",
  1587. X    "v        be more verbose",
  1588. X    "V        show version information",
  1589. X    (char *)0
  1590. };
  1591. X
  1592. char acOArgs[] =
  1593. X    "[-dGhilLvV] [-C config] [-g group] [-m mode] [-o owner]";
  1594. X
  1595. /*
  1596. X * Usage
  1597. X *    Output a useful, std usage message. Maybe a longer one if requested
  1598. X */
  1599. int
  1600. Usage(fp, bVerbose)
  1601. FILE *fp;        /* file to output to                */
  1602. int bVerbose;        /* should we explain options more        */
  1603. {
  1604. X    register char **ppc;
  1605. X
  1606. X    (void)fprintf(fp, "%s: usage %s [dirs]\n", progname, acOArgs);
  1607. X    if (bVerbose) {
  1608. X        for (ppc = apcHelp; (char *)0 != *ppc; ++ppc) {
  1609. X            (void)fprintf(fp, *ppc, OLDDIR);
  1610. X            (void)fputc('\n', fp);
  1611. X        }
  1612. X        (void)fprintf(fp, "%s", copyright);
  1613. X    }
  1614. }
  1615. X
  1616. X
  1617. /*
  1618. X * parse options with getopt and install files
  1619. X */
  1620. int
  1621. main(argc, argv)
  1622. int argc;
  1623. char **argv;
  1624. {
  1625. X    extern char *getenv();    /* we want an env var            */
  1626. X    static char Opts[] =    /* valid options            */
  1627. X        "C:dGg:hilLm:o:SvV";
  1628. X    auto char *pcEnv;    /* options passed through env        */
  1629. X    auto int iOption;    /* argument pointer            */
  1630. X    auto char acMBuf[20];    /* mode buffer                */
  1631. X    auto int iM, iO;    /* more mode buffers            */
  1632. X    auto int fVersion;    /* we should just output version info    */
  1633. X    auto char *pcOwner;    /* login name for default owner        */
  1634. X    auto char *pcGroup;    /* group name for default group        */
  1635. X
  1636. X    /* Figure out our name and fix argv[0] for getopt() if necessary.
  1637. X     */
  1638. X    progname = StrTail(argv[0]);
  1639. X    if (NULL == progname || NULL == *progname)
  1640. X        progname = "instck";
  1641. X
  1642. X    /* Check for environtment options
  1643. X     */
  1644. X    if ((char *)0 != (pcEnv = getenv("INSTCK"))) {
  1645. X        envopt(pcEnv);
  1646. X    }
  1647. X
  1648. X    /* are we the superuser
  1649. X     */
  1650. X    bHaveRoot = 0 == geteuid();
  1651. X
  1652. X    /* Parse command line options, set flags, etc.
  1653. X     */
  1654. X    fVersion = FALSE;
  1655. X    pcGroup = pcOwner = (char *)0;
  1656. X    while (EOF != (iOption = getopt(argc, argv, Opts))) {
  1657. X        switch (iOption) {
  1658. X        case 'C':    /* check list    */
  1659. X            pcSpecial = optarg;
  1660. X            break;
  1661. X        case 'd':    /* don't drop down into given dirs    */
  1662. X            fDirs = FALSE;
  1663. X            break;
  1664. X        case 'g':    /* new default group            */
  1665. X            pcGroup = optarg;
  1666. X            break;
  1667. X        case 'G':    /* output a new .cf file for dirs    */
  1668. X            fGen = TRUE;
  1669. X            break;
  1670. X        case 'h':    /* help        */
  1671. X            Usage(stdout, 1);
  1672. X            exit(0);
  1673. X            break;
  1674. X        case 'i':
  1675. X            fInteract = TRUE;
  1676. X            break;
  1677. X        case 'l':    /* long list */
  1678. X            fLongList = TRUE;
  1679. X            break;
  1680. X        case 'L':    /* link format */
  1681. X            fLinks = TRUE;
  1682. X            break;
  1683. X        case 'm':    /* set mode */
  1684. X            pcMode = optarg;
  1685. X            break;
  1686. X        case 'o':    /* set default owner            */
  1687. X            pcOwner = optarg;
  1688. X            break;
  1689. X        case 'S':    /* we *are* the superuser        */
  1690. X            bHaveRoot = TRUE;
  1691. X            break;
  1692. X        case 'v':    /* run ls(1), and insert comments    */
  1693. X            fVerbose = TRUE;
  1694. X            break;
  1695. X        case 'V':
  1696. X            fVersion = TRUE;
  1697. X            break;
  1698. X        case BADCH:    /* illegal option */
  1699. X            Usage(stderr, 0);
  1700. X            exit(EXIT_OPT);
  1701. X            break;
  1702. X        }
  1703. X    }
  1704. X
  1705. X
  1706. X    /* set the files we need, instck the dirs we were asked to, end clean
  1707. X     */
  1708. X    (void)setpwent();
  1709. X    (void)setgrent();
  1710. X    InitCfg(pcOwner, pcGroup);
  1711. X
  1712. X    pcDefMode = acMBuf;
  1713. X    acMBuf[0] = '-';
  1714. X    if ((char *)0 == pcMode || '\000' == pcMode[0]) {
  1715. X        pcMode = (char *)0;
  1716. X    } else {
  1717. X        CvtMode(pcMode, & iM, & iO);
  1718. X        ModetoStr(pcDefMode+1, iM, iO);
  1719. X    }
  1720. X
  1721. X    argc -= optind;
  1722. X    argv += optind;
  1723. X    argc = ElimDups(argc, argv);
  1724. X
  1725. X    if (fVersion) {
  1726. X        static char acInh[] = "inherited";
  1727. X
  1728. X        printf("%s: version: $Id: main.c,v 7.0 90/09/17 10:09:23 ksb Exp $\n", progname);
  1729. X        printf("%s: configuration file: %s\n", progname, pcSpecial);
  1730. #if defined(INST_FACILITY)
  1731. X        printf("%s: syslog facility: %d\n", progname, INST_FACILITY);
  1732. #endif
  1733. 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);
  1734. X    } else if (fGen) {
  1735. X        GenCk(argc, argv);
  1736. X    } else {
  1737. #if defined(INST_FACILITY)
  1738. X        if (bHaveRoot && fInteract) {
  1739. X            extern char *getlogin();
  1740. X            openlog(progname, 0, INST_FACILITY);
  1741. X            pcGuilty = getlogin();
  1742. X            if ((char *)0 == pcGuilty || '\000' == *pcGuilty) {
  1743. X                pcGuilty = getenv("USER");
  1744. X                if ((char *)0 == pcGuilty || '\000' == *pcGuilty)
  1745. X                    pcGuilty = getenv("LOGNAME");
  1746. X                if ((char *)0 == pcGuilty || '\000' == *pcGuilty)
  1747. X                    pcGuilty = "root\?";
  1748. X            }
  1749. X        }
  1750. #endif
  1751. X        argc = FilterOld(argc, argv, & CLCheck);
  1752. X        InstCk(argc, argv, pcSpecial, & CLCheck);
  1753. #if defined(INST_FACILITY)
  1754. X        if (bHaveRoot && fInteract) {
  1755. X            closelog();
  1756. X        }
  1757. #endif
  1758. X    }
  1759. X
  1760. X    (void)endpwent();
  1761. X    (void)endgrent();
  1762. X
  1763. X    exit(0);
  1764. }
  1765. Purdue
  1766. chmod 0444 instck/main.c ||
  1767. echo 'restore of instck/main.c failed'
  1768. Wc_c="`wc -c < 'instck/main.c'`"
  1769. test 8078 -eq "$Wc_c" ||
  1770.     echo 'instck/main.c: original size 8078, current size' "$Wc_c"
  1771. fi
  1772. # ============= instck/main.h ==============
  1773. if test -f 'instck/main.h' -a X"$1" != X"-c"; then
  1774.     echo 'x - skipping instck/main.h (File already exists)'
  1775. else
  1776. echo 'x - extracting instck/main.h (Text)'
  1777. sed 's/^X//' << 'Purdue' > 'instck/main.h' &&
  1778. /*
  1779. X * $Id: main.h,v 7.1 90/09/17 10:25:39 ksb Exp $
  1780. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  1781. X * 47907.  All rights reserved.
  1782. X *
  1783. X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  1784. X *
  1785. X * This software is not subject to any license of the American Telephone
  1786. X * and Telegraph Company or the Regents of the University of California.
  1787. X *
  1788. X * Permission is granted to anyone to use this software for any purpose on
  1789. X * any computer system, and to alter it and redistribute it freely, subject
  1790. X * to the following restrictions:
  1791. X *
  1792. X * 1. Neither the authors nor Purdue University are responsible for any
  1793. X *    consequences of the use of this software.
  1794. X *
  1795. X * 2. The origin of this software must not be misrepresented, either by
  1796. X *    explicit claim or by omission.  Credit to the authors and Purdue
  1797. X *    University must appear in documentation and sources.
  1798. X *
  1799. X * 3. Altered versions must be plainly marked as such, and must not be
  1800. X *    misrepresented as being the original software.
  1801. X *
  1802. X * 4. This notice may not be removed or altered.
  1803. X */
  1804. X
  1805. /*
  1806. X * paths, names and options of tools we need to fork
  1807. X */
  1808. X
  1809. /* global variables for options
  1810. X */
  1811. extern char *progname;        /* tail of argv[0]            */
  1812. extern char *pcGuilty;        /* who is su'd root?            */
  1813. extern char *pcMode;        /* given mode                */
  1814. extern char *pcSpecial;        /* .cf file for normal mode        */
  1815. extern int fDirs;        /* scan dirs or not            */
  1816. extern int fInteract;        /* ask the user if we should fix things    */
  1817. extern int fLongList;        /* long list, list leftovers        */
  1818. extern int fTrace;        /* keep install part happy        */
  1819. extern int fVerbose;        /* if verbose                */
  1820. extern int fLinks;        /* record links in special link format    */
  1821. extern int bHaveRoot;        /* we are the superuser            */
  1822. extern char *pcDefMode;        /* string mode we need (this dir)    */
  1823. X
  1824. #define INSTCK    1        /* we are not install, we are instck    */
  1825. Purdue
  1826. chmod 0444 instck/main.h ||
  1827. echo 'restore of instck/main.h failed'
  1828. Wc_c="`wc -c < 'instck/main.h'`"
  1829. test 1858 -eq "$Wc_c" ||
  1830.     echo 'instck/main.h: original size 1858, current size' "$Wc_c"
  1831. fi
  1832. # ============= install.cf/install.cf ==============
  1833. if test ! -d 'install.cf'; then
  1834.     echo 'x - creating directory install.cf'
  1835.     mkdir 'install.cf'
  1836. fi
  1837. if test -f 'install.cf/install.cf' -a X"$1" != X"-c"; then
  1838.     echo 'x - skipping install.cf/install.cf (File already exists)'
  1839. else
  1840. echo 'x - extracting install.cf/install.cf (Text)'
  1841. sed 's/^X//' << 'Purdue' > 'install.cf/install.cf' &&
  1842. # $Id: install.cf,v 7.2 90/11/08 11:00:36 ksb Exp $
  1843. # This file tells install(1l) what files to check as special
  1844. # file        modes        owner    group    strip?    comment
  1845. X
  1846. # protect dirs in the std search path
  1847. /        dr?xr-xr-x    root    *    -
  1848. /bin        "        "    "    "
  1849. /usr        "        "    "    "
  1850. /etc        "        "    "    "
  1851. /lib        "        "    "    "
  1852. /usr/bin    "        "    "    "
  1853. /usr/lib    "        "    "    "
  1854. /usr/etc    "        "    "    "
  1855. /usr/local/bin    "        "    "    "
  1856. X
  1857. # protect user file systems
  1858. /user?        dr?xr-xr-x    root    *    -
  1859. /home        "        "    "    "
  1860. /users        "        "    "    "
  1861. /home/*        "        "    "    "
  1862. X
  1863. # (unix and variants)
  1864. /unix        -r?-r--r--    root    *    n    new kernel
  1865. /vmunix        "        "    "    "    "
  1866. /dynix        "        "    "    "    "
  1867. /hp-ux        "        "    "    "    "
  1868. vmunix        "        "    "    "    new client kernel
  1869. X
  1870. # important special binaries
  1871. /bin/sh        -rwx?-x?-x    *    *    ?
  1872. /bin/su        -rws?-x?-?    root    *    ?
  1873. /bin/init    -rwx?--?--     root    *    ?
  1874. /etc/init    "         "    *    ?
  1875. X
  1876. # important data files
  1877. /etc/shadow     drwx------      root    *    -
  1878. /etc/shadow/OLD drwx????-?    "       *    -
  1879. /etc/passwd    -r?-r--r--    "    "    -
  1880. /etc/shadow/passwd "            "       "    "
  1881. /etc/group    "        "    "    "
  1882. /etc/shadow/*   "               "       "       "
  1883. X
  1884. # one might make a directory with install
  1885. /tmp        drwxrwxrwt     root    system    -
  1886. /usr/tmp    "         "    "    -
  1887. lost+found    drwxr-xr-x    "    "    -    for fcsk(8)
  1888. X
  1889. # new files should be owner by the installer for tickle(8)
  1890. /usr/new/bin/OLD drwxr-xr-x    root    *    -
  1891. /usr/new/bin/*    -rwxr-x?-?/7000    !root    *    ?    test installation
  1892. /usr/new/etc/OLD drwxr-xr-x    root    *    -
  1893. /usr/new/etc/*    -rwxr-x?-?/7000    !root    *    ?    test installation
  1894. X
  1895. # these cannot be stripped (and must have the world read bit)
  1896. saved_kcl    -rwxr-xr-x    *    *    n
  1897. X
  1898. # protect from default execute bit
  1899. /usr/lib/libg.a -r?-r--r--    *    *    n    not a library
  1900. *.a        -r?-??-??-    *    *    l    library
  1901. *.so.[0-9]*    "        "    "    n    dynamic library
  1902. *.o        "        *    *    n
  1903. *.ln        "        *    *    n
  1904. *.[hc]        "        "    "    "
  1905. Purdue
  1906. chmod 0444 install.cf/install.cf ||
  1907. echo 'restore of install.cf/install.cf failed'
  1908. Wc_c="`wc -c < 'install.cf/install.cf'`"
  1909. test 1669 -eq "$Wc_c" ||
  1910.     echo 'install.cf/install.cf: original size 1669, current size' "$Wc_c"
  1911. fi
  1912. true || echo 'restore of install.d/install.1l failed'
  1913. echo End of part 3, continue with part 4
  1914. exit 0
  1915.  
  1916. exit 0 # Just in case...
  1917.