home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD2.bin / bbs / gnu / rcs-5.6.0.1-src.lha / rcs-5.6.0.1 / src / rcsutil.c < prev    next >
C/C++ Source or Header  |  1991-11-22  |  20KB  |  995 lines

  1. /*
  2.  *                     RCS utilities
  3.  */
  4.  
  5. /* Copyright (C) 1982, 1988, 1989 Walter Tichy
  6.    Copyright 1990, 1991 by Paul Eggert
  7.    Distributed under license by the Free Software Foundation, Inc.
  8.  
  9. This file is part of RCS.
  10.  
  11. RCS is free software; you can redistribute it and/or modify
  12. it under the terms of the GNU General Public License as published by
  13. the Free Software Foundation; either version 2, or (at your option)
  14. any later version.
  15.  
  16. RCS is distributed in the hope that it will be useful,
  17. but WITHOUT ANY WARRANTY; without even the implied warranty of
  18. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19. GNU General Public License for more details.
  20.  
  21. You should have received a copy of the GNU General Public License
  22. along with RCS; see the file COPYING.  If not, write to
  23. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25. Report problems and direct all questions to:
  26.  
  27.     rcs-bugs@cs.purdue.edu
  28.  
  29. */
  30.  
  31.  
  32.  
  33.  
  34. /* $Log: rcsutil.c,v $
  35.  * Revision 5.10  1991/10/07  17:32:46  eggert
  36.  * Support piece tables even if !has_mmap.
  37.  *
  38.  * Revision 5.9  1991/08/19  03:13:55  eggert
  39.  * Add spawn() support.  Explicate assumptions about getting invoker's name.
  40.  * Standardize user-visible dates.  Tune.
  41.  *
  42.  * Revision 5.8  1991/04/21  11:58:30  eggert
  43.  * Plug setuid security hole.
  44.  *
  45.  * Revision 5.6  1991/02/26  17:48:39  eggert
  46.  * Fix setuid bug.  Use fread, fwrite more portably.
  47.  * Support waitpid.  Don't assume -1 is acceptable to W* macros.
  48.  * strsave -> str_save (DG/UX name clash)
  49.  *
  50.  * Revision 5.5  1990/12/04  05:18:49  eggert
  51.  * Don't output a blank line after a signal diagnostic.
  52.  * Use -I for prompts and -q for diagnostics.
  53.  *
  54.  * Revision 5.4  1990/11/01  05:03:53  eggert
  55.  * Remove unneeded setid check.  Add awrite(), fremember().
  56.  *
  57.  * Revision 5.3  1990/10/06  00:16:45  eggert
  58.  * Don't fread F if feof(F).
  59.  *
  60.  * Revision 5.2  1990/09/04  08:02:31  eggert
  61.  * Store fread()'s result in an fread_type object.
  62.  *
  63.  * Revision 5.1  1990/08/29  07:14:07  eggert
  64.  * Declare getpwuid() more carefully.
  65.  *
  66.  * Revision 5.0  1990/08/22  08:13:46  eggert
  67.  * Add setuid support.  Permit multiple locks per user.
  68.  * Remove compile-time limits; use malloc instead.
  69.  * Switch to GMT.  Permit dates past 1999/12/31.
  70.  * Add -V.  Remove snooping.  Ansify and Posixate.
  71.  * Tune.  Some USG hosts define NSIG but not sys_siglist.
  72.  * Don't run /bin/sh if it's hopeless.
  73.  * Don't leave garbage behind if the output is an empty pipe.
  74.  * Clean up after SIGXCPU or SIGXFSZ.  Print name of signal that caused cleanup.
  75.  *
  76.  * Revision 4.6  89/05/01  15:13:40  narten
  77.  * changed copyright header to reflect current distribution rules
  78.  * 
  79.  * Revision 4.5  88/11/08  16:01:02  narten
  80.  * corrected use of varargs routines
  81.  * 
  82.  * Revision 4.4  88/08/09  19:13:24  eggert
  83.  * Check for memory exhaustion.
  84.  * Permit signal handlers to yield either 'void' or 'int'; fix oldSIGINT botch.
  85.  * Use execv(), not system(); yield exit status like diff(1)'s.
  86.  * 
  87.  * Revision 4.3  87/10/18  10:40:22  narten
  88.  * Updating version numbers. Changes relative to 1.1 actually
  89.  * relative to 4.1
  90.  * 
  91.  * Revision 1.3  87/09/24  14:01:01  narten
  92.  * Sources now pass through lint (if you ignore printf/sprintf/fprintf 
  93.  * warnings)
  94.  * 
  95.  * Revision 1.2  87/03/27  14:22:43  jenkins
  96.  * Port to suns
  97.  * 
  98.  * Revision 4.1  83/05/10  15:53:13  wft
  99.  * Added getcaller() and findlock().
  100.  * Changed catchints() to check SIGINT for SIG_IGN before setting up the signal
  101.  * (needed for background jobs in older shells). Added restoreints().
  102.  * Removed printing of full RCS path from logcommand().
  103.  * 
  104.  * Revision 3.8  83/02/15  15:41:49  wft
  105.  * Added routine fastcopy() to copy remainder of a file in blocks.
  106.  *
  107.  * Revision 3.7  82/12/24  15:25:19  wft
  108.  * added catchints(), ignoreints() for catching and ingnoring interrupts;
  109.  * fixed catchsig().
  110.  *
  111.  * Revision 3.6  82/12/08  21:52:05  wft
  112.  * Using DATEFORM to format dates.
  113.  *
  114.  * Revision 3.5  82/12/04  18:20:49  wft
  115.  * Replaced SNOOPDIR with SNOOPFILE; changed addlock() to update
  116.  * lockedby-field.
  117.  *
  118.  * Revision 3.4  82/12/03  17:17:43  wft
  119.  * Added check to addlock() ensuring only one lock per person.
  120.  * Addlock also returns a pointer to the lock created. Deleted fancydate().
  121.  *
  122.  * Revision 3.3  82/11/27  12:24:37  wft
  123.  * moved rmsema(), trysema(), trydiraccess(), getfullRCSname() to rcsfnms.c.
  124.  * Introduced macro SNOOP so that snoop can be placed in directory other than
  125.  * TARGETDIR. Changed %02d to %.2d for compatibility reasons.
  126.  *
  127.  * Revision 3.2  82/10/18  21:15:11  wft
  128.  * added function getfullRCSname().
  129.  *
  130.  * Revision 3.1  82/10/13  16:17:37  wft
  131.  * Cleanup message is now suppressed in quiet mode.
  132.  */
  133.  
  134.  
  135.  
  136.  
  137. #include "rcsbase.h"
  138.  
  139. libId(utilId, "$Id: rcsutil.c,v 5.10 1991/10/07 17:32:46 eggert Exp $")
  140.  
  141. #if !has_memcmp
  142.     int
  143. memcmp(s1, s2, n)
  144.     void const *s1, *s2;
  145.     size_t n;
  146. {
  147.     register unsigned char const
  148.         *p1 = (unsigned char const*)s1,
  149.         *p2 = (unsigned char const*)s2;
  150.     register size_t i = n;
  151.     register int r = 0;
  152.     while (i--  &&  !(r = (*p1++ - *p2++)))
  153.         ;
  154.     return r;
  155. }
  156. #endif
  157.  
  158. #if !has_memcpy
  159.     void *
  160. memcpy(s1, s2, n)
  161.     void *s1;
  162.     void const *s2;
  163.     size_t n;
  164. {
  165.     register char *p1 = (char*)s1;
  166.     register char const *p2 = (char const*)s2;
  167.     while (n--)
  168.         *p1++ = *p2++;
  169.     return s1;
  170. }
  171. #endif
  172.  
  173. #if lint
  174.     malloc_type lintalloc;
  175. #endif
  176.  
  177. /*
  178.  * list of blocks allocated with ftestalloc()
  179.  * These blocks can be freed by ffree when we're done with the current file.
  180.  * We could put the free block inside struct alloclist, rather than a pointer
  181.  * to the free block, but that would be less portable.
  182.  */
  183. struct alloclist {
  184.     malloc_type alloc;
  185.     struct alloclist *nextalloc;
  186. };
  187. static struct alloclist *alloced;
  188.  
  189.  
  190.     static malloc_type
  191. okalloc(p)
  192.     malloc_type p;
  193. {
  194.     if (!p)
  195.         faterror("out of memory");
  196.     return p;
  197. }
  198.  
  199.     malloc_type
  200. testalloc(size)
  201.     size_t size;
  202. /* Allocate a block, testing that the allocation succeeded.  */
  203. {
  204.     return okalloc(malloc(size));
  205. }
  206.  
  207.     malloc_type
  208. testrealloc(ptr, size)
  209.     malloc_type ptr;
  210.     size_t size;
  211. /* Reallocate a block, testing that the allocation succeeded.  */
  212. {
  213.     return okalloc(realloc(ptr, size));
  214. }
  215.  
  216.     malloc_type
  217. fremember(ptr)
  218.     malloc_type ptr;
  219. /* Remember PTR in 'alloced' so that it can be freed later.  Yield PTR.  */
  220. {
  221.     register struct alloclist *q = talloc(struct alloclist);
  222.     q->nextalloc = alloced;
  223.     alloced = q;
  224.     return q->alloc = ptr;
  225. }
  226.  
  227.     malloc_type
  228. ftestalloc(size)
  229.     size_t size;
  230. /* Allocate a block, putting it in 'alloced' so it can be freed later. */
  231. {
  232.     return fremember(testalloc(size));
  233. }
  234.  
  235.     void
  236. ffree()
  237. /* Free all blocks allocated with ftestalloc().  */
  238. {
  239.     register struct alloclist *p, *q;
  240.     for (p = alloced;  p;  p = q) {
  241.         q = p->nextalloc;
  242.         tfree(p->alloc);
  243.         tfree(p);
  244.     }
  245.     alloced = nil;
  246. }
  247.  
  248.     void
  249. ffree1(f)
  250.     register char const *f;
  251. /* Free the block f, which was allocated by ftestalloc.  */
  252. {
  253.     register struct alloclist *p, **a = &alloced;
  254.  
  255.     while ((p = *a)->alloc  !=  f)
  256.         a = &p->nextalloc;
  257.     *a = p->nextalloc;
  258.     tfree(p->alloc);
  259.     tfree(p);
  260. }
  261.  
  262.     char *
  263. str_save(s)
  264.     char const *s;
  265. /* Save s in permanently allocated storage. */
  266. {
  267.     return strcpy(tnalloc(char, strlen(s)+1), s);
  268. }
  269.  
  270.     char *
  271. fstr_save(s)
  272.     char const *s;
  273. /* Save s in storage that will be deallocated when we're done with this file. */
  274. {
  275.     return strcpy(ftnalloc(char, strlen(s)+1), s);
  276. }
  277.  
  278.     char *
  279. cgetenv(name)
  280.     char const *name;
  281. /* Like getenv(), but yield a copy; getenv() can overwrite old results. */
  282. {
  283.     register char *p;
  284.  
  285.     return (p=getenv(name)) ? str_save(p) : p;
  286. }
  287.  
  288.     char const *
  289. getusername(suspicious)
  290.     int suspicious;
  291. /* Get the caller's login name.  Trust only getwpuid if SUSPICIOUS.  */
  292. {
  293.     static char *name;
  294.  
  295.     if (!name) {
  296.         if (
  297.             /* Prefer getenv() unless suspicious; it's much faster.  */
  298. #            if getlogin_is_secure
  299.                 (suspicious
  300.                 ||
  301.                 !(name = cgetenv("LOGNAME"))
  302.                 &&  !(name = cgetenv("USER")))
  303.             &&  !(name = getlogin())
  304. #            else
  305.             suspicious
  306.             ||
  307.                 !(name = cgetenv("LOGNAME"))
  308.                 &&  !(name = cgetenv("USER"))
  309.                 &&  !(name = getlogin())
  310. #            endif
  311.         ) {
  312. #if has_getuid && has_getpwuid
  313.             struct passwd const *pw = getpwuid(ruid());
  314.             if (!pw)
  315.                 faterror("no password entry for userid %lu",
  316.                      (unsigned long)ruid()
  317.                 );
  318.             name = pw->pw_name;