home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / rcs-5.6 / part07 < prev    next >
Encoding:
Text File  |  1991-12-19  |  72.2 KB  |  2,896 lines

  1. Newsgroups: comp.sources.unix
  2. From: hammer@cs.purdue.edu (Adam Hammer)
  3. Subject: v25i083: rcs-5.6 - Revision Control System, V5.6, Part07/11
  4. Sender: sources-moderator@pa.dec.com
  5. Approved: vixie@pa.dec.com
  6.  
  7. Submitted-By: hammer@cs.purdue.edu (Adam Hammer)
  8. Posting-Number: Volume 25, Issue 83
  9. Archive-Name: rcs-5.6/part07
  10.  
  11. #! /bin/sh
  12. # This is a shell archive.  Remove anything before this line, then unpack
  13. # it by saving it into a file and typing "sh file".  To overwrite existing
  14. # files, type "sh file -c".  You can also feed this as standard input via
  15. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  16. # will see the following message at the end:
  17. #        "End of archive 7 (of 11)."
  18. # Contents:  src/ci.c src/conf.sh
  19. # Wrapped by vixie@cognition.pa.dec.com on Fri Dec 20 16:23:41 1991
  20. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  21. if test -f 'src/ci.c' -a "${1}" != "-c" ; then 
  22.   echo shar: Will not clobber existing file \"'src/ci.c'\"
  23. else
  24. echo shar: Extracting \"'src/ci.c'\" \(33764 characters\)
  25. sed "s/^X//" >'src/ci.c' <<'END_OF_FILE'
  26. X/* Copyright (C) 1982, 1988, 1989 Walter Tichy
  27. X   Copyright 1990, 1991 by Paul Eggert
  28. X   Distributed under license by the Free Software Foundation, Inc.
  29. X
  30. This file is part of RCS.
  31. X
  32. RCS is free software; you can redistribute it and/or modify
  33. it under the terms of the GNU General Public License as published by
  34. the Free Software Foundation; either version 2, or (at your option)
  35. any later version.
  36. X
  37. RCS is distributed in the hope that it will be useful,
  38. but WITHOUT ANY WARRANTY; without even the implied warranty of
  39. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  40. GNU General Public License for more details.
  41. X
  42. You should have received a copy of the GNU General Public License
  43. along with RCS; see the file COPYING.  If not, write to
  44. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  45. X
  46. Report problems and direct all questions to:
  47. X
  48. X    rcs-bugs@cs.purdue.edu
  49. X
  50. X*/
  51. X
  52. X/*
  53. X *                     RCS checkin operation
  54. X */
  55. X/*******************************************************************
  56. X *                       check revisions into RCS files
  57. X *******************************************************************
  58. X */
  59. X
  60. X
  61. X
  62. X/* $Log: ci.c,v $
  63. X * Revision 5.21  1991/11/20  17:58:07  eggert
  64. X * Don't read the delta tree from a nonexistent RCS file.
  65. X *
  66. X * Revision 5.20  1991/10/07  17:32:46  eggert
  67. X * Fix log bugs.  Remove lint.
  68. X *
  69. X * Revision 5.19  1991/09/26  23:10:30  eggert
  70. X * Plug file descriptor leak.
  71. X *
  72. X * Revision 5.18  1991/09/18  07:29:10  eggert
  73. X * Work around a common ftruncate() bug.
  74. X *
  75. X * Revision 5.17  1991/09/10  22:15:46  eggert
  76. X * Fix test for redirected stdin.
  77. X *
  78. X * Revision 5.16  1991/08/19  23:17:54  eggert
  79. X * When there are no changes, revert to previous revision instead of aborting.
  80. X * Add piece tables, -M, -r$.  Tune.
  81. X *
  82. X * Revision 5.15  1991/04/21  11:58:14  eggert
  83. X * Ensure that working file is newer than RCS file after ci -[lu].
  84. X * Add -x, RCSINIT, MS-DOS support.
  85. X *
  86. X * Revision 5.14  1991/02/28  19:18:47  eggert
  87. X * Don't let a setuid ci create a new RCS file; rcs -i -a must be run first.
  88. X * Fix ci -ko -l mode bug.  Open work file at most once.
  89. X *
  90. X * Revision 5.13  1991/02/25  07:12:33  eggert
  91. X * getdate -> getcurdate (SVR4 name clash)
  92. X *
  93. X * Revision 5.12  1990/12/31  01:00:12  eggert
  94. X * Don't use uninitialized storage when handling -{N,n}.
  95. X *
  96. X * Revision 5.11  1990/12/04  05:18:36  eggert
  97. X * Use -I for prompts and -q for diagnostics.
  98. X *
  99. X * Revision 5.10  1990/11/05  20:30:10  eggert
  100. X * Don't remove working file when aborting due to no changes.
  101. X *
  102. X * Revision 5.9  1990/11/01  05:03:23  eggert
  103. X * Add -I and new -t behavior.  Permit arbitrary data in logs.
  104. X *
  105. X * Revision 5.8  1990/10/04  06:30:09  eggert
  106. X * Accumulate exit status across files.
  107. X *
  108. X * Revision 5.7  1990/09/25  20:11:46  hammer
  109. X * fixed another small typo
  110. X *
  111. X * Revision 5.6  1990/09/24  21:48:50  hammer
  112. X * added cleanups from Paul Eggert.
  113. X *
  114. X * Revision 5.5  1990/09/21  06:16:38  hammer
  115. X * made it handle multiple -{N,n}'s.  Also, made it treat re-directed stdin
  116. X * the same as the terminal
  117. X *
  118. X * Revision 5.4  1990/09/20  02:38:51  eggert
  119. X * ci -k now checks dates more thoroughly.
  120. X *
  121. X * Revision 5.3  1990/09/11  02:41:07  eggert
  122. X * Fix revision bug with `ci -k file1 file2'.
  123. X *
  124. X * Revision 5.2  1990/09/04  08:02:10  eggert
  125. X * Permit adjacent revisions with identical time stamps (possible on fast hosts).
  126. X * Improve incomplete line handling.  Standardize yes-or-no procedure.
  127. X *
  128. X * Revision 5.1  1990/08/29  07:13:44  eggert
  129. X * Expand locker value like co.  Clean old log messages too.
  130. X *
  131. X * Revision 5.0  1990/08/22  08:10:00  eggert
  132. X * Don't require a final newline.
  133. X * Make lock and temp files faster and safer.
  134. X * Remove compile-time limits; use malloc instead.
  135. X * Permit dates past 1999/12/31.  Switch to GMT.
  136. X * Add setuid support.  Don't pass +args to diff.  Check diff's output.
  137. X * Ansify and Posixate.  Add -k, -V.  Remove snooping.  Tune.
  138. X * Check diff's output.
  139. X *
  140. X * Revision 4.9  89/05/01  15:10:54  narten
  141. X * changed copyright header to reflect current distribution rules
  142. X * 
  143. X * Revision 4.8  88/11/08  13:38:23  narten
  144. X * changes from root@seismo.CSS.GOV (Super User)
  145. X * -d with no arguments uses the mod time of the file it is checking in
  146. X * 
  147. X * Revision 4.7  88/08/09  19:12:07  eggert
  148. X * Make sure workfile is a regular file; use its mode if RCSfile doesn't have one.
  149. X * Use execv(), not system(); allow cc -R; remove lint.
  150. X * isatty(fileno(stdin)) -> ttystdin()
  151. X * 
  152. X * Revision 4.6  87/12/18  11:34:41  narten
  153. X * lint cleanups (from Guy Harris)
  154. X * 
  155. X * Revision 4.5  87/10/18  10:18:48  narten
  156. X * Updating version numbers. Changes relative to revision 1.1 are actually
  157. X * relative to 4.3
  158. X * 
  159. X * Revision 1.3  87/09/24  13:57:19  narten
  160. X * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  161. X * warnings)
  162. X * 
  163. X * Revision 1.2  87/03/27  14:21:33  jenkins
  164. X * Port to suns
  165. X * 
  166. X * Revision 4.3  83/12/15  12:28:54  wft
  167. X * ci -u and ci -l now set mode of working file properly.
  168. X * 
  169. X * Revision 4.2  83/12/05  13:40:54  wft
  170. X * Merged with 3.9.1.1: added calls to clearerr(stdin).
  171. X * made rewriteflag external.
  172. X * 
  173. X * Revision 4.1  83/05/10  17:03:06  wft
  174. X * Added option -d and -w, and updated assingment of date, etc. to new delta.
  175. X * Added handling of default branches.
  176. X * Option -k generates std. log message; fixed undef. pointer in reading of log.
  177. X * Replaced getlock() with findlock(), link--unlink with rename(),
  178. X * getpwuid() with getcaller().
  179. X * Moved all revision number generation to new routine addelta().
  180. X * Removed calls to stat(); now done by pairfilenames().
  181. X * Changed most calls to catchints() with restoreints().
  182. X * Directed all interactive messages to stderr.
  183. X * 
  184. X * Revision 3.9.1.1  83/10/19  04:21:03  lepreau
  185. X * Added clearerr(stdin) to getlogmsg() for re-reading stdin.
  186. X * 
  187. X * Revision 3.9  83/02/15  15:25:44  wft
  188. X * 4.2 prerelease
  189. X * 
  190. X * Revision 3.9  83/02/15  15:25:44  wft
  191. X * Added call to fastcopy() to copy remainder of RCS file.
  192. X *
  193. X * Revision 3.8  83/01/14  15:34:05  wft
  194. X * Added ignoring of interrupts while new RCS file is renamed;
  195. X * Avoids deletion of RCS files by interrupts.
  196. X *
  197. X * Revision 3.7  82/12/10  16:09:20  wft
  198. X * Corrected checking of return code from diff.
  199. X *
  200. X * Revision 3.6  82/12/08  21:34:49  wft
  201. X * Using DATEFORM to prepare date of checked-in revision;
  202. X * Fixed return from addbranch().
  203. X *
  204. X * Revision 3.5  82/12/04  18:32:42  wft
  205. X * Replaced getdelta() with gettree(), SNOOPDIR with SNOOPFILE. Updated
  206. X * field lockedby in removelock(), moved getlogmsg() before calling diff.
  207. X *
  208. X * Revision 3.4  82/12/02  13:27:13  wft
  209. X * added option -k.
  210. X *
  211. X * Revision 3.3  82/11/28  20:53:31  wft
  212. X * Added mustcheckin() to check for redundant checkins.
  213. X * Added xpandfile() to do keyword expansion for -u and -l;
  214. X * -m appends linefeed to log message if necessary.
  215. X * getlogmsg() suppresses prompt if stdin is not a terminal.
  216. X * Replaced keeplock with lockflag, fclose() with ffclose(),
  217. X * %02d with %.2d, getlogin() with getpwuid().
  218. X *
  219. X * Revision 3.2  82/10/18  20:57:23  wft
  220. X * An RCS file inherits its mode during the first ci from the working file,
  221. X * otherwise it stays the same, except that write permission is removed.
  222. X * Fixed ci -l, added ci -u (both do an implicit co after the ci).
  223. X * Fixed call to getlogin(), added call to getfullRCSname(), added check
  224. X * for write error.
  225. X * Changed conflicting identifiers.
  226. X *
  227. X * Revision 3.1  82/10/13  16:04:59  wft
  228. X * fixed type of variables receiving from getc() (char -> int).
  229. X * added include file dbm.h for getting BYTESIZ. This is used
  230. X * to check the return code from diff portably.
  231. X */
  232. X
  233. X#include "rcsbase.h"
  234. X
  235. struct Symrev {
  236. X       char const *ssymbol;
  237. X       int override;
  238. X       struct Symrev * nextsym;
  239. X};
  240. X
  241. static char const *getcurdate P((void));
  242. static int addbranch P((struct hshentry*,struct buf*));
  243. static int addelta P((void));
  244. static int addsyms P((char const*));
  245. static int fixwork P((mode_t,char const*));
  246. static int removelock P((struct hshentry*));
  247. static int xpandfile P((RILE*,char const*,struct hshentry const*,char const**));
  248. static struct cbuf getlogmsg P((void));
  249. static void cleanup P((void));
  250. static void incnum P((char const*,struct buf*));
  251. static void addassoclst P((int, char *));
  252. X
  253. static FILE *exfile;
  254. static RILE *workptr;            /* working file pointer        */
  255. static struct buf newdelnum;        /* new revision number        */
  256. static struct cbuf msg;
  257. static int exitstatus;
  258. static int forceciflag;            /* forces check in        */
  259. static int keepflag, keepworkingfile, rcsinitflag;
  260. static struct hshentries *gendeltas;    /* deltas to be generated    */
  261. static struct hshentry *targetdelta;    /* old delta to be generated    */
  262. static struct hshentry newdelta;    /* new delta to be inserted    */
  263. static struct stat workstat;
  264. static struct Symrev *assoclst, *lastassoc;
  265. X
  266. mainProg(ciId, "ci", "$Id: ci.c,v 5.21 1991/11/20 17:58:07 eggert Exp $")
  267. X{
  268. X    static char const cmdusage[] =
  269. X        "\nci usage: ci -{fklqru}[rev] -mmsg -{nN}name -sstate -t[textfile] -Vn file ...";
  270. X    static char const default_state[] = DEFAULTSTATE;
  271. X
  272. X    char altdate[datesize];
  273. X    char olddate[datesize];
  274. X    char newdatebuf[datesize], targetdatebuf[datesize];
  275. X    char *a, **newargv, *textfile;
  276. X    char const *author, *krev, *rev, *state;
  277. X    char const *diffilename, *expfilename;
  278. X    char const *workdiffname, *newworkfilename;
  279. X    char const *mtime;
  280. X    int lockflag, lockthis, mtimeflag, removedlock;
  281. X    int r;
  282. X    int changedRCS, changework, newhead;
  283. X    int usestatdate; /* Use mod time of file for -d.  */
  284. X    mode_t newworkmode; /* mode for working file */
  285. X    struct hshentry *workdelta;
  286. X    
  287. X    setrid();
  288. X
  289. X    author = rev = state = textfile = nil;
  290. X    lockflag = false;
  291. X    mtimeflag = false;
  292. X    altdate[0]= '\0'; /* empty alternate date for -d */
  293. X    usestatdate=false;
  294. X    suffixes = X_DEFAULT;
  295. X
  296. X    argc = getRCSINIT(argc, argv, &newargv);
  297. X    argv = newargv;
  298. X    while (a = *++argv,  0<--argc && *a++=='-') {
  299. X        switch (*a++) {
  300. X
  301. X                case 'r':
  302. X            keepworkingfile = lockflag = false;
  303. X        revno:
  304. X            if (*a) {
  305. X                if (rev) warn("redefinition of revision number");
  306. X                rev = a;
  307. X                        }
  308. X                        break;
  309. X
  310. X                case 'l':
  311. X                        keepworkingfile=lockflag=true;
  312. X                        goto revno;
  313. X
  314. X                case 'u':
  315. X                        keepworkingfile=true; lockflag=false;
  316. X                        goto revno;
  317. X
  318. X        case 'I':
  319. X            interactiveflag = true;
  320. X            goto revno;
  321. X
  322. X                case 'q':
  323. X                        quietflag=true;
  324. X                        goto revno;
  325. X
  326. X                case 'f':
  327. X                        forceciflag=true;
  328. X                        goto revno;
  329. X
  330. X                case 'k':
  331. X                        keepflag=true;
  332. X                        goto revno;
  333. X
  334. X                case 'm':
  335. X            if (msg.size) redefined('m');
  336. X            msg = cleanlogmsg(a, strlen(a));
  337. X            if (!msg.size)
  338. X                warn("missing message for -m option");
  339. X                        break;
  340. X
  341. X                case 'n':
  342. X            if (!*a) {
  343. X                                error("missing symbolic name after -n");
  344. X                break;
  345. X                    }
  346. X            checksid(a);
  347. X            addassoclst(false, a);
  348. X                break;
  349. X        
  350. X        case 'N':
  351. X            if (!*a) {
  352. X                                error("missing symbolic name after -N");
  353. X                break;
  354. X                    }
  355. X            checksid(a);
  356. X            addassoclst(true, a);
  357. X                break;
  358. X
  359. X                case 's':
  360. X            if (*a) {
  361. X                if (state) redefined('s');
  362. X                checksid(a);
  363. X                state = a;
  364. X            } else
  365. X                warn("missing state for -s option");
  366. X                        break;
  367. X
  368. X                case 't':
  369. X            if (*a) {
  370. X                if (textfile) redefined('t');
  371. X                textfile = a;
  372. X                        }
  373. X                        break;
  374. X
  375. X        case 'd':
  376. X            if (altdate[0] || usestatdate)
  377. X                redefined('d');
  378. X            altdate[0] = 0;
  379. X            if (!(usestatdate = !*a))
  380. X                str2date(a, altdate);
  381. X                        break;
  382. X
  383. X        case 'M':
  384. X            mtimeflag = true;
  385. X            goto revno;
  386. X
  387. X        case 'w':
  388. X            if (*a) {
  389. X                if (author) redefined('w');
  390. X                checksid(a);
  391. X                author = a;
  392. X            } else
  393. X                warn("missing author for -w option");
  394. X                        break;
  395. X
  396. X        case 'x':
  397. X            suffixes = a;
  398. X            break;
  399. X
  400. X        case 'V':
  401. X            setRCSversion(*argv);
  402. X            break;
  403. X
  404. X
  405. X
  406. X                default:
  407. X            faterror("unknown option: %s%s", *argv, cmdusage);
  408. X                };
  409. X        }  /* end processing of options */
  410. X
  411. X    if (argc<1) faterror("no input file%s", cmdusage);
  412. X
  413. X        /* now handle all filenames */
  414. X        do {
  415. X        targetdelta=nil;
  416. X    ffree();
  417. X
  418. X    switch (pairfilenames(argc, argv, rcswriteopen, false, false)) {
  419. X
  420. X        case -1:                /* New RCS file */
  421. X#        if has_setuid && has_getuid
  422. X            if (euid() != ruid()) {
  423. X            error("setuid initial checkin prohibited; use `rcs -i -a' first");
  424. X            continue;
  425. X            }
  426. X#        endif
  427. X        rcsinitflag = true;
  428. X                break;
  429. X
  430. X        case 0:                 /* Error */
  431. X                continue;
  432. X
  433. X        case 1:                 /* Normal checkin with prev . RCS file */
  434. X        rcsinitflag = !Head;
  435. X        }
  436. X
  437. X        /* now RCSfilename contains the name of the RCS file, and
  438. X         * workfilename contains the name of the working file.
  439. X     * If the RCS file exists, finptr contains the file descriptor for the
  440. X         * RCS file. The admin node is initialized.
  441. X     * RCSstat is set.
  442. X         */
  443. X
  444. X    diagnose("%s  <--  %s\n", RCSfilename,workfilename);
  445. X
  446. X    if (!(workptr = Iopen(workfilename, FOPEN_R_WORK, &workstat))) {
  447. X        eerror(workfilename);
  448. X        continue;
  449. X    }
  450. X    if (finptr && !checkaccesslist()) continue; /* give up */
  451. X
  452. X    krev = rev;
  453. X        if (keepflag) {
  454. X                /* get keyword values from working file */
  455. X        if (!getoldkeys(workptr)) continue;
  456. X        if (!rev  &&  !*(krev = prevrev.string)) {
  457. X            error("can't find a revision number in %s",workfilename);
  458. X                        continue;
  459. X                }
  460. X        if (!*prevdate.string && *altdate=='\0' && usestatdate==false)
  461. X            warn("can't find a date in %s", workfilename);
  462. X        if (!*prevauthor.string && !author)
  463. X            warn("can't find an author in %s", workfilename);
  464. X        if (!*prevstate.string && !state)
  465. X            warn("can't find a state in %s", workfilename);
  466. X        } /* end processing keepflag */
  467. X
  468. X    /* Read the delta tree.  */
  469. X    if (finptr)
  470. X        gettree();
  471. X
  472. X        /* expand symbolic revision number */
  473. X    if (!fexpandsym(krev, &newdelnum, workptr))
  474. X        continue;
  475. X
  476. X        /* splice new delta into tree */
  477. X    if ((removedlock = addelta()) < 0)
  478. X        continue;
  479. X
  480. X    newdelta.num = newdelnum.string;
  481. X        newdelta.branches=nil;
  482. X        newdelta.lockedby=nil; /*might be changed by addlock() */
  483. X    newdelta.selector = true;
  484. X    /* set author */
  485. X    if (author!=nil)
  486. X        newdelta.author=author;     /* set author given by -w         */
  487. X    else if (keepflag && *prevauthor.string)
  488. X        newdelta.author=prevauthor.string; /* preserve old author if possible*/
  489. X    else    newdelta.author=getcaller();/* otherwise use caller's id      */
  490. X    newdelta.state = default_state;
  491. X    if (state!=nil)
  492. X        newdelta.state=state;       /* set state given by -s          */
  493. X    else if (keepflag && *prevstate.string)
  494. X        newdelta.state=prevstate.string;   /* preserve old state if possible */
  495. X    if (usestatdate) {
  496. X        time2date(workstat.st_mtime, altdate);
  497. X    }
  498. X    if (*altdate!='\0')
  499. X        newdelta.date=altdate;      /* set date given by -d           */
  500. X    else if (keepflag && *prevdate.string) {
  501. X        /* Preserve old date if possible.  */
  502. X        str2date(prevdate.string, olddate);
  503. X        newdelta.date = olddate;
  504. X    } else
  505. X        newdelta.date = getcurdate();  /* use current date */
  506. X    /* now check validity of date -- needed because of -d and -k          */
  507. X    if (targetdelta!=nil &&
  508. X        cmpnum(newdelta.date,targetdelta->date) < 0) {
  509. X        error("Date %s precedes %s in existing revision %s.",
  510. X            date2str(newdelta.date, newdatebuf),
  511. X            date2str(targetdelta->date, targetdatebuf),
  512. X            targetdelta->num
  513. X        );
  514. X        continue;
  515. X    }
  516. X
  517. X
  518. X    if (lockflag  &&  addlock(&newdelta) < 0) continue;
  519. X    if (!addsyms(newdelta.num))
  520. X        continue;
  521. X
  522. X    
  523. X        putadmin(frewrite);
  524. X        puttree(Head,frewrite);
  525. X    putdesc(false,textfile);
  526. X
  527. X    changework = Expand != OLD_EXPAND;
  528. X    lockthis = lockflag;
  529. X    workdelta = &newdelta;
  530. X
  531. X        /* build rest of file */
  532. X    if (rcsinitflag) {
  533. X        diagnose("initial revision: %s\n", newdelnum.string);
  534. X                /* get logmessage */
  535. X                newdelta.log=getlogmsg();
  536. X        if (!putdftext(newdelnum.string,newdelta.log,workptr,frewrite,false)) continue;
  537. X        RCSstat.st_mode = workstat.st_mode;
  538. X        changedRCS = true;
  539. X        } else {
  540. X        diffilename = maketemp(0);
  541. X        workdiffname = workfilename;
  542. X        if (workdiffname[0] == '+') {
  543. X            /* Some diffs have options with leading '+'.  */
  544. X            char *dp = ftnalloc(char, strlen(workfilename)+3);
  545. X            workdiffname = dp;
  546. X            *dp++ = '.';
  547. X            *dp++ = SLASH;
  548. X            VOID strcpy(dp, workfilename);
  549. X        }
  550. X        newhead  =  Head == &newdelta;
  551. X        if (!newhead)
  552. X            foutptr = frewrite;
  553. X        expfilename = buildrevision(
  554. X            gendeltas, targetdelta, (FILE*)0, false
  555. X        );
  556. X        if (
  557. X            !forceciflag  &&
  558. X            (changework = rcsfcmp(
  559. X            workptr, &workstat, expfilename, targetdelta
  560. X            )) <= 0
  561. X        ) {
  562. X            diagnose("file is unchanged; reverting to previous revision %s\n",
  563. X            targetdelta->num
  564. X            );
  565. X            if (removedlock < lockflag) {
  566. X            diagnose("previous revision was not locked; ignoring -l option\n");
  567. X            lockthis = 0;
  568. X            }
  569. X            if (!(changedRCS  =
  570. X                lockflag < removedlock
  571. X            ||  assoclst
  572. X            ||    newdelta.state != default_state
  573. X                &&    strcmp(newdelta.state, targetdelta->state) != 0
  574. X            ))
  575. X            workdelta = targetdelta;
  576. X            else {
  577. X            /*
  578. X             * We have started to build the wrong new RCS file.
  579. X             * Start over from the beginning.
  580. X             */
  581. X            long hwm = ftell(frewrite);
  582. X            int bad_truncate;
  583. X            if (fseek(frewrite, 0L, SEEK_SET) != 0)
  584. X                Oerror();
  585. X#            if !has_ftruncate
  586. X                bad_truncate = 1;
  587. X#            else
  588. X                /*
  589. X                 * Work around a common ftruncate() bug.
  590. X                 * We can't rely on has_truncate, because we might
  591. X                 * be using a filesystem exported to us via NFS.
  592. X                 */
  593. X                bad_truncate = ftruncate(fileno(frewrite),(off_t)0);
  594. X                if (bad_truncate  &&  errno != EACCES)
  595. X                Oerror();
  596. X#            endif
  597. X            Irewind(finptr);
  598. X            Lexinit();
  599. X            getadmin();
  600. X            gettree();
  601. X            if (!(workdelta = genrevs(
  602. X                targetdelta->num, (char*)0, (char*)0, (char*)0,
  603. X                &gendeltas
  604. X            )))
  605. X                continue;
  606. X            workdelta->log = targetdelta->log;
  607. X            if (newdelta.state != default_state)
  608. X                workdelta->state = newdelta.state;
  609. X            if (removedlock && removelock(workdelta)<0)
  610. X                continue;
  611. X            if (!addsyms(workdelta->num))
  612. X                continue;
  613. X            if (!dorewrite(true, true))
  614. X                continue;
  615. X            fastcopy(finptr, frewrite);
  616. X            if (bad_truncate)
  617. X                while (ftell(frewrite) < hwm)
  618. X                /* White out any earlier mistake with '\n's.  */
  619. X                /* This is unlikely.  */
  620. X                afputc('\n', frewrite);
  621. X            }
  622. X        } else {
  623. X            diagnose("new revision: %s; previous revision: %s\n",
  624. X            newdelnum.string, targetdelta->num
  625. X            );
  626. X            newdelta.log = getlogmsg();
  627. X            switch (run((char*)0, diffilename,
  628. X            DIFF DIFF_FLAGS,
  629. X            newhead ? workdiffname : expfilename,
  630. X            newhead ? expfilename : workdiffname,
  631. X            (char*)0
  632. X            )) {
  633. X            case DIFF_FAILURE: case DIFF_SUCCESS: break;
  634. X            default: faterror("diff failed");
  635. X            }
  636. X            if (newhead) {
  637. X            Irewind(workptr);
  638. X            if (!putdftext(newdelnum.string,newdelta.log,workptr,frewrite,false)) continue;
  639. X            if (!putdtext(targetdelta->num,targetdelta->log,diffilename,frewrite,true)) continue;
  640. X            } else
  641. X            if (!putdtext(newdelnum.string,newdelta.log,diffilename,frewrite,true)) continue;
  642. X            changedRCS = true;
  643. X                }
  644. X        }
  645. X    if (!donerewrite(changedRCS))
  646. X        continue;
  647. X
  648. X        if (!keepworkingfile) {
  649. X        Izclose(&workptr);
  650. X        r = un_link(workfilename); /* Get rid of old file */
  651. X        } else {
  652. X        newworkmode = WORKMODE(RCSstat.st_mode,
  653. X            !   (Expand==VAL_EXPAND  ||  lockthis < StrictLocks)
  654. X        );
  655. X        mtime = mtimeflag ? workdelta->date : (char const*)0;
  656. X
  657. X        /* Expand if it might change or if we can't fix mode, time.  */
  658. X        if (changework  ||  (r=fixwork(newworkmode,mtime)) != 0) {
  659. X            Irewind(workptr);
  660. X            /* Expand keywords in file.  */
  661. X            locker_expansion = lockthis;
  662. X            switch (xpandfile(
  663. X            workptr, workfilename,
  664. X            workdelta, &newworkfilename
  665. X            )) {
  666. X            default:
  667. X                continue;
  668. X
  669. X            case 0:
  670. X                /*
  671. X                 * No expansion occurred; try to reuse working file
  672. X                 * unless we already tried and failed.
  673. X                 */
  674. X                if (changework)
  675. X                if ((r=fixwork(newworkmode,mtime)) == 0)
  676. X                    break;
  677. X                /* fall into */
  678. X            case 1:
  679. X                if (!(r = setfiledate(newworkfilename,mtime))) {
  680. X                Izclose(&workptr);
  681. X                ignoreints();
  682. X                r = chnamemod(&exfile, newworkfilename, workfilename, newworkmode);
  683. X                keepdirtemp(newworkfilename);
  684. X                restoreints();
  685. X                }
  686. X            }
  687. X        }
  688. X        }
  689. X    if (r != 0) {
  690. X        eerror(workfilename);
  691. X        continue;
  692. X    }
  693. X    diagnose("done\n");
  694. X
  695. X        } while (cleanup(),
  696. X                 ++argv, --argc >=1);
  697. X
  698. X    tempunlink();
  699. X    exitmain(exitstatus);
  700. X}       /* end of main (ci) */
  701. X
  702. X    static void
  703. cleanup()
  704. X{
  705. X    if (nerror) exitstatus = EXIT_FAILURE;
  706. X    Izclose(&finptr);
  707. X    Izclose(&workptr);
  708. X    Ozclose(&exfile);
  709. X    Ozclose(&fcopy);
  710. X    Ozclose(&frewrite);
  711. X    dirtempunlink();
  712. X}
  713. X
  714. X#if lint
  715. X#    define exiterr ciExit
  716. X#endif
  717. X    exiting void
  718. exiterr()
  719. X{
  720. X    dirtempunlink();
  721. X    tempunlink();
  722. X    _exit(EXIT_FAILURE);
  723. X}
  724. X
  725. X/*****************************************************************/
  726. X/* the rest are auxiliary routines                               */
  727. X
  728. X
  729. X    static int
  730. addelta()
  731. X/* Function: Appends a delta to the delta tree, whose number is
  732. X * given by newdelnum.  Updates Head, newdelnum, newdelnumlength,
  733. X * and the links in newdelta.
  734. X * Return -1 on error, 1 if a lock is removed, 0 otherwise.
  735. X */
  736. X{
  737. X    register char *tp;
  738. X    register unsigned i;
  739. X    int removedlock;
  740. X    unsigned newdnumlength;  /* actual length of new rev. num. */
  741. X
  742. X    newdnumlength = countnumflds(newdelnum.string);
  743. X
  744. X    if (rcsinitflag) {
  745. X                /* this covers non-existing RCS file and a file initialized with rcs -i */
  746. X        if ((newdnumlength==0)&&(Dbranch!=nil)) {
  747. X            bufscpy(&newdelnum, Dbranch);
  748. X            newdnumlength = countnumflds(Dbranch);
  749. X        }
  750. X        if (newdnumlength==0) bufscpy(&newdelnum, "1.1");
  751. X        else if (newdnumlength==1) bufscat(&newdelnum, ".1");
  752. X        else if (newdnumlength>2) {
  753. X            error("Branch point doesn't exist for %s.",newdelnum.string);
  754. X            return -1;
  755. X                } /* newdnumlength == 2 is OK;  */
  756. X                Head = &newdelta;
  757. X                newdelta.next=nil;
  758. X        return 0;
  759. X        }
  760. X        if (newdnumlength==0) {
  761. X                /* derive new revision number from locks */
  762. X        switch (findlock(true, &targetdelta)) {
  763. X
  764. X          default:
  765. X            /* found two or more old locks */
  766. X            return -1;
  767. X
  768. X          case 1:
  769. X                    /* found an old lock */
  770. X                    /* check whether locked revision exists */
  771. X            if (!genrevs(targetdelta->num,(char*)0,(char*)0,(char*)0,&gendeltas))
  772. X            return -1;
  773. X                    if (targetdelta==Head) {
  774. X                        /* make new head */
  775. X                        newdelta.next=Head;
  776. X                        Head= &newdelta;
  777. X            } else if (!targetdelta->next && countnumflds(targetdelta->num)>2) {
  778. X                        /* new tip revision on side branch */
  779. X                        targetdelta->next= &newdelta;
  780. X                        newdelta.next = nil;
  781. X                    } else {
  782. X                        /* middle revision; start a new branch */
  783. X            bufscpy(&newdelnum, "");
  784. X            return addbranch(targetdelta,&newdelnum);
  785. X                    }
  786. X            incnum(targetdelta->num, &newdelnum);
  787. X            return 1; /* successful use of existing lock */
  788. X
  789. X          case 0:
  790. X                    /* no existing lock; try Dbranch */
  791. X                    /* update newdelnum */
  792. X            if (StrictLocks || !myself(RCSstat.st_uid)) {
  793. X            error("no lock set by %s",getcaller());
  794. X            return -1;
  795. X                    }
  796. X                    if (Dbranch) {
  797. X            bufscpy(&newdelnum, Dbranch);
  798. X                    } else {
  799. X            incnum(Head->num, &newdelnum);
  800. X                    }
  801. X            newdnumlength = countnumflds(newdelnum.string);
  802. X                    /* now fall into next statement */
  803. X                }
  804. X        }
  805. X        if (newdnumlength<=2) {
  806. X                /* add new head per given number */
  807. X                if(newdnumlength==1) {
  808. X                    /* make a two-field number out of it*/
  809. X            if (cmpnumfld(newdelnum.string,Head->num,1)==0)
  810. X            incnum(Head->num, &newdelnum);
  811. X            else
  812. X            bufscat(&newdelnum, ".1");
  813. X                }
  814. X        if (cmpnum(newdelnum.string,Head->num) <= 0) {
  815. X                    error("deltanumber %s too low; must be higher than %s",
  816. X              newdelnum.string, Head->num);
  817. X            return -1;
  818. X                }
  819. X        targetdelta = Head;
  820. X        if (0 <= (removedlock = removelock(Head))) {
  821. X            if (!genrevs(Head->num,(char*)0,(char*)0,(char*)0,&gendeltas))
  822. X            return -1;
  823. X            newdelta.next = Head;
  824. X            Head = &newdelta;
  825. X        }
  826. X        return removedlock;
  827. X        } else {
  828. X                /* put new revision on side branch */
  829. X                /*first, get branch point */
  830. X        tp = newdelnum.string;
  831. X        for (i = newdnumlength - (newdnumlength&1 ^ 1);  (--i);  )
  832. X            while (*tp++ != '.')
  833. X                ;
  834. X        *--tp = 0; /* Kill final dot to get old delta temporarily. */
  835. X        if (!(targetdelta=genrevs(newdelnum.string,(char*)nil,(char*)nil,(char*)nil,&gendeltas)))
  836. X            return -1;
  837. X        if (cmpnum(targetdelta->num, newdelnum.string) != 0) {
  838. X            error("can't find branchpoint %s", newdelnum.string);
  839. X            return -1;
  840. X                }
  841. X        *tp = '.'; /* Restore final dot. */
  842. X        return addbranch(targetdelta,&newdelnum);
  843. X        }
  844. X}
  845. X
  846. X
  847. X
  848. X    static int
  849. addbranch(branchpoint,num)
  850. X    struct hshentry *branchpoint;
  851. X    struct buf *num;
  852. X/* adds a new branch and branch delta at branchpoint.
  853. X * If num is the null string, appends the new branch, incrementing
  854. X * the highest branch number (initially 1), and setting the level number to 1.
  855. X * the new delta and branchhead are in globals newdelta and newbranch, resp.
  856. X * the new number is placed into num.
  857. X * Return -1 on error, 1 if a lock is removed, 0 otherwise.
  858. X */
  859. X{
  860. X    struct branchhead *bhead, **btrail;
  861. X    struct buf branchnum;
  862. X    int removedlock, result;
  863. X    unsigned field, numlength;
  864. X    static struct branchhead newbranch;  /* new branch to be inserted */
  865. X
  866. X    numlength = countnumflds(num->string);
  867. X
  868. X        if (branchpoint->branches==nil) {
  869. X                /* start first branch */
  870. X                branchpoint->branches = &newbranch;
  871. X                if (numlength==0) {
  872. X            bufscpy(num, branchpoint->num);
  873. X            bufscat(num, ".1.1");
  874. X        } else if (numlength&1)
  875. X            bufscat(num, ".1");
  876. X                newbranch.nextbranch=nil;
  877. X
  878. X    } else if (numlength==0) {
  879. X                /* append new branch to the end */
  880. X                bhead=branchpoint->branches;
  881. X                while (bhead->nextbranch) bhead=bhead->nextbranch;
  882. X                bhead->nextbranch = &newbranch;
  883. X        bufautobegin(&branchnum);
  884. X        getbranchno(bhead->hsh->num, &branchnum);
  885. X        incnum(branchnum.string, num);
  886. X        bufautoend(&branchnum);
  887. X        bufscat(num, ".1");
  888. X                newbranch.nextbranch=nil;
  889. X        } else {
  890. X                /* place the branch properly */
  891. X        field = numlength - (numlength&1 ^ 1);
  892. X                /* field of branch number */
  893. X        btrail = &branchpoint->branches;
  894. X        while (0 < (result=cmpnumfld(num->string,(*btrail)->hsh->num,field))) {
  895. X            btrail = &(*btrail)->nextbranch;
  896. X            if (!*btrail) {
  897. X                result = -1;
  898. X                break;
  899. X            }
  900. X                }
  901. X        if (result < 0) {
  902. X                        /* insert/append new branchhead */
  903. X            newbranch.nextbranch = *btrail;
  904. X            *btrail = &newbranch;
  905. X            if (numlength&1) bufscat(num, ".1");
  906. X                } else {
  907. X                        /* branch exists; append to end */
  908. X            bufautobegin(&branchnum);
  909. X            getbranchno(num->string, &branchnum);
  910. X            targetdelta=genrevs(branchnum.string,(char*)nil,
  911. X                        (char*)nil,(char*)nil,&gendeltas);
  912. X            bufautoend(&branchnum);
  913. X            if (!targetdelta)
  914. X                return -1;
  915. X            if (cmpnum(num->string,targetdelta->num) <= 0) {
  916. X                                error("deltanumber %s too low; must be higher than %s",
  917. X                      num->string,targetdelta->num);
  918. X                return -1;
  919. X                        }
  920. X            if (0 <= (removedlock = removelock(targetdelta))) {
  921. X                if (numlength&1)
  922. X                incnum(targetdelta->num,num);
  923. X                targetdelta->next = &newdelta;
  924. X                newdelta.next = 0;
  925. X            }
  926. X            return removedlock;
  927. X            /* Don't do anything to newbranch.  */
  928. X                }
  929. X        }
  930. X        newbranch.hsh = &newdelta;
  931. X        newdelta.next=nil;
  932. X    return 0;
  933. X}
  934. X
  935. X    static int
  936. addsyms(num)
  937. X    char const *num;
  938. X{
  939. X    register struct Symrev *p;
  940. X
  941. X    for (p = assoclst;  p;  p = p->nextsym)
  942. X        if (!addsymbol(num, p->ssymbol, p->override))
  943. X            return false;
  944. X    return true;
  945. X}
  946. X
  947. X
  948. X    static void
  949. incnum(onum,nnum)
  950. X    char const *onum;
  951. X    struct buf *nnum;
  952. X/* Increment the last field of revision number onum by one and
  953. X * place the result into nnum.
  954. X */
  955. X{
  956. X    register char *tp, *np;
  957. X    register size_t l;
  958. X
  959. X    l = strlen(onum);
  960. X    bufalloc(nnum, l+2);
  961. X    np = tp = nnum->string;
  962. X    VOID strcpy(np, onum);
  963. X    for (tp = np + l;  np != tp;  )
  964. X        if (isdigit(*--tp)) {
  965. X            if (*tp != '9') {
  966. X                ++*tp;
  967. X                return;
  968. X            }
  969. X            *tp = '0';
  970. X        } else {
  971. X            tp++;
  972. X            break;
  973. X        }
  974. X    /* We changed 999 to 000; now change it to 1000.  */
  975. X    *tp = '1';
  976. X    tp = np + l;
  977. X    *tp++ = '0';
  978. X    *tp = 0;
  979. X}
  980. X
  981. X
  982. X
  983. X    static int
  984. removelock(delta)
  985. struct hshentry * delta;
  986. X/* function: Finds the lock held by caller on delta,
  987. X * removes it, and returns nonzero if successful.
  988. X * Print an error message and return -1 if there is no such lock.
  989. X * An exception is if !StrictLocks, and caller is the owner of
  990. X * the RCS file. If caller does not have a lock in this case,
  991. X * return 0; return 1 if a lock is actually removed.
  992. X */
  993. X{
  994. X    register struct lock *next, **trail;
  995. X    char const *num;
  996. X
  997. X        num=delta->num;
  998. X    for (trail = &Locks;  (next = *trail);  trail = &next->nextlock)
  999. X        if (next->delta == delta)
  1000. X        if (strcmp(getcaller(), next->login) == 0) {
  1001. X            /* We found a lock on delta by caller; delete it.  */
  1002. X            *trail = next->nextlock;
  1003. X            delta->lockedby = 0;
  1004. X            return 1;
  1005. X        } else {
  1006. X                    error("revision %s locked by %s",num,next->login);
  1007. X            return -1;
  1008. X                }
  1009. X    if (!StrictLocks && myself(RCSstat.st_uid))
  1010. X        return 0;
  1011. X    error("no lock set by %s for revision %s", getcaller(), num);
  1012. X    return -1;
  1013. X}
  1014. X
  1015. X
  1016. X
  1017. X    static char const *
  1018. getcurdate()
  1019. X/* Return a pointer to the current date.  */
  1020. X{
  1021. X    static char buffer[datesize]; /* date buffer */
  1022. X    time_t t;
  1023. X
  1024. X    if (!buffer[0]) {
  1025. X        t = time((time_t *)0);
  1026. X        if (t == -1)
  1027. X            faterror("time not available");
  1028. X        time2date(t, buffer);
  1029. X    }
  1030. X        return buffer;
  1031. X}
  1032. X
  1033. X    static int
  1034. X#if has_prototypes
  1035. fixwork(mode_t newworkmode, char const *mtime)
  1036. X  /* The `#if has_prototypes' is needed because mode_t might promote to int.  */
  1037. X#else
  1038. X  fixwork(newworkmode, mtime)
  1039. X    mode_t newworkmode;
  1040. X    char const *mtime;
  1041. X#endif
  1042. X{
  1043. X    int r;
  1044. X    return
  1045. X            1 < workstat.st_nlink
  1046. X            ||    newworkmode&S_IWUSR && !myself(workstat.st_uid)
  1047. X        ?   -1
  1048. X        :
  1049. X            workstat.st_mode != newworkmode
  1050. X            &&
  1051. X            (r =
  1052. X#                if has_fchmod
  1053. X                fchmod(Ifileno(workptr), newworkmode)
  1054. X#                else
  1055. X                chmod(workfilename, newworkmode)
  1056. X#                endif
  1057. X            ) != 0
  1058. X        ?   r
  1059. X        :
  1060. X        setfiledate(workfilename, mtime);
  1061. X}
  1062. X
  1063. X    static int
  1064. xpandfile(unexfile, dir, delta, exfilename)
  1065. X    RILE *unexfile;
  1066. X    char const *dir;
  1067. X    struct hshentry const *delta;
  1068. X    char const **exfilename;
  1069. X/*
  1070. X * Read unexfile and copy it to a
  1071. X * file in dir, performing keyword substitution with data from delta.
  1072. X * Return -1 if unsuccessful, 1 if expansion occurred, 0 otherwise.
  1073. X * If successful, stores the stream descriptor into *EXFILEP
  1074. X * and its name into *EXFILENAME.
  1075. X */
  1076. X{
  1077. X    char const *targetfname;
  1078. X    int e, r;
  1079. X
  1080. X    targetfname = makedirtemp(dir, 1);
  1081. X    if (!(exfile = fopen(targetfname, FOPEN_W_WORK))) {
  1082. X        eerror(targetfname);
  1083. X        error("can't expand working file");
  1084. X        return -1;
  1085. X        }
  1086. X    r = 0;
  1087. X    if (Expand == OLD_EXPAND)
  1088. X        fastcopy(unexfile,exfile);
  1089. X    else {
  1090. X        for (;;) {
  1091. X            e = expandline(unexfile,exfile,delta,false,(FILE*)nil);
  1092. X            if (e < 0)
  1093. X                break;
  1094. X            r |= e;
  1095. X            if (e <= 1)
  1096. X                break;
  1097. X        }
  1098. X    }
  1099. X    *exfilename = targetfname;
  1100. X    aflush(exfile);
  1101. X    return r & 1;
  1102. X}
  1103. X
  1104. X
  1105. X
  1106. X
  1107. X/* --------------------- G E T L O G M S G --------------------------------*/
  1108. X
  1109. X
  1110. X    static struct cbuf
  1111. getlogmsg()
  1112. X/* Obtain and yield a log message.
  1113. X * If a log message is given with -m, yield that message.
  1114. X * If this is the initial revision, yield a standard log message.
  1115. X * Otherwise, reads a character string from the terminal.
  1116. X * Stops after reading EOF or a single '.' on a
  1117. X * line. getlogmsg prompts the first time it is called for the
  1118. X * log message; during all later calls it asks whether the previous
  1119. X * log message can be reused.
  1120. X */
  1121. X{
  1122. X    static char const
  1123. X        emptych[] = EMPTYLOG,
  1124. X        initialch[] = "Initial revision";
  1125. X    static struct cbuf const
  1126. X        emptylog = { emptych, sizeof(emptych)-sizeof(char) },
  1127. X        initiallog = { initialch, sizeof(initialch)-sizeof(char) };
  1128. X    static struct buf logbuf;
  1129. X    static struct cbuf logmsg;
  1130. X
  1131. X    register char *tp;
  1132. X    register size_t i;
  1133. X    char const *caller;
  1134. X
  1135. X    if (msg.size) return msg;
  1136. X
  1137. X    if (keepflag) {
  1138. X        /* generate std. log message */
  1139. X        caller = getcaller();
  1140. X        i = sizeof(ciklog)+strlen(caller)+3;
  1141. X        bufalloc(&logbuf, i+datesize);
  1142. X        tp = logbuf.string;
  1143. X        VOID sprintf(tp, "%s%s at ", ciklog, caller);
  1144. X        VOID date2str(getcurdate(), tp+i);
  1145. X        logmsg.string = tp;
  1146. X        logmsg.size = strlen(tp);
  1147. X        return logmsg;
  1148. X    }
  1149. X
  1150. X    if (!targetdelta && (
  1151. X        cmpnum(newdelnum.string,"1.1")==0 ||
  1152. X        cmpnum(newdelnum.string,"1.0")==0
  1153. X    ))
  1154. X        return initiallog;
  1155. X
  1156. X    if (logmsg.size) {
  1157. X                /*previous log available*/
  1158. X        if (yesorno(true, "reuse log message of previous file? [yn](y): "))
  1159. X        return logmsg;
  1160. X        }
  1161. X
  1162. X        /* now read string from stdin */
  1163. X    logmsg = getsstdin("m", "log message", "", &logbuf);
  1164. X
  1165. X        /* now check whether the log message is not empty */
  1166. X    if (logmsg.size)
  1167. X        return logmsg;
  1168. X    return emptylog;
  1169. X}
  1170. X
  1171. X/*  Make a linked list of Symbolic names  */
  1172. X
  1173. X        static void
  1174. addassoclst(flag, sp)
  1175. int  flag;
  1176. char * sp;
  1177. X{
  1178. X        struct Symrev *pt;
  1179. X    
  1180. X    pt = talloc(struct Symrev);
  1181. X    pt->ssymbol = sp;
  1182. X    pt->override = flag;
  1183. X    pt->nextsym = nil;
  1184. X    if (lastassoc)
  1185. X            lastassoc->nextsym = pt;
  1186. X    else
  1187. X            assoclst = pt;
  1188. X    lastassoc = pt;
  1189. X    return;
  1190. X}
  1191. END_OF_FILE
  1192. if test 33764 -ne `wc -c <'src/ci.c'`; then
  1193.     echo shar: \"'src/ci.c'\" unpacked with wrong size!
  1194. fi
  1195. # end of 'src/ci.c'
  1196. fi
  1197. if test -f 'src/conf.sh' -a "${1}" != "-c" ; then 
  1198.   echo shar: Will not clobber existing file \"'src/conf.sh'\"
  1199. else
  1200. echo shar: Extracting \"'src/conf.sh'\" \(35856 characters\)
  1201. sed "s/^X//" >'src/conf.sh' <<'END_OF_FILE'
  1202. X#!/bin/sh
  1203. X# Output RCS compile-time configuration.
  1204. Id='$Id: conf.sh,v 5.14 1991/11/20 18:21:10 eggert Exp $'
  1205. X#    Copyright 1990, 1991 by Paul Eggert
  1206. X#    Distributed under license by the Free Software Foundation, Inc.
  1207. X
  1208. X# This file is part of RCS.
  1209. X#
  1210. X# RCS is free software; you can redistribute it and/or modify
  1211. X# it under the terms of the GNU General Public License as published by
  1212. X# the Free Software Foundation; either version 2, or (at your option)
  1213. X# any later version.
  1214. X#
  1215. X# RCS is distributed in the hope that it will be useful,
  1216. X# but WITHOUT ANY WARRANTY; without even the implied warranty of
  1217. X# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  1218. X# GNU General Public License for more details.
  1219. X#
  1220. X# You should have received a copy of the GNU General Public License
  1221. X# along with RCS; see the file COPYING.  If not, write to
  1222. X# the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  1223. X#
  1224. X# Report problems and direct all questions to:
  1225. X#
  1226. X#     rcs-bugs@cs.purdue.edu
  1227. X
  1228. X
  1229. X# Standard output should already be directed to "a.h";
  1230. X# later parts of this procedure need it.
  1231. X# Standard error can be ignored if a.h is OK,
  1232. X# and can be inspected for clues otherwise.
  1233. X
  1234. X# The Makefile overrides the following defaults.
  1235. X: ${CC=cc}
  1236. X: ${CFLAGS=-O}
  1237. X: ${COMPAT2=0}
  1238. X: ${DIFF3=${RCSPREFIX}diff3}
  1239. X: ${DIFF3_BIN=1}
  1240. X: ${DIFF=${RCSPREFIX}diff}
  1241. X: ${DIFF_FLAGS=-an}
  1242. X: ${DIFF_L=1}
  1243. X: ${DIFF_SUCCESS=0} ${DIFF_FAILURE=1} ${DIFF_TROUBLE=2}
  1244. X: ${ED=/bin/ed}
  1245. X: ${RCSPREFIX=/usr/local/bin/}
  1246. X: ${SENDMAIL='"/usr/lib/sendmail"'}
  1247. X# : ${LDFLAGS=} ${LDLIBS=} tickles old shell bug
  1248. X
  1249. C="$CC $CFLAGS"
  1250. CL="$CC $CFLAGS $LDFLAGS"
  1251. L=$LDLIBS
  1252. RM='rm -f a.out'
  1253. X
  1254. cat <<EOF
  1255. X/* RCS compile-time configuration */
  1256. X
  1257. X    /* $Id */
  1258. X
  1259. X/*
  1260. X * This file is generated automatically.
  1261. X * If you edit it by hand your changes may be lost.
  1262. X * Instead, please try to fix conf.sh,
  1263. X * and send your fixes to rcs-bugs@cs.purdue.edu.
  1264. X */
  1265. X
  1266. XEOF
  1267. X
  1268. X: exitmain
  1269. cat >a.c <<EOF
  1270. X#include "a.h"
  1271. int main(argc,argv) int argc; char **argv; { return argc-1; }
  1272. XEOF
  1273. X$RM && $CL a.c $L >&2 || exit
  1274. e='exit(n), 3 /* lint fodder */'
  1275. if ./a.out -
  1276. then :
  1277. elif ./a.out
  1278. then e=n
  1279. fi
  1280. echo "#define exitmain(n) return $e /* how to exit from main() */"
  1281. X
  1282. X: _POSIX_SOURCE
  1283. cat >a.c <<'EOF'
  1284. X#include "a.h"
  1285. X#include <stdio.h>
  1286. int main() { exitmain(fileno(stdout) < 0); }
  1287. XEOF
  1288. a='/* ' z='*/ '
  1289. X$RM || exit
  1290. if ($CL a.c $L && ./a.out) >&2
  1291. then :
  1292. elif $RM || exit; ($CL -D_POSIX_SOURCE a.c $L && ./a.out) >&2
  1293. then a= z=
  1294. fi
  1295. cat <<EOF
  1296. X$a#define _POSIX_SOURCE $z/* Define this if Posix + strict Standard C.  */
  1297. X
  1298. X#include <errno.h>
  1299. X#include <stdio.h>
  1300. X#include <time.h>
  1301. XEOF
  1302. X
  1303. cat <<'EOF'
  1304. X
  1305. X/* Comment out #include lines below that do not work.  */
  1306. XEOF
  1307. X
  1308. X# Run `$CS a.c $LS' instead of `$CL a.c $L' for compile-time checking only.
  1309. X# This speeds up the configuration process.
  1310. if $C -S a.c >&2
  1311. then CS="$C -S" LS=    # Generate assembly language output.
  1312. elif $C -c a.c >&2
  1313. then CS="$C -c" LS=    # Generate object code.
  1314. else CS=$CL LS=$L    # Generate an executable.
  1315. fi
  1316. X
  1317. X# standard include files
  1318. X# sys/types.h and sys/stat.h must come first because others depend on them.
  1319. has_signal=1
  1320. for h in \
  1321. X    sys/types sys/stat \
  1322. X    dirent fcntl limits pwd signal stdlib string sys/mman sys/wait unistd utime vfork
  1323. do
  1324. X    i="#include <$h.h>"
  1325. X    : $i
  1326. X    cat >a.c <<EOF
  1327. X#include "a.h"
  1328. X$i
  1329. int main(){ exitmain(0); }
  1330. XEOF
  1331. X    $RM || exit
  1332. X    ($CL a.c $L && ./a.out) >&2 || {
  1333. X        case $h in
  1334. X        string)
  1335. X            i='#include <strings.h>';;
  1336. X        *)
  1337. X            i="/* $i */"
  1338. X        esac
  1339. X        case $h in
  1340. X        signal) has_signal=0
  1341. X        esac
  1342. X    }
  1343. X    echo "$i"
  1344. done
  1345. X
  1346. cat <<'EOF'
  1347. X
  1348. X/* Define the following symbols to be 1 or 0.  */
  1349. XEOF
  1350. X
  1351. X# has_sys_*_h
  1352. for H in dir param
  1353. do
  1354. X    : has_sys_${H}_h
  1355. X    cat >a.c <<EOF
  1356. X#include "a.h"
  1357. X#include <sys/$H.h>
  1358. int main() { exitmain(0); }
  1359. XEOF
  1360. X    $RM || exit
  1361. X    if ($CL a.c $L && ./a.out) >&2
  1362. X    then h=1
  1363. X    else h=0
  1364. X    fi
  1365. X    echo "#define has_sys_${H}_h $h /* Does #include <sys/$H.h> work?  */"
  1366. done
  1367. X
  1368. X
  1369. X# We must do NAME_MAX and has_readlink next, because they might generate
  1370. X# #include directives that affect later definitions.
  1371. X
  1372. X: NAME_MAX
  1373. cat >a.c <<'EOF'
  1374. X#include "a.h"
  1375. char b[NAME_MAX + 2];
  1376. main()
  1377. X{
  1378. X#if !defined(NAME_MAX)
  1379. X    exitmain(1);
  1380. X#else
  1381. X    int i;
  1382. X    b[0] = 'a'; b[1] = '.';
  1383. X    for (i = 2;  i < NAME_MAX;  i++)
  1384. X        b[i] = 'a';
  1385. X    b[i] = 'b';
  1386. X    exitmain(creat(b, 0) < 0);
  1387. X#endif
  1388. X}
  1389. XEOF
  1390. X$RM a.*ab || exit
  1391. if $CL a.c $L >&2 && ./a.out && test -f a.*ab
  1392. then a= z=
  1393. else a='/* ' z='*/ '
  1394. fi
  1395. rm -f a.*ab || exit
  1396. X
  1397. X: has_readlink
  1398. cat >a.c <<'EOF'
  1399. X#include "a.h"
  1400. char b[7];
  1401. int main()
  1402. X{
  1403. X    exitmain(readlink("a.sym2",b,7) != 6  ||  strcmp(b, "a.sym1") != 0);
  1404. X}
  1405. XEOF
  1406. X$RM a.sym* || exit
  1407. if (ln -s a.sym1 a.sym2 && $CL a.c $L && ./a.out) >&2
  1408. then h=1
  1409. else h=0
  1410. fi
  1411. cat <<EOF
  1412. X#define has_readlink $h /* Does readlink() work?  */
  1413. X
  1414. X$a#undef NAME_MAX $z/* Uncomment this if NAME_MAX is broken.  */
  1415. X
  1416. X#if !defined(NAME_MAX) && !defined(_POSIX_NAME_MAX)
  1417. X#    if has_sys_dir_h
  1418. X#        include <sys/dir.h>
  1419. X#    endif
  1420. X#    ifndef NAME_MAX
  1421. X#        ifndef MAXNAMLEN
  1422. X#            define MAXNAMLEN 14
  1423. X#        endif
  1424. X#        define NAME_MAX MAXNAMLEN
  1425. X#    endif
  1426. X#endif
  1427. X#if !defined(PATH_MAX) && !defined(_POSIX_PATH_MAX)
  1428. X#    if has_sys_param_h
  1429. X#        include <sys/param.h>
  1430. X#        define included_sys_param_h 1
  1431. X#    endif
  1432. X#    ifndef PATH_MAX
  1433. X#        ifndef MAXPATHLEN
  1434. X#            define MAXPATHLEN 1024
  1435. X#        endif
  1436. X#        define PATH_MAX (MAXPATHLEN-1)
  1437. X#    endif
  1438. X#endif
  1439. X#if has_readlink && !defined(MAXSYMLINKS)
  1440. X#    if has_sys_param_h && !included_sys_param_h
  1441. X#        include <sys/param.h>
  1442. X#    endif
  1443. X#    ifndef MAXSYMLINKS
  1444. X#        define MAXSYMLINKS 20 /* BSD; not standard yet */
  1445. X#    endif
  1446. X#endif
  1447. XEOF
  1448. X
  1449. cat <<'EOF'
  1450. X
  1451. X/* Comment out the keyword definitions below if the keywords work.  */
  1452. XEOF
  1453. X
  1454. X: const, volatile
  1455. for i in const volatile
  1456. do
  1457. X    cat >a.c <<EOF
  1458. X#    include "a.h"
  1459. X    enum Boolean { false, true };
  1460. X    static enum Boolean $i zero;
  1461. X    static enum Boolean $i * $i azero = &zero;
  1462. X    static enum Boolean $i * $i * $i aazero = &azero;
  1463. X    int main() { exitmain(!!**aazero); }
  1464. XEOF
  1465. X    a= z=
  1466. X    if $CS a.c $LS >&2
  1467. X    then
  1468. X        cat >a.c <<EOF
  1469. X            typedef unsigned char $i *Iptr_type;
  1470. X            struct { Iptr_type lim; } s, *f = &s;
  1471. X            int main() {
  1472. X                Iptr_type lim;
  1473. X                lim = f->lim;
  1474. X                return !!lim;
  1475. X            }
  1476. XEOF
  1477. X        if $CS a.c $LS >&2
  1478. X        then a='/* ' z=' */'
  1479. X        fi
  1480. X    fi
  1481. X    echo "$a#define $i$z"
  1482. done
  1483. X
  1484. X# *_t
  1485. cat <<'EOF'
  1486. X
  1487. X/* Comment out the typedefs below if the types are already declared.  */
  1488. X/* Fix any uncommented typedefs that are wrong.  */
  1489. XEOF
  1490. cat >a.c <<'EOF'
  1491. X#include "a.h"
  1492. t x;
  1493. int main() { exitmain(0); }
  1494. XEOF
  1495. for t in mode_t pid_t sig_atomic_t size_t ssize_t time_t uid_t
  1496. do
  1497. X    : $t
  1498. X    case $t in
  1499. X    size_t) i=unsigned;;
  1500. X    time_t) i=long;;
  1501. X    *) i=int;;
  1502. X    esac
  1503. X    if $CS -Dt=$t a.c $LS >&2
  1504. X    then a='/* ' z=' */'
  1505. X    else a= z=
  1506. X    fi
  1507. X    echo "${a}typedef $i $t;$z"
  1508. done
  1509. X
  1510. X: has_prototypes, has_stdarg, has_varargs, va_start_args
  1511. cat >a.ha <<'EOF'
  1512. X#if has_prototypes
  1513. X#    define P(params) params
  1514. X#else
  1515. X#    define P(params) ()
  1516. X#endif
  1517. X#if has_stdarg
  1518. X#    include <stdarg.h>
  1519. X#else
  1520. X#    if has_varargs
  1521. X#        include <varargs.h>
  1522. X#    else
  1523. X        typedef char *va_list;
  1524. X#        define va_dcl int va_alist;
  1525. X#        define va_start(ap) ((ap) = (va_list)&va_alist)
  1526. X#        define va_arg(ap,t) (((t*) ((ap)+=sizeof(t)))  [-1])
  1527. X#        define va_end(ap)
  1528. X#    endif
  1529. X#endif
  1530. X#if va_start_args == 2
  1531. X#    define vararg_start va_start
  1532. X#else
  1533. X#    define vararg_start(ap,p) va_start(ap)
  1534. X#endif
  1535. XEOF
  1536. cat >a.c <<'EOF'
  1537. X#include "a.h"
  1538. X#include "a.ha"
  1539. X#if has_prototypes
  1540. char *f(char **p, ...)
  1541. X#else
  1542. char *f(p, va_alist) char **p; va_dcl
  1543. X#endif
  1544. X{
  1545. X    char *s;
  1546. X    va_list v;
  1547. X    vararg_start(v,p);
  1548. X    s = p[va_arg(v,int)];
  1549. X    va_end(v);
  1550. X    return s;
  1551. X}
  1552. int main P((int, char**));
  1553. int main(argc, argv) int argc; char **argv; {
  1554. X    exitmain(f(argv,0) != argv[0]  ||  f(argv,1) != argv[1]);
  1555. X}
  1556. XEOF
  1557. for has_prototypes in 1 0
  1558. do
  1559. X    for has_stdarg in 1 v 0
  1560. X    do
  1561. X        case $has_stdarg in
  1562. X        v) has_varargs=1 has_stdarg=0;;
  1563. X        *) has_varargs=0
  1564. X        esac
  1565. X        case $has_stdarg in
  1566. X        0) as='1 2';;
  1567. X        1) as='2 1'
  1568. X        esac
  1569. X        for va_start_args in $as
  1570. X        do
  1571. X            $RM || exit
  1572. X            $CL \
  1573. X                -Dhas_prototypes=$has_prototypes \
  1574. X                -Dhas_stdarg=$has_stdarg \
  1575. X                -Dhas_varargs=$has_varargs \
  1576. X                -Dva_start_args=$va_start_args \
  1577. X                a.c $L >&2 && ./a.out && break
  1578. X        done && break
  1579. X    done && break
  1580. done || {
  1581. X    echo >&2 "cannot deduce has_prototypes, has_stdarg, va_start_args"
  1582. X    exit 1
  1583. X}
  1584. cat - a.ha <<EOF
  1585. X
  1586. X/* Define the following symbols to be 1 or 0.  */
  1587. X#define has_prototypes $has_prototypes /* Do function prototypes work?  */
  1588. X#define has_stdarg $has_stdarg /* Does <stdarg.h> work?  */
  1589. X#define has_varargs $has_varargs /* Does <varargs.h> work?  */
  1590. X#define va_start_args $va_start_args /* How many args does va_start() take?  */
  1591. XEOF
  1592. X
  1593. X: text_equals_binary_stdio, FOPEN_...
  1594. cat >a.c <<'EOF'
  1595. X#include "a.h"
  1596. X    int
  1597. copyto(filename, mode)
  1598. X    char const *filename, *mode;
  1599. X{
  1600. X    int c;
  1601. X    FILE *f, *g;
  1602. X    if (!(f = fopen("a.out", "rb")) || !(g = fopen(filename, mode)))
  1603. X        return 1;
  1604. X    while (c=getc(f), !feof(f))
  1605. X        if (ferror(f)  ||  putc(c,g)<0 && ferror(g))
  1606. X            return 1;
  1607. X    return fclose(f)!=0 || fclose(g)!=0;
  1608. X}
  1609. int main() { exitmain(copyto("a.d", "w+b") || copyto("a.e", "w+")); }
  1610. XEOF
  1611. e=1
  1612. X$RM a.d a.e || exit
  1613. X$CL a.c $L >&2 && ./a.out && cmp a.out a.d && {
  1614. X    cmp a.out a.e || e=0
  1615. X}
  1616. cat <<EOF
  1617. X
  1618. X#define text_equals_binary_stdio $e /* Does stdio treat text like binary?  */
  1619. X#define text_work_stdio 0 /* Text i/o for working file, binary for RCS file?  */
  1620. X#if text_equals_binary_stdio
  1621. X    /* Text and binary i/o behave the same, or binary i/o does not work.  */
  1622. X#    define FOPEN_R "r"
  1623. X#    define FOPEN_W "w"
  1624. X#    define FOPEN_WPLUS "w+"
  1625. X#else
  1626. X    /* Text and binary i/o behave differently.  */
  1627. X    /* This is incompatible with Posix and Unix.  */
  1628. X#    define FOPEN_R "rb"
  1629. X#    define FOPEN_W "wb"
  1630. X#    define FOPEN_WPLUS "w+b"
  1631. X#endif
  1632. X#if text_work_stdio
  1633. X#    define FOPEN_R_WORK "r"
  1634. X#    define FOPEN_W_WORK "w"
  1635. X#    define FOPEN_WPLUS_WORK "w+"
  1636. X#else
  1637. X#    define FOPEN_R_WORK FOPEN_R
  1638. X#    define FOPEN_W_WORK FOPEN_W
  1639. X#    define FOPEN_WPLUS_WORK FOPEN_WPLUS
  1640. X#endif
  1641. X
  1642. X/* Define or comment out the following symbols as needed.  */
  1643. XEOF
  1644. X
  1645. X: bad_fopen_wplus
  1646. cat >a.c <<'EOF'
  1647. X#include "a.h"
  1648. int main() { exitmain(!fopen("a.d",FOPEN_WPLUS)); }
  1649. XEOF
  1650. X$RM || exit
  1651. if echo nonempty >a.d && $CL a.c $L >&2 && ./a.out && test ! -s a.d
  1652. then b=0
  1653. else b=1
  1654. fi
  1655. echo "#define bad_fopen_wplus $b /* Does fopen(f,FOPEN_WPLUS) fail to truncate f?  */"
  1656. X
  1657. X: getlogin_is_secure
  1658. echo "#define getlogin_is_secure 0 /* Is getlogin() secure?  Usually it's not.  */"
  1659. X
  1660. X: has_dirent
  1661. cat >a.c <<'EOF'
  1662. X#include "a.h"
  1663. int main() {
  1664. X    DIR *d = opendir(".");
  1665. X    struct dirent *e;
  1666. X    while ((e = readdir(d)))
  1667. X        if (strcmp(e->d_name, "a.c") == 0  &&  closedir(d) == 0)
  1668. X            exitmain(0);
  1669. X    exitmain(1);
  1670. X}
  1671. XEOF
  1672. X$RM || exit
  1673. if $CL a.c $L >&2 && ./a.out
  1674. then h=1
  1675. else h=0
  1676. fi
  1677. echo "#define has_dirent $h /* Do opendir(), readdir(), closedir() work?  */"
  1678. X
  1679. X: has_fchmod
  1680. cat >a.c <<'EOF'
  1681. X#include "a.h"
  1682. int main() { exitmain(fchmod(fileno(stdin),0) != 0); }
  1683. XEOF
  1684. X$RM || exit
  1685. if $CL a.c $L >&2 && ./a.out <a.c && test ! -r a.c
  1686. then h=1
  1687. else h=0
  1688. fi
  1689. echo "#define has_fchmod $h /* Does fchmod() work?  */"
  1690. rm -f a.c || exit
  1691. X
  1692. X: has_fputs
  1693. cat >a.c <<'EOF'
  1694. X#include "a.h"
  1695. int main() { exitmain(fputs("Hello\"\nworld", stdout) != 12); }
  1696. XEOF
  1697. Hello='Hello"
  1698. world'
  1699. X$RM || exit
  1700. if $CL a.c $L >&2 && ./a.out >/dev/null && x=`./a.out` && test " $x" = " $Hello"
  1701. then h=1
  1702. else h=0
  1703. fi
  1704. echo "#define has_fputs $h /* Does fputs() work?  */"
  1705. X
  1706. X: has_ftruncate
  1707. cat >a.c <<'EOF'
  1708. X#include "a.h"
  1709. int main(argc, argv) int argc; char **argv; {
  1710. X    int f = creat(argv[1], 0);
  1711. X    if (f<0 || write(f,"abc",3)!=3 || ftruncate(f,(off_t)0)!=0 || close(f)!=0)
  1712. X            exitmain(1);
  1713. X    exitmain(0);
  1714. X}
  1715. XEOF
  1716. X$RM || exit
  1717. if $CL a.c $L >&2
  1718. then
  1719. X    h=1
  1720. X    # Check out /tmp too; it's buggy on some hosts.
  1721. X    for d in . /tmp
  1722. X    do
  1723. X        if test -d $d
  1724. X        then
  1725. X            f=$d/a.d
  1726. X            rm -f $f || exit
  1727. X            ./a.out $f && test ! -s $f && test -f $f  ||  h=0
  1728. X            rm -f $f || exit
  1729. X        fi
  1730. X    done
  1731. else h=0
  1732. fi
  1733. echo "#define has_ftruncate $h /* Does ftruncate() work?  */"
  1734. X
  1735. X: has_getuid
  1736. cat >a.c <<'EOF'
  1737. X#include "a.h"
  1738. X#ifndef getuid
  1739. X    uid_t getuid();
  1740. X#endif
  1741. int main() { exitmain(getuid()!=getuid()); }
  1742. XEOF
  1743. X$RM || exit
  1744. if ($CL a.c $L && ./a.out) >&2
  1745. then has_getuid=1
  1746. else has_getuid=0
  1747. fi
  1748. echo "#define has_getuid $has_getuid /* Does getuid() work?  */"
  1749. X
  1750. X: has_getpwuid
  1751. case $has_getuid in
  1752. X0)
  1753. X    a='/* ' z='*/ ' h=?;;
  1754. X*)
  1755. X    a= z=
  1756. X    cat >a.c <<'EOF'
  1757. X#include "a.h"
  1758. int main() { exitmain(!getpwuid(0)); }
  1759. XEOF
  1760. X    $RM || exit
  1761. X    if ($CL a.c $L && ./a.out) >&2
  1762. X    then h=1
  1763. X    else h=0
  1764. X    fi
  1765. esac
  1766. echo "$a#define has_getpwuid $h $z/* Does getpwuid() work?  */"
  1767. X
  1768. X: has_link
  1769. cat >a.c <<'EOF'
  1770. X#include "a.h"
  1771. int main() { exitmain(link("a.c","a.d") != 0); }
  1772. XEOF
  1773. X$RM a.d || exit
  1774. if ($CL a.c $L && ./a.out && cmp a.c a.d) >&2
  1775. then h=1
  1776. else h=0
  1777. fi
  1778. rm -f a.d || exit
  1779. echo "#define has_link $h /* Does link() work?  */"
  1780. X
  1781. X: has_memcmp
  1782. cat >a.c <<'EOF'
  1783. X#include "a.h"
  1784. int main() { exitmain(memcmp("beautiful","beautiful",10) != 0); }
  1785. XEOF
  1786. X$RM || exit
  1787. if ($CL a.c $L && ./a.out) >&2
  1788. then h=1
  1789. else h=0
  1790. fi
  1791. echo "#define has_memcmp $h /* Does memcmp() work?  */"
  1792. X
  1793. X: has_memcpy
  1794. cat >a.c <<'EOF'
  1795. X#include "a.h"
  1796. char a[3];
  1797. int main() {
  1798. X    memcpy(a,"xy",3);
  1799. X    exitmain(strcmp(a,"xy")!=0);
  1800. X}
  1801. XEOF
  1802. X$RM || exit
  1803. if ($CL a.c $L && ./a.out) >&2
  1804. then h=1
  1805. else h=0
  1806. fi
  1807. echo "#define has_memcpy $h /* Does memcpy() work?  */"
  1808. X
  1809. X: has_memmove
  1810. cat >a.c <<'EOF'
  1811. X#include "a.h"
  1812. char a[4];
  1813. int main() {
  1814. X    strcpy(a, "xy");
  1815. X    memmove(a+1, a, 3);
  1816. X    exitmain(strcmp(a,"xxy")!=0);
  1817. X}
  1818. XEOF
  1819. X$RM || exit
  1820. if ($CL a.c $L && ./a.out) >&2
  1821. then h=1
  1822. else h=0
  1823. fi
  1824. echo "#define has_memmove $h /* Does memmove() work?  */"
  1825. X
  1826. X: has_mmap, has_madvise
  1827. cat >a.c <<'EOF'
  1828. X#define CHAR1 '#' /* the first character in this file */
  1829. X#include "a.h"
  1830. X#ifndef mmap
  1831. X    caddr_t mmap();
  1832. X#endif
  1833. caddr_t a;
  1834. struct stat b;
  1835. X#ifndef MADVISE_OK
  1836. X#    define MADVISE_OK (madvise(a,b.st_size,MADV_SEQUENTIAL)==0 && madvise(a,b.st_size,MADV_NORMAL)==0)
  1837. X#endif
  1838. int main()
  1839. X{
  1840. X    if (fstat(fileno(stdin), &b) != 0)
  1841. X        exitmain(1);
  1842. X    a = mmap(
  1843. X        (caddr_t)0, b.st_size, PROT_READ, MAP_SHARED,
  1844. X        fileno(stdin), (off_t)0
  1845. X    );
  1846. X    exitmain(
  1847. X        a == (caddr_t)-1  ||
  1848. X        !MADVISE_OK ||
  1849. X        *a != CHAR1  ||
  1850. X        munmap(a, b.st_size)  !=  0
  1851. X    );
  1852. X}
  1853. XEOF
  1854. a=0 has_mmap=0
  1855. X$RM || exit
  1856. if ($CL -DMADVISE_OK=1 a.c $L && ./a.out <a.c) >&2
  1857. then
  1858. X    has_mmap=1
  1859. X    $RM || exit
  1860. X    ($CL a.c $L && ./a.out <a.c) >&2 && a=1
  1861. fi
  1862. echo "#define has_madvise $a /* Does madvise() work?  */"
  1863. echo "#define has_mmap $has_mmap /* Does mmap() work on regular files?  */"
  1864. X
  1865. X: has_rename, bad_a_rename, bad_b_rename
  1866. cat >a.c <<'EOF'
  1867. X#include "a.h"
  1868. int main() { exitmain(rename("a.a","a.b") != 0); }
  1869. XEOF
  1870. echo a >a.a && $RM a.b || exit
  1871. if ($CL a.c $L && ./a.out && test -f a.b) >&2
  1872. then
  1873. X    h=1
  1874. X    rm -f a.a a.b &&
  1875. X    echo a >a.a && chmod -w a.a || exit
  1876. X    if ./a.out && test ! -f a.a && test -f a.b
  1877. X    then a=0
  1878. X    else a=1
  1879. X    fi
  1880. X    rm -f a.a a.b &&
  1881. X    echo a >a.a && echo b >a.b && chmod -w a.b || exit
  1882. X    if ./a.out && test ! -f a.a && test -f a.b
  1883. X    then b=0
  1884. X    else b=1
  1885. X    fi
  1886. X    rm -f a.a a.b || exit
  1887. else h=0 a=0 b=0
  1888. fi
  1889. echo "#define has_rename $h /* Does rename() work?  */"
  1890. echo "#define bad_a_rename $a /* Does rename(A,B) fail if A is unwritable?  */"
  1891. echo "#define bad_b_rename $b /* Does rename(A,B) fail if B is unwritable?  */"
  1892. X
  1893. X: void, VOID
  1894. cat >a.c <<'EOF'
  1895. X#include "a.h"
  1896. void f() {}
  1897. int main() {f(); exitmain(0);}
  1898. XEOF
  1899. if $CS a.c $LS >&2
  1900. then
  1901. X    v='(void) '
  1902. else
  1903. X    v=
  1904. X    echo 'typedef int void;'
  1905. fi
  1906. echo "#define VOID $v/* 'VOID e;' discards the value of an expression 'e'.  */"
  1907. X
  1908. X: has_seteuid
  1909. case $has_getuid in
  1910. X0)
  1911. X    a='/* ' z='*/ ' has_seteuid=?;;
  1912. X*)
  1913. X    a= z=
  1914. X    cat >a.c <<'EOF'
  1915. X#include "a.h"
  1916. X#ifndef geteuid
  1917. X    uid_t geteuid();
  1918. X#endif
  1919. int main() {
  1920. X/* Guess, don't test.  Ugh.  Testing would require running conf.sh setuid.  */
  1921. X/* seteuid() isn't standardized yet, so the guess below may well be wrong.  */
  1922. X#if !_POSIX_VERSION || _POSIX_VERSION<=199009L&&!defined(sgi)&&!defined(__sgi__)&&!defined(sun)&&!defined(__sun__)
  1923. X    exitmain(1);
  1924. X#else
  1925. X    exitmain(seteuid(geteuid()) != 0);
  1926. X#endif
  1927. X}
  1928. XEOF
  1929. X    $RM || exit
  1930. X    if ($CL a.c $L && ./a.out) >&2
  1931. X    then has_seteuid=1
  1932. X    else has_seteuid=0
  1933. X    fi
  1934. esac
  1935. echo "$a#define has_seteuid $has_seteuid $z/* Does seteuid() work?  See README.  */"
  1936. X
  1937. X: has_setuid
  1938. h=$has_seteuid
  1939. case $h in
  1940. X0)
  1941. X    cat >a.c <<'EOF'
  1942. X#include "a.h"
  1943. X#ifndef getuid
  1944. X    uid_t getuid();
  1945. X#endif
  1946. int main() { exitmain(setuid(getuid()) != 0); }
  1947. XEOF
  1948. X    $RM || exit
  1949. X    ($CL a.c $L && ./a.out) >&2 && h=1
  1950. esac
  1951. echo "$a#define has_setuid $h $z/* Does setuid() exist?  */"
  1952. X
  1953. X: has_signal, signal_args, signal_type, sig_zaps_handler
  1954. cat >a.c <<'EOF'
  1955. X#include "a.h"
  1956. X#ifndef getpid
  1957. X    pid_t getpid();
  1958. X#endif
  1959. X#if !defined(signal) && declare_signal
  1960. X    signal_type (*signal P((int,signal_type(*)signal_args)))signal_args;
  1961. X#endif
  1962. signal_type nothing(i) int i; {}
  1963. int main(argc, argv) int argc; char **argv;
  1964. X{
  1965. X    signal(SIGINT, nothing);
  1966. X    while (--argc)
  1967. X        kill(getpid(), SIGINT);
  1968. X    exitmain(0);
  1969. X}
  1970. XEOF
  1971. for declare_signal in 1 0
  1972. do
  1973. X    for signal_type in void int
  1974. X    do
  1975. X        for signal_args in 'P((int))' '()'
  1976. X        do
  1977. X            $RM || exit
  1978. X            ($CL \
  1979. X                -Ddeclare_signal=$declare_signal \
  1980. X                -Dsignal_args="$signal_args" \
  1981. X                -Dsignal_type=$signal_type \
  1982. X                    a.c $L && ./a.out 1) >&2 && break
  1983. X        done && break
  1984. X    done && break
  1985. done || {
  1986. X    echo >&2 "cannot deduce signal_args, signal_type"
  1987. X    exit 1
  1988. X}
  1989. if ./a.out 1 2 >&2
  1990. then z=0
  1991. else z=1
  1992. fi
  1993. cat <<EOF
  1994. X#define has_signal $has_signal /* Does signal() work?  */
  1995. X#define signal_args $signal_args /* arguments of signal handlers */
  1996. X#define signal_type $signal_type /* type returned by signal handlers */
  1997. X#define sig_zaps_handler $z /* Must a signal handler reinvoke signal()?  */
  1998. XEOF
  1999. X
  2000. X: has_sigaction
  2001. cat >a.c <<'EOF'
  2002. X#include "a.h"
  2003. X#ifndef getpid
  2004. X    pid_t getpid();
  2005. X#endif
  2006. static sig_atomic_t volatile gotsig;
  2007. static void getsig(i) int i; { gotsig = 1; }
  2008. int main(argc, argv) int argc; char **argv;
  2009. X{
  2010. X    struct sigaction s;
  2011. X    sigset_t t;
  2012. X    if (sigemptyset(&t) != 0  ||  sigaddset(&t, SIGINT) != 0)
  2013. X        exitmain(1);
  2014. X    if (sigaction(SIGINT, (struct sigaction const*)0, &s) != 0)
  2015. X        exitmain(1);
  2016. X    s.sa_handler = getsig;
  2017. X    s.sa_mask = t;
  2018. X    if (sigaction(SIGINT, &s, (struct sigaction*)0) != 0)
  2019. X        exitmain(1);
  2020. X    kill(getpid(), SIGINT);
  2021. X    exitmain(gotsig != 1);
  2022. X}
  2023. XEOF
  2024. X$RM || exit
  2025. if ($CL a.c $L && ./a.out) >&2
  2026. then has_sigaction=1
  2027. else has_sigaction=0
  2028. fi
  2029. echo "#define has_sigaction $has_sigaction /* Does struct sigaction work?  */"
  2030. X
  2031. X: has_sigblock, sigmask
  2032. a='/* ' z='*/ '
  2033. b='/* ' y='*/ '
  2034. case $has_sigaction in
  2035. X1)
  2036. X    h=? n=?;;
  2037. X*)
  2038. X    a= z=
  2039. X    cat >a.c <<'EOF'
  2040. X#include "a.h"
  2041. X#include <signal.h>
  2042. X#if define_sigmask
  2043. X#    define sigmask(s) (1 << ((s)-1))
  2044. X#endif
  2045. int main()
  2046. X{
  2047. X    sigblock(sigmask(SIGHUP));
  2048. X    exitmain(kill(getpid(), SIGHUP) != 0);
  2049. X}
  2050. XEOF
  2051. X    if $RM || exit; ($CL a.c $L && ./a.out) >&2
  2052. X    then h=1
  2053. X    elif $RM || exit; ($CL -Ddefine_sigmask=1 a.c $L && ./a.out) >&2
  2054. X    then h=1 b= y=
  2055. X    else h=0
  2056. X    fi
  2057. esac
  2058. echo "$a#define has_sigblock $h $z/* Does sigblock() work?  */"
  2059. echo "$b#define sigmask(s) (1 << ((s)-1)) $y/* Yield mask for signal number.  */"
  2060. X
  2061. X: has_sys_siglist
  2062. cat >a.c <<'EOF'
  2063. X#include "a.h"
  2064. X#ifndef sys_siglist
  2065. X    extern char const *sys_siglist[];
  2066. X#endif
  2067. int main() { exitmain(!sys_siglist[1][0]); }
  2068. XEOF
  2069. X$RM || exit
  2070. if ($CL a.c $L && ./a.out) >&2
  2071. then h=1
  2072. else h=0
  2073. fi
  2074. echo "#define has_sys_siglist $h /* Does sys_siglist[] work?  */"
  2075. X
  2076. X: fread_type, Fread, Fwrite
  2077. cat >a.c <<'EOF'
  2078. X#define CHAR1 '#' /* the first character in this file */
  2079. X#include "a.h"
  2080. X#if !defined(fread) && declare_fread
  2081. X    fread_type fread P((void*,freadarg_type,freadarg_type,FILE*));
  2082. X#endif
  2083. int main()
  2084. X{
  2085. X    char b;
  2086. X    exitmain(!(
  2087. X        fread(&b, (freadarg_type)1, (freadarg_type)1, stdin) == 1  &&
  2088. X        b==CHAR1
  2089. X    ));
  2090. X}
  2091. XEOF
  2092. for declare_fread in 1 0
  2093. do
  2094. X    for fread_type in ssize_t size_t int unsigned
  2095. X    do
  2096. X        for freadarg_type in size_t ssize_t unsigned int
  2097. X        do
  2098. X            $RM || exit
  2099. X            (
  2100. X                $CL \
  2101. X                    -Ddeclare_fread=$declare_fread \
  2102. X                    -Dfreadarg_type=$freadarg_type \
  2103. X                    -Dfread_type=$fread_type \
  2104. X                    a.c $L &&
  2105. X                ./a.out <a.c
  2106. X            ) >&2 && break
  2107. X        done && break
  2108. X    done && break
  2109. done || {
  2110. X    echo >&2 "cannot deduce fread types"
  2111. X    exit 1
  2112. X}
  2113. cat <<EOF
  2114. typedef $fread_type fread_type; /* type returned by fread() and fwrite() */
  2115. typedef $freadarg_type freadarg_type; /* type of their size arguments */
  2116. XEOF
  2117. X
  2118. X: malloc_type
  2119. cat >a.c <<'EOF'
  2120. X#include "a.h"
  2121. typedef void *malloc_type;
  2122. X#ifndef malloc
  2123. X    malloc_type malloc();
  2124. X#endif
  2125. int main() { exitmain(!malloc(1)); }
  2126. XEOF
  2127. if $CS a.c $LS >&2
  2128. then t=void
  2129. else t=char
  2130. fi
  2131. echo "typedef $t *malloc_type; /* type returned by malloc() */"
  2132. X
  2133. X: has_getcwd
  2134. cat >a.c <<'EOF'
  2135. X#include "a.h"
  2136. X#ifndef getcwd
  2137. X    char *getcwd();
  2138. X#endif
  2139. char buf[10000];
  2140. int main() { exitmain(!getcwd(buf,10000)); }
  2141. XEOF
  2142. X$RM || exit
  2143. if ($CL a.c $L && ./a.out) >&2
  2144. then has_getcwd=1
  2145. else has_getcwd=0
  2146. fi
  2147. echo "#define has_getcwd $has_getcwd /* Does getcwd() work?  */"
  2148. X
  2149. X: has_getwd
  2150. case $has_getcwd in
  2151. X1)
  2152. X    a='/* ' z='*/ ' h=?;;
  2153. X*)
  2154. X    a= z=
  2155. X    cat >a.c <<'EOF'
  2156. X#include "a.h"
  2157. X#include <sys/param.h>
  2158. X#ifndef getwd
  2159. X    char *getwd();
  2160. X#endif
  2161. char buf[MAXPATHLEN];
  2162. int main() { exitmain(!getwd(buf)); }
  2163. XEOF
  2164. X    $RM || exit
  2165. X    if ($CL a.c $L && ./a.out) >&2
  2166. X    then h=1
  2167. X    else h=0
  2168. X    fi
  2169. esac
  2170. echo "$a#define has_getwd $h $z/* Does getwd() work?  */"
  2171. X
  2172. X: has_mktemp
  2173. cat >a.c <<'EOF'
  2174. X#include "a.h"
  2175. X#ifndef mktemp
  2176. X    char *mktemp();
  2177. X#endif
  2178. int main()
  2179. X{
  2180. X    char b[9];
  2181. X    strcpy(b, "a.XXXXXX");
  2182. X    exitmain(!mktemp(b));
  2183. X}
  2184. XEOF
  2185. X$RM || exit
  2186. if ($CL a.c $L && ./a.out) >&2
  2187. then h=1
  2188. else h=0
  2189. fi
  2190. echo "#define has_mktemp $h /* Does mktemp() work?  */"
  2191. X
  2192. X: has_NFS
  2193. echo "#define has_NFS 1 /* Might NFS be used?  */"
  2194. X
  2195. X: strchr
  2196. cat >a.c <<'EOF'
  2197. X#include "a.h"
  2198. X#ifndef strchr
  2199. X    char *strchr();
  2200. X#endif
  2201. int main() {exitmain(!strchr("abc", 'c'));}
  2202. XEOF
  2203. X$RM || exit
  2204. if ($CL a.c $L && ./a.out) >&2
  2205. then a='/* ' z='*/ '
  2206. else a= z=
  2207. fi
  2208. echo "$a#define strchr index $z/* Use old-fashioned name for strchr()?  */"
  2209. X
  2210. X: strrchr
  2211. cat >a.c <<'EOF'
  2212. X#include "a.h"
  2213. X#ifndef strrchr
  2214. X    char *strrchr();
  2215. X#endif
  2216. int main() {exitmain(!strrchr("abc", 'c'));}
  2217. XEOF
  2218. X$RM || exit
  2219. if ($CL a.c $L && ./a.out) >&2
  2220. then a='/* ' z='*/ '
  2221. else a= z=
  2222. fi
  2223. echo "$a#define strrchr rindex $z/* Use old-fashioned name for strrchr()?  */"
  2224. X
  2225. X: bad_unlink
  2226. cat >a.c <<'EOF'
  2227. X#include "a.h"
  2228. int main() { exitmain(unlink("a.c") != 0); }
  2229. XEOF
  2230. X$RM && chmod -w a.c || exit
  2231. if $CL a.c $L >&2 && ./a.out >/dev/null && test ! -f a.c
  2232. then b=0
  2233. else b=1
  2234. fi
  2235. rm -f a.c || exit
  2236. echo "#define bad_unlink $b /* Does unlink() fail on unwritable files?  */"
  2237. X
  2238. X: has_vfork, has_fork, has_spawn, has_wait, has_waitpid, RCS_SHELL
  2239. cat >a.c <<'EOF'
  2240. X#include "a.h"
  2241. X#ifndef getpid
  2242. X    pid_t getpid();
  2243. X#endif
  2244. X#if TRY_VFORK
  2245. X#    ifndef vfork
  2246. X        pid_t vfork();
  2247. X#    endif
  2248. X#else
  2249. X#    ifndef fork
  2250. X        pid_t fork();
  2251. X#    endif
  2252. X#    undef vfork
  2253. X#    define vfork fork
  2254. X#endif
  2255. X#if TRY_WAITPID
  2256. X#    ifndef waitpid
  2257. X        pid_t waitpid();
  2258. X#    endif
  2259. X#else
  2260. X#    ifndef wait
  2261. X        pid_t wait();
  2262. X#    endif
  2263. X#endif
  2264. pid_t child;
  2265. int status;
  2266. struct stat st;
  2267. int main()
  2268. X{
  2269. X    pid_t parent = getpid();
  2270. X    if (!(child = vfork())) {
  2271. X        /* Tickle vfork/compiler bug (e.g. sparc gcc -O (1.37.1).  */
  2272. X        pid_t i = getpid(), j = getpid();
  2273. X        if (i!=getpid() || j!=getpid())
  2274. X            _exit(!i);
  2275. X        /* Tickle file descriptor bug (e.g. IRIX 3.3).  */
  2276. X        _exit(close(1) != 0);
  2277. X    } else {
  2278. X#        if TRY_WAITPID
  2279. X            if (waitpid(child, &status, 0) != child)
  2280. X                exitmain(1);
  2281. X#        else
  2282. X            while (wait(&status) != child)
  2283. X                ;
  2284. X#        endif
  2285. X        /* Test for presence of bugs.  */
  2286. X        exitmain(status  ||  parent != getpid()  ||  fstat(1,&st) != 0);
  2287. X    }
  2288. X}
  2289. XEOF
  2290. X$RM || exit
  2291. if ($CL -DTRY_VFORK=1 a.c $L && ./a.out) >&2
  2292. then has_vfork=1
  2293. else has_vfork=0
  2294. fi
  2295. echo "#define has_vfork $has_vfork /* Does vfork() work?  */"
  2296. h=$has_vfork
  2297. case $h in
  2298. X0)
  2299. X    $RM || exit
  2300. X    ($CL a.c $L && ./a.out) >&2 && h=1
  2301. esac
  2302. echo "#define has_fork $h /* Does fork() work?  */"
  2303. X$RM || exit
  2304. if ($CL -DTRY_VFORK=$has_vfork -DTRY_WAITPID=1 a.c $L && ./a.out) >&2
  2305. then h=1
  2306. else h=0
  2307. fi
  2308. echo "#define has_spawn 0 /* Does spawn*() work?  */"
  2309. echo "#define has_wait 1 /* Does wait() work?  */"
  2310. echo "#define has_waitpid $h /* Does waitpid() work?  */"
  2311. echo '#define RCS_SHELL "/bin/sh" /* shell to run RCS subprograms */'
  2312. X
  2313. X: has_vfprintf
  2314. cat >a.c <<'EOF'
  2315. X#include "a.h"
  2316. X#if has_prototypes
  2317. int p(char const*format,...)
  2318. X#else
  2319. X/*VARARGS1*/ int p(format, va_alist) char *format; va_dcl
  2320. X#endif
  2321. X{
  2322. X    int r;
  2323. X    va_list args;
  2324. X    vararg_start(args, format);
  2325. X    r = vfprintf(stderr, format, args);
  2326. X    va_end(args);
  2327. X    return r;
  2328. X}
  2329. int main() { exitmain(p("") != 0); }
  2330. XEOF
  2331. X$RM || exit
  2332. if ($CL a.c $L && ./a.out) >&2
  2333. then h=1
  2334. else h=0
  2335. fi
  2336. echo "#define has_vfprintf $h /* Does vfprintf() work?  */"
  2337. X
  2338. X: has__doprintf, has__doprnt
  2339. case $h in
  2340. X1)
  2341. X    h=? a='/* ' z='*/ ';;
  2342. X*)
  2343. X    a= z=
  2344. X    cat >a.c <<'EOF'
  2345. X#include "a.h"
  2346. X#if has_prototypes
  2347. int p(char const*format,...)
  2348. X#else
  2349. X/*VARARGS1*/ int p(format, va_alist) char *format; va_dcl
  2350. X#endif
  2351. X{
  2352. X    va_list args;
  2353. X    vararg_start(args, format);
  2354. X#    if TRY__DOPRINTF
  2355. X        _doprintf(stderr, format, args);
  2356. X#    else
  2357. X        _doprnt(format, args, stderr);
  2358. X#    endif
  2359. X    va_end(args);
  2360. X}
  2361. int main() { p(""); exitmain(ferror(stderr) != 0); }
  2362. XEOF
  2363. X    $RM || exit
  2364. X    if ($CL -DTRY__DOPRINTF=1 a.c $L && ./a.out) >&2
  2365. X    then h=1
  2366. X    else h=0
  2367. X    fi
  2368. esac
  2369. echo "$a#define has__doprintf $h $z/* Does _doprintf() work?  */"
  2370. case $h in
  2371. X0)
  2372. X    $RM || exit
  2373. X    if ($CL a.c $L && ./a.out) >&2
  2374. X    then h=1
  2375. X    else h=0
  2376. X    fi
  2377. X    a= z=;;
  2378. X*)
  2379. X    h=? a='/* ' z='*/ '
  2380. esac
  2381. echo "$a#define has__doprnt $h $z/* Does _doprnt() work?  */"
  2382. X
  2383. X: EXIT_FAILURE
  2384. cat >a.c <<'EOF'
  2385. X#include "a.h"
  2386. int main() { exitmain(EXIT_FAILURE); }
  2387. XEOF
  2388. X$RM || exit
  2389. if $CL a.c $L >&2 && ./a.out
  2390. then a= z=
  2391. else a='/* ' z='*/ '
  2392. fi
  2393. echo "$a#undef EXIT_FAILURE $z/* Uncomment this if EXIT_FAILURE is broken.  */"
  2394. X
  2395. X: large_memory
  2396. echo "#define large_memory $has_mmap /* Can main memory hold entire RCS files?  */"
  2397. X
  2398. X: ULONG_MAX
  2399. cat >a.c <<'EOF'
  2400. X#include "a.h"
  2401. X#ifdef ULONG_MAX
  2402. X    /*
  2403. X     * "#if ULONG_MAX/10 <= 0" does not always work,
  2404. X     * because some buggy implementations put casts in ULONG_MAX.
  2405. X     */
  2406. X    int main() { exitmain(ULONG_MAX/10 <= 0); }
  2407. X#else
  2408. X    int main() { exitmain(1); }
  2409. X#endif
  2410. XEOF
  2411. X$RM || exit
  2412. if $CL a.c $L >&2 && ./a.out
  2413. then a='/* ' z='*/ '
  2414. else a= z=
  2415. fi
  2416. echo "$a#undef ULONG_MAX $z/* Uncomment this if ULONG_MAX is broken (e.g. < 0).  */"
  2417. X
  2418. X: struct utimbuf
  2419. cat >a.c <<'EOF'
  2420. X#include "a.h"
  2421. struct utimbuf s;
  2422. int main() { s.actime = s.modtime = 1; exitmain(utime("a.c", &s) != 0); }
  2423. XEOF
  2424. X$RM || exit
  2425. if ($CL a.c $L && ./a.out) >&2
  2426. then a='/* ' z=' */'
  2427. else a= z=
  2428. fi
  2429. echo "${a}struct utimbuf { time_t actime, modtime; };$z /* Uncomment this if needed.  */"
  2430. X
  2431. X: CO
  2432. echo "#define CO \"${RCSPREFIX}co\" /* name of 'co' program */"
  2433. X
  2434. X: COMPAT2
  2435. echo "#define COMPAT2 $COMPAT2 /* Are version 2 files supported?  */"
  2436. X
  2437. X: DATEFORM
  2438. cat >a.c <<'EOF'
  2439. X#include "a.h"
  2440. int main() { printf("%.2d", 1); exitmain(0); }
  2441. XEOF
  2442. X$RM && $CL a.c $L >&2 && r=`./a.out` || exit
  2443. case $r in
  2444. X01)    f=%.2d;;
  2445. X*)    f=%02d
  2446. esac
  2447. echo "#define DATEFORM \"$f.$f.$f.$f.$f.${f}\" /* e.g. 01.01.01.01.01.01 */"
  2448. X
  2449. X: DIFF
  2450. echo "#define DIFF \"${DIFF}\" /* name of 'diff' program */"
  2451. X
  2452. X: DIFF3
  2453. echo "#define DIFF3 \"${DIFF3}\" /* name of 'diff3' program */"
  2454. X
  2455. echo "#define DIFF3_BIN $DIFF3_BIN /* Is diff3 user-visible (not the /usr/lib auxiliary)?  */"
  2456. X
  2457. X: DIFF_FLAGS
  2458. dfs=
  2459. for df in $DIFF_FLAGS
  2460. do dfs="$dfs, \"${df}\""
  2461. done
  2462. echo "#define DIFF_FLAGS $dfs /* Make diff output suitable for RCS.  */"
  2463. X
  2464. X: DIFF_L
  2465. echo "#define DIFF_L $DIFF_L /* Does diff -L work? */"
  2466. X
  2467. X: DIFF_SUCCESS, DIFF_FAILURE, DIFF_TROUBLE
  2468. cat <<EOF
  2469. X#define DIFF_SUCCESS $DIFF_SUCCESS /* DIFF status if no differences are found */
  2470. X#define DIFF_FAILURE $DIFF_FAILURE /* DIFF status if differences are found */
  2471. X#define DIFF_TROUBLE $DIFF_TROUBLE /* DIFF status if trouble */
  2472. XEOF
  2473. X
  2474. X: ED
  2475. echo "#define ED \"${ED}\" /* name of 'ed' program (used only if !DIFF3_BIN) */"
  2476. X
  2477. X: MERGE
  2478. echo "#define MERGE \"${RCSPREFIX}merge\" /* name of 'merge' program */"
  2479. X
  2480. X: '*SLASH*', ROOTPATH, TMPDIR, X_DEFAULT
  2481. case ${PWD-`pwd`} in
  2482. X/*) # Posix
  2483. X    SLASH=/
  2484. X    qSLASH="'/'"
  2485. X    SLASHes=$qSLASH
  2486. X    isSLASH='#define isSLASH(c) ((c) == SLASH)'
  2487. X    ROOTPATH='isSLASH((p)[0])'
  2488. X    X_DEFAULT=",v$SLASH";;
  2489. X?:[/\\]*) # MS-DOS
  2490. X    SLASH='\'
  2491. X    qSLASH="'\\\\'"
  2492. X    SLASHes="$qSLASH: case '/': case ':'"
  2493. X    isSLASH='int isSLASH P((int));'
  2494. X    ROOTPATH='((p)[0] && (p)[1]==':' && isSLASH((p)[2]))'
  2495. X    X_DEFAULT="$SLASH,v";;
  2496. X*)
  2497. X    echo >&2 "cannot deduce SLASH"; exit 1
  2498. esac
  2499. cat <<EOF
  2500. X#define TMPDIR "${SLASH}tmp" /* default directory for temporary files */
  2501. X#define SLASH $qSLASH /* principal pathname separator */
  2502. X#define SLASHes $SLASHes /* \`case SLASHes:' labels all pathname separators */
  2503. X$isSLASH /* Is arg a pathname separator?  */
  2504. X#define ROOTPATH(p) $ROOTPATH /* Is p an absolute pathname?  */
  2505. X#define X_DEFAULT "$X_DEFAULT" /* default value for -x option */
  2506. XEOF
  2507. X
  2508. X: DIFF_ABSOLUTE
  2509. case $DIFF in
  2510. X"$SLASH"*) a=1;;
  2511. X*) a=0
  2512. esac
  2513. echo "#define DIFF_ABSOLUTE $a /* Is ROOTPATH(DIFF) true?  */"
  2514. X
  2515. X: ALL_ABSOLUTE
  2516. a=1
  2517. for i in "$DIFF" "$DIFF3" "$ED" "$RCSPREFIX" "$SENDMAIL"/
  2518. do
  2519. X    case $i in
  2520. X    "$SLASH"* | "\"$SLASH"*) ;;
  2521. X    *) a=0 break
  2522. X    esac
  2523. done
  2524. echo "#define ALL_ABSOLUTE $a /* Are all subprograms absolute pathnames?  */"
  2525. X
  2526. X: SENDMAIL
  2527. case $SENDMAIL in
  2528. X'') a='/* ' z='*/ ';;
  2529. X*) a= z=
  2530. esac
  2531. echo "$a#define SENDMAIL $SENDMAIL $z/* how to send mail */"
  2532. X
  2533. X: TZ_must_be_set
  2534. echo "#define TZ_must_be_set 0 /* Must TZ be set for gmtime() to work?  */"
  2535. X
  2536. X
  2537. X: standard function declarations
  2538. X
  2539. cat <<'EOF'
  2540. X
  2541. X
  2542. X
  2543. X/* Adjust the following declarations as needed.  */
  2544. X
  2545. X
  2546. X#if __GNUC__ && !__STRICT_ANSI__
  2547. X#    define exiting volatile /* GCC extension: function cannot return */
  2548. X#else
  2549. X#    define exiting
  2550. X#endif
  2551. XEOF
  2552. X
  2553. cat >a.ha <<EOF
  2554. X
  2555. X#if has_ftruncate
  2556. X    int ftruncate P((int,off_t));
  2557. X#endif
  2558. X
  2559. X/* <sys/mman.h> */
  2560. X#if has_madvise
  2561. X    int madvise P((caddr_t,size_t,int));
  2562. X#endif
  2563. X#if has_mmap
  2564. X    caddr_t mmap P((caddr_t,size_t,int,int,int,off_t));
  2565. X    int munmap P((caddr_t,size_t));
  2566. X#endif
  2567. X
  2568. X
  2569. X/* Posix (ISO/IEC 9945-1: 1990 / IEEE Std 1003.1-1990) */
  2570. X/* These definitions are for the benefit of non-Posix hosts, and */
  2571. X/* Posix hosts that have Standard C compilers but traditional include files.  */
  2572. X/* Unfortunately, mixed-up hosts are all too common.  */
  2573. X
  2574. X/* <fcntl.h> */
  2575. X#ifdef F_DUPFD
  2576. X    int fcntl P((int,int,...));
  2577. X#else
  2578. X    int dup2 P((int,int));
  2579. X#endif
  2580. X#ifndef O_BINARY /* some non-Posix hosts need O_BINARY */
  2581. X#    define O_BINARY 0 /* no effect on Posix */
  2582. X#endif
  2583. X#ifdef O_CREAT
  2584. X#    define open_can_creat 1
  2585. X#else
  2586. X#    define open_can_creat 0
  2587. X#    define O_RDONLY 0
  2588. X#    define O_WRONLY 1
  2589. X#    define O_RDWR 2
  2590. X#    define O_CREAT 01000
  2591. X#    define O_TRUNC 02000
  2592. X    int creat P((char const*,mode_t));
  2593. X#endif
  2594. X#ifndef O_EXCL
  2595. X#    define O_EXCL 0
  2596. X#endif
  2597. X
  2598. X/* <pwd.h> */
  2599. X#if has_getpwuid
  2600. X    struct passwd *getpwuid P((uid_t));
  2601. X#endif
  2602. X
  2603. X/* <signal.h> */
  2604. X#if has_sigaction
  2605. X    int sigaction P((int,struct sigaction const*,struct sigaction*));
  2606. X    int sigaddset P((sigset_t*,int));
  2607. X    int sigemptyset P((sigset_t*));
  2608. X#else
  2609. X#if has_sigblock
  2610. X    /* BSD */
  2611. X    int sigblock P((int));
  2612. X    int sigmask P((int));
  2613. X    int sigsetmask P((int));
  2614. X#endif
  2615. X#endif
  2616. X
  2617. X/* <stdio.h> */
  2618. XFILE *fdopen P((int,char const*));
  2619. int fileno P((FILE*));
  2620. X
  2621. X/* <sys/stat.h> */
  2622. int chmod P((char const*,mode_t));
  2623. int fstat P((int,struct stat*));
  2624. int stat P((char const*,struct stat*));
  2625. mode_t umask P((mode_t));
  2626. X#if has_fchmod
  2627. X    int fchmod P((int,mode_t));
  2628. X#endif
  2629. X#ifndef S_IRUSR
  2630. X#    ifdef S_IREAD
  2631. X#        define S_IRUSR S_IREAD
  2632. X#    else
  2633. X#        define S_IRUSR 0400
  2634. X#    endif
  2635. X#    ifdef S_IWRITE
  2636. X#        define S_IWUSR S_IWRITE
  2637. X#    else
  2638. X#        define S_IWUSR (S_IRUSR/2)
  2639. X#    endif
  2640. X#endif
  2641. X#ifndef S_IRGRP
  2642. X#    if has_getuid
  2643. X#        define S_IRGRP (S_IRUSR / 0010)
  2644. X#        define S_IWGRP (S_IWUSR / 0010)
  2645. X#        define S_IROTH (S_IRUSR / 0100)
  2646. X#        define S_IWOTH (S_IWUSR / 0100)
  2647. X#    else
  2648. X        /* single user OS -- not Posix or Unix */
  2649. X#        define S_IRGRP 0
  2650. X#        define S_IWGRP 0
  2651. X#        define S_IROTH 0
  2652. X#        define S_IWOTH 0
  2653. X#    endif
  2654. X#endif
  2655. X#ifndef S_ISREG
  2656. X#    define S_ISREG(n) (((n) & S_IFMT) == S_IFREG)
  2657. X#endif
  2658. X
  2659. X/* <sys/wait.h> */
  2660. X#if has_wait
  2661. X    pid_t wait P((int*));
  2662. X#endif
  2663. X#ifndef WEXITSTATUS
  2664. X#    define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
  2665. X#    undef WIFEXITED /* Avoid 4.3BSD incompatibility with Posix.  */
  2666. X#endif
  2667. X#ifndef WIFEXITED
  2668. X#    define WIFEXITED(stat_val) (!((stat_val) & 255))
  2669. X#endif
  2670. X
  2671. X/* <unistd.h> */
  2672. char *getlogin P((void));
  2673. int close P((int));
  2674. int isatty P((int));
  2675. int link P((char const*,char const*));
  2676. int open P((char const*,int,...));
  2677. int unlink P((char const*));
  2678. int _filbuf P((FILE*)); /* keeps lint quiet in traditional C */
  2679. int _flsbuf P((int,FILE*)); /* keeps lint quiet in traditional C */
  2680. long pathconf P((char const*,int));
  2681. ssize_t write P((int,void const*,size_t));
  2682. X#ifndef STDIN_FILENO
  2683. X#    define STDIN_FILENO 0
  2684. X#    define STDOUT_FILENO 1
  2685. X#    define STDERR_FILENO 2
  2686. X#endif
  2687. X#if has_fork
  2688. X#    if !has_vfork
  2689. X#        undef vfork
  2690. X#        define vfork fork
  2691. X#    endif
  2692. X    pid_t vfork P((void)); /* vfork is nonstandard but faster */
  2693. X#endif
  2694. X#if has_getcwd || !has_getwd
  2695. X    char *getcwd P((char*,size_t));
  2696. X#else
  2697. X    char *getwd P((char*));
  2698. X#endif
  2699. X#if has_getuid
  2700. X    uid_t getuid P((void));
  2701. X#endif
  2702. X#if has_readlink
  2703. X    ssize_t readlink P((char const*,char*,size_t)); /* BSD; not standard yet */
  2704. X#endif
  2705. X#if has_setuid
  2706. X#    if !has_seteuid
  2707. X#        undef seteuid
  2708. X#        define seteuid setuid
  2709. X#    endif
  2710. X    int seteuid P((uid_t));
  2711. X    uid_t geteuid P((void));
  2712. X#endif
  2713. X#if has_spawn
  2714. X    int spawnv P((int,char const*,char*const*));
  2715. X#    if ALL_ABSOLUTE
  2716. X#        define spawn_RCS spawnv
  2717. X#    else
  2718. X#        define spawn_RCS spawnvp
  2719. X        int spawnvp P((int,char const*,char*const*));
  2720. X#    endif
  2721. X#else
  2722. X    int execv P((char const*,char*const*));
  2723. X#    if ALL_ABSOLUTE
  2724. X#        define exec_RCS execv
  2725. X#    else
  2726. X#        define exec_RCS execvp
  2727. X        int execvp P((char const*,char*const*));
  2728. X#    endif
  2729. X#endif
  2730. X
  2731. X/* utime.h */
  2732. int utime P((char const*,struct utimbuf const*));
  2733. X
  2734. X
  2735. X/* Standard C library */
  2736. X/* These definitions are for the benefit of hosts that have */
  2737. X/* traditional C include files, possibly with Standard C compilers.  */
  2738. X/* Unfortunately, mixed-up hosts are all too common.  */
  2739. X
  2740. X/* <errno.h> */
  2741. extern int errno;
  2742. X
  2743. X/* <limits.h> */
  2744. X#ifndef ULONG_MAX
  2745. X    /* This does not work in #ifs, but it's good enough for us.  */
  2746. X#    define ULONG_MAX ((unsigned long)-1)
  2747. X#endif
  2748. X
  2749. X/* <signal.h> */
  2750. X#if has_signal
  2751. X    signal_type (*signal P((int,signal_type(*)signal_args)))signal_args;
  2752. X#endif
  2753. X
  2754. X/* <stdio.h> */
  2755. XFILE *fopen P((char const*,char const*));
  2756. fread_type fread P((void*,freadarg_type,freadarg_type,FILE*));
  2757. fread_type fwrite P((void const*,freadarg_type,freadarg_type,FILE*));
  2758. int fclose P((FILE*));
  2759. int feof P((FILE*));
  2760. int ferror P((FILE*));
  2761. int fflush P((FILE*));
  2762. int fprintf P((FILE*,char const*,...));
  2763. int fputs P((char const*,FILE*));
  2764. int fseek P((FILE*,long,int));
  2765. int printf P((char const*,...));
  2766. int rename P((char const*,char const*));
  2767. int sprintf P((char*,char const*,...));
  2768. long ftell P((FILE*));
  2769. void clearerr P((FILE*));
  2770. void perror P((char const*));
  2771. X#ifndef L_tmpnam
  2772. X#    define L_tmpnam 32 /* power of 2 > sizeof("/usr/tmp/xxxxxxxxxxxxxxx") */
  2773. X#endif
  2774. X#ifndef SEEK_SET
  2775. X#    define SEEK_SET 0
  2776. X#endif
  2777. X#if has_mktemp
  2778. X    char *mktemp P((char*)); /* traditional */
  2779. X#else
  2780. X    char *tmpnam P((char*));
  2781. X#endif
  2782. X#if has_vfprintf
  2783. X    int vfprintf P((FILE*,char const*,va_list));
  2784. X#else
  2785. X#if has__doprintf
  2786. X    void _doprintf P((FILE*,char const*,va_list)); /* Minix */
  2787. X#else
  2788. X    void _doprnt P((char const*,va_list,FILE*)); /* BSD */
  2789. X#endif
  2790. X#endif
  2791. X
  2792. X/* <stdlib.h> */
  2793. char *getenv P((char const*));
  2794. exiting void _exit P((int));
  2795. exiting void exit P((int));
  2796. malloc_type malloc P((size_t));
  2797. malloc_type realloc P((malloc_type,size_t));
  2798. void free P((malloc_type));
  2799. X#ifndef EXIT_FAILURE
  2800. X#    define EXIT_FAILURE 1
  2801. X#endif
  2802. X#ifndef EXIT_SUCCESS
  2803. X#    define EXIT_SUCCESS 0
  2804. X#endif
  2805. X#if !has_fork && !has_spawn
  2806. X    int system P((char const*));
  2807. X#endif
  2808. X
  2809. X/* <string.h> */
  2810. char *strcpy P((char*,char const*));
  2811. char *strchr P((char const*,int));
  2812. char *strrchr P((char const*,int));
  2813. int memcmp P((void const*,void const*,size_t));
  2814. int strcmp P((char const*,char const*));
  2815. size_t strlen P((char const*));
  2816. void *memcpy P((void*,void const*,size_t));
  2817. X#if has_memmove
  2818. X    void *memmove P((void*,void const*,size_t));
  2819. X#endif
  2820. X
  2821. X/* <time.h> */
  2822. time_t time P((time_t*));
  2823. XEOF
  2824. X
  2825. cat >a.c <<'EOF'
  2826. X#include "a.h"
  2827. X#define a 0
  2828. X#define b 1
  2829. X#if h==a
  2830. X#    include "a.ha"
  2831. X#else
  2832. X#    include "a.hb"
  2833. X#endif
  2834. int main() { exitmain(0); }
  2835. XEOF
  2836. X
  2837. X# Comment out lines in a.ha that the compiler rejects.
  2838. X# a.ha may not contain comments that cross line boundaries.
  2839. X# Leave the result in a.h$h.
  2840. h=a l=1
  2841. U=`wc -l <a.ha | sed 's| ||g'`
  2842. commentOut='s|^[^#/][^/]*|/* & */|'
  2843. X
  2844. until  test $U -lt $l  ||  $CS -Dh=$h a.c $LS >&2
  2845. do
  2846. X    case $h in
  2847. X    a) i=b;;
  2848. X    *) i=a
  2849. X    esac
  2850. X
  2851. X    # The compiler rejects some line in l..U.
  2852. X    # Use binary search to set l to be the index of the first bad line in l..U.
  2853. X    u=$U
  2854. X    while test $l -lt $u
  2855. X    do
  2856. X        M=`expr '(' $l + $u ')' / 2`
  2857. X        M1=`expr $M + 1`
  2858. X        sed "$M1,\$$commentOut" a.h$h >a.h$i || exit
  2859. X        if $CS -Dh=$i a.c $LS >&2
  2860. X        then l=$M1
  2861. X        else u=$M
  2862. X        fi
  2863. X    done
  2864. X
  2865. X    # Comment out the bad line.
  2866. X    sed "$l$commentOut" a.h$h >a.h$i || exit
  2867. X
  2868. X    h=$i
  2869. X    l=`expr $l + 1`
  2870. done
  2871. X
  2872. cat a.h$h
  2873. END_OF_FILE
  2874. if test 35856 -ne `wc -c <'src/conf.sh'`; then
  2875.     echo shar: \"'src/conf.sh'\" unpacked with wrong size!
  2876. fi
  2877. # end of 'src/conf.sh'
  2878. fi
  2879. echo shar: End of archive 7 \(of 11\).
  2880. cp /dev/null ark7isdone
  2881. MISSING=""
  2882. for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
  2883.     if test ! -f ark${I}isdone ; then
  2884.     MISSING="${MISSING} ${I}"
  2885.     fi
  2886. done
  2887. if test "${MISSING}" = "" ; then
  2888.     echo You have unpacked all 11 archives.
  2889.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  2890. else
  2891.     echo You still need to unpack the following archives:
  2892.     echo "        " ${MISSING}
  2893. fi
  2894. ##  End of shell archive.
  2895. exit 0
  2896.