home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume24 / pucc-install / part02 < prev    next >
Text File  |  1991-03-19  |  52KB  |  1,577 lines

  1. Subject:  v24i064:  Purdue software product installation system, Part02/07
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: 3945ac52 e1a2a571 6b25139c 69c57023
  5.  
  6. Submitted-by: Kevin Braunsdorf <ksb@nostromo.cc.purdue.edu>
  7. Posting-number: Volume 24, Issue 64
  8. Archive-name: pucc-install/part02
  9.  
  10. #!/bin/sh
  11. # This is part 02 of pucc-1b
  12. # ============= install.d/file.c ==============
  13. if test ! -d 'install.d'; then
  14.     echo 'x - creating directory install.d'
  15.     mkdir 'install.d'
  16. fi
  17. if test -f 'install.d/file.c' -a X"$1" != X"-c"; then
  18.     echo 'x - skipping install.d/file.c (File already exists)'
  19. else
  20. echo 'x - extracting install.d/file.c (Text)'
  21. sed 's/^X//' << 'Purdue' > 'install.d/file.c' &&
  22. /*
  23. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  24. X * 47907.  All rights reserved.
  25. X *
  26. X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  27. X *          Jeff Smith, jsmith@cc.purdue.edu, purdue!jsmith
  28. X *
  29. X * This software is not subject to any license of the American Telephone
  30. X * and Telegraph Company or the Regents of the University of California.
  31. X *
  32. X * Permission is granted to anyone to use this software for any purpose on
  33. X * any computer system, and to alter it and redistribute it freely, subject
  34. X * to the following restrictions:
  35. X *
  36. X * 1. Neither the authors nor Purdue University are responsible for any
  37. X *    consequences of the use of this software.
  38. X *
  39. X * 2. The origin of this software must not be misrepresented, either by
  40. X *    explicit claim or by omission.  Credit to the authors and Purdue
  41. X *    University must appear in documentation and sources.
  42. X *
  43. X * 3. Altered versions must be plainly marked as such, and must not be
  44. X *    misrepresented as being the original software.
  45. X *
  46. X * 4. This notice may not be removed or altered.
  47. X */
  48. X
  49. /*
  50. X * install a file
  51. X */
  52. #if !defined(lint)
  53. static char *rcsid = "$Id: file.c,v 7.2 90/10/22 11:46:31 ksb Exp $";
  54. #endif    /* !lint */
  55. X
  56. #include <sys/param.h>
  57. #include <sys/types.h>
  58. #include <sys/stat.h>
  59. #include <sys/file.h>
  60. #include <stdio.h>
  61. #include <ctype.h>
  62. #include <errno.h>
  63. #include <pwd.h>
  64. #include <grp.h>
  65. X
  66. #include "configure.h"
  67. #include "install.h"
  68. #include "main.h"
  69. #include "dir.h"
  70. #include "syscalls.h"
  71. #include "special.h"
  72. X
  73. #if STRINGS
  74. #include <strings.h>
  75. #else
  76. #include <string.h>
  77. #endif
  78. X
  79. X
  80. /*
  81. X * paths, names and options of tools we need to fork
  82. X */
  83. #if !defined(BINSTRIP)
  84. #define BINSTRIP    "/bin/strip"
  85. #endif
  86. X
  87. static char acStrip[] =    BINSTRIP;
  88. X
  89. #if HAVE_RANLIB
  90. #if !defined(BINRANLIB)
  91. #define BINRANLIB    "/usr/bin/ranlib"
  92. #endif
  93. X
  94. static char acRanlib[] =    BINRANLIB;
  95. #endif    /* sysV site do not have to run ranlib    */
  96. X
  97. #if !defined(LSARGS)
  98. #if defined(SYSV) || defined(HPUX7)
  99. #define LSARGS        "-l"
  100. #else    /* bsd needs a -g option to show group    */
  101. #define LSARGS        "-lg"
  102. #endif    /* how does ls(1) show both owner&group    */
  103. #endif
  104. X
  105. static char acLsArgs[] =    LSARGS;
  106. X
  107. X
  108. /* If the backup directory doesn't exist, create it.  We didn't
  109. X * check for this until now because we don't know the name of the
  110. X * backup directory till now, and if there is really a file to install.
  111. X * lop off last component of pcBackPath...
  112. X */
  113. void
  114. MkOld(pcBackPath)
  115. char *pcBackPath;        /* full backup path            */
  116. {
  117. X    register char *pcTemp;
  118. X    auto char acDD[MAXPATHLEN+1];
  119. X    auto struct stat statb;        /* stat of OLD directory     */
  120. X    auto struct stat statb_dd;    /* stat of OLD/.. directory     */
  121. X
  122. X    pcTemp = strrchr(pcBackPath, '/');
  123. X    if (pcTemp == (char *)0) {
  124. X        Die("MkOld");
  125. X    }
  126. X
  127. X    /* This is a bit of a kludge.  mkdir(1) under 2.9bsd can't
  128. X     * stand trailing '/' chars in pathnames.
  129. X     */
  130. X    while ('/' == *pcTemp && pcTemp > pcBackPath) {
  131. X        --pcTemp;
  132. X    }
  133. X
  134. X    if ('/' != *pcTemp)
  135. X        ++pcTemp;
  136. X    *pcTemp = '\000';
  137. X    if ('\000' == pcBackPath[0]) {
  138. X        /* slash must exist! */;
  139. X    } else if (-1 == LSTAT(pcBackPath, &statb)) {
  140. X        /* we don't want to use the mode specified with -m for
  141. X         * the OLD directory since that probably wasn't what they
  142. X         * wanted, so use a reasonable compile-time default
  143. X         */
  144. X        if (FAIL == DirInstall(pcBackPath, FALSE == bHaveRoot ? (char *)0 : ODIROWNER, FALSE == bHaveRoot ? (char *)0 : ODIRGROUP, ODIRMODE, (char *)0, (char *)0, (char *)0, (char *)0, 0)) {
  145. X            (void)fprintf(stderr, "%s: can\'t create `%s\'\n", progname, pcBackPath);
  146. X            exit(EXIT_FSYS);
  147. X        }
  148. X        if (fVerbose != FALSE) {
  149. X            (void)fprintf(stderr, "%s: had to create `%s\'\n", progname, pcBackPath);
  150. X        }
  151. X    } else if (S_IFDIR != (statb.st_mode & S_IFMT)) {
  152. X        (void)fprintf(stderr, "%s: %s must be a directory\n", progname, pcBackPath);
  153. X        exit(EXIT_OPT);
  154. X    } else {
  155. X        (void)strcpy(acDD, pcBackPath);
  156. X        (void)strcat(acDD, "/..");
  157. X        if (-1 == LSTAT(acDD, &statb_dd)) {
  158. X            (void)fprintf(stderr, "%s: stat: %s: %s\n", progname, acDD, strerror(errno));
  159. X            exit(EXIT_OPT);
  160. X        }
  161. X        if (statb.st_dev != statb_dd.st_dev) {
  162. X            (void)fprintf(stderr, "%s: `%s\' is a mount point!\n", progname, pcBackPath);
  163. X            exit(EXIT_OPT);
  164. X        }
  165. X    }
  166. X    *pcTemp = '/';
  167. }
  168. X
  169. X
  170. X
  171. /*
  172. X * DoBackup()
  173. X *    Actually backs up the file by renaming it
  174. X */
  175. /*ARGSUSED*/
  176. static int
  177. DoBackup(bWasLink, pcDestPath, pcBackPath, pcNewBack, pcTellNew)
  178. int bWasLink;        /* file was a symlink                */
  179. char *pcDestPath;    /* file that will be clobbered            */
  180. char *pcBackPath;    /* filename to try as backup name        */
  181. char *pcNewBack;    /* if we moved $DEST/OLD/foo, new name        */
  182. char *pcTellNew;    /* tell the user the new backup name for OLD/foo*/
  183. {
  184. X    auto struct stat statb_backup;    /* stat of OLD/name         */
  185. X
  186. X    pcNewBack[0] = '\000';        /* didn't have to move it    */
  187. X
  188. X    MkOld(pcBackPath);
  189. X
  190. X    if (FALSE != bWasLink) {
  191. #if HAVE_SLINKS
  192. X        if (CopySLink(pcDestPath, pcBackPath)) {
  193. X            return SUCCEED;
  194. X        }
  195. #endif    /* can copy what we do not have?    */
  196. X        return FAIL;
  197. X    }
  198. X
  199. X    /* backup target already exists, mv it
  200. X     */
  201. X    if (-1 != stat(pcBackPath, &statb_backup)) {
  202. X        (void)strcpy(pcNewBack, pcBackPath);
  203. X        MungName(pcNewBack);
  204. X        if (FAIL == Rename(pcBackPath, pcNewBack, pcTellNew)) {
  205. X            /* rename output an error message for us */
  206. X            return FAIL;
  207. X        }
  208. X    }
  209. X
  210. X    /* Just link the backup file to the current file to avoid the window
  211. X     * that results from renaming the backup before the new file is
  212. X     * installed.  Resolve collisions if necessary.  If we can't link, copy.
  213. X     */
  214. X    if (FALSE != fTrace) {
  215. X        (void)printf("%s: ln %s %s\n", progname, pcDestPath, pcBackPath);
  216. X    } else if (-1 == link(pcDestPath, pcBackPath)) {
  217. X        if (FAIL == DoCopy(pcDestPath, pcBackPath)) {
  218. X            (void)fprintf(stderr, "%s: can\'t link or copy `%s\' to `%s\'\n", progname, pcBackPath, pcDestPath);
  219. X            return FAIL;
  220. X        }
  221. X    }
  222. X
  223. X    return SUCCEED;
  224. }
  225. X
  226. X
  227. /*
  228. X * MakeNames()
  229. X *    Given the file to install and the destination, return the full path of
  230. X *    the destination and the full path of the backup file.  This is somewhat
  231. X *    complicated since the destination may be a directory or a full path, and
  232. X *    the full path may end in a filename that exists or not.
  233. X */
  234. void
  235. MakeNames(fStdin, pcFTI, pcDest, pcFull, pcBack)
  236. int fStdin;        /* we are doing stdin here    (in )        */
  237. char *pcFTI;        /* File To Install        (in )        */
  238. char *pcDest;        /* Destination of pcFTI        (in )        */
  239. char *pcFull;        /* full pathname of destination (out)        */
  240. char *pcBack;        /* full pathname of the backup    (out)        */
  241. {
  242. X    register char *pcTailFTI;    /* tail of pcFTI        */
  243. X    register char *pcDestDir;    /* destination directory    */
  244. X    register char *pcTailDest;    /* tail of pcDest        */
  245. X
  246. X    /* Get tail of file to install
  247. X     */
  248. X    if ((pcTailFTI = strrchr(pcFTI, '/')) == (char *)0) {
  249. X        pcTailFTI = pcFTI;
  250. X    } else {
  251. X        ++pcTailFTI;
  252. X    }
  253. X
  254. X    /* Get the name of the destination directory and the name the file
  255. X     * to install will have in that directory.  If the destination we were
  256. X     * passed is a directory then the destination dir is just pcDest
  257. X     * and the filename is the tail of the file to install.  If the
  258. X     * destination isn't a directory, then either they gave a pathname
  259. X     * (something with '/' in it) for the file to install, in which case
  260. X     * the destination directory is the head of that path and the filename
  261. X     * is the tail, or they're installing the file in the current directory
  262. X     * with a different name.  Note that this can't be the case where they
  263. X     * say "install foo bar" and bar is a directory because we already
  264. X     * took care of that in the first case.
  265. X     * (trailing slashes used to choke us, now we remove them first)
  266. X     */
  267. X    while ((char *)0 != (pcTailDest = strrchr(pcDest, '/')) && pcDest != pcTailDest && '\000' == pcTailDest[1]) {
  268. X        *pcTailDest = '\000';
  269. X    }
  270. X    if (FALSE != IsDir(pcDest)) {
  271. X        pcDestDir = pcDest;
  272. X        pcTailDest = pcTailFTI;
  273. X        if (fStdin) {
  274. X            if (fDelete) {
  275. X                (void)fprintf(stderr, "%s: use \"%s -R -d%s %s\" to remove a directory\n", progname, progname, fVerbose ? "v" : "", pcDest);
  276. X            } else {
  277. X                (void)fprintf(stderr, "%s: cannot intuit destination name for `-\' (stdin)\n", progname);
  278. X            }
  279. X            exit(1);
  280. X        }
  281. X    } else if ((char *)0 != pcTailDest) {
  282. X        pcDestDir = pcDest;
  283. X        *pcTailDest++ = '\000';
  284. X    } else {
  285. X        pcDestDir = ".";
  286. X        pcTailDest = pcDest;
  287. X    }
  288. X
  289. X    /* make pathname of file to back up.
  290. X     */
  291. X    (void)sprintf(pcBack, "%s/%s/%s", pcDestDir, OLDDIR, pcTailDest);
  292. X
  293. X    /* Make the pathname the file to install will have
  294. X     */
  295. X    (void)sprintf(pcFull, "%s/%s", pcDestDir, pcTailDest);
  296. }
  297. X
  298. X
  299. #define HARD    0        /* type of link to make            */
  300. #define SOFT    1
  301. static char *apcLType[] = {
  302. X    "hard",
  303. X    "symbolic"
  304. };
  305. static char *apcLText[] = {
  306. X    "ln",
  307. X    "ln -s"
  308. };
  309. X
  310. /*
  311. X * build the links, no errors allowed!                    (ksb)
  312. X */
  313. int
  314. DoLinks(pST, pcFullFile, pcLinks, eType, pwd, grp)
  315. struct stat *pST;        /* stat of file we were linked to    */
  316. char *pcFullFile;        /* name of file we were linked to    */
  317. char *pcLinks;            /* links to build            */
  318. int eType;            /* type of link to build        */
  319. struct passwd *pwd;        /* owner for file            */
  320. struct group *grp;        /* group for file            */
  321. {
  322. X    static char acColon[] = ":";    /* last time through loop    */
  323. X    register char *pcColon;        /* skip through the ':' list    */
  324. X    register char *pcLink;        /* skip through the ':' list    */
  325. X    auto char *pcBusy;        /* used to cut up OLD name    */
  326. X    auto char *pcFile;        /* file name to link to        */
  327. X    auto char *pcBase;        /* just the base of the target    */
  328. X    auto struct stat statb_link;    /* statbuf for stat'ing links    */
  329. X    auto struct stat statb_p2;    /* statbuf for what link -> to    */
  330. X    auto int fRet;            /* value to return        */
  331. X    auto int iLen;            /* lenght of link text        */
  332. X    auto int bBackup;        /* backup the older link    */
  333. X    auto int bSymbolic;        /* existing link it symlink    */
  334. X    auto char *pcMsg;        /* error message flags        */
  335. X    auto char acLink[MAXPATHLEN+1];    /* link text from readlink    */
  336. X    auto char acOld[MAXPATHLEN+1];    /* backup of a link        */
  337. X    auto char acBusy[MAXPATHLEN+1];    /* temp name for last link case    */
  338. X
  339. X    fRet = SUCCEED;
  340. X    pcBase = strrchr(pcFullFile, '/');
  341. X    if ((char *)0 == pcBase)
  342. X        Die("nil pointer");
  343. X    ++pcBase;
  344. X    for (pcLink = pcLinks; '\000' != pcLink[0]; *pcColon = ':', pcLink = pcColon+1) {
  345. X        if ((char *)0 == (pcColon = strchr(pcLink, ':'))) {
  346. X            pcColon = acColon;
  347. X        }
  348. X        *pcColon = '\000';
  349. X
  350. X        /* if we are building a soft link with no slashes
  351. X         * in it we can just use a basename change -- else
  352. X         * use the full path.  We used to stat to see if they
  353. X         * pointed to the same directory, but that might change.
  354. X         * (( after we make the link... *sigh* ))
  355. X         */
  356. X        if (SOFT != eType || (char *)0 != strchr(pcLink, '/')) {
  357. X            pcFile = pcFullFile;
  358. X        } else {
  359. X            pcFile = pcBase;
  360. X        }
  361. X        if (-1 != LSTAT(pcLink, &statb_link)) {
  362. X            pcMsg = NodeType(statb_link.st_mode, (char *)0);
  363. X            bBackup = FALSE;
  364. X            switch (statb_link.st_mode & S_IFMT) {
  365. #if HAVE_SLINKS
  366. X            case S_IFLNK:    /* symbolic link */
  367. X                bSymbolic = TRUE;
  368. X                if (HARD == eType) {
  369. X                    if (FALSE == fQuiet)
  370. X                        (void)fprintf(stderr, "%s: existing symbolic link %s becomes a link hard\n", progname, pcLink);
  371. X                    bBackup = TRUE;
  372. X                }
  373. X                iLen = readlink(pcLink, acLink, MAXPATHLEN);
  374. X                if (-1 == iLen) {
  375. X                    (void)fprintf(stderr, "%s: readlink: %s: %s\n", progname, pcLink, strerror(errno));
  376. X                    continue;
  377. X                }
  378. X                acLink[iLen] = '\000';
  379. X                if (-1 == stat(acLink, & statb_p2)) {
  380. X                    if ((struct stat *)0 != pST || ENOENT != errno) {
  381. X                        (void)fprintf(stderr, "%s: stat: %s: %s\n", progname, acLink, strerror(errno));
  382. X                    }
  383. X                    bBackup = TRUE;
  384. X                } else if (! EQUAL(pcFile, acLink)) {
  385. X                    if (FALSE == fQuiet)
  386. X                        (void)fprintf(stderr, "%s: link `%s\' spelled `%s\', not `%s\'\n", progname, pcLink, acLink, pcFile);
  387. X                    bBackup = TRUE;
  388. X                } else if (HARD != eType) {
  389. X                    /* if delete is set dink it */
  390. X                    if (fDelete) {
  391. X                        break;
  392. X                    }
  393. X                    if (grp->gr_gid != statb_link.st_gid || (bHaveRoot && pwd->pw_uid != statb_link.st_uid)) {
  394. X                        goto fix_mode;
  395. X                    }
  396. X                    /* OK, looks good, leave it be */
  397. X                    continue;
  398. X                }
  399. X                break;
  400. #endif    /* no links to think about    */
  401. #if defined(S_IFIFO)
  402. X            case S_IFIFO:    /* fifo */
  403. #endif    /* no fifos */
  404. #if defined(S_IFSOCK)
  405. X            case S_IFSOCK:    /* socket */
  406. #endif    /* no sockets */
  407. X            case S_IFDIR:    /* directory */
  408. X            case S_IFCHR:    /* character special */
  409. X            case S_IFBLK:    /* block special */
  410. X                (void)fprintf(stderr, "%s: %s link %s is a %s, fail\n", progname, apcLType[eType], pcLink, pcMsg);
  411. X                fRet = FAIL;
  412. X                continue;
  413. X
  414. X            case 0:
  415. X            case S_IFREG:    /* regular */
  416. X                bSymbolic = FALSE;
  417. X                if ((struct stat *)0 != pST && (pST->st_dev != statb_link.st_dev || pST->st_ino != statb_link.st_ino)) {
  418. X                    (void)fprintf(stderr, "%s: existing hard link %s doesn\'t point to old file\n", progname, pcLink);
  419. X                    bBackup = TRUE;
  420. X                }
  421. #if HAVE_SLINKS
  422. X                if (SOFT == eType) {
  423. X                    if (FALSE == fQuiet)
  424. X                        (void)fprintf(stderr,"%s: supposed symbolic link %s was a hard link\n", progname, pcLink);
  425. X                    /* go on and remove it */
  426. X                    bBackup = TRUE;
  427. X                }
  428. #endif
  429. X                break;
  430. X
  431. X            default:
  432. X                (void)fprintf(stderr, "%s: unrecognized file type on %s\n", progname, pcLink);
  433. X                exit(1);
  434. X            }
  435. X            MakeNames(FALSE, pcLink, ".", acLink, acOld);
  436. X            if (bBackup && FAIL == DoBackup(bSymbolic, pcLink, acOld, acLink, (char *)0)) {
  437. X                (void)fprintf(stderr, "%s: backup failed for link `%s\', skipped\n", progname, pcLink);
  438. X                continue;
  439. X            }
  440. X            if (fTrace) {
  441. X                (void)printf("%s: rm -f %s\n", progname, pcLink);
  442. X            } else if (-1 != unlink(pcLink)) {
  443. X                /* OK */;
  444. X            } else if (ETXTBSY != errno) {
  445. X                (void)fprintf(stderr, "%s: unlink: %s: %s\n", progname, pcLink, strerror(errno));
  446. X                continue;
  447. X            } else {
  448. X                /* might be the last link to a running binary
  449. X                 * link to a bogus name and try again...
  450. X                 */
  451. X                pcBusy = strrchr(acOld, '/');
  452. X                if ((char *)0 == pcBusy) {
  453. X                    Die("nil pointer");
  454. X                }
  455. X                *pcBusy = '\000';
  456. X                (void)sprintf(acBusy, "%s/%s", acOld, TMPBOGUS);
  457. X                *pcBusy = '/';
  458. X                MkOld(acBusy);
  459. X                Mytemp(acBusy);
  460. X                if (-1 == Rename(pcLink, acBusy, fVerbose ? "moving busy link" : (char *)0)) {
  461. X                    continue;
  462. X                }
  463. X            }
  464. X        } else if (ENOENT != errno) {
  465. X            (void)fprintf(stderr, "%s: stat: %s: %s\n", progname, pcLink, strerror(errno));
  466. X            fRet = FAIL;
  467. X            continue;
  468. X        }
  469. X        if (FALSE != fDelete) {
  470. X            continue;
  471. X        }
  472. X        if (fTrace) {
  473. X            (void)printf("%s: %s %s %s\n", progname, apcLText[eType], pcFile, pcLink);
  474. X        } else if (HARD == eType) {
  475. X            if (-1 == link(pcFile, pcLink)) {
  476. X                (void)fprintf(stderr, "%s: link: %s to %s: %s\n", progname, pcFile, pcLink, strerror(errno));
  477. X                fRet = FAIL;
  478. X            }
  479. X        } else {
  480. #if HAVE_SLINKS
  481. X            if (-1 == symlink(pcFile, pcLink)) {
  482. X                (void)fprintf(stderr, "%s: symlink: %s to %s: %s\n", progname, pcFile, pcLink, strerror(errno));
  483. X                fRet = FAIL;
  484. X            }
  485. X        }
  486. X        if (SOFT == eType) {
  487. fix_mode:
  488. X            if (FALSE != bHaveRoot) {
  489. X                ChOwnGrp(pcLink, pwd, grp);
  490. X            } else {
  491. X                ChGroup(pcLink, grp);
  492. X            }
  493. #else
  494. X            (void)fprintf(stderr, "%s: symbolic links not supported\n", progname);
  495. X            fRet = FAIL;
  496. #endif
  497. X        }
  498. X    }
  499. X    return fRet;
  500. }
  501. X    
  502. /*
  503. X * start a links process for the -S or -H options            (ksb)
  504. X */
  505. int
  506. LaunchLinks(pST, pcDestPath, pcHLink, pcSLink, mMode, pwd, grp)
  507. char *pcDestPath;
  508. struct stat *pST;        /* old file, if one exists    */
  509. char *pcHLink;
  510. char *pcSLink;
  511. int mMode;
  512. struct group *grp;
  513. struct passwd *pwd;
  514. {
  515. X    static char acDot[] = ".";
  516. X    static char acSlash[] = "/";
  517. X    register int iChild;    /* child we forked, for wait    */
  518. X    register char *pcDir;    /* change to dir        */
  519. X    register char *pcLash;    /* last slash in file path    */
  520. X
  521. X    /* We fork a child to do the linking because we have to
  522. X     * chdir and umask and stuff.  We may not be able to chdir
  523. X     * back to where we are (worst case).
  524. X     */
  525. X    (void)fflush(stdout);
  526. X    (void)fflush(stderr);
  527. X    switch (iChild = fork()) {
  528. X    case -1:    /* system error                */
  529. X        (void)fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
  530. X        exit(EXIT_FSYS);
  531. X    case 0:        /* child, go do linking            */
  532. X        /* cee dee to the destination directory
  533. X         */
  534. X        pcDir = pcDestPath;
  535. X        if ((char *)0 == (pcLash = strrchr(pcDir, '/'))) {
  536. X            pcDir = acDot;
  537. X        } else if (pcDestPath != pcLash) {
  538. X            *pcLash = '\000';
  539. X        } else {
  540. X            pcDir = acSlash;
  541. X        }
  542. X        if (fTrace) {
  543. X            (void)printf("%s: ( cd %s\n", progname, pcDir);
  544. X        }
  545. X        /* we really want to cd, even while just tracing
  546. X         */
  547. X        if (-1 == chdir(pcDir)) {
  548. X            (void)fprintf(stderr, "%s: chdir: %s: %s\n", progname, pcDir, strerror(errno));
  549. X            exit(1);
  550. X        }
  551. X        if (pcLash != acSlash && pcLash != acDot) {
  552. X            *pcLash = '/';
  553. X        }
  554. X
  555. X        /* we are in the correct directory,
  556. X         * now we must build the links
  557. X         */
  558. X        if ((char *)0 != pcHLink) {
  559. X            if (FAIL == DoLinks(pST, pcDestPath, pcHLink, HARD, pwd, grp))
  560. X                exit(1);
  561. X        }
  562. #if HAVE_SLINKS
  563. X        /* symbolic links must be made with the correct umask
  564. X         * we cannot chmod them
  565. X         */
  566. X        if ((char *)0 != pcSLink) {
  567. X            if (fTrace) {
  568. X                (void)printf("%s: umask %03o\n", progname, (~mMode) & 0777);
  569. X            }
  570. X            (void)umask((~mMode) & 0777);
  571. X
  572. X            if (FAIL == DoLinks(pST, pcDestPath, pcSLink, SOFT, pwd, grp))
  573. X                exit(1);
  574. X        }
  575. #endif    /* symbiloc links */
  576. X        if (fTrace) {
  577. X            (void)printf("%s: )\n", progname);
  578. X        }
  579. X        exit(0);
  580. X    default:    /* parrent, wait around a while        */
  581. X        break;
  582. X    }
  583. X    return 0 != MyWait(iChild);
  584. }
  585. X
  586. X
  587. static char acFCreated[] = "file `%s\' created %s.%s(%04o) by %s\n";
  588. static char acFUpdated[] = "file `%s\' updated %s.%s(%04o) by %s\n";
  589. static char acFRemoved[] = "file `%s\' removed %s.%s(%04o) by %s\n";
  590. X
  591. static char *apcFrom[] = {        /* where did we get data from    */
  592. #define FROM_CMD    0
  593. X    "given on the command line",
  594. #define FROM_OLD    1
  595. X    "from the previously installed file",
  596. #define FROM_DEF    2
  597. X    "from the compiled in defaults",
  598. #define FROM_SRC    3
  599. X    "from the source file",
  600. #define FROM_DIR    4
  601. X    "from the destination directory"
  602. };
  603. X
  604. /*
  605. X * backs up the current file and installs a new one            (ksb)
  606. X *
  607. X * if fDelete is set we install a message and remove it,
  608. X * in this case our caller passes "-" as the file to install.
  609. X */
  610. int
  611. Install(pcFilePath, pcDestPath, pcHLink, pcSLink)
  612. char *pcFilePath;     /* the file to be installed            */
  613. char *pcDestPath;    /* the destination directory or file        */
  614. char *pcHLink;        /* hard links to make                */
  615. char *pcSLink;        /* symlinks to make                */
  616. {
  617. X    auto int iOFrom;        /* owner from which source    */
  618. X    auto int iGFrom;        /* group from which source    */
  619. X    auto int iMFrom;        /* mode from which source    */
  620. X    auto int mMode, mOptMode;    /* mode to install with        */
  621. X    auto int bLocalCopy;        /* should we copy or rename    */
  622. X    auto int bDestExists;        /* destination file exists?    */
  623. X    auto int bWasLink;        /* was the file a symlink?    */
  624. X    auto int bBackup;        /* we're backing up this file    */
  625. X    auto int bCollide;        /* cd OLD; install foo .. (fix)    */
  626. X    auto int bStdin;        /* copy ``-'' (stdin) to dest    */
  627. X    auto char *pcSlash;        /* last slash in $DEST/OLD/foo    */
  628. X    auto struct passwd *pwd;    /* /etc/passwd info        */
  629. X    auto struct group *grp;        /* /etc/group info        */
  630. X    auto struct stat statb_file;    /* stat(2) the file to install    */
  631. X    auto struct stat statb_dest;    /* stat(2) the destination    */
  632. X    auto char *pcMsg;        /* flags for error message    */
  633. X    auto char acDestPath[MAXPATHLEN+1];/* pathname of file to install*/
  634. X    auto char acBackPath[MAXPATHLEN+1];/* pathname of backup file    */
  635. X    auto char acNewBack[MAXPATHLEN+1];/* where DoBackup put OLD/foo    */
  636. X    auto char acTempPath[MAXPATHLEN+1];/* pathname for copy & link    */
  637. X    auto char acBusyPath[MAXPATHLEN+1];/* pathname for busy link    */
  638. #if defined(CONFIG)
  639. X    auto CHLIST Check;
  640. #endif    /* we need a check list entry        */
  641. #if defined(INST_FACILITY)
  642. X    auto char *pcLogStat;
  643. X    auto char acLogBuf[MAXLOGLINE];
  644. #endif    /* we should syslog changes        */
  645. X
  646. X    if ((char *)0 == pcFilePath) {
  647. X        Die("nil filepath");
  648. X    }
  649. X
  650. X    /* We always assume we'll back up the file unless we were
  651. X     * told not to.  We may find out later there isn't anything
  652. X     * to back up...
  653. X     */
  654. X    bBackup = (Destroy == FALSE) ? TRUE : FALSE;
  655. X
  656. X    /* See if the file to install exists and it isn't a directory.
  657. X     * This is a problem under 2.9bsd Unix since root can unlink
  658. X     * directories that aren't empty, damaging the file system.
  659. X     * (we also need to set the bLocalCopy flag here)
  660. X     */
  661. X    bStdin = '-' == pcFilePath[0] && '\000' == pcFilePath[1];
  662. X
  663. X    /* Figure out the final destination name of the file to install
  664. X     */
  665. X    MakeNames(bStdin, pcFilePath, pcDestPath, acDestPath, acBackPath);
  666. X    if ((char *)0 == (pcSlash = strrchr(acBackPath, '/'))) {
  667. X        Die("nil from strrchr");
  668. X    }
  669. X
  670. X    /* if we are trying to deinstall a file, built a bogus one to
  671. X     * install in it's place, then remove the bogus one.  This temp
  672. X     * file is treated as `stdin' to the real install process.
  673. X     */
  674. X    if (fDelete) {
  675. X        register FILE *fpRm;
  676. X        auto int afd[2];
  677. X
  678. X        if (-1 == pipe(afd)) {
  679. X            fprintf(stderr, "%s: pipe: %s\n", progname, strerror(errno));
  680. X            return FAIL;
  681. X        }
  682. X        fflush(stdout);
  683. X        fflush(stderr);
  684. X        switch (fork()) {
  685. X        case -1:
  686. X            fprintf(stderr, "%s: fork: %s\n", progname, strerror(errno));
  687. X            return FAIL;
  688. X        default:        /* parent: install rm script    */
  689. X            close(0);
  690. X            dup(afd[0]);
  691. X            close(afd[0]);
  692. X            close(afd[1]);
  693. X            break;
  694. X        case 0:            /* child: output message    */
  695. X            close(afd[0]);
  696. X            if ((FILE *)0 == (fpRm = fdopen(afd[1], "w"))) {
  697. X                Die("fdopen");
  698. X            }
  699. X            (void)fprintf(fpRm, "#!/bin/cat\nThis file, %s, is being removed (by %s)\n", acDestPath, pcGuilty);
  700. X            (void)fflush(fpRm);
  701. X            (void)fclose(fpRm);
  702. X            exit(0);
  703. X        }
  704. X    }
  705. X    if (bStdin) {
  706. X        if (-1 == fstat(fileno(stdin), &statb_file)) {
  707. X            (void)fprintf(stderr, "%s: fstat: stdin: %s\n", progname, strerror(errno));
  708. X            return FAIL;
  709. X        }
  710. X    } else if (-1 == LSTAT(pcFilePath, &statb_file)) {
  711. X        (void)fprintf(stderr, "%s: stat: %s: %s\n", progname, pcFilePath, strerror(errno));
  712. X        return FAIL;
  713. X    }
  714. X
  715. X    bWasLink = FALSE;
  716. X    bLocalCopy = Copy || bStdin;
  717. X    pcMsg = NodeType(statb_file.st_mode, (char *)0);
  718. X    if (!bStdin) switch (statb_file.st_mode & S_IFMT) {
  719. #if HAVE_SLINKS
  720. X    case S_IFLNK:    /* symbolic link */
  721. #if SLINKOK
  722. X        if (FALSE == fQuiet)
  723. X            (void)fprintf(stderr, "%s: source `%s\' is a symbolic link, coping as plain file\n", progname, pcFilePath);
  724. X        break;
  725. #endif    /* think about links */
  726. #endif    /* no links to think about */
  727. #if defined(S_IFIFO)
  728. X    case S_IFIFO:    /* fifo */
  729. #endif    /* no fifos */
  730. #if defined(S_IFSOCK)
  731. X    case S_IFSOCK:    /* socket */
  732. #endif    /* no sockets */
  733. X    case S_IFDIR:    /* directory */
  734. X        (void)fprintf(stderr, "%s: source `%s\' is a %s, fail\n", progname, pcFilePath, pcMsg);
  735. X        return FAIL;
  736. X
  737. X    case S_IFCHR:    /* character special */
  738. X    case S_IFBLK:    /* block special */
  739. X        /* always copy special files, don't remove them.
  740. X         */
  741. X        if (FALSE != fVerbose && FALSE == bLocalCopy && FALSE == fQuiet) {
  742. X            (void)printf("%s: copying special file %s\n", progname, pcFilePath);
  743. X        }
  744. X        bLocalCopy = TRUE;
  745. X        break;
  746. X
  747. X    case 0:
  748. X    case S_IFREG:    /* regular/plain file */
  749. X        break;
  750. X
  751. X    default:
  752. X        (void)fprintf(stderr, "%s: unrecognized file type on %s\n", progname, pcFilePath);
  753. X        return FAIL;
  754. X    }
  755. X
  756. X    /* There is a bad case here, the user is in $DEST/OLD trying to
  757. X     *    $ install foo ..
  758. X     * (`casue $DEST/foo is hosed).  We should move
  759. X     * $DEST/OLD/foo to a foo$$ to make room for the backup, then
  760. X     * link $DEST/foo to $DEST/OLD/foo and copy the broken one back
  761. X     * into place!  Eak.  We warn the user about this case and fix it.
  762. X     */
  763. X    if (-1 != stat(acBackPath, &statb_dest) &&
  764. X        statb_file.st_dev == statb_dest.st_dev &&
  765. X        statb_file.st_ino == statb_dest.st_ino) {
  766. X        if (FALSE == fQuiet)
  767. X            (void)fprintf(stderr, "%s: source `%s\' will be renamed before installation\n", progname, acBackPath);
  768. X        bCollide = TRUE;
  769. X    } else {
  770. X        bCollide = FALSE;
  771. X    }
  772. X
  773. #if defined(CONFIG)
  774. X    /* If the file is one we recognize trap bogus modes/strip
  775. X     */
  776. X    Special(acDestPath, pcSpecial, & Check);
  777. #endif    /* set check list flags from config file */
  778. X
  779. X    /* Make sure we don't install a file on top of itself.  If the stat()
  780. X     * fails then it doesn't exist and we're ok.  Otherwise, if the device
  781. X     * and inode numbers are the same we gripe and die.
  782. X     *
  783. X     * See if there's anything to back up (i.e., an existing file with
  784. X     * the same name as acDestPath).  If this is an initial installation
  785. X     * there won't be anything to back up, but that isn't an error, so we
  786. X     * just note it.
  787. X     *
  788. X     * If they said "-D" (destroy current binary) there's no sense in
  789. X     * complaining that there's nothing to back up...
  790. X     */
  791. X    if (-1 != LSTAT(acDestPath, &statb_dest)) {
  792. X        bDestExists = TRUE;
  793. X        /* Check and see if source and dest are the
  794. X         * same file, or there are extra links to the
  795. X         * existing file and report that (after file type)
  796. X         */
  797. X        if (statb_file.st_dev == statb_dest.st_dev
  798. X            && statb_file.st_ino == statb_dest.st_ino) {
  799. X            (void)fprintf(stderr, "%s: will not move %s onto itself (%s)\n", progname, pcFilePath, acDestPath);
  800. X            exit(EXIT_OPT);
  801. X        }
  802. X
  803. X        /* Here we take note of funny file types, we don't want the
  804. X         * destination to be a funny file (because people shouldn't
  805. X         * live like that -- ksb)
  806. X         */
  807. X        pcMsg = NodeType(statb_dest.st_mode, (char *)0);
  808. X        switch (statb_dest.st_mode & S_IFMT) {
  809. #if HAVE_SLINKS
  810. X        case S_IFLNK:    /* symbolic link */
  811. #if DLINKOK
  812. X            if (FALSE == fQuiet)
  813. X                (void)fprintf(stderr,"%s: destination %s was a symbolic link\n", progname, acDestPath);
  814. X            bWasLink = TRUE;
  815. X            /* for backup of all links, we might be wrong
  816. X             * in even installing it!
  817. X             */
  818. X            bBackup = TRUE;
  819. X            break;
  820. #endif    /* think about links */
  821. #endif    /* no links to think about */
  822. #if defined(S_IFIFO)
  823. X        case S_IFIFO:    /* fifo */
  824. #endif    /* no fifos */
  825. #if defined(S_IFSOCK)
  826. X        case S_IFSOCK:    /* socket */
  827. #endif    /* no sockets */
  828. X        case S_IFDIR:    /* directory */
  829. X        case S_IFCHR:    /* character special */
  830. X        case S_IFBLK:    /* block special */
  831. X            (void)fprintf(stderr, "%s: destination `%s\' is a %s, fail\n", progname, acDestPath, pcMsg);
  832. X            return FAIL;
  833. X
  834. X        case 0:
  835. X        case S_IFREG:    /* regular */
  836. X            break;
  837. X
  838. X        default:
  839. X            (void)fprintf(stderr, "%s: unrecognized file type on `%s\'\n", progname, acDestPath);
  840. X            return FAIL;
  841. X        }
  842. #if defined(INST_FACILITY)
  843. X        pcLogStat = acFUpdated;
  844. #endif    /* we should syslog changes        */
  845. X    } else if (ENOENT != errno) {
  846. X        (void)fprintf(stderr, "%s: stat: %s: %s\n", progname, acDestPath, strerror(errno));
  847. X        exit(EXIT_FSYS);
  848. X    } else if (fDelete) {
  849. X        (void)fprintf(stderr, "%s: no `%s\' to remove\n", progname, acDestPath);
  850. X        return FAIL;
  851. X    } else {
  852. X        bDestExists = FALSE;
  853. X        bBackup = FALSE;
  854. X        if (FALSE == fQuiet) {
  855. X            (void)fprintf(stderr, "%s: no `%s\' to %s\n", progname, acDestPath, Destroy != FALSE ? "overwrite" : "back up");
  856. X        }
  857. X        /* we need to set statb_dest.st_dev so we know what
  858. X         * device the destination will be on, so we can force
  859. X         * a copy rather than a rename
  860. X         * (we might also copy its mode/group/owner if no defaults)
  861. X         */
  862. X        *pcSlash = '\000';
  863. X        if (-1 == stat(acBackPath, &statb_dest)) {
  864. X            register char *pcHelp;
  865. X            if ((char *)0 == (pcHelp = strrchr(acDestPath, '/'))) {
  866. X                Die("nil pointer");
  867. X            }
  868. X            *pcHelp = '\000';
  869. X            if (-1 == stat(acDestPath, &statb_dest)) {
  870. X                fprintf(stderr, "%s: stat: %s: %s\n", progname, acDestPath, strerror(errno));
  871. X                exit(EXIT_OPT);
  872. X            }
  873. X            *pcHelp = '/';
  874. X        }
  875. X        *pcSlash = '/';
  876. #if defined(INST_FACILITY)
  877. X        pcLogStat = acFCreated;
  878. #endif    /* we should syslog changes        */
  879. X    }
  880. #if defined(INST_FACILITY)
  881. X    if (FALSE != fDelete) {
  882. X        pcLogStat = acFRemoved;
  883. X    }
  884. #endif    /* we should syslog changes        */
  885. X
  886. X    /* if they've specified an owner, group or mode we take it,
  887. X     * if the destination file already exists use that,
  888. X     * otherwise, use a reasonable default.
  889. X     */
  890. X    (void)setpwent();
  891. X    if ((char *)0 != Owner) {
  892. X        if ((struct passwd *)0 == (pwd = getpwnam(Owner))) {
  893. X            (void)fprintf(stderr, "%s: no passwd entry for %s\n", progname, Owner);
  894. X            exit(EXIT_OPT);
  895. X        }
  896. X        if (FALSE == bHaveRoot && pwd->pw_uid != geteuid()) {
  897. X            (void)fprintf(stderr, "%s: effective uid cannot make destination owned by %s (%d != %d)\n", progname, Owner, geteuid(), pwd->pw_uid);
  898. X            exit(EXIT_OPT);
  899. X        }
  900. X        iOFrom = FROM_CMD;
  901. X    } else if (bDestExists != FALSE) {
  902. X        if ((struct passwd *)0 == (pwd = getpwuid((int) statb_dest.st_uid))) {
  903. X            (void)fprintf(stderr, "%s: destination owner %d doesn\'t exist\n", progname, statb_dest.st_uid);
  904. X            exit(EXIT_OPT);
  905. X        }
  906. X        iOFrom = FROM_OLD;
  907. X    } else if (bHaveRoot) {
  908. X        if ((char *)0 != DEFOWNER) {
  909. X            if ((struct passwd *)0 == (pwd = getpwnam(DEFOWNER))) {
  910. X                (void)fprintf(stderr, "%s: default owner `%s\' doesn\'t exist\n", progname, DEFOWNER);
  911. X                exit(EXIT_OPT);
  912. X            }
  913. X            iOFrom = FROM_DEF;
  914. X        } else {
  915. X            if ((struct passwd *)0 == (pwd = getpwuid((int) statb_dest.st_uid))) {
  916. X                (void)fprintf(stderr, "%s: destination directory owner %d doesn\'t exist\n", progname, statb_dest.st_uid);
  917. X                exit(EXIT_OPT);
  918. X            }
  919. X            iOFrom = FROM_DIR;
  920. X        }
  921. X    } else if ((struct passwd *)0 == (pwd = getpwuid((int) statb_file.st_uid))) {
  922. X        (void)fprintf(stderr, "%s: no passwd entry for source owner %d\n", progname, statb_file.st_uid);
  923. X        exit(EXIT_OPT);
  924. X        /*NOTREACHED*/
  925. X    } else {
  926. X        iOFrom = FROM_SRC;
  927. X    }
  928. X    pwd = savepwent(pwd);
  929. X    (void)endpwent();
  930. X
  931. X    /* take specified group or existing destination file's group
  932. X     * if destination exists, duplicate its group
  933. X     * else leave group the same as the file to install
  934. X     */
  935. X    (void)setgrent();
  936. X    if ((char *)0 != Group) {
  937. X        grp = getgrnam(Group);
  938. X        if ((struct group *)0 == grp) {
  939. X            (void)fprintf(stderr, "%s: no group entry for %s\n", progname, Group);
  940. X            exit(EXIT_OPT);
  941. X        }
  942. X        iGFrom = FROM_CMD;
  943. X    } else if (bDestExists != FALSE) {
  944. X        grp = getgrgid((int) statb_dest.st_gid);
  945. X        if ((struct group *)0 == grp) {
  946. X            (void)fprintf(stderr, "%s: no group entry for destination group %d\n", progname, statb_dest.st_gid);
  947. X            exit(EXIT_OPT);
  948. X        }
  949. X        iGFrom = FROM_OLD;
  950. X    } else if (bHaveRoot) {
  951. X        if ((char *)0 != DEFOWNER) {
  952. X            if ((struct group *)0 == (grp = getgrnam(DEFGROUP))) {
  953. X                (void)fprintf(stderr, "%s: no group entry for default group %s\n", progname, DEFGROUP);
  954. X                exit(EXIT_OPT);
  955. X            }
  956. X            iGFrom = FROM_DEF;
  957. X        } else {
  958. X            grp = getgrgid((int) statb_dest.st_gid);
  959. X            if ((struct group *)0 == grp) {
  960. X                (void)fprintf(stderr, "%s: no group entry for destination directory group %d\n", progname, statb_dest.st_gid);
  961. X                exit(EXIT_OPT);
  962. X            }
  963. X            iGFrom = FROM_DIR;
  964. X        }
  965. X    } else if ((struct group *)0 == (grp = getgrgid((int) getegid()))) {
  966. X        (void)fprintf(stderr, "%s: no group entry effective group %d\n", progname, getegid());
  967. X        exit(EXIT_OPT);
  968. X        /*NOTREACHED*/
  969. X    } else {
  970. X        iGFrom = FROM_SRC;
  971. X    }
  972. X    grp = savegrent(grp);
  973. X    (void)endgrent();
  974. X
  975. X    /* take specified mode, use destination mode, or default
  976. X     * (we never take the source modes, user uses root defaults)
  977. X     */
  978. X    if ((char *)0 != Mode) {
  979. X        CvtMode(Mode, & mMode, & mOptMode);
  980. X        iMFrom = FROM_CMD;
  981. X        /* here is some magic, if the user is a real install
  982. X         * wiz. he may have left us to tune the final modes...
  983. X         */
  984. X        if (0 != mOptMode) {
  985. X            mMode |= statb_dest.st_mode & mOptMode;
  986. X        }
  987. X    } else if (FALSE != bDestExists) {
  988. #if DLINKOK
  989. X        if (FALSE != bWasLink) {
  990. X            (void)fprintf(stderr, "%s: mode on existing symbolic link `%s\' cannot be used as install mode\n", progname, acDestPath);
  991. X            return FAIL;
  992. X        }
  993. #endif
  994. X        mMode = statb_dest.st_mode &~ S_IFMT;
  995. X        iMFrom = FROM_OLD;
  996. X    } else if ((char *)0 != DEFMODE) {
  997. X        CvtMode(DEFMODE, & mMode, & mOptMode);
  998. X        iMFrom = FROM_DEF;
  999. X        if (0 != mOptMode) {
  1000. X            mMode |= statb_dest.st_mode & mOptMode;
  1001. X        }
  1002. X    } else {
  1003. X        mMode = statb_dest.st_mode &~ (S_IFMT|S_ISUID|S_ISGID|S_ISVTX);
  1004. X        iMFrom = FROM_DIR;
  1005. X    }
  1006. X
  1007. X    /* if a file is already installed warn of potential differences in
  1008. X     * mode bits, owner, or group
  1009. X     */
  1010. X    if (bDestExists != FALSE) {
  1011. X        if (pwd->pw_uid != statb_dest.st_uid && FALSE == fQuiet) {
  1012. X            (void)fprintf(stderr, "%s: `%s\' owner mismatch (%d != %d)\n", progname, acDestPath, pwd->pw_uid, statb_dest.st_uid);
  1013. X        }
  1014. X
  1015. X        if (grp->gr_gid != statb_dest.st_gid && FALSE == fQuiet) {
  1016. X            (void)fprintf(stderr, "%s: `%s\' group mismatch (%d != %d)\n", progname, acDestPath, grp->gr_gid, statb_dest.st_gid);
  1017. X        }
  1018. X
  1019. X        if (PERM_RWX(mMode) != PERM_RWX(statb_dest.st_mode) && FALSE == fQuiet) {
  1020. X            (void)fprintf(stderr, "%s: `%s\' mode mismatch (%04o != %04o)\n", progname, acDestPath, mMode, statb_dest.st_mode &~ S_IFMT);
  1021. X        }
  1022. X        if ((S_ISUID & mMode) != (S_ISUID & statb_dest.st_mode)) {
  1023. X            (void)fprintf(stderr, "%s: `%s\' setuid bit changed, now %s\n", progname, acDestPath, apcOO[0 != (S_ISUID & mMode)]);
  1024. X        }
  1025. X        if ((S_ISGID & mMode) != (S_ISGID & statb_dest.st_mode)) {
  1026. X            (void)fprintf(stderr, "%s: `%s\' setgid bit changed, now %s\n", progname, acDestPath, apcOO[0 != (S_ISGID & mMode)]);
  1027. X        }
  1028. X        if ((S_ISVTX & mMode) != (S_ISVTX & statb_dest.st_mode)) {
  1029. X            (void)fprintf(stderr, "%s: `%s\' sticky bit changed, now %s\n", progname, acDestPath, apcOO[0 != (S_ISVTX & mMode)]);
  1030. X        }
  1031. X    }
  1032. X
  1033. X    /* here we really want to check against the default stuff if the
  1034. X     * modes (owner, group, mode) of the file are not what the default
  1035. X     * would give, choke a little (and the modes are not from the cmd line)
  1036. X     * but this would be too much work; let instck -G save us
  1037. X     * in the broken cases.
  1038. X     */
  1039. X
  1040. #if defined(CONFIG)
  1041. X    /* time to chekc the group and owner against our check list
  1042. X     */
  1043. X    if (Check.ffound) {
  1044. X        register int bFail = FALSE;
  1045. X
  1046. X        if ((char *)0 != Check.pclink) {
  1047. X            (void)fprintf(stderr, "%s: `%s\' be a %s link to `%s\'\n", progname, acDestPath, ':' == Check.pclink[0] ? "hard" : "symbolic", Check.pclink+1);
  1048. X            bFail = TRUE;
  1049. X            goto quit;
  1050. X        }
  1051. X        if ('*' == Check.acowner[0]) {
  1052. X            /* OK no check */;
  1053. X        } else if (Check.fbangowner) {
  1054. X            if (Check.uid == pwd->pw_uid) {
  1055. X                (void)fprintf(stderr, "%s: `%s\' should not have owner %s\n", progname, acDestPath, Check.acowner);
  1056. X                bFail = TRUE;
  1057. X            }
  1058. X        } else if (Check.uid != pwd->pw_uid) {
  1059. X            (void)fprintf(stderr, "%s: `%s\' should have owner %s (not %s)\n", progname, acDestPath, Check.acowner, pwd->pw_name);
  1060. X            bFail = TRUE;
  1061. X        }
  1062. X
  1063. X        if ('*' == Check.acgroup[0]) {
  1064. X            /*OK */;
  1065. X        } else if (Check.fbanggroup) {
  1066. X            if (Check.gid == grp->gr_gid) {
  1067. X                (void)fprintf(stderr, "%s: `%s\' should not have group %s\n", progname, acDestPath, Check.acgroup);
  1068. X                bFail = TRUE;
  1069. X            }
  1070. X        } else if (Check.gid != grp->gr_gid) {
  1071. X            (void)fprintf(stderr, "%s: `%s\' should have group %s (not %s)\n", progname, acDestPath, Check.acgroup, grp->gr_name);
  1072. X            bFail = TRUE;
  1073. X        }
  1074. X
  1075. X        switch (Check.acmode[0]) {
  1076. X        case '?':
  1077. X        case '*':
  1078. X            /*OK*/;
  1079. X        case '-':
  1080. X            if (Check.mmust != (mMode & Check.mmust)) {
  1081. X                (void)fprintf(stderr, "%s: `%s\' mode %04o doesn\'t have bits to match %s (%04o)\n", progname, acDestPath, mMode, Check.acmode, Check.mmust);
  1082. X                bFail = TRUE;
  1083. X            } else if (0 != (mMode &~ (Check.mmust|Check.moptional))) {
  1084. X                (void)fprintf(stderr, "%s: `%s\' mode %04o has too many bits to match %s (%04o)\n", progname, acDestPath, mMode, Check.acmode, Check.mmust|Check.moptional);
  1085. X                bFail = TRUE;
  1086. X            }
  1087. X            if (0 != (S_ISUID & mMode) ? 0 == (S_ISUID & (Check.mmust|Check.moptional)) : 0 != (S_ISUID & Check.mmust)) {
  1088. X                (void)fprintf(stderr, "%s: `%s\' setuid bit must be %s\n", progname, acDestPath, apcOO[0 == (S_ISUID & mMode)]);
  1089. X                bFail = TRUE;
  1090. X            }
  1091. X            if (0 != (S_ISGID & mMode) ? 0 == (S_ISGID & (Check.mmust|Check.moptional)) : 0 != (S_ISGID & Check.mmust)) {
  1092. X                (void)fprintf(stderr, "%s: `%s\' setgid bit must be %s\n", progname, acDestPath, apcOO[0 == (S_ISGID & mMode)]);
  1093. X                bFail = TRUE;
  1094. X            }
  1095. X            if (0 != (S_ISVTX & mMode) ? 0 == (S_ISVTX & (Check.mmust|Check.moptional)) : 0 != (S_ISVTX & Check.mmust)) {
  1096. X                (void)fprintf(stderr, "%s: `%s\' sticky bit must be %s\n", progname, acDestPath, apcOO[0 == (S_ISVTX & mMode)]);
  1097. X                bFail = TRUE;
  1098. X            }
  1099. X            break;
  1100. X        default:
  1101. X            (void)fprintf(stderr, "%s: `%s\' must be a %s\n", progname, acDestPath, NodeType(Check.mtype, (char *)0));
  1102. X            bFail = TRUE;
  1103. X            break;
  1104. X        case '!':
  1105. X            if (fDelete) {
  1106. X                break;
  1107. X            }
  1108. X            /* fall through */
  1109. X        case '~':
  1110. X            (void)fprintf(stderr, "%s: `%s\' should not be %s", progname, acDestPath, fDelete ? "removed" : "installed");
  1111. X            if ((char *)0 != Check.pcmesg && '\000' != Check.pcmesg[0])
  1112. X                (void)fprintf(stderr, ", %s", Check.pcmesg);
  1113. X            (void)fputc('\n', stderr);
  1114. X            bFail = TRUE;
  1115. X            break;
  1116. X        }
  1117. X
  1118. X        switch (Check.chstrip) {
  1119. X        case CF_ANY:
  1120. X            break;
  1121. X        case CF_STRIP:
  1122. X            if (!fDelete && !Strip) {
  1123. X                (void)fprintf(stderr, "%s: `%s\' must be strip\'ed (use -s)\n", progname, acDestPath);
  1124. X                bFail = TRUE;
  1125. X            }
  1126. X            break;
  1127. X        case CF_RANLIB:
  1128. X            if (!fDelete && !Ranlib) {
  1129. X                (void)fprintf(stderr, "%s: `%s\' must be ranlib\'ed (use -l)\n", progname, acDestPath);
  1130. X                bFail = TRUE;
  1131. X            }
  1132. X            break;
  1133. X        case CF_NONE:
  1134. X            if (!fDelete && (Strip || Ranlib)) {
  1135. X                (void)fprintf(stderr, "%s: `%s\' must not be strip\'ed or ranlib\'ed (do not use -l or -s)\n", progname, acDestPath);
  1136. X                bFail = TRUE;
  1137. X            }
  1138. X            break;
  1139. X        }
  1140. X
  1141. X    quit:
  1142. X        if (FALSE != bFail) {
  1143. X            (void)fprintf(stderr, "%s: `%s\' failed check in `%s\'\n", progname, acDestPath, pcSpecial);
  1144. X            return FAIL;
  1145. X        }
  1146. X        if (fDelete) {
  1147. X            (void)printf("%s: %s(%d) %s pattern `%s\'\n", progname, Check.pcspecial, Check.iline, 0 == strcmp(Check.pcpat, acDestPath) ? "remove" : "check", Check.pcpat);
  1148. X        }
  1149. #if defined(PARANOID)
  1150. X    } else if (bHaveRoot && 0 != (mMode & (S_ISUID|S_ISGID)) && (char *)0 != pcSpecial) {
  1151. X        fprintf(stderr, "%s: set%cid `%s\' ", progname, (S_ISUID & mMode) ? 'u' : 'g', acDestPath);
  1152. X        if (FROM_OLD != iMFrom) {
  1153. X            if ('\000' == *pcSpecial) {
  1154. X                fprintf(stderr, "needs check list file\n");
  1155. X            } else {
  1156. X                fprintf(stderr, "not found in check list %s\n", pcSpecial);
  1157. X            }
  1158. X            return FAIL;
  1159. X        } else if ('\000' == *pcSpecial) {
  1160. X            fprintf(stderr, "needs to be added to a check list file\n");
  1161. X        } else {
  1162. X            fprintf(stderr, "needs to be added to the check list %s\n", pcSpecial);
  1163. X        }
  1164. #endif    /* all setuid programs must be in check    */
  1165. X    }
  1166. #endif    /* have check list entry to compare    */
  1167. X
  1168. X    /* if we are removing the file, don't strip/ranlib it
  1169. X     */
  1170. X    if (fDelete) {
  1171. X        Ranlib = Strip = FALSE;
  1172. X        mMode = PERM_RWX(mMode);
  1173. X    }
  1174. X
  1175. X    /* Now we back up the old file if we're supposed to
  1176. X     * there might be nothing to backup because of -D
  1177. X     * but we've warned them about links and checked for funny file types
  1178. X     */
  1179. X    if (bBackup != FALSE) {
  1180. X        if (FAIL == DoBackup(bWasLink, acDestPath, acBackPath, acNewBack, FALSE == f1Copy && (FALSE != fVerbose || (Check.ffound && '\000' != Check.pcmesg[0])) ? "rename" : (char *)0)) {
  1181. X            return FAIL;
  1182. X        }
  1183. X        /* see comment where bCollide is set above
  1184. X         */
  1185. X        if (bCollide) {
  1186. X            pcFilePath = acNewBack;
  1187. X        }
  1188. X    } else {
  1189. X        acNewBack[0] = '\000';
  1190. X    }
  1191. X
  1192. X    /* Copy the file to the fs the dest is on, so we can just rename it.
  1193. X     */
  1194. X    if (bLocalCopy != FALSE || statb_dest.st_dev != statb_file.st_dev) {
  1195. X        /* cut backup at last slash, copy to buffer,
  1196. X         * concat on a Mytemp (mktemp) template
  1197. X         */
  1198. X        *pcSlash = '\000';
  1199. X        (void)sprintf(acTempPath, "%s/%s", acBackPath, TMPINST);
  1200. X        *pcSlash = '/';
  1201. X        MkOld(acTempPath);
  1202. X        (void)Mytemp(acTempPath);
  1203. X        if (FAIL == DoCopy(pcFilePath, acTempPath)) {
  1204. X            (void)fprintf(stderr, "%s: copy of %s to %s failed\n", progname, pcFilePath, acDestPath);
  1205. X            if ('\000' != acNewBack[0]) {
  1206. X                (void)Rename(acNewBack, acBackPath, "return");
  1207. X            }
  1208. X            return FAIL;
  1209. X        }
  1210. X        if (FALSE == bLocalCopy) {
  1211. X            if (FALSE != fTrace) {
  1212. X                (void)printf("%s: rm -f %s\n", progname, pcFilePath);
  1213. X            } else if (-1 == unlink(pcFilePath)) {
  1214. X                if (ETXTBSY != errno) {
  1215. X                    (void)fprintf(stderr, "%s: unlink: %s: %s\n", progname, pcFilePath, strerror(errno));
  1216. X                    if ('\000' != acNewBack[0]) {
  1217. X                        (void)Rename(acNewBack, acBackPath, "return");
  1218. X                    }
  1219. X                    return FAIL;
  1220. X                }
  1221. X                /* not quiet because we `failed' here */
  1222. X                fprintf(stderr, "%s: %s is running, not removed\n", progname, pcFilePath);
  1223. X            }
  1224. X        }
  1225. X        pcFilePath = acTempPath;
  1226. X    }
  1227. X
  1228. X    /* if a file is set{u,g}id check for shell script magic number!
  1229. X     * and mixing modes from one source with group/owner of another
  1230. X     */
  1231. X    if (0 != ((S_ISUID|S_ISGID) & mMode)) {
  1232. X        register char chSet;        /* 'g' or 'u', set?id    */
  1233. X        register char *pcSet;        /* "group" or "owner"    */
  1234. X        register int iFrom;        /* where set came from    */
  1235. X        register FILE *fpCheck;        /* file we install    */
  1236. X
  1237. X        chSet = (S_ISUID & mMode) ? 'u' : 'g';
  1238. X        pcSet = (S_ISUID & mMode) ? "owner" : "group";
  1239. X        if ((FILE *)0 != (fpCheck = fopen(pcFilePath, "r"))) {
  1240. X            if ('#' == getc(fpCheck) && '!' == getc(fpCheck)) {
  1241. X                (void)fprintf(stderr, "%s: `%s\' is set%cid and loaded with a `#!\'\n", progname, acDestPath, chSet);
  1242. X            }
  1243. X            (void)fclose(fpCheck);
  1244. X        } else {
  1245. X            (void)fprintf(stderr, "%s: cannot check magic number on set%cid `%s\'\n", progname, chSet, acDestPath);
  1246. X        }
  1247. X
  1248. X        iFrom = (0 != (S_ISUID & mMode)) ? iOFrom : iGFrom;
  1249. X        if (iMFrom != iFrom) {
  1250. X            (void)fprintf(stderr, "%s: `%s\' will not set%cid based on mode %s and %s %s\n", progname, acDestPath, chSet, apcFrom[iMFrom], pcSet, apcFrom[iFrom]);
  1251. X            if ('\000' != acNewBack[0]) {
  1252. X                (void)Rename(acNewBack, acBackPath, "return");
  1253. X            }
  1254. X            return FAIL;
  1255. X        }
  1256. X    }
  1257. X
  1258. X    /* Unlink the current file (which DoBackup() linked to the backup
  1259. X     * file) but only if it exists.
  1260. X     */
  1261. X    if (FALSE != bDestExists) {
  1262. X        if (FALSE != fTrace) {
  1263. X            (void)printf("%s: rm -f %s\n", progname, acDestPath);
  1264. X        } else if (-1 != unlink(acDestPath)) {
  1265. X            /* OK */;
  1266. X        } else if (ETXTBSY != errno) {
  1267. X            (void)fprintf(stderr, "%s: unlink: %s: %s\n", progname, acDestPath, strerror(errno));
  1268. X            if ('\000' != acNewBack[0]) {
  1269. X                (void)Rename(acNewBack, acBackPath, "return");
  1270. X            }
  1271. X            return FAIL;
  1272. X        } else {
  1273. X            /* might be the last link to a running binary under
  1274. X             * sys5, sigh, link to a bogus name and try again...
  1275. X             */
  1276. X            *pcSlash = '\000';
  1277. X            (void)sprintf(acBusyPath, "%s/%s", acBackPath, TMPBOGUS);
  1278. X            *pcSlash = '/';
  1279. X            MkOld(acBusyPath);
  1280. X            (void)Mytemp(acBusyPath);
  1281. X            if (-1 == Rename(acDestPath, acBusyPath, fVerbose ? "moving busy file" : (char *)0)) {
  1282. X                if ('\000' != acNewBack[0]) {
  1283. X                    (void)Rename(acNewBack, acBackPath, "return");
  1284. X                }
  1285. X                return FAIL;
  1286. X            }
  1287. X        }
  1288. X    }
  1289. X
  1290. X    BlockSigs();
  1291. X
  1292. X    if (FAIL == Rename(pcFilePath, acDestPath, (char *)0)) {
  1293. X        /*
  1294. X         * OUCH! why can't we rename this puppy? Here we are in
  1295. X         * big trouble: can't go back in some cases, can't go
  1296. X         * forward in others.  Let the user figure it out.
  1297. X         */
  1298. X        (void)fprintf(stderr, "%s: no currently installed file, aborting\n", progname);
  1299. X        exit(99);
  1300. X    }
  1301. X
  1302. X    /* We have moved the file in, we are commited.
  1303. X     * We *must* complete the installation at all costs now.
  1304. X     * There is no turning back from here on; no more return FAIL.
  1305. X     */
  1306. X    if (FALSE != f1Copy && pcFilePath != acNewBack && '\000' != acNewBack[0]) {
  1307. X        if (FALSE != fTrace) {
  1308. X            (void)printf("%s: rm -f %s\n", progname, acNewBack);
  1309. X        } else if (-1 != unlink(acNewBack)) {
  1310. X            /* OK */;
  1311. X        } else if (ETXTBSY != errno) {
  1312. X            (void)fprintf(stderr, "%s: unlink: %s: %s\n", progname, acNewBack, strerror(errno));
  1313. X        } else {
  1314. X            /* the last link to a running binary (SYSV)
  1315. X             * move it to a bogus name
  1316. X             */
  1317. X            *pcSlash = '\000';
  1318. X            (void)sprintf(acBusyPath, "%s/%s", acBackPath, TMPBOGUS);
  1319. X            *pcSlash = '/';
  1320. X            /* the MkOld below is unneeded
  1321. X             * (we know of at least one file in there)
  1322. X             */
  1323. X            MkOld(acBusyPath);
  1324. X            (void)Mytemp(acBusyPath);
  1325. X            if (-1 == Rename(acNewBack, acBusyPath, "moving busy backup file")) {
  1326. X                (void)fprintf(stderr, "%s: rename %s to %s: %s\n", progname, acNewBack, acBusyPath, strerror(errno));
  1327. X            }
  1328. X        }
  1329. X    }
  1330. X
  1331. X    /* If requested, strip the installed File or ranlib it.  Have to do this
  1332. X     * before ChOwnGrp and ChGroup or 2.9BSD drops the setuid bits...
  1333. X     */
  1334. X    if (FALSE != Strip) {
  1335. X        if (FALSE != fVerbose) {
  1336. X            (void)printf("%s: %s %s\n", progname, acStrip, acDestPath);
  1337. X        }
  1338. X        if (0 != RunCmd(acStrip, acDestPath, (char *)0)) {
  1339. X            (void)fprintf(stderr, "%s: `%s %s\' failed, run strip by hand\?\n", progname, acStrip, acDestPath);
  1340. X        }
  1341. X    }
  1342. X
  1343. X    if (FALSE != Ranlib) {
  1344. #if HAVE_RANLIB
  1345. X        /* on the pdp11/70 this kludge made the ranlib command work
  1346. X         * I don't think we ever knew why... now I don't have an 11
  1347. X         * to find out if we still need it.  Maybe chmod changed
  1348. X         * the times on the file?
  1349. X         */
  1350. #if defined(pdp11)
  1351. X        ChMode(acDestPath, mMode);
  1352. #endif
  1353. X        if (FALSE != fVerbose) {
  1354. X            (void)printf("%s: %s %s\n", progname, acRanlib, acDestPath);
  1355. X        }
  1356. X        if (0 != RunCmd(acRanlib, acDestPath, (char *)0)) {
  1357. X            (void)fprintf(stderr, "%s: `%s %s\' failed, run ranlib by hand\?\n", progname, acRanlib, acDestPath);
  1358. X        }
  1359. #else    /* on sysV fake it, same cmd that way    */
  1360. X        if (FALSE != fVerbose) {
  1361. X            (void)printf("%s: ranlib for `%s\' done by ar(1)\n", progname, acDestPath);
  1362. X        }
  1363. #endif    /* do we really run ranlib(1)        */
  1364. X    }
  1365. X
  1366. X    if ((char *)0 != pcHLink || (char *)0 != pcSLink) {
  1367. X        if (LaunchLinks(bDestExists ? & statb_dest : (struct stat *)0, acDestPath, pcHLink, pcSLink, mMode, pwd, grp)) {
  1368. X        
  1369. X            (void)fprintf(stderr, "%s: links failed, finishing installation anyway\n", progname);
  1370. X        }
  1371. X    }
  1372. X
  1373. X    /* Change ownership, group, timestamp, and mode of installed file
  1374. X     * (chmod must be done last or setuid bits are dropped under 2.9bsd)
  1375. X     */
  1376. X    if (FALSE != bHaveRoot) {
  1377. X        ChOwnGrp(acDestPath, pwd, grp);
  1378. X    } else {
  1379. X        ChGroup(acDestPath, grp);
  1380. X    }
  1381. X    if (FALSE != KeepTimeStamp) {
  1382. X        ChTimeStamp(acDestPath, & statb_file);
  1383. X    }
  1384. X    ChMode(acDestPath, mMode);
  1385. X
  1386. X    UnBlockSigs();
  1387. X
  1388. X    /* re-stat, we may have changed link count
  1389. X     */
  1390. X    if (-1 != stat(acBackPath, & statb_dest) && 1 != statb_dest.st_nlink) {
  1391. X        if ((char *)0 != pcHLink) {
  1392. X            (void)printf("%s: -H option may not have listed all the links to %s, still %d left\n", progname, acDestPath, statb_dest.st_nlink - 1);
  1393. X        } else {
  1394. X            (void)printf("%s: %s may still be installed someplace, link count is too big (%d)\n", progname, acBackPath, statb_dest.st_nlink);
  1395. X        }
  1396. X        *pcSlash = '\000';
  1397. X        (void)printf("%s: use `instck -i %s' to repair link counts\n", progname, acBackPath);
  1398. X        *pcSlash = '/';
  1399. X    }
  1400. X
  1401. X    /*
  1402. X     * and turn off special bits on backup -- in case installation
  1403. X     * was security related
  1404. X     */
  1405. X    if (FALSE != bDestExists && FALSE != bBackup && 0 != (statb_dest.st_mode & ~SAFEMASK)) {
  1406. X        ChMode(acBackPath, (int)statb_dest.st_mode & SAFEMASK);
  1407. X    }
  1408. X
  1409. #if defined(INST_FACILITY)
  1410. X    /*
  1411. X     * syslog out change if we are the superuser and we really changed
  1412. X     * something
  1413. X     */
  1414. X    if (bHaveRoot && FALSE == fTrace) {
  1415. X        (void)sprintf(acLogBuf, pcLogStat, acDestPath, pwd->pw_name, grp->gr_name, mMode, pcGuilty);
  1416. X        syslog(LOG_INFO, acLogBuf);
  1417. X    }
  1418. #endif    /* we should syslog changes        */
  1419. X
  1420. #if defined(CONFIG)
  1421. X    /* if the file is in a check list report installation message
  1422. X     */
  1423. X    if (Check.ffound && '\000' != Check.pcmesg[0]) {
  1424. X        (void)printf("%s: %s: %s\n", progname, acDestPath, Check.pcmesg);
  1425. X    }
  1426. #endif    /* have check list to output a comment    */
  1427. X
  1428. X    /* if we are supposed to dink it, do it now, else
  1429. X     * if requested, show the results of the installation with ls(1)
  1430. X     */
  1431. X    if (fDelete) {
  1432. X        if (fTrace) {
  1433. X            (void)printf("%s: rm -f %s\n", progname, acDestPath);
  1434. X        } else if (-1 == unlink(acDestPath)) {
  1435. X            fprintf(stderr, "%s: unlink: %s: %s\n", progname, acDestPath, strerror(errno));
  1436. X            return FAIL;
  1437. X        }
  1438. X        (void)RunCmd(acLs, acLsArgs, acBackPath);
  1439. X    } else if (FALSE != fVerbose) {
  1440. X        if (FALSE != bBackup) {
  1441. X            (void)RunCmd(acLs, acLsArgs, acBackPath);
  1442. X        }
  1443. X        (void)RunCmd(acLs, acLsArgs, acDestPath);
  1444. X    }
  1445. X
  1446. X    return SUCCEED;
  1447. }
  1448. Purdue
  1449. chmod 0444 install.d/file.c ||
  1450. echo 'restore of install.d/file.c failed'
  1451. Wc_c="`wc -c < 'install.d/file.c'`"
  1452. test 46361 -eq "$Wc_c" ||
  1453.     echo 'install.d/file.c: original size 46361, current size' "$Wc_c"
  1454. fi
  1455. # ============= instck/instck.h ==============
  1456. if test ! -d 'instck'; then
  1457.     echo 'x - creating directory instck'
  1458.     mkdir 'instck'
  1459. fi
  1460. if test -f 'instck/instck.h' -a X"$1" != X"-c"; then
  1461.     echo 'x - skipping instck/instck.h (File already exists)'
  1462. else
  1463. echo 'x - extracting instck/instck.h (Text)'
  1464. sed 's/^X//' << 'Purdue' > 'instck/instck.h' &&
  1465. /*
  1466. X * $Id: instck.h,v 7.1 90/09/17 10:25:38 ksb Exp $
  1467. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  1468. X * 47907.  All rights reserved.
  1469. X *
  1470. X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  1471. X *
  1472. X * This software is not subject to any license of the American Telephone
  1473. X * and Telegraph Company or the Regents of the University of California.
  1474. X *
  1475. X * Permission is granted to anyone to use this software for any purpose on
  1476. X * any computer system, and to alter it and redistribute it freely, subject
  1477. X * to the following restrictions:
  1478. X *
  1479. X * 1. Neither the authors nor Purdue University are responsible for any
  1480. X *    consequences of the use of this software.
  1481. X *
  1482. X * 2. The origin of this software must not be misrepresented, either by
  1483. X *    explicit claim or by omission.  Credit to the authors and Purdue
  1484. X *    University must appear in documentation and sources.
  1485. X *
  1486. X * 3. Altered versions must be plainly marked as such, and must not be
  1487. X *    misrepresented as being the original software.
  1488. X *
  1489. X * 4. This notice may not be removed or altered.
  1490. X */
  1491. X
  1492. #define PATCH_LEVEL    0
  1493. X
  1494. /*
  1495. X * configure the maxfreq routines for instck                (ksb)
  1496. X */
  1497. X
  1498. typedef struct PDnode {
  1499. X    short fseen;
  1500. } PATH_DATA;
  1501. extern void PUInit();
  1502. X
  1503. #if !defined(BINCHMOD)
  1504. #define BINCHMOD    "/bin/chmod"
  1505. #endif
  1506. X
  1507. #if !defined(BINCHGRP)
  1508. #define BINCHGRP    "/bin/chgrp"
  1509. #endif
  1510. X
  1511. #if !defined(BINCHOWN)
  1512. #define BINCHOWN    "/etc/chown"
  1513. #endif
  1514. X
  1515. #if !defined(BINRANLIB)
  1516. #define BINRANLIB    "/usr/bin/ranlib"
  1517. #endif
  1518. X
  1519. #if !defined(BINSTRIP)
  1520. #define BINSTRIP    "/bin/strip"
  1521. #endif
  1522. X
  1523. #if !defined(BINRM)
  1524. #define BINRM        "/bin/rm"
  1525. #endif
  1526. X
  1527. #if !defined(BINLN)
  1528. #define BINLN        "/bin/ln"
  1529. #endif
  1530. X
  1531. X
  1532. #if !defined(MAXANS)
  1533. #define MAXANS        20        /* answer for QExec prompt    */
  1534. #endif
  1535. X
  1536. X
  1537. extern CHLIST CLCheck;
  1538. extern int iMatches;
  1539. X
  1540. #define fpOut        stdout        /* so we could make it a file    */
  1541. X
  1542. #if HAVE_PROTO
  1543. extern int ElimDups(int, char **);
  1544. extern void NoMatches(char *);
  1545. extern void BadSet(int, int, char *, char *);
  1546. extern int FileMatch(char *, char *, int (*)());
  1547. extern int IsStripped(int, struct stat *);
  1548. extern int IsRanlibbed(int, struct stat *);
  1549. extern int DoCk(char *);
  1550. extern void InstCk(int, char **, char *, CHLIST *);
  1551. extern void OldCk(int, char **, CHLIST *);
  1552. extern int FilterOld(int, char **, CHLIST *);
  1553. #else
  1554. extern int ElimDups();
  1555. extern void NoMatches();
  1556. extern void BadSet();
  1557. extern int FileMatch();
  1558. extern int IsStripped();
  1559. extern int IsRanlibbed();
  1560. extern int DoCk();
  1561. extern void InstCk();
  1562. extern void OldCk();
  1563. extern int FilterOld();
  1564. #endif
  1565. Purdue
  1566. chmod 0444 instck/instck.h ||
  1567. echo 'restore of instck/instck.h failed'
  1568. Wc_c="`wc -c < 'instck/instck.h'`"
  1569. test 2505 -eq "$Wc_c" ||
  1570.     echo 'instck/instck.h: original size 2505, current size' "$Wc_c"
  1571. fi
  1572. true || echo 'restore of install.d/main.c failed'
  1573. echo End of part 2, continue with part 3
  1574. exit 0
  1575.  
  1576. exit 0 # Just in case...
  1577.