1 /* parse_rc.c--rcfile parser for niftyclean
2  *
3  * Written by Jay Laefer and Mike Darweesh
4  * (C) Copyright 1989 by Jay Laefer and Mike Darweesh
5  * All Rights Reserved.
6  * Permission is granted to copy, modify, and use this as long
7  * as this notice remains intact.  This is a nifty program.
8  * (C) Copyright 1991- by Charles Swiger
9  */
10 
11 #include "niftyclean.h"
12 #include <stdlib.h>
13 
14 static struct globtype *globlist = NULL;
15 static struct batchtype *batchlist = NULL;
16 static struct excl_dirtype *excl_dirlist = NULL;
17 
18 /* Here is the default list of regex's to terminate; should move this to a
19  * system-wide config file and not hardcode it within the binary.
20  */
21 
22 char *defaults[] = {
23     "core",
24     "*~",
25     ".*~",
26     "*.BAK",
27     ".*.BAK",
28     "*.CKP",
29     ".*.CKP",
30     "*.NEW",
31     ".*.NEW",
32     "#*#",
33     ".emacs_[0-9]*",
34     "dead.letter",
35     "*.otl",
36     ".*.otl",
37     "*.backup",
38     ".*.backup",
39     NULL
40 };
41 
42 char *def_excl_dirs[] = {
43     ".MESSAGES",
44     NULL
45 };
46 
47 char *objects[] = {
48     "*.o",
49     "*.pyc",
50     "*.pyo",
51     NULL
52 };
53 
54 /* do_default_rc() goes through the array of default globs and adds each item
55  * to the global list of patterns.  It then goes through the array of default
56  * directories and adds them to the list of directories to be excluded.
57  */
58 static void
do_default_rc(void)59 do_default_rc(void)
60 {
61     char **def_ptr;
62 
63     if (!(flag & NOGLOB)) {
64 	def_ptr = defaults;
65         while (*def_ptr) {
66             add_glob(*def_ptr++);
67         }
68     }
69 
70     if (!(flag & NOEXCL)) {
71 	def_ptr = def_excl_dirs;
72         while (*def_ptr) {
73             add_glob(*def_ptr++);
74         }
75     }
76 }
77 
78 void
do_rc(void)79 do_rc(void)
80 {
81     FILE *fp;
82     char *home, rcfile[MAXPATHLEN], line[1024], **def_ptr;
83     int noglob, noexcl;
84 
85     noglob = flag & NOGLOB;
86     noexcl = flag & NOEXCL;
87 
88     if (flag & OBJECTS) {
89 	def_ptr = objects;
90         printf("in objects, def_ptr = %s\n", *def_ptr);
91         while (*def_ptr) {
92             add_glob(*def_ptr++);
93         }
94     }
95 
96     /* return if we don't want the defaults */
97     if(noglob && noexcl)
98         return;
99 
100     /* get home directory */
101     home = getenv("HOME");
102     if (home == NULL) {
103 	do_default_rc();
104 	return;
105     }
106 
107     if ((strlen(home) + strlen(RCFILE)) > MAXPATHLEN)
108         errorh(FATAL,"Pathlength to ~/.cleanrc too long");
109 
110     strcpy(rcfile, home);
111     strcat(rcfile, "/");
112     strcat(rcfile, RCFILE);
113 
114     /* open .cleanrc */
115     if ((fp = fopen(rcfile, "r")) == NULL) {
116 	do_default_rc();
117 	return;
118     }
119 
120     /* read patterns from file */
121     while (fgets(line, MAXPATHLEN, fp) != NULL) {
122 	int len, c;
123 
124 	len = strlen(line) - 1;
125 	if (line[len] == '\n')
126             line[len] = '\0';
127 	else
128             while (((c = getc(fp)) != EOF) && (c != '\n'));
129 
130 	/* check for comment or blank line */
131 	if ((line[0] != '#') && (line[0] != '\0')) {
132 	    if (line[0] == '!') {
133 		if (!noexcl)
134                     add_excl_dir(line + 1);
135 	    } else if (!noglob) {
136 		if ((line[0] == '\\') &&
137 		    ((line[1] == '#') || (line[1] == '!') || (line[1] == '\\')))
138                     add_glob(line + 1);
139 		else
140                     add_glob(line);
141 	    }
142 	}
143     }
144 
145     if (fclose(fp))
146         errorh(WARNING,"Problem closing ~/.cleanrc");
147 }
148 
149 /* find_match() takes a string and goes through the list of patterns until it
150  * either finds a match or runs out of patterns.
151  */
152 static int
find_match(char * file)153 find_match (char *file)
154 {
155     struct globtype *temp;
156 
157     temp = globlist;
158     while (temp) {
159 	if (match(file, temp->glob))
160             return 1;
161 	temp = temp->next;
162     }
163     return 0;
164 }
165 
166 /* dofile() takes a directory and a filename and acts based on whether FORCE,
167  * BATCH, or INTERACTIVE mode is on.
168  */
169 int
dofile(char * dir,char * file)170 dofile (char *dir, char *file)
171 {
172     char    unlinkerr[MAXPATHLEN + 100], c;
173 
174     if (find_match(file)) {	/* if the file matches a pattern */
175 	char fullpath[MAXPATHLEN];
176 
177 	strcpy(fullpath, dir);
178 	strcat(fullpath, "/");
179 	strcat(fullpath, file);
180 
181 	if (flag & FORCE)
182             (void)unlink(fullpath);
183 	else if (flag & BATCH)
184             add_batch(fullpath);
185 	else {
186 	    fputs("Remove ", stdout);
187 	    fputs(fullpath, stdout);
188 	    fputs(" y/n/s [y]: ", stdout);
189 	    c = getfirstchar(stdin);
190 	    /* kill file if user wants it killed */
191 	    switch (c) {
192               case 'y':
193               case 'Y':
194               case '\n':
195 		if (unlink(fullpath)) {
196 		    strcpy(unlinkerr, "Could not remove: ");
197 		    strcat(unlinkerr, fullpath);
198 		    errorh(WARNING, unlinkerr);
199 		} else {
200 		    fputs("Removed: ", stdout);
201 		    puts(fullpath);
202 		}
203 		break;
204               case 's':
205               case 'S':
206 		skip = 1;
207 		puts("Skipping this directory...");
208 		break;
209 	    }
210 	}
211 	return 1;
212     } else
213         return 0;
214 }
215 
216 /* add_batch() takes the full pathname to a file that is slated for deletion.
217  * It then adds that to the globab linked list of such files.
218  */
219 void
add_batch(char * path)220 add_batch (char *path)
221 {
222     struct batchtype *batchptr;
223     batchptr = (struct batchtype *) malloc((sizeof (struct batchtype)
224                                             + strlen(path)));
225     if (batchptr == NULL)
226         errorh(FATAL, "Malloc failed in add_batch()");
227 
228     strcpy(batchptr->path, path);
229     batchptr->next = batchlist;
230     batchlist = batchptr;
231 }
232 
233 /* dobatch() runs through the list of files slated for deletion and asks the
234  * user if he wants to delete them.
235  */
236 void
dobatch(void)237 dobatch (void)
238 {
239     struct batchtype *temp;
240     char unlinkerr[MAXPATHLEN + 100];
241     int c;
242 
243     if (!batchlist) {
244 	puts("No non-nifty files found.");
245 	return;
246     }
247 
248     puts("\nThe following are non-nifty files:");
249     for (temp = batchlist; temp; temp = temp->next)
250         puts(temp->path);
251 
252     fputs("Delete them y/n [y]: ", stdout);
253     c = getfirstchar(stdin);
254 
255     if ((c = ((c == 'y') || (c == 'Y') || (c == '\n'))))
256         puts("Deleting files...");
257     else
258         puts("Files not deleted.");
259 
260     /* delete the files and free the memory */
261     while (batchlist) {
262 	if (c && unlink(batchlist->path)) {
263 	    strcpy(unlinkerr, "Could not remove: ");
264 	    strcat(unlinkerr, batchlist->path);
265 	    errorh(WARNING,unlinkerr);
266 	}
267 	temp = batchlist;
268 	batchlist = batchlist->next;
269 	free(temp);
270     }
271 }
272 
273 /* add_glob() takes a word, malloc's space for a structure, and adds it to the
274  * front of the list of patterns to be matched.
275  */
276 void
add_glob(char * word)277 add_glob (char *word)
278 {
279     struct globtype *globptr;
280 
281     if (0)
282         printf("add_glob(): word = %s\n", word);
283 
284     globptr = (struct globtype *)malloc((sizeof (struct globtype)) + strlen(word));
285     if (globptr == NULL)
286         errorh(FATAL, "Malloc failed in add_glob()");
287 
288     strcpy(globptr->glob, word);
289 
290     globptr->next = globlist;
291 
292     globlist = globptr;
293 }
294 
295 /* add_excl_dir() takes a word, malloc's space for a structure, and adds it to
296  * the front of the list of directories to be excluded from the traversal.
297  */
298 void
add_excl_dir(char * word)299 add_excl_dir (char *word)
300 {
301     struct excl_dirtype *excl_dirptr;
302     if ((excl_dirptr = (struct excl_dirtype *)malloc((sizeof (struct excl_dirtype)) + strlen(word))) == NULL)
303         errorh(FATAL, "Malloc failed in add_excl_dir()");
304 
305     strcpy(excl_dirptr->excl_dir, word);
306 
307     excl_dirptr->next = excl_dirlist;
308 
309     excl_dirlist = excl_dirptr;
310 }
311 
312 /* check_excl_list() takes a directory name and checks to see if it is on the
313  * list of directories to be excluded.  If so, a 0 is returned.  Otherwise,
314  * return 1.
315  */
316 int
check_excl_list(char * dir)317 check_excl_list (char *dir)
318 {
319     struct excl_dirtype *temp;
320 
321     /* Move down the linked list that starts with excl_dirlist */
322     for (temp = excl_dirlist; temp; temp = temp->next)
323         if (!strcmp(temp->excl_dir, dir))
324             return 0;		/* Found */
325 
326     return 1;
327 }
328