summaryrefslogtreecommitdiffstats
path: root/gnu/usr.bin/rcs/rcsclean/rcsclean.c
diff options
context:
space:
mode:
Diffstat (limited to 'gnu/usr.bin/rcs/rcsclean/rcsclean.c')
-rw-r--r--gnu/usr.bin/rcs/rcsclean/rcsclean.c297
1 files changed, 297 insertions, 0 deletions
diff --git a/gnu/usr.bin/rcs/rcsclean/rcsclean.c b/gnu/usr.bin/rcs/rcsclean/rcsclean.c
new file mode 100644
index 0000000..ba24ab7
--- /dev/null
+++ b/gnu/usr.bin/rcs/rcsclean/rcsclean.c
@@ -0,0 +1,297 @@
+/* rcsclean - clean up working files */
+
+/* Copyright 1991 by Paul Eggert
+ Distributed under license by the Free Software Foundation, Inc.
+
+This file is part of RCS.
+
+RCS is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 2, or (at your option)
+any later version.
+
+RCS is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with RCS; see the file COPYING. If not, write to
+the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+
+Report problems and direct all questions to:
+
+ rcs-bugs@cs.purdue.edu
+
+*/
+
+#include "rcsbase.h"
+
+#if has_dirent
+ static int get_directory P((char const*,char***));
+#endif
+
+static int unlock P((struct hshentry *));
+static void cleanup P((void));
+
+static RILE *workptr;
+static int exitstatus;
+
+mainProg(rcscleanId, "rcsclean", "$Id: rcsclean.c,v 5.1 1991/11/03 01:11:44 eggert Exp $")
+{
+ static char const usage[] =
+ "\nrcsclean: usage: rcsclean [-ksubst] [-{nqru}[rev]] [-Vn] [-xsuffixes] [file ...]";
+
+ static struct buf revision;
+
+ char *a, **newargv;
+ char const *rev, *p;
+ int changelock, expmode, perform, unlocked, unlockflag, waslocked;
+ struct hshentries *deltas;
+ struct hshentry *delta;
+ struct stat workstat;
+
+ setrid();
+
+ expmode = -1;
+ rev = nil;
+ suffixes = X_DEFAULT;
+ perform = true;
+ unlockflag = false;
+
+ argc = getRCSINIT(argc, argv, &newargv);
+ argv = newargv;
+ for (;;) {
+ if (--argc <= 0) {
+# if has_dirent
+ argc = get_directory(".", &newargv);
+ argv = newargv;
+ break;
+# else
+ faterror("no file names specified");
+# endif
+ }
+ a = *++argv;
+ if (*a++ != '-')
+ break;
+ switch (*a++) {
+ case 'k':
+ if (0 <= expmode)
+ redefined('k');
+ if ((expmode = str2expmode(a)) < 0)
+ goto unknown;
+ break;
+
+ case 'n':
+ perform = false;
+ goto handle_revision;
+
+ case 'q':
+ quietflag = true;
+ /* fall into */
+ case 'r':
+ handle_revision:
+ if (*a) {
+ if (rev)
+ warn("redefinition of revision number");
+ rev = a;
+ }
+ break;
+
+ case 'u':
+ unlockflag = true;
+ goto handle_revision;
+
+ case 'V':
+ setRCSversion(*argv);
+ break;
+
+ case 'x':
+ suffixes = a;
+ break;
+
+ default:
+ unknown:
+ faterror("unknown option: %s%s", *argv, usage);
+ }
+ }
+
+ do {
+ ffree();
+
+ if (!(
+ 0 < pairfilenames(
+ argc, argv,
+ unlockflag&perform ? rcswriteopen : rcsreadopen,
+ true, true
+ ) &&
+ (workptr = Iopen(workfilename,FOPEN_R_WORK,&workstat))
+ ))
+ continue;
+
+ gettree();
+
+ p = 0;
+ if (rev) {
+ if (!fexpandsym(rev, &revision, workptr))
+ continue;
+ p = revision.string;
+ } else if (Head)
+ switch (unlockflag ? findlock(false,&delta) : 0) {
+ default:
+ continue;
+ case 0:
+ p = Dbranch ? Dbranch : "";
+ break;
+ case 1:
+ p = delta->num;
+ break;
+ }
+ delta = 0;
+ deltas = 0; /* Keep lint happy. */
+ if (p && !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
+ continue;
+
+ waslocked = delta && delta->lockedby;
+ locker_expansion = unlock(delta);
+ unlocked = locker_expansion & unlockflag;
+ changelock = unlocked & perform;
+ if (unlocked<waslocked && workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
+ continue;
+
+ if (!dorewrite(unlockflag, changelock))
+ continue;
+
+ if (0 <= expmode)
+ Expand = expmode;
+ else if (
+ waslocked &&
+ Expand == KEYVAL_EXPAND &&
+ WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
+ )
+ Expand = KEYVALLOCK_EXPAND;
+
+ getdesc(false);
+
+ if (
+ !delta ? workstat.st_size!=0 :
+ 0 < rcsfcmp(
+ workptr, &workstat,
+ buildrevision(deltas, delta, (FILE*)0, false),
+ delta
+ )
+ )
+ continue;
+
+ if (quietflag < unlocked)
+ aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSfilename);
+
+ if_advise_access(changelock && deltas->first != delta,
+ finptr, MADV_SEQUENTIAL
+ );
+ if (!donerewrite(changelock))
+ continue;
+
+ if (!quietflag)
+ aprintf(stdout, "rm -f %s\n", workfilename);
+ Izclose(&workptr);
+ if (perform && un_link(workfilename) != 0)
+ eerror(workfilename);
+
+ } while (cleanup(), ++argv, 0 < --argc);
+
+ tempunlink();
+ if (!quietflag)
+ Ofclose(stdout);
+ exitmain(exitstatus);
+}
+
+ static void
+cleanup()
+{
+ if (nerror) exitstatus = EXIT_FAILURE;
+ Izclose(&finptr);
+ Izclose(&workptr);
+ Ozclose(&fcopy);
+ Ozclose(&frewrite);
+ dirtempunlink();
+}
+
+#if lint
+# define exiterr rcscleanExit
+#endif
+ exiting void
+exiterr()
+{
+ dirtempunlink();
+ tempunlink();
+ _exit(EXIT_FAILURE);
+}
+
+ static int
+unlock(delta)
+ struct hshentry *delta;
+{
+ register struct lock **al, *l;
+
+ if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
+ for (al = &Locks; (l = *al); al = &l->nextlock)
+ if (l->delta == delta) {
+ *al = l->nextlock;
+ delta->lockedby = 0;
+ return true;
+ }
+ return false;
+}
+
+#if has_dirent
+ static int
+get_directory(dirname, aargv)
+ char const *dirname;
+ char ***aargv;
+/*
+ * Put a vector of all DIRNAME's directory entries names into *AARGV.
+ * Ignore names of RCS files.
+ * Yield the number of entries found. Terminate the vector with 0.
+ * Allocate the storage for the vector and entry names.
+ * Do not sort the names. Do not include '.' and '..'.
+ */
+{
+ int i, entries = 0, entries_max = 64;
+ size_t chars = 0, chars_max = 1024;
+ size_t *offset = tnalloc(size_t, entries_max);
+ char *a = tnalloc(char, chars_max), **p;
+ DIR *d;
+ struct dirent *e;
+
+ if (!(d = opendir(dirname)))
+ efaterror(dirname);
+ while ((errno = 0, e = readdir(d))) {
+ char const *en = e->d_name;
+ size_t s = strlen(en) + 1;
+ if (en[0]=='.' && (!en[1] || en[1]=='.' && !en[2]))
+ continue;
+ if (rcssuffix(en))
+ continue;
+ while (chars_max < s + chars)
+ a = trealloc(char, a, chars_max<<=1);
+ if (entries == entries_max)
+ offset = trealloc(size_t, offset, entries_max<<=1);
+ offset[entries++] = chars;
+ VOID strcpy(a+chars, en);
+ chars += s;
+ }
+ if (errno || closedir(d) != 0)
+ efaterror(dirname);
+ if (chars)
+ a = trealloc(char, a, chars);
+ else
+ tfree(a);
+ *aargv = p = tnalloc(char*, entries+1);
+ for (i=0; i<entries; i++)
+ *p++ = a + offset[i];
+ *p = 0;
+ tfree(offset);
+ return entries;
+}
+#endif
OpenPOWER on IntegriCloud