|
|
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.