home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 22 gnu / 22-gnu.zip / rcs57pc3.zip / rcs / src / rcsclean.c < prev    next >
C/C++ Source or Header  |  1995-06-16  |  7KB  |  334 lines

  1. /* Clean up working files.  */
  2.  
  3. /* Copyright 1991, 1992, 1993, 1994, 1995 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.
  20. If not, write to the Free Software Foundation,
  21. 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  22.  
  23. Report problems and direct all questions to:
  24.  
  25.     rcs-bugs@cs.purdue.edu
  26.  
  27. */
  28.  
  29. #include "rcsbase.h"
  30.  
  31. #if has_dirent
  32.     static int get_directory P((char const*,char***));
  33. #endif
  34.  
  35. static int unlock P((struct hshentry *));
  36. static void cleanup P((void));
  37.  
  38. static RILE *workptr;
  39. static int exitstatus;
  40.  
  41. mainProg(rcscleanId, "rcsclean", "$Id: rcsclean.c,v 5.9 1995/06/16 06:19:24 eggert Exp $")
  42. {
  43.     static char const usage[] =
  44.         "\nrcsclean: usage: rcsclean -ksubst -{nqru}[rev] -T -Vn -xsuff -zzone file ...";
  45.  
  46.     static struct buf revision;
  47.  
  48.     char *a, **newargv;
  49.     char const *rev, *p;
  50.     int dounlock, expmode, perform, unlocked, unlockflag, waslocked;
  51.     int Ttimeflag;
  52.     struct hshentries *deltas;
  53.     struct hshentry *delta;
  54.     struct stat workstat;
  55.  
  56.     setrid();
  57.  
  58.     expmode = -1;
  59.     rev = 0;
  60.     suffixes = X_DEFAULT;
  61.     perform = true;
  62.     unlockflag = false;
  63.     Ttimeflag = false;
  64.  
  65.     argc = getRCSINIT(argc, argv, &newargv);
  66.     argv = newargv;
  67.     for (;;) {
  68.         if (--argc < 1) {
  69. #            if has_dirent
  70.                 argc = get_directory(".", &newargv);
  71.                 argv = newargv;
  72.                 break;
  73. #            else
  74.                 faterror("no pathnames specified");
  75. #            endif
  76.         }
  77.         a = *++argv;
  78.         if (!*a  ||  *a++ != '-')
  79.             break;
  80.         switch (*a++) {
  81.             case 'k':
  82.                 if (0 <= expmode)
  83.                     redefined('k');
  84.                 if ((expmode = str2expmode(a))  <  0)
  85.                     goto unknown;
  86.                 break;
  87.  
  88.             case 'n':
  89.                 perform = false;
  90.                 goto handle_revision;
  91.  
  92.             case 'q':
  93.                 quietflag = true;
  94.                 /* fall into */
  95.             case 'r':
  96.             handle_revision:
  97.                 if (*a) {
  98.                     if (rev)
  99.                         warn("redefinition of revision number");
  100.                     rev = a;
  101.                 }
  102.                 break;
  103.  
  104.             case 'T':
  105.                 if (*a)
  106.                     goto unknown;
  107.                 Ttimeflag = true;
  108.                 break;
  109.  
  110.             case 'u':
  111.                 unlockflag = true;
  112.                 goto handle_revision;
  113.  
  114.             case 'V':
  115.                 setRCSversion(*argv);
  116.                 break;
  117.  
  118.             case 'x':
  119.                 suffixes = a;
  120.                 break;
  121.  
  122.             case 'z':
  123.                 zone_set(a);
  124.                 break;
  125.  
  126.             default:
  127.             unknown:
  128.                 error("unknown option: %s%s", *argv, usage);
  129.         }
  130.     }
  131.  
  132.     dounlock = perform & unlockflag;
  133.  
  134.     if (nerror)
  135.       cleanup();
  136.     else
  137.       for (;  0 < argc;  cleanup(), ++argv, --argc) {
  138.  
  139.         ffree();
  140.  
  141.         if (!(
  142.             0 < pairnames(
  143.                 argc, argv,
  144.                 dounlock ? rcswriteopen : rcsreadopen,
  145.                 true, true
  146.             ) &&
  147.             (workptr = Iopen(workname, FOPEN_R_WORK, &workstat))
  148.         ))
  149.             continue;
  150.  
  151.         if (same_file(RCSstat, workstat, 0)) {
  152.             rcserror("RCS file is the same as working file %s.",
  153.                 workname
  154.             );
  155.             continue;
  156.         }
  157.  
  158.         gettree();
  159.  
  160.         p = 0;
  161.         if (rev) {
  162.             if (!fexpandsym(rev, &revision, workptr))
  163.                 continue;
  164.             p = revision.string;
  165.         } else if (Head)
  166.             switch (unlockflag ? findlock(false,&delta) : 0) {
  167.                 default:
  168.                     continue;
  169.                 case 0:
  170.                     p = Dbranch ? Dbranch : "";
  171.                     break;
  172.                 case 1:
  173.                     p = delta->num;
  174.                     break;
  175.             }
  176.         delta = 0;
  177.         deltas = 0;  /* Keep lint happy.  */
  178.         if (p  &&  !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
  179.             continue;
  180.  
  181.         waslocked = delta && delta->lockedby;
  182.         locker_expansion = unlock(delta);
  183.         unlocked = locker_expansion & unlockflag;
  184.         if (unlocked<waslocked  &&  workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
  185.             continue;
  186.  
  187.         if (unlocked && !checkaccesslist())
  188.             continue;
  189.  
  190.         if (dorewrite(dounlock, unlocked) != 0)
  191.             continue;
  192.  
  193.         if (0 <= expmode)
  194.             Expand = expmode;
  195.         else if (
  196.             waslocked  &&
  197.             Expand == KEYVAL_EXPAND  &&
  198.             WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
  199.         )
  200.             Expand = KEYVALLOCK_EXPAND;
  201.  
  202.         getdesc(false);
  203.  
  204.         if (
  205.             !delta ? workstat.st_size!=0 :
  206.             0 < rcsfcmp(
  207.                 workptr, &workstat,
  208.                 buildrevision(deltas, delta, (FILE*)0, false),
  209.                 delta
  210.             )
  211.         )
  212.             continue;
  213.  
  214.         if (quietflag < unlocked)
  215.             aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSname);
  216.  
  217.         if (perform & unlocked) {
  218.             if_advise_access(deltas->first != delta, finptr, MADV_SEQUENTIAL);
  219.             if (donerewrite(true,
  220.                 Ttimeflag ? RCSstat.st_mtime : (time_t)-1
  221.             ) != 0)
  222.                 continue;
  223.         }
  224.  
  225.         if (!quietflag)
  226.             aprintf(stdout, "rm -f %s\n", workname);
  227.         Izclose(&workptr);
  228.         if (perform  &&  un_link(workname) != 0)
  229.             eerror(workname);
  230.  
  231.       }
  232.  
  233.     tempunlink();
  234.     if (!quietflag)
  235.         Ofclose(stdout);
  236.     exitmain(exitstatus);
  237. }
  238.  
  239.     static void
  240. cleanup()
  241. {
  242.     if (nerror) exitstatus = EXIT_FAILURE;
  243.     Izclose(&finptr);
  244.     Izclose(&workptr);
  245.     Ozclose(&fcopy);
  246.     ORCSclose();
  247.     dirtempunlink();
  248. }
  249.  
  250. #if RCS_lint
  251. #    define exiterr rcscleanExit
  252. #endif
  253.     void
  254. exiterr()
  255. {
  256.     ORCSerror();
  257.     dirtempunlink();
  258.     tempunlink();
  259.     _exit(EXIT_FAILURE);
  260. }
  261.  
  262.     static int
  263. unlock(delta)
  264.     struct hshentry *delta;
  265. {
  266.     register struct rcslock **al, *l;
  267.  
  268.     if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
  269.         for (al = &Locks;  (l = *al);  al = &l->nextlock)
  270.             if (l->delta == delta) {
  271.                 *al = l->nextlock;
  272.                 delta->lockedby = 0;
  273.                 return true;
  274.             }
  275.     return false;
  276. }
  277.  
  278. #if has_dirent
  279.     static int
  280. get_directory(dirname, aargv)
  281.     char const *dirname;
  282.     char ***aargv;
  283. /*
  284.  * Put a vector of all DIRNAME's directory entries names into *AARGV.
  285.  * Ignore names of RCS files.
  286.  * Yield the number of entries found.  Terminate the vector with 0.
  287.  * Allocate the storage for the vector and entry names.
  288.  * Do not sort the names.  Do not include '.' and '..'.
  289.  */
  290. {
  291.     int i, entries = 0, entries_max = 64;
  292.     size_t chars = 0, chars_max = 1024;
  293.     size_t *offset = tnalloc(size_t, entries_max);
  294.     char *a = tnalloc(char, chars_max), **p;
  295.     DIR *d;
  296.     struct dirent *e;
  297.  
  298.     if (!(d = opendir(dirname)))
  299.         efaterror(dirname);
  300.     while ((errno = 0,  e = readdir(d))) {
  301.         char const *en = e->d_name;
  302.         size_t s = strlen(en) + 1;
  303.         if (en[0]=='.'   &&   (!en[1]  ||  (en[1]=='.' && !en[2])))
  304.             continue;
  305.         if (rcssuffix(en))
  306.             continue;
  307.         while (chars_max < s + chars)
  308.             a = trealloc(char, a, chars_max<<=1);
  309.         if (entries == entries_max)
  310.             offset = trealloc(size_t, offset, entries_max<<=1);
  311.         offset[entries++] = chars;
  312.         VOID strcpy(a+chars, en);
  313.         chars += s;
  314.     }
  315. #    if void_closedir
  316. #        define close_directory(d) (closedir(d), 0)
  317. #    else
  318. #        define close_directory(d) closedir(d)
  319. #    endif
  320.     if (errno  ||  close_directory(d) != 0)
  321.         efaterror(dirname);
  322.     if (chars)
  323.         a = trealloc(char, a, chars);
  324.     else
  325.         tfree(a);
  326.     *aargv = p = tnalloc(char*, entries+1);
  327.     for (i=0; i<entries; i++)
  328.         *p++ = a + offset[i];
  329.     *p = 0;
  330.     tfree(offset);
  331.     return entries;
  332. }
  333. #endif
  334.