home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / dev / misc / hwgrcs / src / rcs.rcsfiles / rcsutil.c,v < prev    next >
Encoding:
Text File  |  1995-06-25  |  46.0 KB  |  2,272 lines

  1. head    5.10;
  2. branch    5.10.1;
  3. access;
  4. symbols
  5.     HWGRCSP12F:5.10.1.7
  6.     HWGRCSP11F:5.10.1.7
  7.     HWGRCSP10F:5.10.1.7
  8.     HWGRCSP9:5.10.1.7
  9.     HWGRCSP8F:5.10.1.6
  10.     HWGRCSP7F:5.10.1.4
  11.     C_15:5.10.1.4
  12.     HWGRCSP6F:5.10.1.3
  13.     HWGRCSP5F:5.10.1.1
  14.     HWGRCSp4:5.10.1.1
  15.     HWGRCSp3:5.10.1
  16.     HWGRCS_Fish:5.10.1
  17.     HWGRCS:5.10.1;
  18. locks; strict;
  19. comment    @ * @;
  20.  
  21.  
  22. 5.10
  23. date    91.10.07.17.32.46;    author eggert;    state Exp;
  24. branches
  25.     5.10.1.1;
  26. next    ;
  27.  
  28. 5.10.1.1
  29. date    93.01.18.14.36.30;    author heinz;    state Exp;
  30. branches;
  31. next    5.10.1.2;
  32.  
  33. 5.10.1.2
  34. date    93.12.18.16.12.22;    author heinz;    state Exp;
  35. branches;
  36. next    5.10.1.3;
  37.  
  38. 5.10.1.3
  39. date    93.12.18.17.17.59;    author heinz;    state Exp;
  40. branches;
  41. next    5.10.1.4;
  42.  
  43. 5.10.1.4
  44. date    94.01.06.11.33.27;    author heinz;    state Exp;
  45. branches;
  46. next    5.10.1.5;
  47.  
  48. 5.10.1.5
  49. date    94.02.11.19.53.26;    author heinz;    state Exp;
  50. branches;
  51. next    5.10.1.6;
  52.  
  53. 5.10.1.6
  54. date    94.03.14.09.22.53;    author heinz;    state Exp;
  55. branches;
  56. next    5.10.1.7;
  57.  
  58. 5.10.1.7
  59. date    94.04.23.19.51.04;    author heinz;    state Exp;
  60. branches;
  61. next    ;
  62.  
  63.  
  64. desc
  65. @Checked in with -k 16.jan.93 HWG
  66. @
  67.  
  68.  
  69. 5.10
  70. log
  71. @checked in with -k by heinz at 1993/01/17 01:53:17
  72. @
  73. text
  74. @/*
  75.  *                     RCS utilities
  76.  */
  77.  
  78. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  79.    Copyright 1990, 1991 by Paul Eggert
  80.    Distributed under license by the Free Software Foundation, Inc.
  81.  
  82. This file is part of RCS.
  83.  
  84. RCS is free software; you can redistribute it and/or modify
  85. it under the terms of the GNU General Public License as published by
  86. the Free Software Foundation; either version 2, or (at your option)
  87. any later version.
  88.  
  89. RCS is distributed in the hope that it will be useful,
  90. but WITHOUT ANY WARRANTY; without even the implied warranty of
  91. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  92. GNU General Public License for more details.
  93.  
  94. You should have received a copy of the GNU General Public License
  95. along with RCS; see the file COPYING.  If not, write to
  96. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  97.  
  98. Report problems and direct all questions to:
  99.  
  100.     rcs-bugs@@cs.purdue.edu
  101.  
  102. */
  103.  
  104.  
  105.  
  106.  
  107. /* $Log: rcsutil.c,v $
  108.  * Revision 5.10  1991/10/07  17:32:46  eggert
  109.  * Support piece tables even if !has_mmap.
  110.  *
  111.  * Revision 5.9  1991/08/19  03:13:55  eggert
  112.  * Add spawn() support.  Explicate assumptions about getting invoker's name.
  113.  * Standardize user-visible dates.  Tune.
  114.  *
  115.  * Revision 5.8  1991/04/21  11:58:30  eggert
  116.  * Plug setuid security hole.
  117.  *
  118.  * Revision 5.6  1991/02/26  17:48:39  eggert
  119.  * Fix setuid bug.  Use fread, fwrite more portably.
  120.  * Support waitpid.  Don't assume -1 is acceptable to W* macros.
  121.  * strsave -> str_save (DG/UX name clash)
  122.  *
  123.  * Revision 5.5  1990/12/04  05:18:49  eggert
  124.  * Don't output a blank line after a signal diagnostic.
  125.  * Use -I for prompts and -q for diagnostics.
  126.  *
  127.  * Revision 5.4  1990/11/01  05:03:53  eggert
  128.  * Remove unneeded setid check.  Add awrite(), fremember().
  129.  *
  130.  * Revision 5.3  1990/10/06  00:16:45  eggert
  131.  * Don't fread F if feof(F).
  132.  *
  133.  * Revision 5.2  1990/09/04  08:02:31  eggert
  134.  * Store fread()'s result in an fread_type object.
  135.  *
  136.  * Revision 5.1  1990/08/29  07:14:07  eggert
  137.  * Declare getpwuid() more carefully.
  138.  *
  139.  * Revision 5.0  1990/08/22  08:13:46  eggert
  140.  * Add setuid support.  Permit multiple locks per user.
  141.  * Remove compile-time limits; use malloc instead.
  142.  * Switch to GMT.  Permit dates past 1999/12/31.
  143.  * Add -V.  Remove snooping.  Ansify and Posixate.
  144.  * Tune.  Some USG hosts define NSIG but not sys_siglist.
  145.  * Don't run /bin/sh if it's hopeless.
  146.  * Don't leave garbage behind if the output is an empty pipe.
  147.  * Clean up after SIGXCPU or SIGXFSZ.  Print name of signal that caused cleanup.
  148.  *
  149.  * Revision 4.6  89/05/01  15:13:40  narten
  150.  * changed copyright header to reflect current distribution rules
  151.  * 
  152.  * Revision 4.5  88/11/08  16:01:02  narten
  153.  * corrected use of varargs routines
  154.  * 
  155.  * Revision 4.4  88/08/09  19:13:24  eggert
  156.  * Check for memory exhaustion.
  157.  * Permit signal handlers to yield either 'void' or 'int'; fix oldSIGINT botch.
  158.  * Use execv(), not system(); yield exit status like diff(1)'s.
  159.  * 
  160.  * Revision 4.3  87/10/18  10:40:22  narten
  161.  * Updating version numbers. Changes relative to 1.1 actually
  162.  * relative to 4.1
  163.  * 
  164.  * Revision 1.3  87/09/24  14:01:01  narten
  165.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  166.  * warnings)
  167.  * 
  168.  * Revision 1.2  87/03/27  14:22:43  jenkins
  169.  * Port to suns
  170.  * 
  171.  * Revision 4.1  83/05/10  15:53:13  wft
  172.  * Added getcaller() and findlock().
  173.  * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal
  174.  * (needed for background jobs in older shells). Added restoreints().
  175.  * Removed printing of full RCS path from logcommand().
  176.  * 
  177.  * Revision 3.8  83/02/15  15:41:49  wft
  178.  * Added routine fastcopy() to copy remainder of a file in blocks.
  179.  *
  180.  * Revision 3.7  82/12/24  15:25:19  wft
  181.  * added catchints(), ignoreints() for catching and ingnoring interrupts;
  182.  * fixed catchsig().
  183.  *
  184.  * Revision 3.6  82/12/08  21:52:05  wft
  185.  * Using DATEFORM to format dates.
  186.  *
  187.  * Revision 3.5  82/12/04  18:20:49  wft
  188.  * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update
  189.  * lockedby-field.
  190.  *
  191.  * Revision 3.4  82/12/03  17:17:43  wft
  192.  * Added check to addlock() ensuring only one lock per person.
  193.  * Addlock also returns a pointer to the lock created. Deleted fancydate().
  194.  *
  195.  * Revision 3.3  82/11/27  12:24:37  wft
  196.  * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c.
  197.  * Introduced macro SNOOP so that snoop can be placed in directory other than
  198.  * TARGETDIR. Changed %02d to %.2d for compatibility reasons.
  199.  *
  200.  * Revision 3.2  82/10/18  21:15:11  wft
  201.  * added function getfullRCSname().
  202.  *
  203.  * Revision 3.1  82/10/13  16:17:37  wft
  204.  * Cleanup message is now suppressed in quiet mode.
  205.  */
  206.  
  207.  
  208.  
  209.  
  210. #include "rcsbase.h"
  211.  
  212. libId(utilId, "$Id: rcsutil.c,v 5.10 1991/10/07 17:32:46 eggert Exp $")
  213.  
  214. #if !has_memcmp
  215.     int
  216. memcmp(s1, s2, n)
  217.     void const *s1, *s2;
  218.     size_t n;
  219. {
  220.     register unsigned char const
  221.         *p1 = (unsigned char const*)s1,
  222.         *p2 = (unsigned char const*)s2;
  223.     register size_t i = n;
  224.     register int r = 0;
  225.     while (i--  &&  !(r = (*p1++ - *p2++)))
  226.         ;
  227.     return r;
  228. }
  229. #endif
  230.  
  231. #if !has_memcpy
  232.     void *
  233. memcpy(s1, s2, n)
  234.     void *s1;
  235.     void const *s2;
  236.     size_t n;
  237. {
  238.     register char *p1 = (char*)s1;
  239.     register char const *p2 = (char const*)s2;
  240.     while (n--)
  241.         *p1++ = *p2++;
  242.     return s1;
  243. }
  244. #endif
  245.  
  246. #if lint
  247.     malloc_type lintalloc;
  248. #endif
  249.  
  250. /*
  251.  * list of blocks allocated with ftestalloc()
  252.  * These blocks can be freed by ffree when we're done with the current file.
  253.  * We could put the free block inside struct alloclist, rather than a pointer
  254.  * to the free block, but that would be less portable.
  255.  */
  256. struct alloclist {
  257.     malloc_type alloc;
  258.     struct alloclist *nextalloc;
  259. };
  260. static struct alloclist *alloced;
  261.  
  262.  
  263.     static malloc_type
  264. okalloc(p)
  265.     malloc_type p;
  266. {
  267.     if (!p)
  268.         faterror("out of memory");
  269.     return p;
  270. }
  271.  
  272.     malloc_type
  273. testalloc(size)
  274.     size_t size;
  275. /* Allocate a block, testing that the allocation succeeded.  */
  276. {
  277.     return okalloc(malloc(size));
  278. }
  279.  
  280.     malloc_type
  281. testrealloc(ptr, size)
  282.     malloc_type ptr;
  283.     size_t size;
  284. /* Reallocate a block, testing that the allocation succeeded.  */
  285. {
  286.     return okalloc(realloc(ptr, size));
  287. }
  288.  
  289.     malloc_type
  290. fremember(ptr)
  291.     malloc_type ptr;
  292. /* Remember PTR in 'alloced' so that it can be freed later.  Yield PTR.  */
  293. {
  294.     register struct alloclist *q = talloc(struct alloclist);
  295.     q->nextalloc = alloced;
  296.     alloced = q;
  297.     return q->alloc = ptr;
  298. }
  299.  
  300.     malloc_type
  301. ftestalloc(size)
  302.     size_t size;
  303. /* Allocate a block, putting it in 'alloced' so it can be freed later. */
  304. {
  305.     return fremember(testalloc(size));
  306. }
  307.  
  308.     void
  309. ffree()
  310. /* Free all blocks allocated with ftestalloc().  */
  311. {
  312.     register struct alloclist *p, *q;
  313.     for (p = alloced;  p;  p = q) {
  314.         q = p->nextalloc;
  315.         tfree(p->alloc);
  316.         tfree(p);
  317.     }
  318.     alloced = nil;
  319. }
  320.  
  321.     void
  322. ffree1(f)
  323.     register char const *f;
  324. /* Free the block f, which was allocated by ftestalloc.  */
  325. {
  326.     register struct alloclist *p, **a = &alloced;
  327.  
  328.     while ((p = *a)->alloc  !=  f)
  329.         a = &p->nextalloc;
  330.     *a = p->nextalloc;
  331.     tfree(p->alloc);
  332.     tfree(p);
  333. }
  334.  
  335.     char *
  336. str_save(s)
  337.     char const *s;
  338. /* Save s in permanently allocated storage. */
  339. {
  340.     return strcpy(tnalloc(char, strlen(s)+1), s);
  341. }
  342.  
  343.     char *
  344. fstr_save(s)
  345.     char const *s;
  346. /* Save s in storage that will be deallocated when we're done with this file. */
  347. {
  348.     return strcpy(ftnalloc(char, strlen(s)+1), s);
  349. }
  350.  
  351.     char *
  352. cgetenv(name)
  353.     char const *name;
  354. /* Like getenv(), but yield a copy; getenv() can overwrite old results. */
  355. {
  356.     register char *p;
  357.  
  358.     return (p=getenv(name)) ? str_save(p) : p;
  359. }
  360.  
  361.     char const *
  362. getusername(suspicious)
  363.     int suspicious;
  364. /* Get the caller's login name.  Trust only getwpuid if SUSPICIOUS.  */
  365. {
  366.     static char *name;
  367.  
  368.     if (!name) {
  369.         if (
  370.             /* Prefer getenv() unless suspicious; it's much faster.  */
  371. #            if getlogin_is_secure
  372.                 (suspicious
  373.                 ||
  374.                 !(name = cgetenv("LOGNAME"))
  375.                 &&  !(name = cgetenv("USER")))
  376.             &&  !(name = getlogin())
  377. #            else
  378.             suspicious
  379.             ||
  380.                 !(name = cgetenv("LOGNAME"))
  381.                 &&  !(name = cgetenv("USER"))
  382.                 &&  !(name = getlogin())
  383. #            endif
  384.         ) {
  385. #if has_getuid && has_getpwuid
  386.             struct passwd const *pw = getpwuid(ruid());
  387.             if (!pw)
  388.                 faterror("no password entry for userid %lu",
  389.                      (unsigned long)ruid()
  390.                 );
  391.             name = pw->pw_name;
  392. #else
  393. #if has_setuid
  394.             faterror("setuid not supported");
  395. #else
  396.             faterror("Who are you?  Please set LOGNAME.");
  397. #endif
  398. #endif
  399.         }
  400.         checksid(name);
  401.     }
  402.     return name;
  403. }
  404.  
  405.  
  406.  
  407.  
  408. #if has_signal
  409.  
  410. /*
  411.  *     Signal handling
  412.  *
  413.  * Standard C places too many restrictions on signal handlers.
  414.  * We obey as many of them as we can.
  415.  * Posix places fewer restrictions, and we are Posix-compatible here.
  416.  */
  417.  
  418. static sig_atomic_t volatile heldsignal, holdlevel;
  419.  
  420.     static signal_type
  421. catchsig(s)
  422.     int s;
  423. {
  424.     char const *sname;
  425.     char buf[BUFSIZ];
  426.  
  427. #if sig_zaps_handler
  428.     /* If a signal arrives before we reset the signal handler, we lose. */
  429.     VOID signal(s, SIG_IGN);
  430. #endif
  431.     if (holdlevel) {
  432.         heldsignal = s;
  433.         return;
  434.     }
  435.     ignoreints();
  436.     setrid();
  437.     if (!quietflag) {
  438.         sname = nil;
  439. #if has_sys_siglist && defined(NSIG)
  440.         if ((unsigned)s < NSIG) {
  441. #        ifndef sys_siglist
  442.             extern char const *sys_siglist[];
  443. #        endif
  444.         sname = sys_siglist[s];
  445.         }
  446. #else
  447.         switch (s) {
  448. #ifdef SIGHUP
  449.         case SIGHUP:    sname = "Hangup";  break;
  450. #endif
  451. #ifdef SIGINT
  452.         case SIGINT:    sname = "Interrupt";  break;
  453. #endif
  454. #ifdef SIGPIPE
  455.         case SIGPIPE:    sname = "Broken pipe";  break;
  456. #endif
  457. #ifdef SIGQUIT
  458.         case SIGQUIT:    sname = "Quit";  break;
  459. #endif
  460. #ifdef SIGTERM
  461.         case SIGTERM:    sname = "Terminated";  break;
  462. #endif
  463. #ifdef SIGXCPU
  464.         case SIGXCPU:    sname = "Cputime limit exceeded";  break;
  465. #endif
  466. #ifdef SIGXFSZ
  467.         case SIGXFSZ:    sname = "Filesize limit exceeded";  break;
  468. #endif
  469.         }
  470. #endif
  471.         if (sname)
  472.         VOID sprintf(buf, "\nRCS: %s.  Cleaning up.\n", sname);
  473.         else
  474.         VOID sprintf(buf, "\nRCS: Signal %d.  Cleaning up.\n", s);
  475.         VOID write(STDERR_FILENO, buf, strlen(buf));
  476.     }
  477.     exiterr();
  478. }
  479.  
  480.     void
  481. ignoreints()
  482. {
  483.     ++holdlevel;
  484. }
  485.  
  486.     void
  487. restoreints()
  488. {
  489.     if (!--holdlevel && heldsignal)
  490.         VOID catchsig(heldsignal);
  491. }
  492.  
  493.  
  494. static int const sig[] = {
  495. #ifdef SIGHUP
  496.     SIGHUP,
  497. #endif
  498. #ifdef SIGINT
  499.     SIGINT,
  500. #endif
  501. #ifdef SIGPIPE
  502.     SIGPIPE,
  503. #endif
  504. #ifdef SIGQUIT
  505.     SIGQUIT,
  506. #endif
  507. #ifdef SIGTERM
  508.     SIGTERM,
  509. #endif
  510. #ifdef SIGXCPU
  511.     SIGXCPU,
  512. #endif
  513. #ifdef SIGXFSZ
  514.     SIGXFSZ,
  515. #endif
  516. };
  517. #define SIGS (sizeof(sig)/sizeof(*sig))
  518.  
  519.  
  520. #if has_sigaction
  521.  
  522.     static void
  523.   check_sig(r)
  524.     int r;
  525.   {
  526.     if (r != 0)
  527.         efaterror("signal");
  528.   }
  529.  
  530.     static void
  531.   setup_catchsig()
  532.   {
  533.     register int i;
  534.     sigset_t blocked;
  535.     struct sigaction act;
  536.  
  537.     check_sig(sigemptyset(&blocked));
  538.     for (i=SIGS; 0<=--i; )
  539.         check_sig(sigaddset(&blocked, sig[i]));
  540.     for (i=SIGS; 0<=--i; ) {
  541.         check_sig(sigaction(sig[i], (struct sigaction*)nil, &act));
  542.         if (act.sa_handler != SIG_IGN) {
  543.             act.sa_handler = catchsig;
  544.             act.sa_mask = blocked;
  545.             check_sig(sigaction(sig[i], &act, (struct sigaction*)nil));
  546.         }
  547.     }
  548.   }
  549.  
  550. #else
  551. #if has_sigblock
  552.  
  553.     static void
  554.   setup_catchsig()
  555.   {
  556.     register int i;
  557.     int mask;
  558.  
  559.     mask = 0;
  560.     for (i=SIGS; 0<=--i; )
  561.         mask |= sigmask(sig[i]);
  562.     mask = sigblock(mask);
  563.     for (i=SIGS; 0<=--i; )
  564.         if (
  565.             signal(sig[i], catchsig) == SIG_IGN  &&
  566.             signal(sig[i], SIG_IGN) != catchsig
  567.         )
  568.             faterror("signal catcher failure");
  569.     VOID sigsetmask(mask);
  570.   }
  571.  
  572. #else
  573.  
  574.     static void
  575.   setup_catchsig()
  576.   {
  577.     register i;
  578.  
  579.     for (i=SIGS; 0<=--i; )
  580.         if (
  581.             signal(sig[i], SIG_IGN) != SIG_IGN  &&
  582.             signal(sig[i], catchsig) != SIG_IGN
  583.         )
  584.             faterror("signal catcher failure");
  585.   }
  586.  
  587. #endif
  588. #endif
  589.  
  590.     void
  591. catchints()
  592. {
  593.     static int catching_ints;
  594.     if (!catching_ints) {
  595.         catching_ints = true;
  596.         setup_catchsig();
  597.     }
  598. }
  599.  
  600. #endif /* has_signal */
  601.  
  602.  
  603.     void
  604. fastcopy(inf,outf)
  605.     register RILE *inf;
  606.     FILE *outf;
  607. /* Function: copies the remainder of file inf to outf.
  608.  */
  609. {
  610. #if large_memory
  611. #    if has_mmap
  612.         awrite((char const*)inf->ptr, (size_t)(inf->lim - inf->ptr), outf);
  613.         inf->ptr = inf->lim;
  614. #    else
  615.         for (;;) {
  616.         awrite((char const*)inf->ptr, (size_t)(inf->readlim - inf->ptr), outf);
  617.         inf->ptr = inf->readlim;
  618.         if (inf->ptr == inf->lim)
  619.             break;
  620.         VOID Igetmore(inf);
  621.         }
  622. #    endif
  623. #else
  624.     char buf[BUFSIZ*8];
  625.     register fread_type rcount;
  626.  
  627.         /*now read the rest of the file in blocks*/
  628.     while (!feof(inf)) {
  629.         if (!(rcount = Fread(buf,sizeof(*buf),sizeof(buf),inf))) {
  630.             testIerror(inf);
  631.             return;
  632.         }
  633.         awrite(buf, (size_t)rcount, outf);
  634.         }
  635. #endif
  636. }
  637.  
  638. #ifndef SSIZE_MAX
  639.  /* This does not work in #ifs, but it's good enough for us.  */
  640.  /* Underestimating SSIZE_MAX may slow us down, but it won't break us.  */
  641. #    define SSIZE_MAX ((unsigned)-1 >> 1)
  642. #endif
  643.  
  644.     void
  645. awrite(buf, chars, f)
  646.     char const *buf;
  647.     size_t chars;
  648.     FILE *f;
  649. {
  650.     /* Posix 1003.1-1990 ssize_t hack */
  651.     while (SSIZE_MAX < chars) {
  652.         if (Fwrite(buf, sizeof(*buf), SSIZE_MAX, f)  !=  SSIZE_MAX)
  653.             Oerror();
  654.         buf += SSIZE_MAX;
  655.         chars -= SSIZE_MAX;
  656.     }
  657.  
  658.     if (Fwrite(buf, sizeof(*buf), chars, f)  !=  chars)
  659.         Oerror();
  660. }
  661.  
  662.  
  663.  
  664.  
  665.  
  666.     static int
  667. movefd(old, new)
  668.     int old, new;
  669. {
  670.     if (old < 0  ||  old == new)
  671.         return old;
  672. #    ifdef F_DUPFD
  673.         new = fcntl(old, F_DUPFD, new);
  674. #    else
  675.         new = dup2(old, new);
  676. #    endif
  677.     return close(old)==0 ? new : -1;
  678. }
  679.  
  680.     static int
  681. fdreopen(fd, file, flags)
  682.     int fd;
  683.     char const *file;
  684.     int flags;
  685. {
  686.     int newfd;
  687.     VOID close(fd);
  688.     newfd =
  689. #if !open_can_creat
  690.         flags&O_CREAT ? creat(file, S_IRUSR|S_IWUSR) :
  691. #endif
  692.         open(file, flags, S_IRUSR|S_IWUSR);
  693.     return movefd(newfd, fd);
  694. }
  695.  
  696. #if !has_spawn
  697.     static void
  698. tryopen(fd,file,flags)
  699.     int fd, flags;
  700.     char const *file;
  701. {
  702.     if (file  &&  fdreopen(fd,file,flags) != fd)
  703.         efaterror(file);
  704. }
  705. #else
  706.     static int
  707. tryopen(fd,file,flags)
  708.     int fd, flags;
  709.     char const *file;
  710. {
  711.     int newfd = -1;
  712.     if (file  &&  ((newfd=dup(fd)) < 0  ||  fdreopen(fd,file,flags) != fd))
  713.         efaterror(file);
  714.     return newfd;
  715. }
  716.     static void
  717. redirect(old, new)
  718.     int old, new;
  719. {
  720.     if (0 <= old   &&   (close(new) != 0  ||  movefd(old,new) < 0))
  721.         efaterror("spawn I/O redirection");
  722. }
  723. #endif
  724.  
  725.  
  726.  
  727. #if !has_fork && !has_spawn
  728.     static void
  729. bufargcat(b, c, s)
  730.     register struct buf *b;
  731.     int c;
  732.     register char const *s;
  733. /* Append to B a copy of C, plus a quoted copy of S.  */
  734. {
  735.     register char *p;
  736.     register char const *t;
  737.     size_t bl, sl;
  738.  
  739.     for (t=s, sl=0;  *t;  )
  740.         sl  +=  3*(*t++=='\'') + 1;
  741.     bl = strlen(b->string);
  742.     bufrealloc(b, bl + sl + 4);
  743.     p = b->string + bl;
  744.     *p++ = c;
  745.     *p++ = '\'';
  746.     while (*s) {
  747.         if (*s == '\'') {
  748.             *p++ = '\'';
  749.             *p++ = '\\';
  750.             *p++ = '\'';
  751.         }
  752.         *p++ = *s++;
  753.     }
  754.     *p++ = '\'';
  755.     *p = 0;
  756. }
  757. #endif
  758.  
  759. /*
  760. * Run a command specified by the strings in 'inoutargs'.
  761. * inoutargs[0], if nonnil, is the name of the input file.
  762. * inoutargs[1], if nonnil, is the name of the output file.
  763. * inoutargs[2..] form the command to be run.
  764. */
  765.     int
  766. runv(inoutargs)
  767.     char const **inoutargs;
  768. {
  769.     register char const **p;
  770.     int wstatus;
  771.  
  772.     oflush();
  773.     eflush();
  774.     {
  775. #if has_spawn
  776.     int in, out;
  777.     p = inoutargs;
  778.     in = tryopen(STDIN_FILENO, *p++, O_BINARY|O_RDONLY);
  779.     out = tryopen(STDOUT_FILENO, *p++, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY);
  780.     wstatus = spawn_RCS(0, *p, (char*const*)p);
  781.     if (wstatus == -1  &&  errno == ENOEXEC) {
  782.         *--p = RCS_SHELL;
  783.         wstatus = spawnv(0, *p, (char*const*)p);
  784.     }
  785.     redirect(in, STDIN_FILENO);
  786.     redirect(out, STDOUT_FILENO);
  787. #else
  788. #if has_fork
  789.     pid_t pid;
  790. #    if !has_waitpid
  791.         pid_t w;
  792. #    endif
  793.     if (!(pid = vfork())) {
  794.         p = inoutargs;
  795.         tryopen(STDIN_FILENO, *p++, O_BINARY|O_RDONLY);
  796.         tryopen(STDOUT_FILENO, *p++, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY);
  797.         VOID exec_RCS(*p, (char*const*)p);
  798.         if (errno == ENOEXEC) {
  799.             *--p = RCS_SHELL;
  800.             VOID execv(*p, (char*const*)p);
  801.         }
  802.         VOID write(STDERR_FILENO, *p, strlen(*p));
  803.         VOID write(STDERR_FILENO, ": not found\n", 12);
  804.         _exit(EXIT_TROUBLE);
  805.     }
  806.     if (pid < 0)
  807.         efaterror("fork");
  808. #    if has_waitpid
  809.         if (waitpid(pid, &wstatus, 0) < 0)
  810.             efaterror("waitpid");
  811. #    else
  812.         do {
  813.             if ((w = wait(&wstatus)) < 0)
  814.                 efaterror("wait");
  815.         } while (w != pid);
  816. #    endif
  817. #else
  818.     static struct buf b;
  819.  
  820.     /* Use system().  On many hosts system() discards signals.  Yuck!  */
  821.     p = inoutargs+2;
  822.     bufscpy(&b, *p);
  823.     while (*++p)
  824.         bufargcat(&b, ' ', *p);
  825.     if (inoutargs[0])
  826.         bufargcat(&b, '<', inoutargs[0]);
  827.     if (inoutargs[1])
  828.         bufargcat(&b, '>', inoutargs[1]);
  829.     wstatus = system(b.string);
  830. #endif
  831. #endif
  832.     }
  833.     if (!WIFEXITED(wstatus))
  834.         faterror("%s failed", inoutargs[2]);
  835.     return WEXITSTATUS(wstatus);
  836. }
  837.  
  838. #define CARGSMAX 20
  839. /*
  840. * Run a command.
  841. * The first two arguments are the input and output files (if nonnil);
  842. * the rest specify the command and its arguments.
  843. */
  844.     int
  845. #if has_prototypes
  846. run(char const *infile, char const *outfile, ...)
  847. #else
  848.     /*VARARGS2*/
  849. run(infile, outfile, va_alist)
  850.     char const *infile;
  851.     char const *outfile;
  852.     va_dcl
  853. #endif
  854. {
  855.     va_list ap;
  856.     char const *rgargs[CARGSMAX];
  857.     register i = 0;
  858.     rgargs[0] = infile;
  859.     rgargs[1] = outfile;
  860.     vararg_start(ap, outfile);
  861.     for (i = 2;  (rgargs[i++] = va_arg(ap, char const*));  )
  862.         if (CARGSMAX <= i)
  863.             faterror("too many command arguments");
  864.     va_end(ap);
  865.     return runv(rgargs);
  866. }
  867.  
  868.  
  869.     char const *
  870. date2str(date, datebuf)
  871.     char const date[datesize];
  872.     char datebuf[datesize];
  873. /*
  874. * Format a user-readable form of the RCS format DATE into the buffer DATEBUF.
  875. * Yield DATEBUF.
  876. */
  877. {
  878.     register char const *p = date;
  879.  
  880.     while (*p++ != '.')
  881.         ;
  882.     VOID sprintf(datebuf,
  883.         "19%.*s/%.2s/%.2s %.2s:%.2s:%s" +
  884.             (date[2]=='.' && VERSION(5)<=RCSversion  ?  0  :  2),
  885.         (int)(p-date-1), date,
  886.         p, p+3, p+6, p+9, p+12
  887.     );
  888.     return datebuf;
  889. }
  890.  
  891.  
  892. int RCSversion;
  893.  
  894.     void
  895. setRCSversion(str)
  896.     char const *str;
  897. {
  898.     static int oldversion;
  899.  
  900.     register char const *s = str + 2;
  901.     int v = VERSION_DEFAULT;
  902.  
  903.     if (oldversion)
  904.         redefined('V');
  905.     oldversion = true;
  906.  
  907.     if (*s) {
  908.         v = 0;
  909.         while (isdigit(*s))
  910.             v  =  10*v + *s++ - '0';
  911.         if (*s)
  912.             faterror("%s isn't a number", str);
  913.         if (v < VERSION_min  ||  VERSION_max < v)
  914.             faterror("%s out of range %d..%d", str, VERSION_min, VERSION_max);
  915.     }
  916.  
  917.     RCSversion = VERSION(v);
  918. }
  919.  
  920.     int
  921. getRCSINIT(argc, argv, newargv)
  922.     int argc;
  923.     char **argv, ***newargv;
  924. {
  925.     register char *p, *q, **pp;
  926.     unsigned n;
  927.  
  928.     if (!(q = cgetenv("RCSINIT")))
  929.         *newargv = argv;
  930.     else {
  931.         n = argc + 2;
  932.         /*
  933.          * Count spaces in RCSINIT to allocate a new arg vector.
  934.          * This is an upper bound, but it's OK even if too large.
  935.          */
  936.         for (p = q;  ;  ) {
  937.             switch (*p++) {
  938.                 default:
  939.                 continue;
  940.  
  941.                 case ' ':
  942.                 case '\b': case '\f': case '\n':
  943.                 case '\r': case '\t': case '\v':
  944.                 n++;
  945.                 continue;
  946.  
  947.                 case '\0':
  948.                 break;
  949.             }
  950.             break;
  951.         }
  952.         *newargv = pp = tnalloc(char*, n);
  953.         *pp++ = *argv++; /* copy program name */
  954.         for (p = q;  ;  ) {
  955.             for (;;) {
  956.                 switch (*q) {
  957.                     case '\0':
  958.                     goto copyrest;
  959.  
  960.                     case ' ':
  961.                     case '\b': case '\f': case '\n':
  962.                     case '\r': case '\t': case '\v':
  963.                     q++;
  964.                     continue;
  965.                 }
  966.                 break;
  967.             }
  968.             *pp++ = p;
  969.             ++argc;
  970.             for (;;) {
  971.                 switch ((*p++ = *q++)) {
  972.                     case '\0':
  973.                     goto copyrest;
  974.  
  975.                     case '\\':
  976.                     if (!*q)
  977.                         goto copyrest;
  978.                     p[-1] = *q++;
  979.                     continue;
  980.  
  981.                     default:
  982.                     continue;
  983.  
  984.                     case ' ':
  985.                     case '\b': case '\f': case '\n':
  986.                     case '\r': case '\t': case '\v':
  987.                     break;
  988.                 }
  989.                 break;
  990.             }
  991.             p[-1] = '\0';
  992.         }
  993.         copyrest:
  994.         while ((*pp++ = *argv++))
  995.             ;
  996.     }
  997.     return argc;
  998. }
  999.  
  1000.  
  1001. #define cacheid(E) static uid_t i; static int s; if (!s){ s=1; i=(E); } return i
  1002.  
  1003. #if has_getuid
  1004.     uid_t ruid() { cacheid(getuid()); }
  1005. #endif
  1006. #if has_setuid
  1007.     uid_t euid() { cacheid(geteuid()); }
  1008. #endif
  1009.  
  1010.  
  1011. #if has_setuid
  1012.  
  1013. /*
  1014.  * Setuid execution really works only with Posix 1003.1a Draft 5 seteuid(),
  1015.  * because it lets us switch back and forth between arbitrary users.
  1016.  * If seteuid() doesn't work, we fall back on setuid(),
  1017.  * which works if saved setuid is supported,
  1018.  * unless the real or effective user is root.
  1019.  * This area is such a mess that we always check switches at runtime.
  1020.  */
  1021.  
  1022.     static void
  1023. set_uid_to(u)
  1024.     uid_t u;
  1025. /* Become user u.  */
  1026. {
  1027.     static int looping;
  1028.  
  1029.     if (euid() == ruid())
  1030.         return;
  1031. #if (has_fork||has_spawn) && DIFF_ABSOLUTE
  1032.     if (seteuid(u) != 0)
  1033.         efaterror("setuid");
  1034. #endif
  1035.     if (geteuid() != u) {
  1036.         if (looping)
  1037.             return;
  1038.         looping = true;
  1039.         faterror("root setuid not supported" + (u?5:0));
  1040.     }
  1041. }
  1042.  
  1043. static int stick_with_euid;
  1044.  
  1045.     void
  1046. /* Ignore all calls to seteid() and setrid().  */
  1047. nosetid()
  1048. {
  1049.     stick_with_euid = true;
  1050. }
  1051.  
  1052.     void
  1053. seteid()
  1054. /* Become effective user.  */
  1055. {
  1056.     if (!stick_with_euid)
  1057.         set_uid_to(euid());
  1058. }
  1059.  
  1060.     void
  1061. setrid()
  1062. /* Become real user.  */
  1063. {
  1064.     if (!stick_with_euid)
  1065.         set_uid_to(ruid());
  1066. }
  1067. #endif
  1068. @
  1069.  
  1070.  
  1071. 5.10.1.1
  1072. log
  1073. @Start of the AMIGA port of RCS 5.6. I call it HWGRCS now ;^)
  1074. @
  1075. text
  1076. @d2 1
  1077. a2 1
  1078.  *               RCS utilities
  1079. d35 1
  1080. a35 1
  1081.  * Revision 5.10  1991/10/07  17:32:46    eggert
  1082. d67 1
  1083. a67 1
  1084.  * Add setuid support.    Permit multiple locks per user.
  1085. d78 1
  1086. a78 1
  1087.  *
  1088. d81 1
  1089. a81 1
  1090.  *
  1091. d86 1
  1092. a86 1
  1093.  *
  1094. d90 1
  1095. a90 1
  1096.  *
  1097. d92 1
  1098. a92 1
  1099.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf
  1100. d94 1
  1101. a94 1
  1102.  *
  1103. d97 1
  1104. a97 1
  1105.  *
  1106. d103 1
  1107. a103 1
  1108.  *
  1109. d302 1
  1110. a302 1
  1111.                 &&    !(name = cgetenv("USER")))
  1112. d308 2
  1113. a309 2
  1114.                 &&    !(name = cgetenv("USER"))
  1115.                 &&    !(name = getlogin())
  1116. d554 1
  1117. a554 1
  1118.     /*now read the rest of the file in blocks*/
  1119. d561 1
  1120. a561 1
  1121.     }
  1122. d592 1
  1123. a592 1
  1124. #if has_spawn || has_fork
  1125. d651 1
  1126. a651 1
  1127. #endif
  1128. d667 1
  1129. a667 1
  1130.         sl  +=    3*(*t++=='\'') + 1;
  1131. a701 6
  1132. #ifdef AMIGA
  1133.     /* Lousy style, I know. But I don't want to patch into the header for this */
  1134.     int AMIGArunv(const char **args);
  1135.  
  1136.     wstatus = AMIGArunv(inoutargs);
  1137. #else
  1138. a758 1
  1139. #endif
  1140. a854 3
  1141. #ifdef AMIGA
  1142.     if (!(q = cgetenv("RCS/INIT")))
  1143. #else
  1144. a855 1
  1145. #endif
  1146. @
  1147.  
  1148.  
  1149. 5.10.1.2
  1150. log
  1151. @Changed all checks for AMIGA to _AMIGA. This is more standard like
  1152. and helps future updates. Major patch cleanup on the way.
  1153. [Note: Added a VOID_CLOSEDIR define for this global change, too!]
  1154. @
  1155. text
  1156. @d2 1
  1157. a2 1
  1158.  *                     RCS utilities
  1159. d35 1
  1160. a35 4
  1161.  * Revision 5.10.1.1  1993/01/18  14:36:30  heinz
  1162.  * Start of the AMIGA port of RCS 5.6. I call it HWGRCS now ;^)
  1163.  *
  1164.  * Revision 5.10  1991/10/07  17:32:46  eggert
  1165. d67 1
  1166. a67 1
  1167.  * Add setuid support.  Permit multiple locks per user.
  1168. d139 1
  1169. a139 1
  1170. libId(utilId, "$Id: rcsutil.c,v 5.10.1.1 1993/01/18 14:36:30 heinz Exp heinz $")
  1171. d142 1
  1172. a142 1
  1173.         int
  1174. d144 2
  1175. a145 2
  1176.         void const *s1, *s2;
  1177.         size_t n;
  1178. d147 8
  1179. a154 8
  1180.         register unsigned char const
  1181.                 *p1 = (unsigned char const*)s1,
  1182.                 *p2 = (unsigned char const*)s2;
  1183.         register size_t i = n;
  1184.         register int r = 0;
  1185.         while (i--  &&  !(r = (*p1++ - *p2++)))
  1186.                 ;
  1187.         return r;
  1188. d159 1
  1189. a159 1
  1190.         void *
  1191. d161 9
  1192. a169 9
  1193.         void *s1;
  1194.         void const *s2;
  1195.         size_t n;
  1196. {
  1197.         register char *p1 = (char*)s1;
  1198.         register char const *p2 = (char const*)s2;
  1199.         while (n--)
  1200.                 *p1++ = *p2++;
  1201.         return s1;
  1202. d174 1
  1203. a174 1
  1204.         malloc_type lintalloc;
  1205. d184 2
  1206. a185 2
  1207.         malloc_type alloc;
  1208.         struct alloclist *nextalloc;
  1209. d190 1
  1210. a190 1
  1211.         static malloc_type
  1212. d192 1
  1213. a192 1
  1214.         malloc_type p;
  1215. d194 3
  1216. a196 3
  1217.         if (!p)
  1218.                 faterror("out of memory");
  1219.         return p;
  1220. d199 1
  1221. a199 1
  1222.         malloc_type
  1223. d201 1
  1224. a201 1
  1225.         size_t size;
  1226. d204 1
  1227. a204 1
  1228.         return okalloc(malloc(size));
  1229. d207 1
  1230. a207 1
  1231.         malloc_type
  1232. d209 2
  1233. a210 2
  1234.         malloc_type ptr;
  1235.         size_t size;
  1236. d213 1
  1237. a213 1
  1238.         return okalloc(realloc(ptr, size));
  1239. d216 1
  1240. a216 1
  1241.         malloc_type
  1242. d218 1
  1243. a218 1
  1244.         malloc_type ptr;
  1245. d221 4
  1246. a224 4
  1247.         register struct alloclist *q = talloc(struct alloclist);
  1248.         q->nextalloc = alloced;
  1249.         alloced = q;
  1250.         return q->alloc = ptr;
  1251. d227 1
  1252. a227 1
  1253.         malloc_type
  1254. d229 1
  1255. a229 1
  1256.         size_t size;
  1257. d232 1
  1258. a232 1
  1259.         return fremember(testalloc(size));
  1260. d235 1
  1261. a235 1
  1262.         void
  1263. d239 7
  1264. a245 7
  1265.         register struct alloclist *p, *q;
  1266.         for (p = alloced;  p;  p = q) {
  1267.                 q = p->nextalloc;
  1268.                 tfree(p->alloc);
  1269.                 tfree(p);
  1270.         }
  1271.         alloced = nil;
  1272. d248 1
  1273. a248 1
  1274.         void
  1275. d250 1
  1276. a250 1
  1277.         register char const *f;
  1278. d253 1
  1279. a253 1
  1280.         register struct alloclist *p, **a = &alloced;
  1281. d255 5
  1282. a259 5
  1283.         while ((p = *a)->alloc  !=  f)
  1284.                 a = &p->nextalloc;
  1285.         *a = p->nextalloc;
  1286.         tfree(p->alloc);
  1287.         tfree(p);
  1288. d262 1
  1289. a262 1
  1290.         char *
  1291. d264 1
  1292. a264 1
  1293.         char const *s;
  1294. d267 1
  1295. a267 1
  1296.         return strcpy(tnalloc(char, strlen(s)+1), s);
  1297. d270 1
  1298. a270 1
  1299.         char *
  1300. d272 1
  1301. a272 1
  1302.         char const *s;
  1303. d275 1
  1304. a275 1
  1305.         return strcpy(ftnalloc(char, strlen(s)+1), s);
  1306. d278 1
  1307. a278 1
  1308.         char *
  1309. d280 1
  1310. a280 1
  1311.         char const *name;
  1312. d283 1
  1313. a283 1
  1314.         register char *p;
  1315. d285 1
  1316. a285 1
  1317.         return (p=getenv(name)) ? str_save(p) : p;
  1318. d288 1
  1319. a288 1
  1320.         char const *
  1321. d290 1
  1322. a290 1
  1323.         int suspicious;
  1324. d293 1
  1325. a293 1
  1326.         static char *name;
  1327. d295 17
  1328. a311 17
  1329.         if (!name) {
  1330.                 if (
  1331.                     /* Prefer getenv() unless suspicious; it's much faster.  */
  1332. #                   if getlogin_is_secure
  1333.                             (suspicious
  1334.                             ||
  1335.                                 !(name = cgetenv("LOGNAME"))
  1336.                             &&  !(name = cgetenv("USER")))
  1337.                         &&  !(name = getlogin())
  1338. #                   else
  1339.                         suspicious
  1340.                         ||
  1341.                                 !(name = cgetenv("LOGNAME"))
  1342.                             &&  !(name = cgetenv("USER"))
  1343.                             &&  !(name = getlogin())
  1344. #                   endif
  1345.                 ) {
  1346. d313 6
  1347. a318 6
  1348.                         struct passwd const *pw = getpwuid(ruid());
  1349.                         if (!pw)
  1350.                             faterror("no password entry for userid %lu",
  1351.                                      (unsigned long)ruid()
  1352.                             );
  1353.                         name = pw->pw_name;
  1354. d321 1
  1355. a321 1
  1356.                         faterror("setuid not supported");
  1357. d323 1
  1358. a323 1
  1359.                         faterror("Who are you?  Please set LOGNAME.");
  1360. d326 4
  1361. a329 4
  1362.                 }
  1363.                 checksid(name);
  1364.         }
  1365.         return name;
  1366. d338 1
  1367. a338 1
  1368.  *       Signal handling
  1369. d347 1
  1370. a347 1
  1371.         static signal_type
  1372. d349 1
  1373. a349 1
  1374.         int s;
  1375. d351 2
  1376. a352 2
  1377.         char const *sname;
  1378.         char buf[BUFSIZ];
  1379. d355 2
  1380. a356 2
  1381.         /* If a signal arrives before we reset the signal handler, we lose. */
  1382.         VOID signal(s, SIG_IGN);
  1383. d358 8
  1384. a365 8
  1385.         if (holdlevel) {
  1386.                 heldsignal = s;
  1387.                 return;
  1388.         }
  1389.         ignoreints();
  1390.         setrid();
  1391.         if (!quietflag) {
  1392.             sname = nil;
  1393. d367 6
  1394. a372 6
  1395.             if ((unsigned)s < NSIG) {
  1396. #               ifndef sys_siglist
  1397.                     extern char const *sys_siglist[];
  1398. #               endif
  1399.                 sname = sys_siglist[s];
  1400.             }
  1401. d374 1
  1402. a374 1
  1403.             switch (s) {
  1404. d376 1
  1405. a376 1
  1406.                 case SIGHUP:    sname = "Hangup";  break;
  1407. d379 1
  1408. a379 1
  1409.                 case SIGINT:    sname = "Interrupt";  break;
  1410. d382 1
  1411. a382 1
  1412.                 case SIGPIPE:   sname = "Broken pipe";  break;
  1413. d385 1
  1414. a385 1
  1415.                 case SIGQUIT:   sname = "Quit";  break;
  1416. d388 1
  1417. a388 1
  1418.                 case SIGTERM:   sname = "Terminated";  break;
  1419. d391 1
  1420. a391 1
  1421.                 case SIGXCPU:   sname = "Cputime limit exceeded";  break;
  1422. d394 1
  1423. a394 1
  1424.                 case SIGXFSZ:   sname = "Filesize limit exceeded";  break;
  1425. d396 1
  1426. a396 1
  1427.             }
  1428. d398 7
  1429. a404 7
  1430.             if (sname)
  1431.                 VOID sprintf(buf, "\nRCS: %s.  Cleaning up.\n", sname);
  1432.             else
  1433.                 VOID sprintf(buf, "\nRCS: Signal %d.  Cleaning up.\n", s);
  1434.             VOID write(STDERR_FILENO, buf, strlen(buf));
  1435.         }
  1436.         exiterr();
  1437. d407 1
  1438. a407 1
  1439.         void
  1440. d410 1
  1441. a410 1
  1442.         ++holdlevel;
  1443. d413 1
  1444. a413 1
  1445.         void
  1446. d416 2
  1447. a417 2
  1448.         if (!--holdlevel && heldsignal)
  1449.                 VOID catchsig(heldsignal);
  1450. d423 1
  1451. a423 1
  1452.         SIGHUP,
  1453. d426 1
  1454. a426 1
  1455.         SIGINT,
  1456. d429 1
  1457. a429 1
  1458.         SIGPIPE,
  1459. d432 1
  1460. a432 1
  1461.         SIGQUIT,
  1462. d435 1
  1463. a435 1
  1464.         SIGTERM,
  1465. d438 1
  1466. a438 1
  1467.         SIGXCPU,
  1468. d441 1
  1469. a441 1
  1470.         SIGXFSZ,
  1471. d449 1
  1472. a449 1
  1473.         static void
  1474. d451 1
  1475. a451 1
  1476.         int r;
  1477. d453 2
  1478. a454 2
  1479.         if (r != 0)
  1480.                 efaterror("signal");
  1481. d457 1
  1482. a457 1
  1483.         static void
  1484. d460 15
  1485. a474 15
  1486.         register int i;
  1487.         sigset_t blocked;
  1488.         struct sigaction act;
  1489.  
  1490.         check_sig(sigemptyset(&blocked));
  1491.         for (i=SIGS; 0<=--i; )
  1492.             check_sig(sigaddset(&blocked, sig[i]));
  1493.         for (i=SIGS; 0<=--i; ) {
  1494.             check_sig(sigaction(sig[i], (struct sigaction*)nil, &act));
  1495.             if (act.sa_handler != SIG_IGN) {
  1496.                     act.sa_handler = catchsig;
  1497.                     act.sa_mask = blocked;
  1498.                     check_sig(sigaction(sig[i], &act, (struct sigaction*)nil));
  1499.             }
  1500.         }
  1501. d480 1
  1502. a480 1
  1503.         static void
  1504. d483 2
  1505. a484 2
  1506.         register int i;
  1507.         int mask;
  1508. d486 11
  1509. a496 11
  1510.         mask = 0;
  1511.         for (i=SIGS; 0<=--i; )
  1512.                 mask |= sigmask(sig[i]);
  1513.         mask = sigblock(mask);
  1514.         for (i=SIGS; 0<=--i; )
  1515.                 if (
  1516.                     signal(sig[i], catchsig) == SIG_IGN  &&
  1517.                     signal(sig[i], SIG_IGN) != catchsig
  1518.                 )
  1519.                         faterror("signal catcher failure");
  1520.         VOID sigsetmask(mask);
  1521. d501 1
  1522. a501 1
  1523.         static void
  1524. d504 1
  1525. a504 1
  1526.         register i;
  1527. d506 6
  1528. a511 6
  1529.         for (i=SIGS; 0<=--i; )
  1530.                 if (
  1531.                     signal(sig[i], SIG_IGN) != SIG_IGN  &&
  1532.                     signal(sig[i], catchsig) != SIG_IGN
  1533.                 )
  1534.                         faterror("signal catcher failure");
  1535. d517 1
  1536. a517 1
  1537.         void
  1538. d520 5
  1539. a524 5
  1540.         static int catching_ints;
  1541.         if (!catching_ints) {
  1542.                 catching_ints = true;
  1543.                 setup_catchsig();
  1544.         }
  1545. d530 1
  1546. a530 1
  1547.         void
  1548. d532 2
  1549. a533 2
  1550.         register RILE *inf;
  1551.         FILE *outf;
  1552. d538 24
  1553. a561 24
  1554. #       if has_mmap
  1555.             awrite((char const*)inf->ptr, (size_t)(inf->lim - inf->ptr), outf);
  1556.             inf->ptr = inf->lim;
  1557. #       else
  1558.             for (;;) {
  1559.                 awrite((char const*)inf->ptr, (size_t)(inf->readlim - inf->ptr), outf);
  1560.                 inf->ptr = inf->readlim;
  1561.                 if (inf->ptr == inf->lim)
  1562.                     break;
  1563.                 VOID Igetmore(inf);
  1564.             }
  1565. #       endif
  1566. #else
  1567.         char buf[BUFSIZ*8];
  1568.         register fread_type rcount;
  1569.  
  1570.         /*now read the rest of the file in blocks*/
  1571.         while (!feof(inf)) {
  1572.                 if (!(rcount = Fread(buf,sizeof(*buf),sizeof(buf),inf))) {
  1573.                         testIerror(inf);
  1574.                         return;
  1575.                 }
  1576.                 awrite(buf, (size_t)rcount, outf);
  1577.         }
  1578. d568 1
  1579. a568 1
  1580. #       define SSIZE_MAX ((unsigned)-1 >> 1)
  1581. d571 1
  1582. a571 1
  1583.         void
  1584. d573 11
  1585. a583 11
  1586.         char const *buf;
  1587.         size_t chars;
  1588.         FILE *f;
  1589. {
  1590.         /* Posix 1003.1-1990 ssize_t hack */
  1591.         while (SSIZE_MAX < chars) {
  1592.                 if (Fwrite(buf, sizeof(*buf), SSIZE_MAX, f)  !=  SSIZE_MAX)
  1593.                         Oerror();
  1594.                 buf += SSIZE_MAX;
  1595.                 chars -= SSIZE_MAX;
  1596.         }
  1597. d585 2
  1598. a586 2
  1599.         if (Fwrite(buf, sizeof(*buf), chars, f)  !=  chars)
  1600.                 Oerror();
  1601. d593 1
  1602. a593 1
  1603.         static int
  1604. d595 1
  1605. a595 1
  1606.         int old, new;
  1607. d597 8
  1608. a604 8
  1609.         if (old < 0  ||  old == new)
  1610.                 return old;
  1611. #       ifdef F_DUPFD
  1612.                 new = fcntl(old, F_DUPFD, new);
  1613. #       else
  1614.                 new = dup2(old, new);
  1615. #       endif
  1616.         return close(old)==0 ? new : -1;
  1617. d607 1
  1618. a607 1
  1619.         static int
  1620. d609 7
  1621. a615 7
  1622.         int fd;
  1623.         char const *file;
  1624.         int flags;
  1625. {
  1626.         int newfd;
  1627.         VOID close(fd);
  1628.         newfd =
  1629. d617 1
  1630. a617 1
  1631.                 flags&O_CREAT ? creat(file, S_IRUSR|S_IWUSR) :
  1632. d619 2
  1633. a620 2
  1634.                 open(file, flags, S_IRUSR|S_IWUSR);
  1635.         return movefd(newfd, fd);
  1636. d624 1
  1637. a624 1
  1638.         static void
  1639. d626 2
  1640. a627 2
  1641.         int fd, flags;
  1642.         char const *file;
  1643. d629 2
  1644. a630 2
  1645.         if (file  &&  fdreopen(fd,file,flags) != fd)
  1646.                 efaterror(file);
  1647. d633 1
  1648. a633 1
  1649.         static int
  1650. d635 2
  1651. a636 2
  1652.         int fd, flags;
  1653.         char const *file;
  1654. d638 4
  1655. a641 4
  1656.         int newfd = -1;
  1657.         if (file  &&  ((newfd=dup(fd)) < 0  ||  fdreopen(fd,file,flags) != fd))
  1658.                 efaterror(file);
  1659.         return newfd;
  1660. d643 1
  1661. a643 1
  1662.         static void
  1663. d645 1
  1664. a645 1
  1665.         int old, new;
  1666. d647 2
  1667. a648 2
  1668.         if (0 <= old   &&   (close(new) != 0  ||  movefd(old,new) < 0))
  1669.                 efaterror("spawn I/O redirection");
  1670. d655 1
  1671. a655 1
  1672.         static void
  1673. d657 3
  1674. a659 3
  1675.         register struct buf *b;
  1676.         int c;
  1677.         register char const *s;
  1678. d662 21
  1679. a682 21
  1680.         register char *p;
  1681.         register char const *t;
  1682.         size_t bl, sl;
  1683.  
  1684.         for (t=s, sl=0;  *t;  )
  1685.                 sl  +=  3*(*t++=='\'') + 1;
  1686.         bl = strlen(b->string);
  1687.         bufrealloc(b, bl + sl + 4);
  1688.         p = b->string + bl;
  1689.         *p++ = c;
  1690.         *p++ = '\'';
  1691.         while (*s) {
  1692.                 if (*s == '\'') {
  1693.                         *p++ = '\'';
  1694.                         *p++ = '\\';
  1695.                         *p++ = '\'';
  1696.                 }
  1697.                 *p++ = *s++;
  1698.         }
  1699.         *p++ = '\'';
  1700.         *p = 0;
  1701. d692 1
  1702. a692 1
  1703.         int
  1704. d694 1
  1705. a694 1
  1706.         char const **inoutargs;
  1707. d696 2
  1708. a697 2
  1709.         register char const **p;
  1710.         int wstatus;
  1711. d699 2
  1712. a700 2
  1713.         oflush();
  1714.         eflush();
  1715. d702 3
  1716. a704 3
  1717. #ifdef _AMIGA
  1718.         /* Lousy style, I know. But I don't want to patch into the header for this */
  1719.         int AMIGArunv(const char **args);
  1720. d706 1
  1721. a706 2
  1722.         /* This does the complete work to run a command. */
  1723.         wstatus = AMIGArunv(inoutargs);
  1724. d709 11
  1725. a719 11
  1726.         int in, out;
  1727.         p = inoutargs;
  1728.         in = tryopen(STDIN_FILENO, *p++, O_BINARY|O_RDONLY);
  1729.         out = tryopen(STDOUT_FILENO, *p++, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY);
  1730.         wstatus = spawn_RCS(0, *p, (char*const*)p);
  1731.         if (wstatus == -1  &&  errno == ENOEXEC) {
  1732.                 *--p = RCS_SHELL;
  1733.                 wstatus = spawnv(0, *p, (char*const*)p);
  1734.         }
  1735.         redirect(in, STDIN_FILENO);
  1736.         redirect(out, STDOUT_FILENO);
  1737. d722 42
  1738. a763 41
  1739.         pid_t pid;
  1740. #       if !has_waitpid
  1741.                 pid_t w;
  1742. #       endif
  1743.         if (!(pid = vfork())) {
  1744.                 p = inoutargs;
  1745.                 tryopen(STDIN_FILENO, *p++, O_BINARY|O_RDONLY);
  1746.                 tryopen(STDOUT_FILENO, *p++, O_BINARY|O_CREAT|O_TRUNC|O_WRONLY);
  1747.                 VOID exec_RCS(*p, (char*const*)p);
  1748.                 if (errno == ENOEXEC) {
  1749.                         *--p = RCS_SHELL;
  1750.                         VOID execv(*p, (char*const*)p);
  1751.                 }
  1752.                 VOID write(STDERR_FILENO, *p, strlen(*p));
  1753.                 VOID write(STDERR_FILENO, ": not found\n", 12);
  1754.                 _exit(EXIT_TROUBLE);
  1755.         }
  1756.         if (pid < 0)
  1757.                 efaterror("fork");
  1758. #       if has_waitpid
  1759.                 if (waitpid(pid, &wstatus, 0) < 0)
  1760.                         efaterror("waitpid");
  1761. #       else
  1762.                 do {
  1763.                         if ((w = wait(&wstatus)) < 0)
  1764.                                 efaterror("wait");
  1765.                 } while (w != pid);
  1766. #       endif
  1767. #else
  1768.         static struct buf b;
  1769.  
  1770.         /* Use system().  On many hosts system() discards signals.  Yuck!  */
  1771.         p = inoutargs+2;
  1772.         bufscpy(&b, *p);
  1773.         while (*++p)
  1774.                 bufargcat(&b, ' ', *p);
  1775.         if (inoutargs[0])
  1776.                 bufargcat(&b, '<', inoutargs[0]);
  1777.         if (inoutargs[1])
  1778.                 bufargcat(&b, '>', inoutargs[1]);
  1779.         wstatus = system(b.string);
  1780. a765 1
  1781. #endif /* _AMIGA */
  1782. d767 3
  1783. a769 3
  1784.         if (!WIFEXITED(wstatus))
  1785.                 faterror("%s failed", inoutargs[2]);
  1786.         return WEXITSTATUS(wstatus);
  1787. d778 1
  1788. a778 1
  1789.         int
  1790. d782 1
  1791. a782 1
  1792.         /*VARARGS2*/
  1793. d784 16
  1794. a799 16
  1795.         char const *infile;
  1796.         char const *outfile;
  1797.         va_dcl
  1798. #endif
  1799. {
  1800.         va_list ap;
  1801.         char const *rgargs[CARGSMAX];
  1802.         register i = 0;
  1803.         rgargs[0] = infile;
  1804.         rgargs[1] = outfile;
  1805.         vararg_start(ap, outfile);
  1806.         for (i = 2;  (rgargs[i++] = va_arg(ap, char const*));  )
  1807.                 if (CARGSMAX <= i)
  1808.                         faterror("too many command arguments");
  1809.         va_end(ap);
  1810.         return runv(rgargs);
  1811. d803 1
  1812. a803 1
  1813.         char const *
  1814. d805 2
  1815. a806 2
  1816.         char const date[datesize];
  1817.         char datebuf[datesize];
  1818. d812 1
  1819. a812 1
  1820.         register char const *p = date;
  1821. d814 9
  1822. a822 9
  1823.         while (*p++ != '.')
  1824.                 ;
  1825.         VOID sprintf(datebuf,
  1826.                 "19%.*s/%.2s/%.2s %.2s:%.2s:%s" +
  1827.                         (date[2]=='.' && VERSION(5)<=RCSversion  ?  0  :  2),
  1828.                 (int)(p-date-1), date,
  1829.                 p, p+3, p+6, p+9, p+12
  1830.         );
  1831.         return datebuf;
  1832. d828 1
  1833. a828 1
  1834.         void
  1835. d830 1
  1836. a830 1
  1837.         char const *str;
  1838. d832 1
  1839. a832 1
  1840.         static int oldversion;
  1841. d834 2
  1842. a835 2
  1843.         register char const *s = str + 2;
  1844.         int v = VERSION_DEFAULT;
  1845. d837 3
  1846. a839 3
  1847.         if (oldversion)
  1848.                 redefined('V');
  1849.         oldversion = true;
  1850. d841 9
  1851. a849 9
  1852.         if (*s) {
  1853.                 v = 0;
  1854.                 while (isdigit(*s))
  1855.                         v  =  10*v + *s++ - '0';
  1856.                 if (*s)
  1857.                         faterror("%s isn't a number", str);
  1858.                 if (v < VERSION_min  ||  VERSION_max < v)
  1859.                         faterror("%s out of range %d..%d", str, VERSION_min, VERSION_max);
  1860.         }
  1861. d851 1
  1862. a851 1
  1863.         RCSversion = VERSION(v);
  1864. d854 1
  1865. a854 1
  1866.         int
  1867. d856 2
  1868. a857 2
  1869.         int argc;
  1870.         char **argv, ***newargv;
  1871. d859 2
  1872. a860 2
  1873.         register char *p, *q, **pp;
  1874.         unsigned n;
  1875. d862 74
  1876. a935 80
  1877. #ifdef _AMIGA
  1878.         /* This is a change to keep ENV: clean on the Amiga. Every RCS
  1879.            specific environment should be in ENV:RCS! While this is
  1880.            theoretically not necessary because RCS works anyway, I consider
  1881.            it good style. It keeps ENV: from being cluttered and doesn't
  1882.            slow down standard ENV: accesses by adding "just one more". */
  1883.  
  1884.         if (!(q = cgetenv("RCS/INIT")))
  1885. #else
  1886.         if (!(q = cgetenv("RCSINIT")))
  1887. #endif /* _AMIGA */
  1888.                 *newargv = argv;
  1889.         else {
  1890.                 n = argc + 2;
  1891.                 /*
  1892.                  * Count spaces in RCSINIT to allocate a new arg vector.
  1893.                  * This is an upper bound, but it's OK even if too large.
  1894.                  */
  1895.                 for (p = q;  ;  ) {
  1896.                         switch (*p++) {
  1897.                             default:
  1898.                                 continue;
  1899.  
  1900.                             case ' ':
  1901.                             case '\b': case '\f': case '\n':
  1902.                             case '\r': case '\t': case '\v':
  1903.                                 n++;
  1904.                                 continue;
  1905.  
  1906.                             case '\0':
  1907.                                 break;
  1908.                         }
  1909.                         break;
  1910.                 }
  1911.                 *newargv = pp = tnalloc(char*, n);
  1912.                 *pp++ = *argv++; /* copy program name */
  1913.                 for (p = q;  ;  ) {
  1914.                         for (;;) {
  1915.                                 switch (*q) {
  1916.                                     case '\0':
  1917.                                         goto copyrest;
  1918.  
  1919.                                     case ' ':
  1920.                                     case '\b': case '\f': case '\n':
  1921.                                     case '\r': case '\t': case '\v':
  1922.                                         q++;
  1923.                                         continue;
  1924.                                 }
  1925.                                 break;
  1926.                         }
  1927.                         *pp++ = p;
  1928.                         ++argc;
  1929.                         for (;;) {
  1930.                                 switch ((*p++ = *q++)) {
  1931.                                     case '\0':
  1932.                                         goto copyrest;
  1933.  
  1934.                                     case '\\':
  1935.                                         if (!*q)
  1936.                                                 goto copyrest;
  1937.                                         p[-1] = *q++;
  1938.                                         continue;
  1939.  
  1940.                                     default:
  1941.                                         continue;
  1942.  
  1943.                                     case ' ':
  1944.                                     case '\b': case '\f': case '\n':
  1945.                                     case '\r': case '\t': case '\v':
  1946.                                         break;
  1947.                                 }
  1948.                                 break;
  1949.                         }
  1950.                         p[-1] = '\0';
  1951.                 }
  1952.             copyrest:
  1953.                 while ((*pp++ = *argv++))
  1954.                         ;
  1955.         }
  1956.         return argc;
  1957. d942 1
  1958. a942 1
  1959.         uid_t ruid() { cacheid(getuid()); }
  1960. d945 1
  1961. a945 1
  1962.         uid_t euid() { cacheid(geteuid()); }
  1963. d960 1
  1964. a960 1
  1965.         static void
  1966. d962 1
  1967. a962 1
  1968.         uid_t u;
  1969. d965 1
  1970. a965 1
  1971.         static int looping;
  1972. d967 2
  1973. a968 2
  1974.         if (euid() == ruid())
  1975.                 return;
  1976. d970 2
  1977. a971 2
  1978.         if (seteuid(u) != 0)
  1979.                 efaterror("setuid");
  1980. d973 6
  1981. a978 6
  1982.         if (geteuid() != u) {
  1983.                 if (looping)
  1984.                         return;
  1985.                 looping = true;
  1986.                 faterror("root setuid not supported" + (u?5:0));
  1987.         }
  1988. d983 1
  1989. a983 1
  1990.         void
  1991. d987 1
  1992. a987 1
  1993.         stick_with_euid = true;
  1994. d990 1
  1995. a990 1
  1996.         void
  1997. d994 2
  1998. a995 2
  1999.         if (!stick_with_euid)
  2000.                 set_uid_to(euid());
  2001. d998 1
  2002. a998 1
  2003.         void
  2004. d1002 2
  2005. a1003 2
  2006.         if (!stick_with_euid)
  2007.                 set_uid_to(ruid());
  2008. @
  2009.  
  2010.  
  2011. 5.10.1.3
  2012. log
  2013. @Some cosmetic changes to prepare for test diffing to the RCS5.6.0.1
  2014. sources.
  2015. @
  2016. text
  2017. @a34 5
  2018.  * Revision 5.10.1.2  1993/12/18  16:12:22  heinz
  2019.  * Changed all checks for AMIGA to _AMIGA. This is more standard like
  2020.  * and helps future updates. Major patch cleanup on the way.
  2021.  * [Note: Added a VOID_CLOSEDIR define for this global change, too!]
  2022.  *
  2023. d142 1
  2024. a142 1
  2025. libId(utilId, "$Id: rcsutil.c,v 5.10.1.2 1993/12/18 16:12:22 heinz Exp heinz $")
  2026. d595 1
  2027. a595 8
  2028.  
  2029. #ifndef _AMIGA
  2030. /* We don't have spawn or fork on the Amiga, so we don't need this stuff!
  2031.    Leaving it in would only create compile problems. Actually this applies
  2032.    to any host, so it IMHO should be an: "ifdef has_spawn || has_fork".
  2033.    But for now it is an Amiga change only!
  2034. */
  2035.  
  2036. d654 1
  2037. a654 2
  2038. #endif /* _AMIGA */
  2039.  
  2040. a705 7
  2041. /* As the Amiga does not have fork(), we have to do it differently. I use
  2042.    one of my support routines, but that is not the only way to do it. One
  2043.    might as well create something out of system() or System(). Whatever you
  2044.    want. I don't use system here, because I think it behaves rather dim in
  2045.    SAS/C 6.3. If you like it, try it.
  2046. */
  2047.  
  2048. d867 5
  2049. a871 6
  2050. /* This is a change to keep ENV: clean on the Amiga. Every RCS
  2051.    specific environment should be in ENV:RCS! While this is
  2052.    theoretically not necessary because RCS works anyway, I consider
  2053.    it good style. It keeps ENV: from being cluttered and doesn't
  2054.    slow down standard ENV: accesses by adding "just one more var".
  2055. */
  2056. @
  2057.  
  2058.  
  2059. 5.10.1.4
  2060. log
  2061. @Put in the change by Paul Eggert.
  2062. @
  2063. text
  2064. @a34 4
  2065.  * Revision 5.10.1.3  1993/12/18  17:17:59  heinz
  2066.  * Some cosmetic changes to prepare for test diffing to the RCS5.6.0.1
  2067.  * sources.
  2068.  *
  2069. d147 1
  2070. a147 1
  2071. libId(utilId, "$Id: rcsutil.c,v 5.10.1.3 1993/12/18 17:17:59 heinz Exp heinz $")
  2072. d601 6
  2073. a606 1
  2074. #if has_fork || has_spawn
  2075. d666 1
  2076. d670 1
  2077. a670 1
  2078. #else /* !has_fork && !has_spawn */
  2079. @
  2080.  
  2081.  
  2082. 5.10.1.5
  2083. log
  2084. @getRCSINIT now ignores RCS_link and tries to use a command
  2085. specific RCS/INIT.
  2086. @
  2087. text
  2088. @a34 3
  2089.  * Revision 5.10.1.4  1994/01/06  11:33:27  heinz
  2090.  * Put in the change by Paul Eggert.
  2091.  *
  2092. d151 1
  2093. a151 1
  2094. libId(utilId, "$Id: rcsutil.c,v 5.10.1.4 1994/01/06 11:33:27 heinz Exp heinz $")
  2095. d885 1
  2096. a885 10
  2097. /*
  2098.    First, we remove all command line references to RCS_link here.
  2099.    They can come from filename expansion in the startup and disrupt
  2100.    normal RCS processing.
  2101.  
  2102.    The we check for RCS[/]INIT_<prgname> and only if this one does not
  2103.    exist, we check for RCS[/]INIT. This allows the user to have different
  2104.    preferences for the different commands.
  2105.  
  2106.    This is a change to keep ENV: clean on the Amiga. Every RCS
  2107. a889 1
  2108.  
  2109. a890 17
  2110.         AMIGA_ignorercslink(&argc, argv);
  2111.  
  2112. #define RCSINITNAME     "RCS/INIT"
  2113.         {
  2114.             char buf[BUFSIZ];
  2115.  
  2116.             strcpy(buf, RCSINITNAME);
  2117.             strcat(buf, "_");
  2118.             strcat(buf, argv[0]);
  2119.  
  2120.             q = cgetenv(buf);
  2121.         }
  2122.  
  2123.         if(!q)
  2124.         {
  2125.             q = cgetenv(RCSINITNAME);
  2126.         } /* if */
  2127. d892 1
  2128. a892 1
  2129.         if(!q)
  2130. @
  2131.  
  2132.  
  2133. 5.10.1.6
  2134. log
  2135. @RCS_link preprocessing and inti variable stuff should work fine, now.
  2136. @
  2137. text
  2138. @a34 4
  2139.  * Revision 5.10.1.5  1994/02/11  19:53:26  heinz
  2140.  * getRCSINIT now ignores RCS_link and tries to use a command
  2141.  * specific RCS/INIT.
  2142.  *
  2143. d154 1
  2144. a154 1
  2145. libId(utilId, "$Id: rcsutil.c,v 5.10.1.5 1994/02/11 19:53:26 heinz Exp heinz $")
  2146. d891 1
  2147. a891 2
  2148.    normal RCS processing. We also check RCS_link for any option specs that
  2149.    we should use for the command.
  2150. d904 1
  2151. a904 1
  2152.         q = AMIGA_handlercslink(&argc, argv);
  2153. a906 1
  2154.         if(!q)
  2155. d912 1
  2156. a912 1
  2157.             strcat(buf, basename(argv[0]));
  2158. d915 1
  2159. a915 1
  2160.         } /* if */
  2161. @
  2162.  
  2163.  
  2164. 5.10.1.7
  2165. log
  2166. @delete bit is now handled more relaxed.
  2167. @
  2168. text
  2169. @a34 3
  2170.  * Revision 5.10.1.6  1994/03/14  09:22:53  heinz
  2171.  * RCS_link preprocessing and inti variable stuff should work fine, now.
  2172.  *
  2173. d158 1
  2174. a158 1
  2175. libId(utilId, "$Id: rcsutil.c,v 5.10.1.6 1994/03/14 09:22:53 heinz Exp heinz $")
  2176. a636 8
  2177. #ifdef _AMIGA
  2178. /* We want the delete bit, too! */
  2179.  
  2180. #if !open_can_creat
  2181.                 flags&O_CREAT ? creat(file, S_IRUSR|S_IWUSR|S_IDUSR) :
  2182. #endif
  2183.                 open(file, flags, S_IRUSR|S_IWUSR|S_IDUSR);
  2184. #else
  2185. a640 1
  2186. #endif /* _AMIGA */
  2187. @
  2188.  
  2189.  
  2190.  
  2191.  
  2192.  
  2193.  
  2194.  
  2195.  
  2196.  
  2197.  
  2198.  
  2199.  
  2200.  
  2201.  
  2202.  
  2203.  
  2204.  
  2205.  
  2206.  
  2207.  
  2208.  
  2209.  
  2210.  
  2211.  
  2212.  
  2213.  
  2214.  
  2215.  
  2216.  
  2217.  
  2218.  
  2219.  
  2220.  
  2221.  
  2222.  
  2223.  
  2224.  
  2225.  
  2226.  
  2227.  
  2228.  
  2229.  
  2230.  
  2231.  
  2232.  
  2233.  
  2234.  
  2235.  
  2236.  
  2237.  
  2238.  
  2239.  
  2240.  
  2241.  
  2242.  
  2243.  
  2244.  
  2245.  
  2246.  
  2247.  
  2248.  
  2249.  
  2250.  
  2251.  
  2252.  
  2253.  
  2254.  
  2255.  
  2256.  
  2257.  
  2258.  
  2259.  
  2260.  
  2261.  
  2262.  
  2263.  
  2264.  
  2265.  
  2266.  
  2267.  
  2268.  
  2269.  
  2270.  
  2271.  
  2272.