1*fa28c6faSchristos /* $NetBSD: rcsclean.c,v 1.2 2016/01/14 04:22:39 christos Exp $ */
27bdc2678Schristos
37bdc2678Schristos /* Clean up working files. */
47bdc2678Schristos
57bdc2678Schristos /* Copyright 1991, 1992, 1993, 1994, 1995 Paul Eggert
67bdc2678Schristos Distributed under license by the Free Software Foundation, Inc.
77bdc2678Schristos
87bdc2678Schristos This file is part of RCS.
97bdc2678Schristos
107bdc2678Schristos RCS is free software; you can redistribute it and/or modify
117bdc2678Schristos it under the terms of the GNU General Public License as published by
127bdc2678Schristos the Free Software Foundation; either version 2, or (at your option)
137bdc2678Schristos any later version.
147bdc2678Schristos
157bdc2678Schristos RCS is distributed in the hope that it will be useful,
167bdc2678Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
177bdc2678Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
187bdc2678Schristos GNU General Public License for more details.
197bdc2678Schristos
207bdc2678Schristos You should have received a copy of the GNU General Public License
217bdc2678Schristos along with RCS; see the file COPYING.
227bdc2678Schristos If not, write to the Free Software Foundation,
237bdc2678Schristos 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
247bdc2678Schristos
257bdc2678Schristos Report problems and direct all questions to:
267bdc2678Schristos
277bdc2678Schristos rcs-bugs@cs.purdue.edu
287bdc2678Schristos
297bdc2678Schristos */
307bdc2678Schristos
317bdc2678Schristos #include "rcsbase.h"
327bdc2678Schristos
337bdc2678Schristos #if has_dirent
347bdc2678Schristos static int get_directory P((char const*,char***));
357bdc2678Schristos #endif
367bdc2678Schristos
377bdc2678Schristos static int unlock P((struct hshentry *));
387bdc2678Schristos static void cleanup P((void));
397bdc2678Schristos
407bdc2678Schristos static RILE *workptr;
417bdc2678Schristos static int exitstatus;
427bdc2678Schristos
437bdc2678Schristos mainProg(rcscleanId, "rcsclean", "Id: rcsclean.c,v 5.9 1995/06/16 06:19:24 eggert Exp ")
447bdc2678Schristos {
457bdc2678Schristos static char const usage[] =
467bdc2678Schristos "\nrcsclean: usage: rcsclean -ksubst -{nqru}[rev] -T -Vn -xsuff -zzone file ...";
477bdc2678Schristos
487bdc2678Schristos static struct buf revision;
497bdc2678Schristos
507bdc2678Schristos char *a, **newargv;
517bdc2678Schristos char const *rev, *p;
527bdc2678Schristos int dounlock, expmode, perform, unlocked, unlockflag, waslocked;
537bdc2678Schristos int Ttimeflag;
547bdc2678Schristos struct hshentries *deltas;
557bdc2678Schristos struct hshentry *delta;
567bdc2678Schristos struct stat workstat;
577bdc2678Schristos
587bdc2678Schristos setrid();
597bdc2678Schristos
607bdc2678Schristos expmode = -1;
617bdc2678Schristos rev = 0;
627bdc2678Schristos suffixes = X_DEFAULT;
637bdc2678Schristos perform = true;
647bdc2678Schristos unlockflag = false;
657bdc2678Schristos Ttimeflag = false;
667bdc2678Schristos
677bdc2678Schristos argc = getRCSINIT(argc, argv, &newargv);
687bdc2678Schristos argv = newargv;
697bdc2678Schristos for (;;) {
707bdc2678Schristos if (--argc < 1) {
717bdc2678Schristos # if has_dirent
727bdc2678Schristos argc = get_directory(".", &newargv);
737bdc2678Schristos argv = newargv;
747bdc2678Schristos break;
757bdc2678Schristos # else
767bdc2678Schristos faterror("no pathnames specified");
777bdc2678Schristos # endif
787bdc2678Schristos }
797bdc2678Schristos a = *++argv;
807bdc2678Schristos if (!*a || *a++ != '-')
817bdc2678Schristos break;
827bdc2678Schristos switch (*a++) {
837bdc2678Schristos case 'k':
847bdc2678Schristos if (0 <= expmode)
857bdc2678Schristos redefined('k');
867bdc2678Schristos if ((expmode = str2expmode(a)) < 0)
877bdc2678Schristos goto unknown;
887bdc2678Schristos break;
897bdc2678Schristos
907bdc2678Schristos case 'n':
917bdc2678Schristos perform = false;
927bdc2678Schristos goto handle_revision;
937bdc2678Schristos
947bdc2678Schristos case 'q':
957bdc2678Schristos quietflag = true;
967bdc2678Schristos /* fall into */
977bdc2678Schristos case 'r':
987bdc2678Schristos handle_revision:
997bdc2678Schristos if (*a) {
1007bdc2678Schristos if (rev)
1017bdc2678Schristos warn("redefinition of revision number");
1027bdc2678Schristos rev = a;
1037bdc2678Schristos }
1047bdc2678Schristos break;
1057bdc2678Schristos
1067bdc2678Schristos case 'T':
1077bdc2678Schristos if (*a)
1087bdc2678Schristos goto unknown;
1097bdc2678Schristos Ttimeflag = true;
1107bdc2678Schristos break;
1117bdc2678Schristos
1127bdc2678Schristos case 'u':
1137bdc2678Schristos unlockflag = true;
1147bdc2678Schristos goto handle_revision;
1157bdc2678Schristos
1167bdc2678Schristos case 'V':
1177bdc2678Schristos setRCSversion(*argv);
1187bdc2678Schristos break;
1197bdc2678Schristos
1207bdc2678Schristos case 'x':
1217bdc2678Schristos suffixes = a;
1227bdc2678Schristos break;
1237bdc2678Schristos
1247bdc2678Schristos case 'z':
1257bdc2678Schristos zone_set(a);
1267bdc2678Schristos break;
1277bdc2678Schristos
1287bdc2678Schristos default:
1297bdc2678Schristos unknown:
1307bdc2678Schristos error("unknown option: %s%s", *argv, usage);
1317bdc2678Schristos }
1327bdc2678Schristos }
1337bdc2678Schristos
1347bdc2678Schristos dounlock = perform & unlockflag;
1357bdc2678Schristos
1367bdc2678Schristos if (nerror)
1377bdc2678Schristos cleanup();
1387bdc2678Schristos else
1397bdc2678Schristos for (; 0 < argc; cleanup(), ++argv, --argc) {
1407bdc2678Schristos
1417bdc2678Schristos ffree();
1427bdc2678Schristos
1437bdc2678Schristos if (!(
1447bdc2678Schristos 0 < pairnames(
1457bdc2678Schristos argc, argv,
1467bdc2678Schristos dounlock ? rcswriteopen : rcsreadopen,
1477bdc2678Schristos true, true
1487bdc2678Schristos ) &&
1497bdc2678Schristos (workptr = Iopen(workname, FOPEN_R_WORK, &workstat))
1507bdc2678Schristos ))
1517bdc2678Schristos continue;
1527bdc2678Schristos
1537bdc2678Schristos if (same_file(RCSstat, workstat, 0)) {
1547bdc2678Schristos rcserror("RCS file is the same as working file %s.",
1557bdc2678Schristos workname
1567bdc2678Schristos );
1577bdc2678Schristos continue;
1587bdc2678Schristos }
1597bdc2678Schristos
1607bdc2678Schristos gettree();
1617bdc2678Schristos
1627bdc2678Schristos p = 0;
1637bdc2678Schristos if (rev) {
1647bdc2678Schristos if (!fexpandsym(rev, &revision, workptr))
1657bdc2678Schristos continue;
1667bdc2678Schristos p = revision.string;
1677bdc2678Schristos } else if (Head)
1687bdc2678Schristos switch (unlockflag ? findlock(false,&delta) : 0) {
1697bdc2678Schristos default:
1707bdc2678Schristos continue;
1717bdc2678Schristos case 0:
1727bdc2678Schristos p = Dbranch ? Dbranch : "";
1737bdc2678Schristos break;
1747bdc2678Schristos case 1:
1757bdc2678Schristos p = delta->num;
1767bdc2678Schristos break;
1777bdc2678Schristos }
1787bdc2678Schristos delta = 0;
1797bdc2678Schristos deltas = 0; /* Keep lint happy. */
1807bdc2678Schristos if (p && !(delta = genrevs(p,(char*)0,(char*)0,(char*)0,&deltas)))
1817bdc2678Schristos continue;
1827bdc2678Schristos
1837bdc2678Schristos waslocked = delta && delta->lockedby;
1847bdc2678Schristos locker_expansion = unlock(delta);
1857bdc2678Schristos unlocked = locker_expansion & unlockflag;
1867bdc2678Schristos if (unlocked<waslocked && workstat.st_mode&(S_IWUSR|S_IWGRP|S_IWOTH))
1877bdc2678Schristos continue;
1887bdc2678Schristos
1897bdc2678Schristos if (unlocked && !checkaccesslist())
1907bdc2678Schristos continue;
1917bdc2678Schristos
1927bdc2678Schristos if (dorewrite(dounlock, unlocked) != 0)
1937bdc2678Schristos continue;
1947bdc2678Schristos
1957bdc2678Schristos if (0 <= expmode)
1967bdc2678Schristos Expand = expmode;
1977bdc2678Schristos else if (
1987bdc2678Schristos waslocked &&
1997bdc2678Schristos Expand == KEYVAL_EXPAND &&
2007bdc2678Schristos WORKMODE(RCSstat.st_mode,true) == workstat.st_mode
2017bdc2678Schristos )
2027bdc2678Schristos Expand = KEYVALLOCK_EXPAND;
2037bdc2678Schristos
2047bdc2678Schristos getdesc(false);
2057bdc2678Schristos
2067bdc2678Schristos if (
2077bdc2678Schristos !delta ? workstat.st_size!=0 :
2087bdc2678Schristos 0 < rcsfcmp(
2097bdc2678Schristos workptr, &workstat,
2107bdc2678Schristos buildrevision(deltas, delta, (FILE*)0, false),
2117bdc2678Schristos delta
2127bdc2678Schristos )
2137bdc2678Schristos )
2147bdc2678Schristos continue;
2157bdc2678Schristos
2167bdc2678Schristos if (quietflag < unlocked)
2177bdc2678Schristos aprintf(stdout, "rcs -u%s %s\n", delta->num, RCSname);
2187bdc2678Schristos
2197bdc2678Schristos if (perform & unlocked) {
2207bdc2678Schristos if_advise_access(deltas->first != delta, finptr, MADV_SEQUENTIAL);
2217bdc2678Schristos if (donerewrite(true,
2227bdc2678Schristos Ttimeflag ? RCSstat.st_mtime : (time_t)-1
2237bdc2678Schristos ) != 0)
2247bdc2678Schristos continue;
2257bdc2678Schristos }
2267bdc2678Schristos
2277bdc2678Schristos if (!quietflag)
2287bdc2678Schristos aprintf(stdout, "rm -f %s\n", workname);
2297bdc2678Schristos Izclose(&workptr);
2307bdc2678Schristos if (perform && un_link(workname) != 0)
2317bdc2678Schristos eerror(workname);
2327bdc2678Schristos
2337bdc2678Schristos }
2347bdc2678Schristos
2357bdc2678Schristos tempunlink();
2367bdc2678Schristos if (!quietflag)
2377bdc2678Schristos Ofclose(stdout);
2387bdc2678Schristos exitmain(exitstatus);
2397bdc2678Schristos }
2407bdc2678Schristos
2417bdc2678Schristos static void
cleanup()2427bdc2678Schristos cleanup()
2437bdc2678Schristos {
2447bdc2678Schristos if (nerror) exitstatus = EXIT_FAILURE;
2457bdc2678Schristos Izclose(&finptr);
2467bdc2678Schristos Izclose(&workptr);
2477bdc2678Schristos Ozclose(&fcopy);
2487bdc2678Schristos ORCSclose();
2497bdc2678Schristos dirtempunlink();
2507bdc2678Schristos }
2517bdc2678Schristos
2527bdc2678Schristos #if RCS_lint
2537bdc2678Schristos # define exiterr rcscleanExit
2547bdc2678Schristos #endif
2557bdc2678Schristos void
exiterr()2567bdc2678Schristos exiterr()
2577bdc2678Schristos {
2587bdc2678Schristos ORCSerror();
2597bdc2678Schristos dirtempunlink();
2607bdc2678Schristos tempunlink();
2617bdc2678Schristos _exit(EXIT_FAILURE);
2627bdc2678Schristos }
2637bdc2678Schristos
2647bdc2678Schristos static int
unlock(delta)2657bdc2678Schristos unlock(delta)
2667bdc2678Schristos struct hshentry *delta;
2677bdc2678Schristos {
2687bdc2678Schristos register struct rcslock **al, *l;
2697bdc2678Schristos
2707bdc2678Schristos if (delta && delta->lockedby && strcmp(getcaller(),delta->lockedby)==0)
2717bdc2678Schristos for (al = &Locks; (l = *al); al = &l->nextlock)
2727bdc2678Schristos if (l->delta == delta) {
2737bdc2678Schristos *al = l->nextlock;
2747bdc2678Schristos delta->lockedby = 0;
2757bdc2678Schristos return true;
2767bdc2678Schristos }
2777bdc2678Schristos return false;
2787bdc2678Schristos }
2797bdc2678Schristos
2807bdc2678Schristos #if has_dirent
2817bdc2678Schristos static int
get_directory(dirname,aargv)2827bdc2678Schristos get_directory(dirname, aargv)
2837bdc2678Schristos char const *dirname;
2847bdc2678Schristos char ***aargv;
2857bdc2678Schristos /*
2867bdc2678Schristos * Put a vector of all DIRNAME's directory entries names into *AARGV.
2877bdc2678Schristos * Ignore names of RCS files.
2887bdc2678Schristos * Yield the number of entries found. Terminate the vector with 0.
2897bdc2678Schristos * Allocate the storage for the vector and entry names.
2907bdc2678Schristos * Do not sort the names. Do not include '.' and '..'.
2917bdc2678Schristos */
2927bdc2678Schristos {
2937bdc2678Schristos int i, entries = 0, entries_max = 64;
2947bdc2678Schristos size_t chars = 0, chars_max = 1024;
2957bdc2678Schristos size_t *offset = tnalloc(size_t, entries_max);
2967bdc2678Schristos char *a = tnalloc(char, chars_max), **p;
2977bdc2678Schristos DIR *d;
2987bdc2678Schristos struct dirent *e;
2997bdc2678Schristos
3007bdc2678Schristos if (!(d = opendir(dirname)))
3017bdc2678Schristos efaterror(dirname);
3027bdc2678Schristos while ((errno = 0, e = readdir(d))) {
3037bdc2678Schristos char const *en = e->d_name;
3047bdc2678Schristos size_t s = strlen(en) + 1;
3057bdc2678Schristos if (en[0]=='.' && (!en[1] || (en[1]=='.' && !en[2])))
3067bdc2678Schristos continue;
3077bdc2678Schristos if (rcssuffix(en))
3087bdc2678Schristos continue;
3097bdc2678Schristos while (chars_max < s + chars)
3107bdc2678Schristos a = trealloc(char, a, chars_max<<=1);
3117bdc2678Schristos if (entries == entries_max)
3127bdc2678Schristos offset = trealloc(size_t, offset, entries_max<<=1);
3137bdc2678Schristos offset[entries++] = chars;
3147bdc2678Schristos VOID strcpy(a+chars, en);
3157bdc2678Schristos chars += s;
3167bdc2678Schristos }
3177bdc2678Schristos # if void_closedir
3187bdc2678Schristos # define close_directory(d) (closedir(d), 0)
3197bdc2678Schristos # else
3207bdc2678Schristos # define close_directory(d) closedir(d)
3217bdc2678Schristos # endif
3227bdc2678Schristos if (errno || close_directory(d) != 0)
3237bdc2678Schristos efaterror(dirname);
3247bdc2678Schristos if (chars)
3257bdc2678Schristos a = trealloc(char, a, chars);
326*fa28c6faSchristos else {
3277bdc2678Schristos tfree(a);
328*fa28c6faSchristos a = NULL;
329*fa28c6faSchristos }
3307bdc2678Schristos *aargv = p = tnalloc(char*, entries+1);
331*fa28c6faSchristos if (a)
3327bdc2678Schristos for (i=0; i<entries; i++)
3337bdc2678Schristos *p++ = a + offset[i];
3347bdc2678Schristos *p = 0;
3357bdc2678Schristos tfree(offset);
3367bdc2678Schristos return entries;
3377bdc2678Schristos }
3387bdc2678Schristos #endif
339