home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / prgramer / rcs / sources / rcsclean.c < prev    next >
C/C++ Source or Header  |  1992-02-17  |  7KB  |  306 lines

  1. /* rcsclean - clean up working files */
  2.  
  3. /* Copyright 1991, 1992 by Paul Eggert
  4.    Distributed under license by the Free Software Foundation, Inc.
  5.  
  6. This file is part of RCS.
  7.  
  8. RCS is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2, or (at your option)
  11. any later version.
  12.  
  13. RCS is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. GNU General Public License for more details.
  17.  
  18. You should have received a copy of the GNU General Public License
  19. along with RCS; see the file COPYING.  If not, write to
  20. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22. Report problems and direct all questions to:
  23.  
  24.     rcs-bugs@cs.purdue.edu
  25.  
  26. */
  27.  
  28. #include "rcsbase.h"
  29.  
  30. #if has_dirent
  31.     static int get_directory P((char const*,char***));
  32. #endif
  33.  
  34. static int unlock P((struct hshentry *));
  35. static void cleanup P((void));
  36.  
  37. static RILE *workptr;
  38. static int exitstatus;
  39.  
  40. mainProg(rcscleanId, "rcsclean", "$Id: rcsclean.c,v 5.3 1992/02/17 23:02:22 eggert Exp $")
  41. {
  42.     static char const usage[] =
  43.         "\nrcsclean: usage: rcsclean [-ksubst] [-{nqru}[rev]] [-Vn] [-xsuffixes] [file ...]";
  44.  
  45.     static struct buf revision;
  46.  
  47.     char *a, **newargv;
  48.     char const *rev, *p;
  49.     int changelock, expmode, perform, unlocked, unlockflag, waslocked;
  50.     int Ttimeflag;
  51.     struct hshentries *deltas;
  52.     struct hshentry *delta;
  53.     struct stat workstat;
  54.  
  55.     setrid();
  56.  
  57.     expmode = -1;
  58.     rev = nil;
  59.     suffixes = X_DEFAULT;
  60.     perform = true;
  61.     unlockflag = false;
  62.     Ttimeflag = false;
  63.  
  64.     argc = getRCSINIT(argc, argv, &newargv);
  65.     argv = newargv;
  66.     for (;;) {
  67.         if (--argc <= 0) {
  68. #            if has_dirent
  69.                 argc = get_directory(".", &newargv);
  70.                 argv = newargv;
  71.                 break;
  72. #            else
  73.                 faterror("no file names specified");
  74. #            endif
  75.         }
  76.         a = *++argv;
  77.         if (*a++ != '-')
  78.             break;
  79.         switch (*a++) {
  80.             case 'k':
  81.                 if (0 <= expmode)
  82.                     redefined('k');
  83.                 if ((expmode = str2expmode(a))  <  0)
  84.                     goto unknown;
  85.                 break;
  86.  
  87.             case 'n':
  88.                 perform = false;
  89.                 goto handle_revision;
  90.  
  91.             case 'q':
  92.                 quietflag = true;
  93.                 /* fall into */
  94.             case 'r':
  95.             handle_revision:
  96.                 if (*a) {
  97.                     if (rev)
  98.                         warn("redefinition of revision number");
  99.                     rev = a;
  100.                 }
  101.                 break;
  102.  
  103.             case 'T':
  104.                 if (*a)
  105.                     goto unknown;
  106.                 Ttimeflag = true;
  107.                 break;
  108.  
  109.             case 'u':
  110.                 unlockflag = true;
  111.                 goto handle_revision;
  112.  
  113.             case 'V':
  114.                 setRCSversion(*argv);
  115.                 break;
  116.  
  117.             case 'x':
  118.                 suffixes = a;
  119.                 break;
  120.  
  121.             default:
  122.             unknown:
  123.                 faterror("unknown option: %s%s", *argv, usage);
  124.         }
  125.     }
  126.  
  127.     do {
  128.         ffree();
  129.  
  130.         if (!(
  131.             0 < pairfilenames(
  132.                 argc, argv,
  133.                 unlockflag&perform ? rcswriteopen : rcsreadopen,
  134.                 true, true
  135.             ) &&
  136.             (workptr = Iopen(workfilename,FOPEN_R_WORK,&workstat))
  137.         ))
  138.             continue;
  139.  
  140.         gettree();
  141.  
  142.         p = 0;
  143.         if (rev) {
  144.             if (!fexpandsym(rev, &revision, workptr))
  145.                 continue;
  146.             p = revision.string;
  147.         } else if (Head)
  148.             switch (unlockflag ? findlock(false,&delta) : 0) {
  149.                 default:
  150.                     continue;
  151.                 case 0:
  152.                     p = Dbranch ? Dbranch : "";
  153.                     break;
  154.                 case 1:
  155.                     p = delta->num;
  156.                     break;
  157.             }
  158.         delta = 0;
  159.         deltas = 0;  /* Keep lint happy.  */
  160.         if (p  &&  !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
  161.             continue;
  162.  
  163.         waslocked = delta && delta->lockedby;
  164.         locker_expansion = unlock(delta);
  165.         unlocked = locker_expansion & unlockflag;
  166.         changelock = unlocked & perform;
  167.         if (unlocked<waslocked  &&  workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
  168.             continue;
  169.  
  170.         if (dorewrite(unlockflag, changelock) != 0)
  171.             continue;
  172.  
  173.         if (0 <= expmode)
  174.             Expand = expmode;
  175.         else if (
  176.             waslocked  &&
  177.             Expand == KEYVAL_EXPAND  &&
  178.             WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
  179.         )
  180.             Expand = KEYVALLOCK_EXPAND;
  181.  
  182.         getdesc(false);
  183.  
  184.         if (
  185.             !delta ? workstat.st_size!=0 :
  186.             0 < rcsfcmp(
  187.                 workptr, &workstat,
  188.                 buildrevision(deltas, delta, (FILE*)0, false),
  189.                 delta
  190.             )
  191.         )
  192.             continue;
  193.  
  194.         if (quietflag < unlocked)
  195.             aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSfilename);
  196.  
  197.         if_advise_access(changelock  &&  deltas->first != delta,
  198.             finptr, MADV_SEQUENTIAL
  199.         );
  200.         if (donerewrite(changelock, Ttimeflag) != 0)
  201.             continue;
  202.  
  203.         if (!quietflag)
  204.             aprintf(stdout, "rm -f %s\n", workfilename);
  205.         Izclose(&workptr);
  206.         if (perform  &&  un_link(workfilename) != 0)
  207.             eerror(workfilename);
  208.  
  209.     } while (cleanup(),  ++argv,  0 < --argc);
  210.  
  211.     tempunlink();
  212.     if (!quietflag)
  213.         Ofclose(stdout);
  214.     exitmain(exitstatus);
  215. }
  216.  
  217.     static void
  218. cleanup()
  219. {
  220.     if (nerror) exitstatus = EXIT_FAILURE;
  221.     Izclose(&finptr);
  222.     Izclose(&workptr);
  223.     Ozclose(&fcopy);
  224.     ORCSclose();
  225.     dirtempunlink();
  226. }
  227.  
  228. #if RCS_lint
  229. #       define exiterr rcscleanExit
  230. #endif
  231.     exiting void
  232. exiterr()
  233. {
  234.     dirtempunlink();
  235.     tempunlink();
  236.     _exit(EXIT_FAILURE);
  237. }
  238.  
  239.     static int
  240. unlock(delta)
  241.     struct hshentry *delta;
  242. {
  243.     register struct lock **al, *l;
  244.  
  245.     if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
  246.         for (al = &Locks;  (l = *al);  al = &l->nextlock)
  247.             if (l->delta == delta) {
  248.                 *al = l->nextlock;
  249.                 delta->lockedby = 0;
  250.                 return true;
  251.             }
  252.     return false;
  253. }
  254.  
  255. #if has_dirent
  256.     static int
  257. get_directory(dirname, aargv)
  258.     char const *dirname;
  259.     char ***aargv;
  260. /*
  261.  * Put a vector of all DIRNAME's directory entries names into *AARGV.
  262.  * Ignore names of RCS files.
  263.  * Yield the number of entries found.  Terminate the vector with 0.
  264.  * Allocate the storage for the vector and entry names.
  265.  * Do not sort the names.  Do not include '.' and '..'.
  266.  */
  267. {
  268.     int i, entries = 0, entries_max = 64;
  269.     size_t chars = 0, chars_max = 1024;
  270.     size_t *offset = tnalloc(size_t, entries_max);
  271.     char *a = tnalloc(char, chars_max), **p;
  272.     DIR *d;
  273.     struct dirent *e;
  274.  
  275.     if (!(d = opendir(dirname)))
  276.         efaterror(dirname);
  277.     while ((errno = 0,  e = readdir(d))) {
  278.         char const *en = e->d_name;
  279.         size_t s = strlen(en) + 1;
  280.         if (en[0]=='.'   &&   (!en[1]  ||  en[1]=='.' && !en[2]))
  281.             continue;
  282.         if (rcssuffix(en))
  283.             continue;
  284.         while (chars_max < s + chars)
  285.             a = trealloc(char, a, chars_max<<=1);
  286.         if (entries == entries_max)
  287.             offset = trealloc(size_t, offset, entries_max<<=1);
  288.         offset[entries++] = chars;
  289.         VOID strcpy(a+chars, en);
  290.         chars += s;
  291.     }
  292.     if (errno  ||  closedir(d) != 0)
  293.         efaterror(dirname);
  294.     if (chars)
  295.         a = trealloc(char, a, chars);
  296.     else
  297.         tfree(a);
  298.     *aargv = p = tnalloc(char*, entries+1);
  299.     for (i=0; i<entries; i++)
  300.         *p++ = a + offset[i];
  301.     *p = 0;
  302.     tfree(offset);
  303.     return entries;
  304. }
  305. #endif
  306.