|
|
1.1 root 1: /*
2: * expire - expire daemon runs around and nails all articles that
3: * have expired.
4: *
5: * Note: This version of expire contains some code to implement new
6: * history features, e.g. to work without a history file or to rebuild
7: * the history file. This code was written for B news 2.9 and would
8: * need some conversion to deal with the 2.10 heirarchical subgroups
9: * in subdirectories. This would imply a recursive traversal of the
10: * tree. Such code could be written but I didn't have the energy to
11: * convert this 2.9 style code.
12: */
13:
14: static char *SccsId = "@(#)expire.c 2.16 6/24/83";
15:
16: #include "params.h"
17: #include "ndir.h"
18:
19: #define NART 100
20:
21: extern char groupdir[BUFSIZ], rcbuf[BUFLEN];
22: extern char ACTIVE[];
23: extern char SPOOL[];
24: extern char ARTFILE[];
25: extern char filename[];
26: char NARTFILE[BUFSIZ], OARTFILE[BUFSIZ];
27: char OLDNEWS[BUFLEN];
28: int verbose = 0;
29: int ignorexp = 0;
30: int doarchive = 0;
31: int nohistory = 0;
32: int rebuild = 0;
33:
34: /*
35: * The code dealing with this is ifdeffed out.
36: * However, it should be redone to malloc the mh_ident
37: * fields, and realloc the multhist array, so that the
38: * fixed constant NART can be done away with. Apparently
39: * when rebuilding the history file, 100 is much too small.
40: */
41: struct multhist {
42: char mh_ident[BUFLEN];
43: char *mh_file;
44: } multhist[NART];
45:
46: typedef struct {
47: char *dptr;
48: int dsize;
49: } datum;
50:
51: long expincr;
52: long atol();
53: time_t cgtdate(), time();
54: FILE *popen();
55:
56: main(argc, argv)
57: int argc;
58: char **argv;
59: {
60: register int i;
61: register FILE *fp = NULL, *actfp;
62: register char *ptr;
63: struct hbuf h;
64: struct stat statbuf;
65: register time_t now, newtime;
66: char ngpat[LBUFLEN];
67: char afline[BUFLEN];
68: char *p1, *p2, *p3;
69: FILE *ohfd, *nhfd;
70: DIR *ngdirp;
71: static struct direct *ngdir;
72: char fn[BUFLEN];
73: datum key;
74:
75: pathinit();
76: umask(N_UMASK);
77: expincr = DFLTEXP;
78: ngpat[0] = '\0';
79: while (argc > 1) {
80: switch (argv[1][1]) {
81: case 'v':
82: if (isdigit(argv[1][2]))
83: verbose = argv[1][2] - '0';
84: else
85: verbose = 1;
86: if (verbose < 3)
87: setbuf(stdout, NULL);
88: break;
89: case 'e': /* Use this as default expiration time */
90: if (argc > 2 && argv[2][0] != '-') {
91: argv++;
92: argc--;
93: expincr = atol(argv[1]) * DAYS;
94: }
95: break;
96: case 'I': /* Ignore any existing expiration date */
97: ignorexp = 2;
98: break;
99: case 'i': /* Ignore any existing expiration date */
100: ignorexp = 1;
101: break;
102: case 'n':
103: if (argc > 2) {
104: argv++;
105: argc--;
106: while (argc > 1 && argv[1][0] != '-') {
107: strcat(ngpat, argv[1]);
108: ngcat(ngpat);
109: argv++;
110: argc--;
111: }
112: argv--;
113: argc++;
114: }
115: break;
116: case 'a': /* archive expired articles */
117: doarchive++;
118: break;
119: #ifdef notdef
120: /*
121: * Nohistory and Rebuild are broken by the new directory format.
122: * A recursive directory traversal needs to be made. I don't
123: * have the energy to do this - hopefully someone else will.
124: */
125: case 'h': /* ignore history */
126: nohistory++;
127: break;
128: case 'r': /* rebuild history file */
129: rebuild++;
130: nohistory++;
131: break;
132: #endif
133: default:
134: printf("Usage: expire [ -v [level] ] [-e days ] [-i] [-n newsgroups]\n");
135: exit(1);
136: }
137: argc--;
138: argv++;
139: }
140: if (ngpat[0] == 0)
141: strcpy(ngpat, "all,");
142: now = time(0);
143: if (chdir(SPOOL))
144: xerror("Cannot chdir %s", SPOOL);
145:
146: sprintf(OARTFILE, "%s/%s", LIB, "ohistory");
147: sprintf(ARTFILE, "%s/%s", LIB, "history");
148: sprintf(NARTFILE, "%s/%s", LIB, "nhistory");
149: #ifdef DBM
150: dbminit(ARTFILE);
151: #endif
152: if (verbose)
153: printf("expire: nohistory %d, rebuild %d, doarchive %d\n",
154: nohistory, rebuild, doarchive);
155:
156: if (nohistory) {
157: ohfd = xfopen(ACTIVE, "r");
158: if (rebuild) {
159: sprintf(afline, "sort +2 >%s", NARTFILE);
160: if ((nhfd = popen(afline, "w")) == NULL)
161: xerror("Cannot exec %s", NARTFILE);
162: } else
163: nhfd = xfopen("/dev/null", "w");
164: } else {
165: ohfd = xfopen(ARTFILE, "r");
166: nhfd = xfopen(NARTFILE, "w");
167: }
168:
169: while (TRUE) {
170: if (nohistory) {
171: #ifdef notdef
172: do {
173: if (ngdir == NULL) {
174: if ( ngdirp != NULL )
175: closedir(ngdirp);
176: if (fgets(afline, BUFLEN, ohfd) == NULL)
177: goto out;
178: strcpy(groupdir, afline);
179: p1 = index(groupdir, ' ');
180: if (p1 == NULL)
181: p1 = index(groupdir, '\n');
182: if (p1 != NULL)
183: *p1 = NULL;
184: ngcat(groupdir);
185: if (!ngmatch(groupdir, ngpat))
186: continue;
187: ngdel(groupdir);
188: if ((ngdirp = opendir(groupdir)) == NULL)
189: continue;
190: }
191: ngdir = readdir(ngdirp);
192: } while ( ngdir == NULL || ngdir->d_name[0] == '.' );
193: sprintf(fn, "%s/%s", groupdir, ngdir->d_name);
194: p2 = fn;
195: if (verbose > 2)
196: printf("article: %s\t", fn);
197: #endif
198: } else {
199: if (fgets(afline, BUFLEN, ohfd) == NULL)
200: break;
201: if (verbose > 2)
202: printf("article: %s", afline);
203: p1 = index(afline, '\t');
204: if (p1)
205: p2 = index(p1 + 1, '\t');
206: else
207: continue;
208: if (!p2)
209: continue;
210: p2++;
211: strcpy(groupdir, p2);
212: p3 = index(groupdir, '/');
213: if (p3)
214: *p3 = 0;
215: else {
216: /*
217: * Nothing after the 2nd tab. This happens
218: * when a control message is stored in the
219: * history file. Use the date in the history
220: * file to decide expiration.
221: */
222: h.expdate[0] = 0;
223: strcpy(h.recdate, p1+1);
224: goto checkdate;
225: }
226: ngcat(groupdir);
227: if (!ngmatch(groupdir, ngpat)) {
228: fputs(afline, nhfd);
229: continue;
230: }
231: ngdel(groupdir);
232: strcpy(fn, p2);
233: p1 = index(fn, ' ');
234: if (p1 == 0)
235: p1 = index(fn, '\n');
236: if (p1)
237: *p1 = 0;
238: }
239:
240: strcpy(filename, dirname(fn));
241: if (access(filename, 4)
242: || (fp = fopen(filename, "r")) == NULL) {
243: if (verbose > 3)
244: printf("Can't open %s.\n", filename);
245: continue;
246: }
247: if (hread(&h, fp, TRUE) == NULL) {
248: if (verbose)
249: printf("Garbled article %s.\n", filename);
250: fclose(fp);
251: continue;
252: }
253: #ifdef notdef
254: if (rebuild) {
255: register char *cp;
256: register struct multhist *mhp;
257:
258: if ((cp = index(h.nbuf, NGDELIM)) == NULL) {
259: saveit:
260: fprintf(nhfd, "%s\t%s\t%s \n", h.ident, h.recdate, filename);
261: fclose(fp);
262: continue;
263: }
264: for (mhp = multhist; mhp->mh_ident[0] != NULL && mhp < &multhist[NART]; mhp++) {
265: if (mhp->mh_file == NULL)
266: continue;
267: if (strcmp(mhp->mh_ident, h.ident) != 0)
268: continue;
269: if (index(mhp->mh_file, ' ') != NULL)
270: cp = index(++cp, NGDELIM);
271: strcat(filename, " ");
272: strcat(filename, mhp->mh_file);
273: free(mhp->mh_file);
274: if (*cp == NULL || (cp = index(++cp, NGDELIM)) == NULL) {
275: mhp->mh_file = NULL;
276: goto saveit;
277: } else
278: break;
279: }
280: if (mhp >= &multhist[NART])
281: xerror("Too many articles with multiple newsgroups");
282: strcpy(mhp->mh_ident, h.ident);
283: cp = malloc(strlen(filename) + 1);
284: if ( cp == NULL)
285: xerror("Out of memory");
286: strcpy(cp, filename);
287: mhp->mh_file = cp;
288: fclose(fp);
289: continue;
290: }
291: #endif
292:
293: fclose(fp);
294: checkdate:
295: if (h.expdate[0])
296: h.exptime = cgtdate(h.expdate);
297: newtime = cgtdate(h.recdate) + expincr;
298: if (!h.expdate[0] || ignorexp == 2 ||
299: (ignorexp == 1 && newtime < h.exptime))
300: h.exptime = newtime;
301: if (now >= h.exptime) {
302: #ifdef DEBUG
303: printf("cancel %s\n", filename);
304: #else
305: if (verbose)
306: printf("cancel %s\n", filename);
307: ulall(p2, &h);
308: # ifdef DBM
309: key.dptr = h.ident;
310: key.dsize = strlen(key.dptr) +1;
311: delete(key);
312: # endif
313: #endif
314: } else {
315: fputs(afline, nhfd);
316: if (verbose > 2)
317: printf("Good article %s\n", rcbuf);
318: }
319: }
320:
321: out:
322: #ifdef notdef
323: if (rebuild) {
324: register struct multhist *mhp;
325: for (mhp = multhist; mhp->mh_ident[0] != NULL && mhp < &multhist[NART]; mhp++)
326: /* should "never" happen */
327: if (mhp->mh_file != NULL )
328: printf("Article: %s %s Cannot find all links\n", mhp->mh_ident, mhp->mh_file);
329: pclose(nhfd);
330: }
331: #endif
332:
333: if (rebuild || !nohistory) {
334: unlink(OARTFILE);
335: link(ARTFILE, OARTFILE);
336: unlink(ARTFILE);
337: link(NARTFILE, ARTFILE);
338: unlink(NARTFILE);
339: }
340: exit(0);
341: }
342:
343: /* Unlink (using tail recursion) all the articles in 'artlist'. */
344: ulall(artlist, h)
345: char *artlist;
346: struct hbuf *h;
347: {
348: char *p;
349: int last = 0;
350: char newname[BUFLEN];
351: char newgroup[BUFLEN];
352: time_t timep[2];
353: char *fn;
354:
355: if (nohistory) {
356: last = 1;
357: } else {
358: while (*artlist == ' ' || *artlist == '\n' || *artlist == ',')
359: artlist++;
360: if (*artlist == 0)
361: return;
362: p = index(artlist, ' ');
363: if (p == 0) {
364: last = 1;
365: p = index(artlist, '\n');
366: }
367: if (p == 0) {
368: last = 1;
369: p = index(artlist, ',');
370: }
371: if (p == 0) {
372: last = 1;
373: fn = dirname(artlist);
374: unlink(fn);
375: return;
376: }
377: if (p)
378: *p = 0;
379: }
380: fn = dirname(artlist);
381: if (doarchive && access(OLDNEWS, 0) == 0) {
382: p = fn + strlen(SPOOL) + 1;
383: sprintf(newname, "%s/%s", OLDNEWS, p);
384: if (verbose > 1)
385: printf("link %s to %s\n", fn, newname);
386: if (link(fn, newname) == -1) {
387: if (mkparents(newname) == 0)
388: link(fn, newname);
389: }
390: timep[0] = timep[1] = cgtdate(h->subdate);
391: utime(newname, timep);
392: }
393:
394: if (verbose)
395: printf("unlink %s\n", fn);
396: unlink(fn);
397: if (!last)
398: ulall(p + 1, h);
399: }
400:
401:
402: xerror(message)
403: char *message;
404: {
405: printf("expire: %s.\n", message);
406: fflush(stdout);
407: exit(1);
408: }
409:
410: /*
411: * If any parent directories of this dir don't exist, create them.
412: */
413: mkparents(dirname)
414: char *dirname;
415: {
416: char buf[200], sysbuf[200];
417: register char *p;
418: int rc;
419: struct passwd *pw;
420:
421: strcpy(buf, dirname);
422: p = rindex(buf, '/');
423: if (p)
424: *p = '\0';
425: if (exists(buf))
426: return;
427: mkparents(buf);
428: sprintf(sysbuf, "mkdir %s", buf);
429: rc = system(sysbuf);
430: strcpy(sysbuf, buf);
431: if (verbose)
432: printf("mkdir %s, rc %d\n", sysbuf, rc);
433: chmod(sysbuf, 0755);
434: if ((pw = getpwnam(NEWSU)) != NULL)
435: chown(sysbuf, pw->pw_uid, pw->pw_gid);
436: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.