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

  1. Subject:  v24i067:  Purdue software product installation system, Part05/07
  2. Newsgroups: comp.sources.unix
  3. Approved: rsalz@uunet.UU.NET
  4. X-Checksum-Snefru: b01331a3 e69bb62d 56bd76e2 aeb1e0f7
  5.  
  6. Submitted-by: Kevin Braunsdorf <ksb@cc.purdue.edu>
  7. Posting-number: Volume 24, Issue 67
  8. Archive-name: pucc-install/part05
  9.  
  10. #!/bin/sh
  11. # This is part 05 of pucc-1b
  12. # ============= install.d/special.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/special.c' -a X"$1" != X"-c"; then
  18.     echo 'x - skipping install.d/special.c (File already exists)'
  19. else
  20. echo 'x - extracting install.d/special.c (Text)'
  21. sed 's/^X//' << 'Purdue' > 'install.d/special.c' &&
  22. /*
  23. X * $Id: special.c,v 7.1 90/09/17 10:33:49 ksb Exp $
  24. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  25. X * 47907.  All rights reserved.
  26. X *
  27. X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  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 * handle the configuration file code                    (ksb)
  51. X */
  52. X
  53. #include <sys/param.h>
  54. #include <sys/types.h>
  55. #include <sys/stat.h>
  56. #include <sys/file.h>
  57. #include <sys/time.h>
  58. #include <stdio.h>
  59. #include <ctype.h>
  60. #include <errno.h>
  61. #include <pwd.h>
  62. #include <grp.h>
  63. X
  64. #include "configure.h"
  65. #include "install.h"
  66. #include "syscalls.h"
  67. #include "special.h"
  68. #include "main.h"
  69. #if defined(INSTCK)
  70. #include "instck.h"
  71. #endif
  72. X
  73. #if STRINGS
  74. #include <strings.h>
  75. #else
  76. #include <string.h>
  77. #endif
  78. X
  79. char *apcOO[] = {    /* name of 0/1 for user            */
  80. X    "off",
  81. X    "on"
  82. };
  83. X
  84. struct group *grpDef;        /* default group on all files (this dir)*/
  85. struct passwd *pwdDef;        /* default owner on all files (this dir)*/
  86. X
  87. /* set up the users values for '=' in the config file            (ksb)
  88. X */
  89. void
  90. InitCfg(pcOwner, pcGroup)
  91. char *pcOwner, *pcGroup;
  92. {
  93. X    extern char *getenv();
  94. X    pwdDef = (struct passwd *)0;
  95. X    if ((char *)0 == pcOwner) {
  96. X        if (bHaveRoot) {
  97. X            pcOwner = DEFOWNER;
  98. X        } else {
  99. X            auto char *pcUser;
  100. X
  101. X            pcUser = getenv("USER");
  102. X            if ((char *)0 == pcUser) {
  103. X                pcUser = getenv("LOGNAME");
  104. X            }
  105. X            if ((char *)0 != pcUser && '\000' != pcUser[0] && (struct passwd *)0 != (pwdDef = getpwnam(pcUser)) && getuid() == pwdDef->pw_uid) {
  106. X                /* got him */;
  107. X            } else if ((struct passwd *)0 == (pwdDef = getpwuid(getuid()))) {
  108. X                fprintf(stderr, "%s: getpwuid: %d: %s\n", progname, getuid(), strerror(errno));
  109. X                exit(10);
  110. X            }
  111. X            pwdDef = savepwent(pwdDef);
  112. X            pcOwner = pwdDef->pw_name;
  113. X        }
  114. X    }
  115. X    if ((char *)0 == pcOwner || '\000' == *pcOwner) {
  116. X        pcOwner = (char *)0;
  117. X    } else if ((struct passwd *)0 == pwdDef) {
  118. X        pwdDef = getpwnam(pcOwner);
  119. X        if ((struct passwd *)0 == pwdDef) {
  120. X            fprintf(stderr, "%s: getpwname: %s: %s\n", progname, pcOwner, strerror(errno));
  121. X            exit(10);
  122. X        }
  123. X        pwdDef = savepwent(pwdDef);
  124. X    }
  125. X
  126. X    grpDef = (struct group *)0;
  127. X    if ((char *)0 == pcGroup) {
  128. X        if (bHaveRoot) {
  129. X            pcGroup = DEFGROUP;
  130. X        } else {
  131. X            if ((struct group *)0 == (grpDef = getgrgid(getgid()))) {
  132. X                fprintf(stderr, "%s: getgrgid: %d: %s\n", progname, getgid(), strerror(errno));
  133. X                exit(11);
  134. X            }
  135. X            grpDef = savegrent(grpDef);
  136. X            pcGroup = grpDef->gr_name;
  137. X        }
  138. X    }
  139. X    if ((char *)0 == pcGroup || '\000' == *pcGroup) {
  140. X        pcGroup = (char *)0;
  141. X    } else if ((struct group *)0 == grpDef) {
  142. X        grpDef = getgrnam(pcGroup);
  143. X        if ((struct group *)0 == grpDef) {
  144. X            fprintf(stderr, "%s: getgrname: %s: %s\n", progname, pcGroup, strerror(errno));
  145. X            exit(11);
  146. X        }
  147. X        grpDef = savegrent(grpDef);
  148. X    }
  149. }
  150. X
  151. X
  152. /*
  153. X * get the user-level name for this node `plain file' or `socket'    (ksb)
  154. X *    return string, ref-out single char
  155. X */
  156. char *
  157. NodeType(mType, pcChar)
  158. unsigned int mType;
  159. char *pcChar;
  160. {
  161. X    auto char acTemp[2];
  162. X    if ((char *)0 == pcChar)
  163. X        pcChar = acTemp;
  164. X
  165. X    switch (mType & S_IFMT) {
  166. X    case S_IFDIR:
  167. X        *pcChar = 'd';
  168. X        return "directory";
  169. #if defined(S_IFSOCK)
  170. X    case S_IFSOCK:
  171. X        *pcChar = 's';
  172. X        return "socket";
  173. #endif    /* no sockets */
  174. #if defined(S_IFIFO)
  175. X    case S_IFIFO:
  176. X        *pcChar = 'p';
  177. X        return "fifo";
  178. #endif
  179. #if defined(S_IFLNK)
  180. X    case S_IFLNK:
  181. X        *pcChar = 'l';
  182. X        return "symbolic link";
  183. #endif
  184. X    case S_IFBLK:
  185. X        *pcChar = 'b';
  186. X        return "block device";
  187. X    case S_IFCHR:
  188. X        *pcChar = 'c';
  189. X        return "character device";
  190. X    case S_IFREG:
  191. X    case 0:
  192. X        *pcChar = '-';
  193. X        return "plain file";
  194. X    default:
  195. X        break;
  196. X    }
  197. X    *pcChar = '?';
  198. X    return "type unknown";
  199. }
  200. X
  201. /*
  202. X * convert an octal mode to an integer                    (jms)
  203. X */
  204. static void
  205. OctMode(pcLMode, pmMode)
  206. char *pcLMode;        /* the string to convert (e.g., "755")        */
  207. int *pmMode;        /* the place to put the converted mode        */
  208. {
  209. X    register int mode;    /* mode of installed file        */
  210. X    register int c;        /* next character            */
  211. X
  212. X    for (mode = 0; (c = *pcLMode) != '\000'; ++pcLMode) {
  213. X        if (c >= '0' && c <= '7') {
  214. X            mode = (mode << 3) + (c - '0');
  215. X            continue;
  216. X        }
  217. X        (void)fprintf(stderr, "%s: bad digit int mode `%c\'\n", progname, *pcLMode);
  218. X        exit(EXIT_OPT);
  219. X    }
  220. X    if ((int *)0 != pmMode) {
  221. X        *pmMode |= mode;
  222. X    }
  223. }
  224. X
  225. X
  226. /*
  227. X * extra bits in the bit listing are handled strangely            (ksb)
  228. X */
  229. static void
  230. EBit(pcBit, bSet, cSet, cNotSet)
  231. char *pcBit;        /* pointer the the alpha bit            */
  232. int bSet;        /* should it set over struck            */
  233. int cSet;        /* overstrike with this                */
  234. int cNotSet;        /* it should have been this, else upper case it    */
  235. {
  236. X    if (0 != bSet) {
  237. X        *pcBit = (cNotSet == *pcBit) ? cSet : toupper(cSet);
  238. X    }
  239. }
  240. X
  241. X
  242. static char acOnes[] = "rwxrwxrwx";        /* mode 0777        */
  243. /*
  244. X * string to octal mode mask "rwxr-s--x" -> 02751.            (ksb)
  245. X * Note that we modify the string to do this, but we put it back.
  246. X */
  247. static void
  248. StrMode(pcLMode, pmBits, pmQuests)
  249. char *pcLMode;        /* alpha bits buffer (about 10 chars)        */
  250. register int *pmBits;    /* manditory mode                */
  251. int *pmQuests;        /* optional mode bits                */
  252. {
  253. X    register int iBit, i;
  254. X    register char *pcBit;
  255. X
  256. X    *pmBits = 0;
  257. X    if ((int *)0 != pmQuests) {
  258. X        *pmQuests = 0;
  259. X    }
  260. X
  261. X    /* if the mode is long enough to have a file type field check that
  262. X     * out and set the file type bits too
  263. X     */
  264. X    switch (i = strlen(pcLMode)) {
  265. X    default:
  266. X        (void)fprintf(stderr, "%s: alphabetical mode must be 9 or 10 characters `%s\' is %d\n", progname, pcLMode, i);
  267. X        exit(EXIT_OPT);
  268. X    case 9:
  269. X        *pmBits |= S_IFREG;
  270. X        break;
  271. X    case 10:
  272. X        switch (*pcLMode) {
  273. #if HAVE_SLINKS
  274. X        case 'l':    /* symbolic link */
  275. X            *pmBits |= S_IFLNK;
  276. X            break;
  277. #endif    /* no links to think about */
  278. #if defined(S_IFIFO)
  279. X        case 'p':    /* fifo */
  280. X            *pmBits |= S_IFIFO;
  281. X            break;
  282. #endif    /* no fifos */
  283. #if defined(S_IFSOCK)
  284. X        case 's':    /* socket */
  285. X            *pmBits |= S_IFSOCK;
  286. X            break;
  287. #endif    /* no sockets */
  288. X        case 'b':
  289. X            *pmBits |= S_IFBLK;
  290. X            break;
  291. X        case 'c':
  292. X            *pmBits |= S_IFCHR;
  293. X            break;
  294. X        case '-':
  295. X        case 'f':
  296. X            *pmBits |= S_IFREG;
  297. X            break;
  298. X        case 'd':
  299. X            *pmBits |= S_IFDIR;
  300. X            break;
  301. X        default:
  302. X            (void)fprintf(stderr, "%s: unknown file type `%c\'\n", progname, *pcLMode);
  303. X            exit(EXIT_OPT);
  304. X        }
  305. X        ++pcLMode;
  306. X        break;
  307. X    }
  308. X
  309. X    /* copy out and turn off set{g,u}id and stick bits
  310. X     * (The upper case bit means no execute underneath.)
  311. X     */
  312. X    if ((char *)0 != (pcBit = strchr("sS", pcLMode[2]))) {
  313. X        pcLMode[2] = isupper(*pcBit) ? '-' : 'x';
  314. X        *pmBits |= S_ISUID;
  315. X    }
  316. X    if ((char *)0 != (pcBit = strchr("sS", pcLMode[5]))) {
  317. X        pcLMode[5] = isupper(*pcBit) ? '-' : 'x';
  318. X        *pmBits |= S_ISGID;
  319. X    }
  320. X    if ((char *)0 != (pcBit = strchr("tT", pcLMode[8]))) {
  321. X        pcLMode[8] = isupper(*pcBit) ? '-' : 'x';
  322. X        *pmBits |= S_ISVTX;
  323. X    }
  324. X
  325. X    /* read normal mode bits
  326. X     */
  327. X    for (i = 0, iBit = 0400; i < 9; ++i, iBit >>= 1) {
  328. X        if (pcLMode[i] == acOnes[i]) {
  329. X            *pmBits |= iBit;
  330. X        } else if ('-' == pcLMode[i]) {
  331. X            continue;
  332. X        } else if ('\?' == pcLMode[i]) {
  333. X            if ((int *)0 != pmQuests)
  334. X                *pmQuests |= iBit;
  335. X        } else if ('\000' == pcLMode[i]) {
  336. X            (void)fprintf(stderr, "%s: not enough bits in file mode\n", progname);
  337. X        } else if ((char *)0 != strchr("rwxtTsS", pcLMode[i])) {
  338. X            (void)fprintf(stderr, "%s: bit `%c\' in file mode is in the wrong column\n", progname, pcLMode[i]);
  339. X            exit(EXIT_OPT);
  340. X        } else {
  341. X            (void)fprintf(stderr, "%s: unknown bit in file mode `%c\'\n", progname, pcLMode[i]);
  342. X            exit(EXIT_OPT);
  343. X        }
  344. X    }
  345. X
  346. X    /* here we put the set{u,g}id and sticky bits back
  347. X     */
  348. X    EBit(pcLMode+2, S_ISUID & *pmBits, 's', 'x');
  349. X    EBit(pcLMode+5, S_ISGID & *pmBits, 's', 'x');
  350. X    EBit(pcLMode+8, S_ISVTX & *pmBits, 't', 'x');
  351. }
  352. X
  353. X
  354. /*
  355. X * Convert a string that ls(1) understands into something that         (jms&ksb)
  356. X * chmod(2) understands (extended), or an octal mode.
  357. X ! The string we are given may be in the text (const) segment,
  358. X ! we have to copy it to a write segment to allow StrMode to work.
  359. X *
  360. X * Optional bits may be specified after a `/' as in
  361. X *    0711/044
  362. X * which allows any of {0711, 0751, 0715, 0755}, or write symolicly
  363. X *    -rwx--x--x/----r--r--
  364. X * or a symbolic mode may contain a `?' in place of a bit for optional:
  365. X *    -rwx?-x?-x
  366. X * (which is quite readable).
  367. X *
  368. X * The slash notaion is needed for optional setgid directories, at least.
  369. X */
  370. void
  371. CvtMode(pcLMode, pmMode, pmQuest)
  372. char *pcLMode;        /* the string to convert (e.g., "755")        */
  373. int *pmMode;        /* the place to put the converted mode        */
  374. int *pmQuest;        /* the place to put the converted optional mode    */
  375. {
  376. X    register char *pcScan;    /* copy mode so we can write on it    */
  377. X    auto char acDown[MAXPATHLEN+1];    /* where we write        */
  378. X
  379. X    if ((int *)0 != pmMode)
  380. X        *pmMode = 0;
  381. X    if ((int *)0 != pmQuest)
  382. X        *pmQuest = 0;
  383. X
  384. X    pcScan = acDown;
  385. X    while ('/' != *pcLMode && '\000' != *pcLMode) {
  386. X        *pcScan++ = *pcLMode++;
  387. X    }
  388. X    *pcScan = '\000';
  389. X
  390. X    if (isdigit(*acDown)) {
  391. X        OctMode(acDown, pmMode);
  392. X    } else {
  393. X        StrMode(acDown, pmMode, pmQuest);
  394. X    }
  395. X
  396. X    if ('/' == *pcLMode && (int *)0 != pmQuest) {
  397. X        ++pcLMode;
  398. X        (void)strcpy(acDown, pcLMode);    /* need a writable copy */
  399. X        if (isdigit(*acDown)) {
  400. X            OctMode(acDown, pmQuest);
  401. X        } else {
  402. X            StrMode(acDown, pmQuest, pmQuest);
  403. X        }
  404. X    }
  405. }
  406. X
  407. X
  408. #if defined(CONFIG)
  409. /*
  410. X * convert an integer mode into a symbolic format            (ksb)
  411. X */
  412. void
  413. ModetoStr(pcLMode, mMode, mOptional)
  414. char *pcLMode;        /* alpha bits buffer (10 chars or more)        */
  415. int mMode;        /* maditory mode bits                */
  416. int mOptional;        /* optional mode bits                */
  417. {
  418. X    register int i, iBit;
  419. X
  420. X    (void)strcpy(pcLMode, acOnes);
  421. X    for (i = 0, iBit = 0400; i < 9; ++i, iBit >>= 1) {
  422. X        if (0 == (mMode & iBit))
  423. X            pcLMode[i] = '-';
  424. X    }
  425. X    EBit(pcLMode+2, S_ISUID & mMode, 's', 'x');
  426. X    EBit(pcLMode+5, S_ISGID & mMode, 's', 'x');
  427. X    EBit(pcLMode+8, S_ISVTX & mMode, 't', 'x');
  428. X    for (i = 0, iBit = 0400; i < 9; ++i, iBit >>= 1) {
  429. X        if (0 == (mOptional & iBit))
  430. X            continue;
  431. X        if ('-' == pcLMode[i])
  432. X            pcLMode[i] = '\?';
  433. X    }
  434. }
  435. X
  436. X
  437. /*
  438. X * CompPath()
  439. X *    Compress a path by assuming that . and .. really point to    (ksb)
  440. X *    what they should (good under BSD at least :-|), we also
  441. X *    assume the all things used as a directory all directories
  442. X *    (and exist)
  443. X *
  444. X * Remove extra `/', `./', `foo/..'  (in place)
  445. X * also replace a null path with `.'
  446. X */
  447. static char *
  448. CompPath(pcFile)
  449. char *pcFile;        /* path to compress                */
  450. {
  451. X    register char *pcScan, *pcPut;
  452. X    register int bFirst;
  453. X
  454. X    pcScan = pcPut = pcFile;
  455. X    bFirst = 1;
  456. X    for (;;) { switch (*pcPut = *pcScan) {
  457. X    case '/':
  458. X        ++pcPut;
  459. X        do
  460. X            ++pcScan;
  461. X        while ('/' == *pcScan);
  462. X        bFirst = 1;
  463. X        continue;
  464. X    case '.':
  465. X        if (!bFirst) {
  466. X            ++pcPut, ++pcScan;
  467. X            continue;
  468. X        }
  469. X        if ('/' == pcScan[1] || '\000' == pcScan[1]) {
  470. X            do
  471. X                ++pcScan;
  472. X            while ('/' == *pcScan);
  473. X            continue;
  474. X        }
  475. X        /* do foo/.., but not /.. or just ..
  476. X         */
  477. X        if ('.' == pcScan[1] && pcPut != pcFile &&
  478. X            ('/' == pcScan[2] || '\000' == pcScan[2]) &&
  479. X            !('/' == pcFile[0] && pcPut == pcFile+1)) {
  480. X            --pcPut;
  481. X            do
  482. X                --pcPut;
  483. X            while ('/' != *pcPut && pcPut != pcFile);
  484. X            if ('/' == *pcPut)
  485. X                ++pcPut;
  486. X            pcScan += 2;
  487. X            while ('/' == *pcScan)
  488. X                ++pcScan;
  489. X            continue;
  490. X        }
  491. X    default:
  492. X        ++pcPut, ++pcScan;
  493. X        bFirst = 0;
  494. X        continue;
  495. X    case '\000':
  496. X        break;
  497. X    } break; }
  498. X
  499. X    /* clean up trailing / and empty path name
  500. X     */
  501. X    if (pcPut != pcFile) {
  502. X        while (--pcPut != pcFile && '/' == *pcPut)
  503. X            *pcPut = '\000';
  504. X    }
  505. X    if ('\000' == *pcFile) {
  506. X        pcFile[0] = '.';
  507. X        pcFile[1] = '\000';
  508. X    }
  509. X    return pcFile;
  510. }
  511. X
  512. X
  513. X
  514. /*
  515. X * _SamePath()
  516. X *    We want /bin/* to match every file in /bin OK.            (ksb)
  517. X *    return 1 for ==, 0 for !=
  518. X *
  519. X * N.B. Must call CompPath on pcFile first, or know it is minimal
  520. X */
  521. int
  522. _SamePath(pcGlob, pcFile, fDot)
  523. char *pcGlob;        /* the pattern to match                */
  524. char *pcFile;        /* the file to match with            */
  525. int fDot;        /* are we at the start of pcFile, or post '/'    */
  526. {
  527. X    register char *pc;
  528. X    register int iLenGlob, iLenFile;
  529. X    auto int bFound, cStop;
  530. X
  531. X    for (;;) { switch (*pcGlob) {
  532. X    case '*':        /* match any string            */
  533. X        pc = ++pcGlob;
  534. X        iLenGlob = 0;
  535. X        while ('\\' != *pc && '?' != *pc && '[' != *pc && '*' != *pc && '\000' != *pc && '/' != *pc) {
  536. X            ++pc, ++iLenGlob;
  537. X        }
  538. X
  539. X        iLenFile = 0;
  540. X        while ('/' != pcFile[iLenFile] && '\000' != pcFile[iLenFile] &&
  541. X               (!fDot || '.' != pcFile[iLenFile])) {
  542. X            ++iLenFile;
  543. X            fDot = 0;
  544. X        }
  545. X
  546. X        bFound = 0;
  547. X        do {
  548. X            if (iLenGlob == 0 || 0 == strncmp(pcGlob, pcFile, iLenGlob)) {
  549. X                if (_SamePath(pc, pcFile+iLenGlob, fDot)) {
  550. X                    bFound = 1;
  551. X                    break;
  552. X                }
  553. X            }
  554. X            --iLenFile, ++pcFile;
  555. X        } while (iLenFile >= iLenGlob);
  556. X        return bFound;
  557. X    case '[':        /* any of                */
  558. X        ++pcGlob;
  559. X        cStop = *pcFile++;
  560. X        if (cStop == '/')    /* range never match '/'    */
  561. X            break;
  562. X        bFound = 0;
  563. X        if ('-' == *pcGlob) {
  564. X            bFound = '-' == cStop;
  565. X            ++pcGlob;
  566. X        }
  567. X        while (']' != *pcGlob) {
  568. X            if ('-' == pcGlob[1]) {
  569. X                if (pcGlob[0] <= cStop && cStop <= pcGlob[2])
  570. X                    bFound = 1;
  571. X                pcGlob += 2;
  572. X            } else {
  573. X                if (pcGlob[0] == cStop)
  574. X                    bFound = 1;
  575. X            }
  576. X            ++pcGlob;
  577. X        }
  578. X        ++pcGlob;
  579. X        if (!bFound)
  580. X            break;
  581. X        continue;
  582. X    case '?':        /* and single char but '/'        */
  583. X        if ('/' == *pcFile || (fDot && '.' == *pcFile) || '\000' == *pcFile)
  584. X            break;
  585. X        ++pcGlob, ++pcFile;
  586. X        fDot = 0;
  587. X        continue;
  588. X    case '\\':        /* next char not special        */
  589. X        ++pcGlob;
  590. X        /*fall through*/
  591. X    case '/':        /* delimiter                */
  592. X        fDot = 1;
  593. X        if (*pcGlob != *pcFile)
  594. X            break;
  595. X        ++pcGlob;
  596. X        do {
  597. X            ++pcFile;
  598. X        } while ('/' == *pcFile);
  599. X        continue;
  600. X    default:        /* or any other character        */
  601. X        fDot = 0;
  602. X        if (*pcGlob != *pcFile)
  603. X            break;
  604. X        ++pcGlob, ++pcFile;
  605. X        continue;
  606. X    case '\000':        /* end of pattern, end of file name    */
  607. X        return '\000' == *pcFile;
  608. X    } break; }
  609. X    return 0;
  610. }
  611. X
  612. /*
  613. X * called if we have a config line that makes little sense        (ksb)
  614. X *  (in that is says to set{u,g}id to a `*' {user,group})
  615. X */
  616. void
  617. BadSet(iLine, cWhich, pcNoun, pcBadMode)
  618. int iLine;
  619. char cWhich, *pcNoun, *pcBadMode;
  620. {
  621. #if INSTALL
  622. X    if (FALSE == fVerbose)
  623. X        return;
  624. X    (void)fprintf(stderr, "%s: %s(%d): checklist specifies set%cid to a random %s with mode %s\n", progname, pcSpecial, iLine, cWhich, pcNoun, pcBadMode);
  625. #else
  626. X    (void)fprintf(fpOut, "%s: %s(%d): checklist specifies set%cid to a random %s with mode %s\n", progname, pcSpecial, iLine, cWhich, pcNoun, pcBadMode);
  627. #endif
  628. }
  629. X
  630. X
  631. /*
  632. X * find an apropriate place to compare a file to a pattern        (ksb)
  633. X *  pat == `RCS/*,v'
  634. X *  file == /tmp/junk/RCS/main.h,v
  635. X * return a pointer to
  636. X *  `RCS/main.h,v'
  637. X */
  638. static char *
  639. RJust(pcPat, pcFile, pcLast)
  640. char *pcPat, *pcFile, *pcLast;
  641. {
  642. X    register char *pcRev;
  643. X
  644. X    if ('/' == pcPat[0])
  645. X        return pcFile;
  646. X    pcRev = pcPat + strlen(pcPat);
  647. X    do {
  648. X        do {
  649. X            --pcRev;
  650. X        } while (pcPat != pcRev && '/' != *pcRev);
  651. X        if ('/' == *pcRev) {
  652. X            do {
  653. X                --pcRev;
  654. X            } while (pcPat != pcRev && '/' == *pcRev);
  655. X            do {
  656. X                --pcLast;
  657. X            } while (pcFile != pcLast && '/' == *pcLast);
  658. X            while (pcFile != pcLast && '/' != *pcLast)
  659. X                --pcLast;
  660. X            if (pcLast == pcFile)
  661. X                return pcFile;
  662. X            while ('/' == *pcLast)
  663. X                ++pcLast;
  664. X        }
  665. X    } while (pcPat != pcRev);
  666. X    return pcLast;
  667. }
  668. X
  669. /* build "DirCk"  or "Special"
  670. X */
  671. #include "special.i"
  672. X
  673. #if defined(INSTCK)
  674. /* if we are instck build "Specail"
  675. X */
  676. #undef INSTCK
  677. #define INSTALL    1
  678. #include "special.i"
  679. #undef INSTALL
  680. #endif
  681. X
  682. #endif    /* check list file */
  683. Purdue
  684. chmod 0444 install.d/special.c ||
  685. echo 'restore of install.d/special.c failed'
  686. Wc_c="`wc -c < 'install.d/special.c'`"
  687. test 15681 -eq "$Wc_c" ||
  688.     echo 'install.d/special.c: original size 15681, current size' "$Wc_c"
  689. fi
  690. # ============= install.d/dir.c ==============
  691. if test -f 'install.d/dir.c' -a X"$1" != X"-c"; then
  692.     echo 'x - skipping install.d/dir.c (File already exists)'
  693. else
  694. echo 'x - extracting install.d/dir.c (Text)'
  695. sed 's/^X//' << 'Purdue' > 'install.d/dir.c' &&
  696. /*
  697. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  698. X * 47907.  All rights reserved.
  699. X *
  700. X * Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  701. X *
  702. X * This software is not subject to any license of the American Telephone
  703. X * and Telegraph Company or the Regents of the University of California.
  704. X *
  705. X * Permission is granted to anyone to use this software for any purpose on
  706. X * any computer system, and to alter it and redistribute it freely, subject
  707. X * to the following restrictions:
  708. X *
  709. X * 1. Neither the authors nor Purdue University are responsible for any
  710. X *    consequences of the use of this software.
  711. X *
  712. X * 2. The origin of this software must not be misrepresented, either by
  713. X *    explicit claim or by omission.  Credit to the authors and Purdue
  714. X *    University must appear in documentation and sources.
  715. X *
  716. X * 3. Altered versions must be plainly marked as such, and must not be
  717. X *    misrepresented as being the original software.
  718. X *
  719. X * 4. This notice may not be removed or altered.
  720. X */
  721. X
  722. /*
  723. X * install a directory                        (ksb)
  724. X */
  725. #if !defined(lint)
  726. static char *rcsid = "$Id: dir.c,v 7.2 90/10/22 11:47:04 ksb Exp $";
  727. #endif    /* !lint */
  728. X
  729. #include <sys/param.h>
  730. #include <sys/types.h>
  731. #include <sys/stat.h>
  732. #include <sys/file.h>
  733. #include <stdio.h>
  734. #include <ctype.h>
  735. #include <errno.h>
  736. #include <pwd.h>
  737. #include <grp.h>
  738. X
  739. #include "configure.h"
  740. #include "install.h"
  741. #include "main.h"
  742. #include "dir.h"
  743. #include "file.h"
  744. #include "syscalls.h"
  745. #include "special.h"
  746. X
  747. #if STRINGS
  748. #include <strings.h>
  749. #else
  750. #include <string.h>
  751. #endif
  752. X
  753. #if !defined(F_OK)
  754. #define F_OK    0
  755. #endif
  756. X
  757. #if !defined(BINLS)
  758. #define BINLS        "/bin/ls"
  759. #endif
  760. X
  761. char acLs[] =        BINLS;
  762. X
  763. X
  764. #if !defined(LSDIRARGS)
  765. #if defined(SYSV) || defined(HPUX7)
  766. #define LSDIRARGS    "-ld"
  767. #else    /* bsd needs a -g option to show group    */
  768. #define LSDIRARGS    "-lgd"
  769. #endif    /* how does ls(1) show both owner&group    */
  770. #endif
  771. X
  772. char acLsDirArgs[] =    LSDIRARGS;
  773. X
  774. X
  775. #if !HAVE_MKDIR
  776. #if !defined(BINMKDIR)
  777. #define BINMKDIR    "/bin/mkdir"
  778. #endif
  779. char acMkdir[] =    BINMKDIR;
  780. #endif
  781. X
  782. X
  783. static char acDCreated[] = "directory `%s\' created %s.%s(%04o) by %s\n";
  784. static char acDUpdated[] = "directory `%s\' updated %s.%s(%04o) by %s\n";
  785. static char acDRemoved[] = "directory `%s\' removed %s.%s(%04o) by %s\n";
  786. X
  787. /*
  788. X * DirInstall()
  789. X *    Create a directory with given modes and owners
  790. X *
  791. X * Side effects
  792. X *    Creates a directory somewhere
  793. X */
  794. int
  795. DirInstall(pcDir, pcOwner, pcGroup, pcMode, pcDefOwner, pcDefGroup, pcDefMode, pcSLinks, fRemove)
  796. char *pcDir;        /* the directory to create            */
  797. char *pcOwner;        /* owner to give it                */
  798. char *pcGroup;        /* group ownership                */
  799. char *pcMode;        /* explicit -m option                */
  800. char *pcDefOwner;    /* default owner to give it            */
  801. char *pcDefGroup;    /* default group ownership            */
  802. char *pcDefMode;    /* default if no -m option and doesn't exist    */
  803. char *pcSLinks;        /* symbolic links to the directory        */
  804. int fRemove;        /* remove the directory, do not install        */
  805. {
  806. X    register char *pcSlash;
  807. X    auto int bSame;            /* exist dir is the same as req.*/
  808. X    auto struct passwd *pwd;    /* owner of this dir.        */
  809. X    auto struct group *grp;        /* group of this directory    */
  810. X    auto int mMode, mOptMode;    /* mode of this directory    */
  811. X    auto struct stat statb_dir;    /* for this dir or parrent    */
  812. X    auto int bDestExists;        /* destination file exists?    */
  813. X    auto char acDir[MAXPATHLEN+1];    /* copy of our name to munge    */
  814. X    auto char *pcMsg;        /* error message        */
  815. #if defined(CONFIG)
  816. X    auto CHLIST Check;        /* must match this record    */
  817. #endif    /* set check flags from config file    */
  818. #if defined(INST_FACILITY)
  819. X    auto char *pcLogStat;
  820. X    auto char acLogBuf[MAXLOGLINE];
  821. #endif    /* we should syslog changes        */
  822. X
  823. X    if (strlen(pcDir) > MAXPATHLEN) {
  824. #if defined(ENAMETOOLONG)
  825. X        fprintf(stderr, "%s: directory name: %s\n", progname, strerror(ENAMETOOLONG));
  826. #else
  827. X        fprintf(stderr, "%s: directory name: name too long\n", progname);
  828. #endif
  829. X        return FAIL;
  830. X    }
  831. X
  832. X    /*    install -d /bin/
  833. X     * used to choke us because we tried to make `/bin' and `/bin/'
  834. X     *    install -d /usr/local//bin
  835. X     * was a funny case too
  836. X     */
  837. X    /* the New Castle Conection would hate us here ... */
  838. X    for (bSame = '\000', pcSlash = acDir; '\000' != *pcDir; ++pcDir) {
  839. X        if ('/' == bSame && '/' == *pcDir)
  840. X            continue;
  841. X        *pcSlash++ = bSame = *pcDir;
  842. X    }
  843. X    if (pcSlash == acDir) {
  844. X        (void)strcpy(acDir, ".");
  845. X    } else if (pcSlash != acDir+1 && '/' == pcSlash[-1]) {
  846. X        pcSlash[-1] = '\000';
  847. X    } else {
  848. X        pcSlash[0] = '\000';
  849. X    }
  850. X
  851. #if defined(CONFIG)
  852. X    Special(acDir, pcSpecial, & Check);
  853. #endif    /* set check flags from config file    */
  854. X
  855. X    if (-1 != stat(acDir, & statb_dir)) {
  856. X        bDestExists = TRUE;
  857. X    } else {
  858. X
  859. X        /* we need the parrent dirs modes to copy here...
  860. X         */
  861. X        if ((char *)0 != (pcSlash = strrchr(acDir, '/'))) {
  862. X            while (pcSlash != acDir && '/' == pcSlash[-1])
  863. X                pcSlash--;
  864. X            *pcSlash = '\000';
  865. X            if (pcSlash == acDir) {
  866. X                if (-1 == stat("/", & statb_dir)) {
  867. X                    fprintf(stderr, "%s: stat: /: %s\n", progname, strerror(errno));
  868. X                    return FAIL;
  869. X                }
  870. X            } else if (-1 == stat(acDir, & statb_dir)) {
  871. X                /* we could use code like this to get
  872. X                 * Sun-like recursive dir install behavior
  873. X                 */
  874. X                if (errno != ENOENT || FALSE == fRecurse) {
  875. X                    fprintf(stderr, "%s: stat: %s: %s\n", progname, acDir, strerror(errno));
  876. X                    return FAIL;
  877. X                } else if (FAIL == DirInstall(acDir, pcOwner, pcGroup, pcMode, pcDefOwner, pcDefGroup, pcDefMode, (char *)0, 0)) {
  878. X                    return FAIL;
  879. X                }
  880. X                if (FALSE == fTrace && -1 == stat(acDir, & statb_dir)) {
  881. X                    fprintf(stderr, "%s: stat: %s: %s\n", progname, acDir, strerror(errno));
  882. X                    return FAIL;
  883. X                }
  884. X            }
  885. X            *pcSlash = '/';
  886. X        } else  if (-1 == stat(".", & statb_dir)) {
  887. X            fprintf(stderr, "%s: stat: .: %s\n", progname, strerror(errno));
  888. X            return FAIL;
  889. X        }
  890. X        bDestExists = FALSE;
  891. X    }
  892. X
  893. X    (void)setpwent();
  894. X    if ((char *)0 != pcOwner) {
  895. X        if ((struct passwd *)0 == (pwd = getpwnam(pcOwner))) {
  896. X            (void)fprintf(stderr, "%s: getpwname: %s not found\n", progname, pcOwner);
  897. X            exit(EXIT_OPT);
  898. X        }
  899. X        if (FALSE == bHaveRoot && pwd->pw_uid != geteuid()) {
  900. X            (void)fprintf(stderr, "%s: effective uid cannot make directory owned by %s (%d != %d)\n", progname, pcOwner, geteuid(), pwd->pw_uid);
  901. X            exit(EXIT_OPT);
  902. X        }
  903. X    } else if (bDestExists != FALSE) {
  904. X        if ((struct passwd *)0 == (pwd = getpwuid((int) statb_dir.st_uid))) {
  905. X            (void)fprintf(stderr, "%s: destination owner %d doesn\'t exist\n", progname, statb_dir.st_uid);
  906. X            exit(EXIT_OPT);
  907. X        }
  908. X    } else if (bHaveRoot) {
  909. X        if ((char *)0 != pcDefOwner) {
  910. X            pcOwner = pcDefOwner;
  911. X            if ((struct passwd *)0 == (pwd = getpwnam(pcOwner))) {
  912. X                (void)fprintf(stderr, "%s: getpwname: %s not found\n", progname, pcOwner);
  913. X                exit(EXIT_OPT);
  914. X            }
  915. X        } else {
  916. X            if ((struct passwd *)0 == (pwd = getpwuid((int) statb_dir.st_uid))) {
  917. X                (void)fprintf(stderr, "%s: destination directory owner %d doesn\'t exist\n", progname, statb_dir.st_uid);
  918. X                exit(EXIT_OPT);
  919. X            }
  920. X        }
  921. X    } else if ((struct passwd *)0 == (pwd = getpwuid((int) geteuid()))) {
  922. X        (void)fprintf(stderr, "%s: getpwuid: %d (effective uid) not found\n", progname, geteuid());
  923. X        exit(EXIT_OPT);
  924. X    }
  925. X    pwd = savepwent(pwd);
  926. X    (void)endpwent();
  927. X
  928. X    (void)setgrent();
  929. X    if ((char *)0 != pcGroup) {
  930. X        if ((struct group *)0 == (grp = getgrnam(pcGroup))) {
  931. X            (void)fprintf(stderr, "%s: getgrname: %s not found\n", progname, pcGroup);
  932. X            exit(EXIT_OPT);
  933. X        }
  934. X    } else if (bDestExists != FALSE) {
  935. X        grp = getgrgid((int) statb_dir.st_gid);
  936. X        if ((struct group *)0 == grp) {
  937. X            (void)fprintf(stderr, "%s: no group entry for destination group %d\n", progname, statb_dir.st_gid);
  938. X            exit(EXIT_OPT);
  939. X        }
  940. X    } else if (bHaveRoot) {
  941. X        if ((char *)0 != pcDefGroup) {
  942. X            pcGroup = pcDefGroup;
  943. X            if ((struct group *)0 == (grp = getgrnam(pcGroup))) {
  944. X                (void)fprintf(stderr, "%s: getgrname: %s not found\n", progname, pcGroup);
  945. X                exit(EXIT_OPT);
  946. X            }
  947. X        } else {
  948. X            grp = getgrgid((int) statb_dir.st_gid);
  949. X            if ((struct group *)0 == grp) {
  950. X                (void)fprintf(stderr, "%s: no group entry for destination directory group %d\n", progname, statb_dir.st_gid);
  951. X                exit(EXIT_OPT);
  952. X            }
  953. X        }
  954. X    } else if ((struct group *)0 == (grp = getgrgid((int) getegid()))) {
  955. X        (void)fprintf(stderr, "%s: getgrgid: %d (effective gid) not found\n", progname, getegid());
  956. X        exit(EXIT_OPT);
  957. X    }
  958. X    grp = savegrent(grp);
  959. X    (void)endgrent();
  960. X
  961. X    /* take specified mode, use destination mode, or the default
  962. X     * or inherit it from the parrent directory
  963. X     */
  964. X    if ((char *)0 != pcMode) {
  965. X        CvtMode(pcMode, & mMode, & mOptMode);
  966. X        if (0 != mOptMode) {
  967. X            mMode |= statb_dir.st_mode & mOptMode;
  968. X        }
  969. X    } else if (bDestExists != FALSE) {
  970. X        mMode = statb_dir.st_mode &~ S_IFMT;
  971. X    } else if ((char *)0 != pcDefMode) {
  972. X        CvtMode(pcDefMode, & mMode, & mOptMode);
  973. X        if (0 != mOptMode) {
  974. X            mMode |= statb_dir.st_mode & mOptMode;
  975. X        }
  976. X    } else {
  977. X        mMode = statb_dir.st_mode &~ S_IFMT;
  978. X    }
  979. X
  980. #if defined(CONFIG)
  981. X    if (Check.ffound) {
  982. X        register int mChk;
  983. X        register int fFail;
  984. X
  985. X        fFail = FALSE;
  986. X        if ((char *)0 != Check.pclink) {
  987. X            (void)fprintf(stderr, "%s: `%s\' be a %s link to `%s\'\n", progname, acDir, ':' == Check.pclink[0] ? "hard" : "symbolic", Check.pclink+1);
  988. X            fFail = TRUE;
  989. X            goto quit;
  990. X        }
  991. X        if ('*' == Check.acowner[0]) {
  992. X            /* OK no check */;
  993. X        } else if (Check.fbangowner) {
  994. X            if (Check.uid == pwd->pw_uid) {
  995. X                (void)fprintf(stderr, "%s: `%s\' should not have owner %s\n", progname, acDir, Check.acowner);
  996. X                fFail = TRUE;
  997. X            }
  998. X        } else if (Check.uid != pwd->pw_uid) {
  999. X            (void)fprintf(stderr, "%s: `%s\' owner %s should be %s\n", progname, acDir, pwd->pw_name, Check.acowner);
  1000. X            fFail = TRUE;
  1001. X        }
  1002. X
  1003. X        if ('*' == Check.acgroup[0]) {
  1004. X            /*OK */;
  1005. X        } else if (Check.fbangowner) {
  1006. X            if (Check.uid == pwd->pw_uid) {
  1007. X                (void)fprintf(stderr, "%s: `%s\' should not have group %s\n", progname, acDir, Check.acgroup);
  1008. X                fFail = TRUE;
  1009. X            }
  1010. X        } else if (Check.gid != grp->gr_gid) {
  1011. X            (void)fprintf(stderr, "%s: `%s\' group %s should be %s\n", progname, acDir, grp->gr_name, Check.acgroup);
  1012. X            fFail = TRUE;
  1013. X        }
  1014. X
  1015. X        switch (Check.acmode[0]) {
  1016. X        case '?':
  1017. X        case '*':
  1018. X            /*OK*/;
  1019. X            break;
  1020. X        case 'd':
  1021. X            mChk = PERM_RWX(Check.mmust|Check.moptional);
  1022. X            if (PERM_RWX(Check.mmust) != PERM_RWX(mMode&Check.mmust)) {
  1023. X                (void)fprintf(stderr, "%s: `%s\' mode %04o doesn\'t have bits to match %s (%04o)\n", progname, acDir, PERM_RWX(mMode), Check.acmode, mChk);
  1024. X                fFail = TRUE;
  1025. X            } else if (0 != (PERM_RWX(mMode) &~ mChk)) {
  1026. X                (void)fprintf(stderr, "%s: `%s\' mode %04o has too many bits to match %s (%04o)\n", progname, acDir, PERM_RWX(mMode), Check.acmode, mChk);
  1027. X                fFail = TRUE;
  1028. X            }
  1029. X            if (0 != (S_ISUID & mMode) ? 0 == (S_ISUID & (Check.mmust|Check.moptional)) : 0 != (S_ISUID & Check.mmust)) {
  1030. X                (void)fprintf(stderr, "%s: `%s\' setuid bit must be %s\n", progname, acDir, apcOO[0 == (S_ISUID & mMode)]);
  1031. X                fFail = TRUE;
  1032. X            }
  1033. X            if (0 != (S_ISGID & mMode) ? 0 == (S_ISGID & (Check.mmust|Check.moptional)) : 0 != (S_ISGID & Check.mmust)) {
  1034. X                (void)fprintf(stderr, "%s: `%s\' setgid bit must be %s\n", progname, acDir, apcOO[0 == (S_ISGID & mMode)]);
  1035. X                fFail = TRUE;
  1036. X            }
  1037. X            if (0 != (S_ISVTX & mMode) ? 0 == (S_ISVTX & (Check.mmust|Check.moptional)) : 0 != (S_ISVTX & Check.mmust)) {
  1038. X                (void)fprintf(stderr, "%s: `%s\' sticky bit must be %s\n", progname, acDir, apcOO[0 == (S_ISVTX & mMode)]);
  1039. X                fFail = TRUE;
  1040. X            }
  1041. X            break;
  1042. X        default:
  1043. X            (void)fprintf(stderr, "%s: `%s\' must be a %s\n", progname, acDir, NodeType(Check.mtype, (char *)0));
  1044. X            fFail = TRUE;
  1045. X            break;
  1046. X        case '!':
  1047. X            (void)fprintf(stderr, "%s: `%s\' should not be installed", progname, acDir);
  1048. X            if ((char *)0 != Check.pcmesg && '\000' != Check.pcmesg[0])
  1049. X                (void)fprintf(stderr, ", %s", Check.pcmesg);
  1050. X            (void)fputc('\n', stderr);
  1051. X            fFail = TRUE;
  1052. X            break;
  1053. X        }
  1054. X    quit:
  1055. X        if (FALSE != fFail) {
  1056. X            return FAIL;
  1057. X        }
  1058. X    }
  1059. #endif    /* have check list to compare with    */
  1060. X
  1061. X    if (fRemove) {
  1062. X        register char *pcEnd;
  1063. X
  1064. X        if (!bDestExists) {
  1065. X            (void)fprintf(stderr, "%s: `%s\' doesn't exist to remove\n", progname, acDir);
  1066. X            return FAIL;
  1067. X        }
  1068. X
  1069. X        /* strangely this will remove /bin/OLD/OLD too,
  1070. X         * but I think this is what we want in that case...
  1071. X         */
  1072. X        if ((char *)0 == (pcEnd = strrchr(acDir, '\000')))
  1073. X            Die("nil eos pointer");
  1074. X        pcEnd[0] = '/';
  1075. X        (void)strcpy(pcEnd+1, OLDDIR);
  1076. X        if (-1 != access(acDir, F_OK) &&
  1077. X            FAIL == DirInstall(acDir, FALSE == bHaveRoot ? (char *)0 : ODIROWNER, FALSE == bHaveRoot ? (char *)0 : ODIRGROUP, ODIRMODE, (char *)0, (char *)0, (char *)0, (char *)0, 1)) {
  1078. X            return FAIL;
  1079. X        }
  1080. X        *pcEnd = '\000';
  1081. X
  1082. #if defined(CONFIG)
  1083. X        if (Check.ffound) {
  1084. X            (void)printf("%s: %s(%d) %s %s, remove it?\n", progname, Check.pcspecial, Check.iline, 0 == strcmp(Check.pcpat, acDir) ? "is" : "matches", acDir);
  1085. X        }
  1086. #endif    /* config list to modify        */
  1087. X
  1088. X        if (FALSE != fTrace) {
  1089. X            (void)printf("%s: rmdir %s\n", progname, acDir);
  1090. X        } else if (-1 == rmdir(acDir)) {
  1091. X            (void)fprintf(stderr, "%s: rmdir: %s: %s\n", progname, acDir, strerror(errno));
  1092. X            return FAIL;
  1093. X        }
  1094. X
  1095. #if defined(INST_FACILITY)
  1096. X        /*
  1097. X         * do not syslog any user built directories
  1098. X         */
  1099. X        if (bHaveRoot && FALSE == fTrace) {
  1100. X            (void)sprintf(acLogBuf, acDRemoved, acDir, pwd->pw_name, grp->gr_name, mMode, pcGuilty);
  1101. X            syslog(LOG_INFO, acLogBuf);
  1102. X        }
  1103. #endif    /* we should syslog changes        */
  1104. X
  1105. X        return SUCCEED;
  1106. X    } else if (bDestExists) {
  1107. X        pcMsg = NodeType(statb_dir.st_mode, (char *)0);
  1108. X        switch (statb_dir.st_mode & S_IFMT) {
  1109. #if HAVE_SLINKS
  1110. X        case S_IFLNK:    /* symbolic link */
  1111. #endif    /* no links to think about */
  1112. #if defined(S_IFIFO)
  1113. X        case S_IFIFO:    /* fifo */
  1114. #endif    /* no fifos */
  1115. #if defined(S_IFSOCK)
  1116. X        case S_IFSOCK:    /* socket */
  1117. #endif    /* no sockets */
  1118. X        case S_IFCHR:    /* character special */
  1119. X        case S_IFBLK:    /* block special */
  1120. X        case 0:
  1121. X        case S_IFREG:
  1122. X            (void)fprintf(stderr, "%s: directory `%s\' is already a %s\n", progname, acDir, pcMsg);
  1123. X            return FAIL;
  1124. X
  1125. X        case S_IFDIR:    /* directory */
  1126. X            break;
  1127. X
  1128. X        default:
  1129. X            (void)fprintf(stderr, "%s: unrecognized file type on `%s\'\n", progname, acDir);
  1130. X            return FAIL;
  1131. X        }
  1132. X        bSame = TRUE;
  1133. X        if (statb_dir.st_uid != pwd->pw_uid) {
  1134. X            if (FALSE == fQuiet)
  1135. X                (void)fprintf(stderr, "%s: `%s\' owner mismatch (%d != %d)\n", progname, acDir, pwd->pw_uid, statb_dir.st_uid);
  1136. X            bSame = FALSE;
  1137. X        }
  1138. X        if (statb_dir.st_gid != grp->gr_gid) {
  1139. X            if (FALSE == fQuiet)
  1140. X                (void)fprintf(stderr, "%s: `%s\' group mismatch (%d != %d)\n", progname, acDir, grp->gr_gid, statb_dir.st_gid);
  1141. X            bSame = FALSE;
  1142. X        }
  1143. X        if (PERM_BITS(statb_dir.st_mode) != PERM_BITS(mMode)) {
  1144. X            if (FALSE == fQuiet)
  1145. X                (void)fprintf(stderr, "%s: `%s\' mode mismatch (%04o != %04o)\n", progname, acDir, mMode, statb_dir.st_mode &~ S_IFMT);
  1146. X            bSame = FALSE;
  1147. X        }
  1148. X        if ((S_ISUID & mMode) != (S_ISUID & statb_dir.st_mode)) {
  1149. X            (void)fprintf(stderr, "%s: `%s\' setuid bit changed, was %s\n", progname, acDir, apcOO[0 != (S_ISUID & mMode)]);
  1150. X            bSame = FALSE;
  1151. X        }
  1152. X        if ((S_ISGID & mMode) != (S_ISGID & statb_dir.st_mode)) {
  1153. X            (void)fprintf(stderr, "%s: `%s\' setgid bit changed, was %s\n", progname, acDir, apcOO[0 != (S_ISGID & mMode)]);
  1154. X            bSame = FALSE;
  1155. X        }
  1156. X        if ((S_ISVTX & mMode) != (S_ISVTX & statb_dir.st_mode)) {
  1157. X            (void)fprintf(stderr, "%s: `%s\' sticky bit changed, was %s\n", progname, acDir, apcOO[0 != (S_ISVTX & mMode)]);
  1158. X            bSame = FALSE;
  1159. X        }
  1160. X        if (FALSE != bSame) {
  1161. X            goto show_dir;
  1162. X        }
  1163. #if defined(INST_FACILITY)
  1164. X        pcLogStat = acDUpdated;
  1165. #endif    /* we should syslog changes        */
  1166. X    } else {
  1167. #if HAVE_MKDIR
  1168. X        if (FALSE != fTrace) {
  1169. X            (void)printf("%s: mkdir %s\n", progname, acDir);
  1170. X        } else if (-1 == mkdir(acDir, mMode)) {
  1171. X            (void)fprintf(stderr, "%s: mkdir: %s: %s\n", progname, acDir, strerror(errno));
  1172. X            return FAIL;
  1173. X        }
  1174. #else    /* BSD */
  1175. X        if (RunCmd(acMkdir, acDir, (char *)0) != 0) {
  1176. X            /* mkdir reported fail for us */
  1177. X            return FAIL;
  1178. X        }
  1179. #endif    /* make a directory */
  1180. #if defined(INST_FACILITY)
  1181. X        pcLogStat = acDCreated;
  1182. #endif    /* we should syslog changes        */
  1183. X    }
  1184. X
  1185. X    if (FALSE != bHaveRoot) {
  1186. X        ChOwnGrp(acDir, pwd, grp);
  1187. X    } else {
  1188. X        ChGroup(acDir, grp);
  1189. X    }
  1190. X    ChMode(acDir, mMode);
  1191. X
  1192. #if defined(INST_FACILITY)
  1193. X    /*
  1194. X     * do not syslog any user built directories
  1195. X     */
  1196. X    if (bHaveRoot && FALSE == fTrace) {
  1197. X        (void)sprintf(acLogBuf, pcLogStat, acDir, pwd->pw_name, grp->gr_name, mMode, pcGuilty);
  1198. X        syslog(LOG_INFO, acLogBuf);
  1199. X    }
  1200. #endif    /* we should syslog changes        */
  1201. X
  1202. show_dir:
  1203. X    /* here we could make symbolic links    LLL
  1204. X     */
  1205. X    if ((char *)0 != pcSLinks) {
  1206. X        if (LaunchLinks(&statb_dir, acDir, (char *)0, pcSLinks, mMode, pwd, grp)) {
  1207. X            (void)fprintf(stderr, "%s: %s: symbolic links failed\n", progname, acDir);
  1208. X        }
  1209. X    }
  1210. X
  1211. #if defined(CONFIG)
  1212. X    /* if the file is in a check list report installation message
  1213. X     */
  1214. X    if (Check.ffound && '\000' != Check.pcmesg[0]) {
  1215. X        (void)printf("%s: %s: %s\n", progname, acDir, Check.pcmesg);
  1216. X    }
  1217. #endif    /* have check list to output a comment    */
  1218. X
  1219. X    /*
  1220. X     * show what we built with ls(1)
  1221. X     */
  1222. X    if (FALSE != fVerbose) {
  1223. X        (void)RunCmd(acLs, acLsDirArgs, acDir);
  1224. X    }
  1225. X
  1226. X    return SUCCEED;
  1227. }
  1228. Purdue
  1229. chmod 0444 install.d/dir.c ||
  1230. echo 'restore of install.d/dir.c failed'
  1231. Wc_c="`wc -c < 'install.d/dir.c'`"
  1232. test 16773 -eq "$Wc_c" ||
  1233.     echo 'install.d/dir.c: original size 16773, current size' "$Wc_c"
  1234. fi
  1235. # ============= install.cf/install.cf.5l ==============
  1236. if test ! -d 'install.cf'; then
  1237.     echo 'x - creating directory install.cf'
  1238.     mkdir 'install.cf'
  1239. fi
  1240. if test -f 'install.cf/install.cf.5l' -a X"$1" != X"-c"; then
  1241.     echo 'x - skipping install.cf/install.cf.5l (File already exists)'
  1242. else
  1243. echo 'x - extracting install.cf/install.cf.5l (Text)'
  1244. sed 's/^X//' << 'Purdue' > 'install.cf/install.cf.5l' &&
  1245. .\" $Id: install.cf.5l,v 7.0 90/09/17 09:41:53 ksb Exp $
  1246. .\"
  1247. .\" Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  1248. .\" 47907.  All rights reserved.
  1249. .\"
  1250. .\" Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  1251. .\"           Jeff Smith, jsmith@cc.purdue.edu, purdue!jsmith
  1252. .\"
  1253. .\" This software is not subject to any license of the American Telephone
  1254. .\" and Telegraph Company or the Regents of the University of California.
  1255. .\"
  1256. .\" Permission is granted to anyone to use this software for any purpose on
  1257. .\" any computer system, and to alter it and redistribute it freely, subject
  1258. .\" to the following restrictions:
  1259. .\"
  1260. .\" 1. Neither the authors nor Purdue University are responsible for any
  1261. .\"    consequences of the use of this software.
  1262. .\"
  1263. .\" 2. The origin of this software must not be misrepresented, either by
  1264. .\"    explicit claim or by omission.  Credit to the authors and Purdue
  1265. .\"    University must appear in documentation and sources.
  1266. .\"
  1267. .\" 3. Altered versions must be plainly marked as such, and must not be
  1268. .\"    misrepresented as being the original software.
  1269. .\"
  1270. .\" 4. This notice may not be removed or altered.
  1271. .\"
  1272. .\" $Laser: ${tbl-tbl} %f |${ltroff-ltroff} -man
  1273. .\" $Compile: ${tbl-tbl} %f |${nroff-nroff} -man |${PAGER-${more-more}}
  1274. .TH INSTALL.CF 5L PUCC
  1275. .SH NAME
  1276. install.cf \- a check list to confirm correct installations
  1277. .SH DESCRIPTION
  1278. .PP
  1279. .IR Install (1L)
  1280. allows the system administrator to update important files
  1281. while maintaining a backup copy of any old versions.
  1282. .I Install
  1283. checks the actions of the superuser against a
  1284. list of important files, to prevent careless security
  1285. breaches.
  1286. The \fB\-C\fP option controls which
  1287. checklist \fIinstall\fP examines.
  1288. .PP
  1289. .I Install
  1290. searches \fIinstall.cf\fP for an
  1291. .IR sh (1)
  1292. \fIglob\fP expression that matches
  1293. the file to be installed.
  1294. When it finds a matching expression it checks
  1295. the proposed owner, group, and mode against those listed in
  1296. the checklist; any variation causes
  1297. .I install
  1298. to abort.
  1299. This mechanism is provided to protect the superuser from installing,
  1300. for instance, the shell setuid:
  1301. .sp 1
  1302. X    install -m7555 -o root -g wheel sh /bin
  1303. .sp 1
  1304. (note the extra \`5\').
  1305. .PP
  1306. Each data line in \fIinstall.cf\fP consists of 6 fields;
  1307. .br
  1308. X    a glob expression
  1309. .br
  1310. X    a mode, in either octal or symbolic format
  1311. .br
  1312. X    a symbolic owner
  1313. .br
  1314. X    a symbolic group
  1315. .br
  1316. X    a \fIstrip\fR(1) or \fIranlib\fR(1) indicator
  1317. .br
  1318. X    an optional comment
  1319. .br
  1320. Blank lines and lines which begin with a pound sign (#) are ignored.
  1321. .PP
  1322. If the glob expression begins with a slash (\*(lq/\*(rq)
  1323. it is matched against the full \fItarget\fP,
  1324. otherwise it is matched against only the last component of the \fItarget\fP.
  1325. (For the definition of \fItarget\fP see \fIinstall\fP(1L).)
  1326. For instance, the expression
  1327. .br
  1328. X    *.a
  1329. .br
  1330. will match every library (file ending in \`.a\'), while
  1331. .br
  1332. X    /lib/*.a
  1333. .br
  1334. will only match libraries in \*(lq/lib\*(rq.
  1335. .PP
  1336. The mode field may be filled with either an octal number (discouraged)
  1337. or a symbolic mode (see
  1338. .IR ls (1)).
  1339. Any bit specified as on \fBmust\fP be on,
  1340. any bit specified as off (\-) \fBmust\fP be off.
  1341. The symbolic mode may also include \`?\' to indicate an optional bit.
  1342. For instance the mode
  1343. .br
  1344. X    \-r?\-r\-\-r\-\-
  1345. .br
  1346. will match either \-rw\-r\-\-r\-\- (0644) or \-r\-\-r\-\-r\-\- (0444).
  1347. If a setuid, setgid, or sticky bit is set without the underlying
  1348. execute bit being set the \`s\' or \`t\' should be given in
  1349. uppercase.
  1350. .PP
  1351. Some combinations of modes are not expressible in the above format,
  1352. e.g. 0755 with an optional setgid bit.  For such modes a special
  1353. format is allowed:
  1354. .br
  1355. X    \fImode\fP/\fIoptional-mode\fP
  1356. .br
  1357. in which case all the bits in \fIoptional-mode\fP are taken as optional.
  1358. To express our example mode one might use:
  1359. .br
  1360. X    drwxr-xr-x/02000
  1361. .br
  1362. (this is a good mode for a directory under SunOS).
  1363. .PP
  1364. The type bit in the symbolic mode may be any of the \fIfind\fP(1) type
  1365. bits, or an exclamation point (\*(lq!\*(rq).  The ! is used to indicate files
  1366. that should \fBnever\fP exist, and may prefix an auxilary file type.
  1367. .PP
  1368. The owner (group) column may either contain an asterisk (\*(lq*\*(rq) or
  1369. an alphanumeric identifier.
  1370. If an asterisk is given any valid owner (group) may be used.
  1371. No numeric user (group) identifiers are allowed.
  1372. A owner (group) name may be prefixed by an exclamation point (\*(lq!\*(rq)
  1373. which indicates that only this owner (group) is not allowed.
  1374. .PP
  1375. The strip/ranlib indicator follows this table
  1376. .RS
  1377. .TS
  1378. l l.
  1379. n    do not run either \fIstrip\fP(1) or \fIranlib\fP(1)
  1380. l    run \fIranlib\fP(1)
  1381. s    run \fIstrip\fP(1)
  1382. *    allows either to be run, requires neither
  1383. .TE
  1384. .RE
  1385. It makes no sense (to the authors) to run
  1386. both \fIstrip\fP(1) and \fIranlib\fP(1).
  1387. .PP
  1388. .I Install
  1389. displays the comment section when the file is installed.
  1390. .PP
  1391. A double quote (\*(rq) substitutes the entry from the previous line.
  1392. An equals sign (=) substitutes \fIinstall\fP's default value for a field.
  1393. .PP
  1394. The tool \fIinstck\fP(1L) may be used to generate configuration
  1395. files for named files (assuming the current ones are correct).
  1396. .SH EXAMPLE
  1397. .RS
  1398. # this file tells install(1L) what files to check as special
  1399. .br
  1400. .br
  1401. .TS
  1402. l l l l l l.
  1403. # file    modes    owner    group    strip    comment
  1404. # name                ranlib    for user
  1405. /unix    \-r??r\--r\--    binary    *    n    new kernel
  1406. /vmunix    \*(rq    \*(rq    \*(rq    \*(rq    \*(rq
  1407. /dynix    \*(rq    \*(rq    \*(rq    \*(rq    \*(rq
  1408. X
  1409. /bin/sh    \-rwx?\-x?\-x    *    *    *    do not setuid
  1410. /bin/su    \-rws?\-x?\-x    root    *    *    must setuid, not group
  1411. /bin/init    \-rwx\-\-\-\-\-\-    root    *    *    no world execute
  1412. /etc/init    \*(rq    \*(rq    *    *    no world execute
  1413. /etc/passwd    \-r?\-r\-\-r\-\-    root    *    n    forbid world write
  1414. /etc/group    \*(rq    \*(rq    *    n    \*(rq
  1415. /tmp    drwxrwxrwt    binary    *    n    must be sticky at PUCC
  1416. /usr/tmp    \*(rq    \*(rq    *    n    sticky
  1417. /usr/ucb/eyacc    \-rwxr\-x?\-x    *    *    n    no strip
  1418. /usr/ucb/lisp    \*(rq    \*(rq    \*(rq    \*(rq    \*(rq
  1419. X
  1420. core    !-??-?--?--    *    *    n    a bogus core file
  1421. .TE
  1422. .RE
  1423. .SH AUTHORS
  1424. Jeff Smith, Purdue University Computing Center (jsmith@cc.purdue.edu)
  1425. .br
  1426. Kevin Braunsdorf, Purdue University Computing Center (ksb@cc.purdue.edu)
  1427. .br
  1428. Copyright \*(co 1990 Purdue Research Foundation.  All rights reserved.
  1429. .SH SEE ALSO
  1430. install(1L), instck(1L), ls(1), sh(1), strip(1), ranlib(1)
  1431. Purdue
  1432. chmod 0444 install.cf/install.cf.5l ||
  1433. echo 'restore of install.cf/install.cf.5l failed'
  1434. Wc_c="`wc -c < 'install.cf/install.cf.5l'`"
  1435. test 6131 -eq "$Wc_c" ||
  1436.     echo 'install.cf/install.cf.5l: original size 6131, current size' "$Wc_c"
  1437. fi
  1438. # ============= instck/maxfreq.c ==============
  1439. if test ! -d 'instck'; then
  1440.     echo 'x - creating directory instck'
  1441.     mkdir 'instck'
  1442. fi
  1443. if test -f 'instck/maxfreq.c' -a X"$1" != X"-c"; then
  1444.     echo 'x - skipping instck/maxfreq.c (File already exists)'
  1445. else
  1446. echo 'x - extracting instck/maxfreq.c (Text)'
  1447. sed 's/^X//' << 'Purdue' > 'instck/maxfreq.c' &&
  1448. /*
  1449. X * Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  1450. X * 47907.  All rights reserved.
  1451. X *
  1452. X * Written by D. Scott Guthridge, aho@cc.purdue.edu            (dsg)
  1453. X *
  1454. X * This software is not subject to any license of the American Telephone
  1455. X * and Telegraph Company or the Regents of the University of California.
  1456. X *
  1457. X * Permission is granted to anyone to use this software for any purpose on
  1458. X * any computer system, and to alter it and redistribute it freely, subject
  1459. X * to the following restrictions:
  1460. X *
  1461. X * 1. Neither the authors nor Purdue University are responsible for any
  1462. X *    consequences of the use of this software.
  1463. X *
  1464. X * 2. The origin of this software must not be misrepresented, either by
  1465. X *    explicit claim or by omission.  Credit to the authors and Purdue
  1466. X *    University must appear in documentation and sources.
  1467. X *
  1468. X * 3. Altered versions must be plainly marked as such, and must not be
  1469. X *    misrepresented as being the original software.
  1470. X *
  1471. X * 4. This notice may not be removed or altered.
  1472. X */
  1473. X
  1474. /*
  1475. X * $Compile(test): ${cc-cc} ${cc_debug--g} -DTEST -o %F %f
  1476. X * $Id: maxfreq.c,v 7.1 90/11/28 09:09:55 ksb Exp $
  1477. X * @(#)
  1478. X */
  1479. X
  1480. /*@Header        @*/
  1481. #include <stdio.h>        /* for stderr        */
  1482. #include "configure.h"
  1483. #include "main.h"
  1484. #include "gen.h"
  1485. #include "maxfreq.h"
  1486. X
  1487. #if STRINGS
  1488. #include <strings.h>
  1489. #else
  1490. #include <string.h>
  1491. #endif
  1492. X
  1493. /*@Explode config    @*/
  1494. #ifdef TEST
  1495. X
  1496. /*
  1497. X * copy an ME element
  1498. X *
  1499. X * This happens only when a new element is added to the
  1500. X * cache. Return non-zero on failure.
  1501. X */
  1502. int
  1503. MECopy(pMEDest, pMESource)
  1504. X    ME_ELEMENT *pMEDest, *pMESource;
  1505. {
  1506. X    (void)strcpy(pMEDest->ac, pMESource->ac);
  1507. X    return 0;
  1508. }
  1509. X
  1510. /*
  1511. X * compare two ME elements return 0 if they are equal; non-zero if they
  1512. X * are not
  1513. X */
  1514. int
  1515. MECompare(pME1, pME2)
  1516. X    ME_ELEMENT *pME1, *pME2;
  1517. {
  1518. X    return strcmp(pME1->ac, pME2->ac);
  1519. }
  1520. #endif /* TEST    */
  1521. X
  1522. /*@Explode inc        @*/
  1523. extern char *malloc();
  1524. X
  1525. /*
  1526. X * insert/search for a node then increment the count
  1527. X * (this often means moving it to preserve the lower/equal rules)
  1528. X *
  1529. X * returns the user-defined part of the node it finds or
  1530. X * (ME_ELEMENT *)0 if the copy or malloc fails
  1531. X */
  1532. ME_ELEMENT *
  1533. MFIncrement(ppMFRoot, pME)
  1534. X    MAXFREQ **ppMFRoot;
  1535. X    ME_ELEMENT *pME;
  1536. {
  1537. X    register MAXFREQ *pMF;
  1538. X    register MAXFREQ **ppMFAnchor;
  1539. X    register MAXFREQ *pMFColumn;
  1540. X    register MAXFREQ **ppMFOneBack;
  1541. X    register MAXFREQ **ppMFTwoBack;
  1542. X
  1543. X    ppMFTwoBack = (MAXFREQ **)0;
  1544. X    ppMFOneBack = ppMFRoot;
  1545. X    ppMFAnchor = ppMFRoot;
  1546. X    for (pMFColumn = *ppMFRoot; nilMF != pMFColumn; pMFColumn = pMFColumn->pMFlower) {
  1547. X        for (pMF = pMFColumn; nilMF != pMF; pMF = pMF->pMFequal) {
  1548. X            if (0 == MECompare(pME, & pMF->ME)) {
  1549. X                /*
  1550. X                 * remove this one even though it may
  1551. X                 * be in the right place -- it's too
  1552. X                 * expensive to find out
  1553. X                 */
  1554. X                ++pMF->icount;
  1555. X                if (nilMF != pMF->pMFequal) {
  1556. X                    *ppMFAnchor = pMF->pMFequal;
  1557. X                    pMF->pMFequal->pMFlower = pMF->pMFlower;
  1558. X                } else {
  1559. X                    *ppMFAnchor = pMF->pMFlower;
  1560. X                }
  1561. X                if ((MAXFREQ **)0 == ppMFTwoBack) {
  1562. X                    pMF->pMFlower = *ppMFRoot;
  1563. X                    pMF->pMFequal = nilMF;
  1564. X                    *ppMFRoot = pMF;
  1565. X                    return & pMF->ME;
  1566. X                }
  1567. X                if ((*ppMFTwoBack)->icount == pMF->icount) {
  1568. X                    pMF->pMFlower = (*ppMFTwoBack)->pMFlower;
  1569. X                    pMF->pMFequal = *ppMFTwoBack;
  1570. X                    (*ppMFTwoBack)->pMFlower = nilMF;
  1571. X                    *ppMFTwoBack = pMF;
  1572. X                    return & pMF->ME;
  1573. X                }
  1574. X                pMF->pMFlower = *ppMFOneBack;
  1575. X                pMF->pMFequal = nilMF;
  1576. X                *ppMFOneBack = pMF;
  1577. X                return & pMF->ME;
  1578. X            }
  1579. X            ppMFAnchor = & pMF->pMFequal;
  1580. X        }
  1581. X        ppMFAnchor = & pMFColumn->pMFlower;
  1582. X        ppMFTwoBack = ppMFOneBack;
  1583. X        ppMFOneBack = & pMFColumn->pMFlower;
  1584. X    }
  1585. X    /*
  1586. X     * not found -- push a new element on the top of the last column
  1587. X     *
  1588. X     * assert(nilMF == pMFColumn);
  1589. X     * assert(nilMF == pMF);
  1590. X     */
  1591. X    if (nilMF == (pMF = (MAXFREQ *)malloc(sizeof(MAXFREQ)))) {
  1592. X        return (ME_ELEMENT *)0;
  1593. X    }
  1594. X    pMF->pMFlower = nilMF;
  1595. X    if (0 != MECopy(& pMF->ME, pME)) {
  1596. X        return (ME_ELEMENT *)0;
  1597. X    }
  1598. X    pMF->icount = 1;
  1599. X    if ((MAXFREQ **)0 != ppMFTwoBack && 1 == (*ppMFTwoBack)->icount) {
  1600. X        pMF->pMFequal = *ppMFTwoBack;
  1601. X        *ppMFTwoBack = pMF;
  1602. X        return & pMF->ME;
  1603. X    }
  1604. X    pMF->pMFequal = nilMF;
  1605. X    *ppMFOneBack = pMF;
  1606. X    return & pMF->ME;
  1607. }
  1608. X
  1609. /*@Explode free    @*/
  1610. /* 
  1611. X * free a maxfreq cache
  1612. X */
  1613. static void
  1614. MFFree(pMFRoot)
  1615. X    MAXFREQ *pMFRoot;
  1616. {
  1617. X    register MAXFREQ *pMF;
  1618. X    register MAXFREQ *pMFFree;
  1619. X    register MAXFREQ *pMFColumn;
  1620. X
  1621. X    for (pMFColumn = pMFRoot; nilMF != pMFColumn; pMFColumn = pMFColumn->pMFlower) {
  1622. X        for (pMF = pMFColumn; nilMF != pMF; /*EMPTY*/) {
  1623. X            pMFFree = pMF;
  1624. X            pMF = pMF->pMFequal;
  1625. X            free((char *)pMFFree);
  1626. X        }
  1627. X    }
  1628. }
  1629. X
  1630. /*@Explode check    @*/
  1631. /*
  1632. X * determine whether a value is among those with the highest
  1633. X * frequency
  1634. X *
  1635. X * return 0 for no; non-zero for yes.
  1636. X */
  1637. int
  1638. MFCheckMax(pMFRoot, pME)
  1639. X    register MAXFREQ *pMFRoot;
  1640. X    ME_ELEMENT *pME; 
  1641. {
  1642. X    while (nilMF != pMFRoot) {
  1643. X        if (0 == MECompare(pME, & pMFRoot->ME)) {
  1644. X            return 1;
  1645. X        }
  1646. X        pMFRoot = pMFRoot->pMFequal;
  1647. X    }
  1648. X    return 0;
  1649. }
  1650. X
  1651. /*@Explode scan    @*/
  1652. /*
  1653. X * scan over the nodes of a maxfreq cache
  1654. X *
  1655. X * Stop the scan and return the non-zero value if the given function
  1656. X * returns non-zero.
  1657. X */
  1658. int
  1659. MFScan(pMFRoot, pfi)
  1660. X    MAXFREQ *pMFRoot;
  1661. X    int (*pfi)();
  1662. {
  1663. X    register MAXFREQ *pMF;
  1664. X    register int iRet;
  1665. X    register MAXFREQ *pMFColumn;
  1666. X
  1667. X    for (pMFColumn = pMFRoot; nilMF != pMFColumn; pMFColumn = pMFColumn->pMFlower) {
  1668. X        for (pMF = pMFColumn; nilMF != pMF; pMF = pMF->pMFequal) {
  1669. X            if (0 != (iRet = (*pfi)(pMF))) {
  1670. X                return iRet;
  1671. X            }
  1672. X        }
  1673. X    }
  1674. X    return 0;
  1675. }
  1676. X
  1677. /*@Explode test        @*/
  1678. #ifdef TEST
  1679. char *progname;
  1680. X
  1681. /*
  1682. X * print routine prototyped for MFScan                    (dsg)
  1683. X */
  1684. static int
  1685. PrintNode(pMF)
  1686. X    MAXFREQ *pMF;
  1687. {
  1688. X    (void)printf("%7d %s", pMF->icount, pMF->ME.ac);
  1689. X    return 0;
  1690. }
  1691. X
  1692. /* a driver                                (dsg)
  1693. X * do maxfreq computation on small strings (group names, for example)
  1694. X */
  1695. int
  1696. main(argc, argv)
  1697. X    int argc;
  1698. X    char **argv;
  1699. {
  1700. X    auto ME_ELEMENT ME;
  1701. X    auto MAXFREQ *pMFRoot;
  1702. X
  1703. X    progname = argv[0];
  1704. X    pMFRoot = nilMF;
  1705. X    while ((char *)0 != fgets(& ME.ac[0], MAXBUF, stdin)) {
  1706. #ifdef TESTCHECK
  1707. X        (void)printf("before insertion element is ");
  1708. X        if (0 == MFCheckMax(pMFRoot, & ME)) {
  1709. X            (void)printf("not ");
  1710. X        }
  1711. X        (void)printf("among those with highest freq\n");
  1712. #endif /* TESTCHECK    */
  1713. X        (void)MFIncrement(& pMFRoot, & ME);
  1714. X    }
  1715. X    (void)MFScan(pMFRoot, PrintNode);
  1716. X    MFFree(pMFRoot);
  1717. X
  1718. X    exit(0);
  1719. }
  1720. #endif /* TEST    */
  1721. Purdue
  1722. chmod 0444 instck/maxfreq.c ||
  1723. echo 'restore of instck/maxfreq.c failed'
  1724. Wc_c="`wc -c < 'instck/maxfreq.c'`"
  1725. test 6205 -eq "$Wc_c" ||
  1726.     echo 'instck/maxfreq.c: original size 6205, current size' "$Wc_c"
  1727. fi
  1728. # ============= instck/Makefile ==============
  1729. if test -f 'instck/Makefile' -a X"$1" != X"-c"; then
  1730.     echo 'x - skipping instck/Makefile (File already exists)'
  1731. else
  1732. echo 'x - extracting instck/Makefile (Text)'
  1733. sed 's/^X//' << 'Purdue' > 'instck/Makefile' &&
  1734. # Copyright 1990 Purdue Research Foundation, West Lafayette, Indiana
  1735. # 47907.  All rights reserved.
  1736. #
  1737. # Written by Kevin S Braunsdorf, ksb@cc.purdue.edu, purdue!ksb
  1738. #
  1739. # This software is not subject to any license of the American Telephone
  1740. # and Telegraph Company or the Regents of the University of California.
  1741. #
  1742. # Permission is granted to anyone to use this software for any purpose on
  1743. # any computer system, and to alter it and redistribute it freely, subject
  1744. # to the following restrictions:
  1745. #
  1746. # 1. Neither the authors nor Purdue University are responsible for any
  1747. #    consequences of the use of this software.
  1748. #
  1749. # 2. The origin of this software must not be misrepresented, either by
  1750. #    explicit claim or by omission.  Credit to the authors and Purdue
  1751. #    University must appear in documentation and sources.
  1752. #
  1753. # 3. Altered versions must be plainly marked as such, and must not be
  1754. #    misrepresented as being the original software.
  1755. #
  1756. # 4. This notice may not be removed or altered.
  1757. #
  1758. # Makefile for instck                            (ksb)
  1759. #
  1760. # $Id: Makefile,v 7.1 90/09/17 11:34:00 ksb Exp $
  1761. #
  1762. X
  1763. BIN=    ${DESTDIR}/usr/local/etc
  1764. PROG=    instck
  1765. X
  1766. # where is the source code for install(1L)?
  1767. INSTALLD= ../install.d
  1768. #INSTALLD= /usr/src/usr.bin/install.d
  1769. #INSTALLD= /usr/src/local/cmd/install.d
  1770. X
  1771. PURGED= ../purge
  1772. #PURGED= /usr/src/local/etc/purge
  1773. X
  1774. # do we have symbolic links?
  1775. #  N.B. without symbolic links the source for install must be on
  1776. #    this file system.
  1777. #LN=ln
  1778. LN=ln -s
  1779. X
  1780. L=../libopt
  1781. #L=/usr/include/local
  1782. I=/usr/include
  1783. S=/usr/include/sys
  1784. P=
  1785. X
  1786. INCLUDE= -I$L
  1787. DEBUG=    -O
  1788. CDEFS=  
  1789. CFLAGS= ${DEBUG} ${CDEFS} ${INCLUDE}
  1790. X
  1791. HDR=    instck.h maxfreq.h main.h path.h gen.h
  1792. SRC=    instck.c maxfreq.c main.c path.c gen.c
  1793. LINKH=    configure.h install.h special.h special.i syscalls.h
  1794. LINKC=    syscalls.c special.c
  1795. LINK=    ${LINKH} ${LINKC}
  1796. LINKPH=    filedup.h
  1797. LINKPC=    filedup.c
  1798. LINKP=    ${LINKPH} ${LINKPC}
  1799. GENC=    ${LINKC} ${LINKPC}
  1800. GENH=    ${LINKH} ${LINKPH}
  1801. DEP=    ${SRC} ${GENC}
  1802. GEN=    ${GENC} ${GENH}
  1803. OBJ=    main.o instck.o maxfreq.o syscalls.o special.o path.o gen.o filedup.o
  1804. MAN=    instck.1l
  1805. OTHER=    README
  1806. SOURCE=    Makefile ${HDR} ${SRC} ${MAN} ${OTHER}
  1807. X
  1808. all: ${PROG}
  1809. X
  1810. ${PROG}:$P ${OBJ}
  1811. #    ${CC} -o $@ ${CFLAGS} ${OBJ} -lopt
  1812. #    ${CC} -o $@ ${CFLAGS} ${OBJ} -L /usr/local/lib -lopt
  1813. X    ${CC} -o $@ ${CFLAGS} ${OBJ} ../libopt/libopt.a
  1814. X
  1815. links: ${LINK} ${LINKP}
  1816. X
  1817. ${LINK}:
  1818. X    ${LN} ${INSTALLD}/$@ ./$@
  1819. X
  1820. ${LINKP}:
  1821. X    ${LN} ${PURGED}/$@ ./$@
  1822. X
  1823. clean: FRC
  1824. X    rm -f Makefile.bak ${PROG} ${GEN} *.o a.out core errs tags
  1825. X
  1826. depend: ${HDR} ${SRC} ${GEN} FRC
  1827. X    maketd ${CDEFS} ${INCLUDE} ${DEP}
  1828. X
  1829. dirs: ${BIN}
  1830. X
  1831. install: all dirs FRC
  1832. X    install -cs ${PROG} ${BIN}/${PROG}
  1833. X
  1834. lint: ${HDR} ${SRC} ${GEN} FRC
  1835. X    lint -h ${CDEFS} ${INCLUDE} ${DEP}
  1836. X
  1837. mkcat: ${MAN}
  1838. X    mkcat ${MAN}
  1839. X
  1840. print: source FRC
  1841. X    lpr -J'${PROG} source' ${SOURCE}
  1842. X
  1843. source: ${SOURCE}
  1844. X
  1845. spotless: clean
  1846. X    rcsclean ${SOURCE}
  1847. X
  1848. tags: ${HDR} ${SRC} ${GEN}
  1849. X    ctags -t ${HDR} ${SRC} ${GEN}
  1850. X
  1851. / ${BIN}:
  1852. X    install -d -r $@
  1853. X
  1854. ${SOURCE}:
  1855. X    co -q $@
  1856. X
  1857. FRC:
  1858. X
  1859. # DO NOT DELETE THIS LINE - maketd DEPENDS ON IT
  1860. X
  1861. instck.o: configure.h install.h instck.c instck.h main.h path.h special.h \
  1862. X    syscalls.h
  1863. X
  1864. maxfreq.o: configure.h gen.h main.h maxfreq.c maxfreq.h
  1865. X
  1866. main.o: configure.h install.h instck.h main.c main.h special.h syscalls.h
  1867. X
  1868. path.o: configure.h install.h instck.h main.h path.c path.h special.h
  1869. X
  1870. syscalls.o: configure.h install.h main.h syscalls.c
  1871. X
  1872. special.o: configure.h install.h instck.h main.h special.c special.h special.i \
  1873. X    syscalls.h
  1874. X
  1875. gen.o: configure.h filedup.h gen.c gen.h install.h instck.h main.h maxfreq.h \
  1876. X    path.h special.h syscalls.h
  1877. X
  1878. filedup.o: filedup.c filedup.h
  1879. X
  1880. # *** Do not add anything here - It will go away. ***
  1881. Purdue
  1882. chmod 0644 instck/Makefile ||
  1883. echo 'restore of instck/Makefile failed'
  1884. Wc_c="`wc -c < 'instck/Makefile'`"
  1885. test 3595 -eq "$Wc_c" ||
  1886.     echo 'instck/Makefile: original size 3595, current size' "$Wc_c"
  1887. fi
  1888. # ============= install.cf/README ==============
  1889. if test -f 'install.cf/README' -a X"$1" != X"-c"; then
  1890.     echo 'x - skipping install.cf/README (File already exists)'
  1891. else
  1892. echo 'x - extracting install.cf/README (Text)'
  1893. sed 's/^X//' << 'Purdue' > 'install.cf/README' &&
  1894. You might want to use instck(1L) to generate more lines for this
  1895. file, for example all the setuid/setgid files on your system:
  1896. X
  1897. X    find / \( -perm -4000 -o -perm -2000 \) -type f -print |
  1898. X        xargs instck -GSLv
  1899. X
  1900. ksb
  1901. Purdue
  1902. chmod 0444 install.cf/README ||
  1903. echo 'restore of install.cf/README failed'
  1904. Wc_c="`wc -c < 'install.cf/README'`"
  1905. test 212 -eq "$Wc_c" ||
  1906.     echo 'install.cf/README: original size 212, current size' "$Wc_c"
  1907. fi
  1908. # ============= purge/main.h ==============
  1909. if test ! -d 'purge'; then
  1910.     echo 'x - creating directory purge'
  1911.     mkdir 'purge'
  1912. fi
  1913. if test -f 'purge/main.h' -a X"$1" != X"-c"; then
  1914.     echo 'x - skipping purge/main.h (File already exists)'
  1915. else
  1916. echo 'x - extracting purge/main.h (Text)'
  1917. sed 's/^X//' << 'Purdue' > 'purge/main.h' &&
  1918. /*
  1919. X * parse options
  1920. X */
  1921. X
  1922. extern char *progname, u_terse[], *u_help[];
  1923. extern int main();
  1924. extern int fAnyOwner, fSuperUser, fVersion, iDays, fExec, fVerbose;
  1925. Purdue
  1926. chmod 0644 purge/main.h ||
  1927. echo 'restore of purge/main.h failed'
  1928. Wc_c="`wc -c < 'purge/main.h'`"
  1929. test 157 -eq "$Wc_c" ||
  1930.     echo 'purge/main.h: original size 157, current size' "$Wc_c"
  1931. fi
  1932. true || echo 'restore of purge/filedup.c failed'
  1933. echo End of part 5, continue with part 6
  1934. exit 0
  1935.  
  1936. exit 0 # Just in case...
  1937.