ecn-pa:ecn-pb:rick (10/27/82)
/* * expire - expire daemon runs around and nails all articles that * have expired. */ static char *SccsId = "@(#) expire.c 2.10 6/21/82"; #include "params.h" #include <ndir.h> extern char groupdir[BUFSIZ], rcbuf[BUFLEN]; extern char *ACTIVE; extern char *SPOOL; extern char *CAND; char ARTFILE[BUFSIZ], NARTFILE[BUFSIZ], OARTFILE[BUFSIZ]; extern char filename[]; char *OLDNEWS = "/usr/spool/oldnews"; int verbose = 0; int ignorexp = 0; int doarchive = 0; int nohistory = 0; int rebuild = 0; #define NART 100 struct multhist { char mh_ident[14]; char *mh_file; }multhist[NART]; long expincr; long atol(); time_t cgtdate(), time(); FILE *popen(); main(argc, argv) int argc; char **argv; { register int i; register FILE *fp = NULL, *actfp; register char *ptr; struct hbuf h; struct stat statbuf; register time_t now, newtime; char ngpat[LBUFLEN]; char afline[BUFLEN]; char *p1, *p2; FILE *ohfd, *nhfd; DIR *ngdirp; static struct direct *ngdir; expincr = DFLTEXP; ngpat[0] = '\0'; while (argc > 1) { switch (argv[1][1]) { case 'v': if (isdigit(argv[1][2])) verbose = argv[1][2] - '0'; else verbose = 1; break; case 'e': /* Use this as default expiration time */ if (argc > 2 && argv[2][0] != '-') { argv++; argc--; expincr = atol(argv[1]) * DAYS; } break; case 'I': /* Ignore any existing expiration date */ ignorexp = 2; break; case 'i': /* Ignore any existing expiration date */ ignorexp = 1; break; case 'n': if (argc > 2) { argv++; argc--; while (argc > 1 && argv[1][0] != '-') { strcat(ngpat, argv[1]); ngcat(ngpat); argv++; argc--; } argv--; argc++; } break; case 'a': /* archive expired articles */ doarchive++; break; case 'h': /* ignore history */ nohistory++; break; case 'r': /* rebuild history file */ rebuild++; nohistory++; break; default: printf("Usage: expire [ -v [level] ] [-e days ] [-i] [-n newsgroups]\n"); exit(1); } argc--; argv++; } if (ngpat[0] == 0) strcpy(ngpat, "all,"); now = time(0); if (chdir(SPOOL)) xerror("Cannot chdir %s", SPOOL); sprintf(OARTFILE, "%s/%s", LIB, "ohistory"); sprintf(ARTFILE, "%s/%s", LIB, "history"); sprintf(NARTFILE, "%s/%s", LIB, "nhistory"); if (nohistory) { ohfd = xfopen(ACTIVE, "r"); if (rebuild){ sprintf(afline,"sort +2 >%s",NARTFILE); if ((nhfd=popen(afline,"w")) == NULL) xerror("Cannot exec %s",NARTFILE); } else nhfd = xfopen("/dev/null", "w"); } else { ohfd = xfopen(ARTFILE, "r"); nhfd = xfopen(NARTFILE, "w"); } while (TRUE) { if (nohistory){ do { if (ngdir == NULL) { if( ngdirp != NULL ) closedir(ngdirp); if (fgets(afline, BUFLEN, ohfd) == NULL) goto out; strcpy(groupdir,afline); p1 = index(groupdir, '\n'); if (p1) *p1 = NULL; ngcat(groupdir); if (!ngmatch(groupdir,ngpat)) continue; ngdel(groupdir); if ((ngdirp=opendir(groupdir)) == NULL) continue; } ngdir = readdir(ngdirp); } while ( ngdir == NULL || ngdir->d_name[0] == '.' ); sprintf(filename,"%s/%s",groupdir,ngdir->d_name); p2 = filename; if (verbose > 2) printf("article: %s\t", filename); } else { if (fgets(afline, BUFLEN, ohfd) == NULL) break; if (verbose > 2) printf("article: %s", afline); p1 = index(afline, '\t'); if (p1) p2 = index(p1+1, '\t'); else continue; if (!p2) continue; p2++; strcpy(groupdir, p2); p1 = index(groupdir, '/'); if (p1) *p1 = 0; else continue; ngcat(groupdir); if (!ngmatch(groupdir, ngpat)) { fputs(afline, nhfd); continue; } ngdel(groupdir); strcpy(filename, p2); p1 = index(filename, ' '); if (p1 == 0) p1 = index(filename, '\n'); if (p1) *p1 = 0; } if (access(filename, 4) || (fp = fopen(filename, "r")) == NULL) { if (verbose > 3) printf("Can't open %s.\n", filename); continue; } if (hread(&h, fp) == NULL) { if (verbose) printf("Garbled article %s.\n", filename); fclose(fp); continue; } if (rebuild){ register char *cp; register struct multhist *mhp; if ((cp=index(h.nbuf,NGDELIM)) == NULL) { saveit: fprintf(nhfd,"%s\t%s\t%s \n",h.ident,h.recdate,filename); fclose(fp); continue; } for (mhp=multhist;mhp->mh_ident[0]!=NULL&&mhp<&multhist[NART];mhp++) { if (mhp->mh_file == NULL) continue; if (strcmp(mhp->mh_ident,h.ident) != 0) continue; if (index(mhp->mh_file,' ') != NULL) cp = index(++cp,NGDELIM); strcat(filename," "); strcat(filename,mhp->mh_file); free(mhp->mh_file); if (*cp == NULL || (cp=index(++cp,NGDELIM)) == NULL) { mhp->mh_file = NULL; goto saveit; } else break; } if (mhp>=&multhist[NART]) xerror("Too many articles with multiple newsgroups"); strcpy(mhp->mh_ident,h.ident); cp = malloc(strlen(filename)+1); if ( cp == NULL) xerror("Out of memory"); strcpy(cp,filename); mhp->mh_file = cp; fclose(fp); continue; } if (h.expdate[0]) h.exptime = cgtdate(h.expdate); newtime = cgtdate(h.recdate) + expincr; if (!h.expdate[0] || ignorexp==2 || (ignorexp==1 && newtime < h.exptime)) h.exptime = newtime; if (now >= h.exptime) { #ifdef DEBUG printf("cancel %s\n", filename); #else if (verbose) printf("cancel %s\n", filename); ulall(p2,&h); #endif } else { fputs(afline, nhfd); if (verbose > 2) printf("Good article %s\n", rcbuf); } fclose(fp); } out: if (rebuild){ register struct multhist *mhp; for (mhp=multhist;mhp->mh_ident[0]!=NULL&&mhp<&multhist[NART];mhp++) /* should "never" happen */ if (mhp->mh_file != NULL ) printf("Article: %s %s Cannot find all links\n",mhp->mh_ident,mhp->mh_file); pclose(nhfd); } if (rebuild || !nohistory){ unlink(OARTFILE); link(ARTFILE, OARTFILE); unlink(ARTFILE); link(NARTFILE, ARTFILE); unlink(NARTFILE); } exit(0); } ulall(artlist,h) char *artlist; struct hbuf *h; { char *p; int last = 0; char newname[BUFLEN]; char newgroup[BUFLEN]; time_t timep[2]; if (nohistory){ last = 1; } else { while (*artlist == ' ' || *artlist == '\n' || *artlist == ',') artlist++; if (*artlist == 0) return; p = index(artlist, ' '); if (p == 0) { last = 1; p = index(artlist, '\n'); } if (p == 0) { last = 1; p = index(artlist, ','); } if (p == 0) { last = 1; unlink(artlist); return; } if (p) *p = 0; } if (doarchive && access(OLDNEWS, 0) == 0) { strcpy(newgroup, artlist); p = index(newgroup, '/'); *p = 0; sprintf(newname, "%s/%s/%s", OLDNEWS, newgroup, h->ident); if (verbose > 1) printf("link %s to %s\n", newname, filename); if (link(artlist, newname) == -1) { if (mkdir(newgroup) == 0) link(artlist, newname); } timep[0] = timep[1] = cgtdate(h->subdate); utime(newname,timep); } if (verbose) printf("unlink %s\n", artlist); unlink(artlist); if (!last) ulall(p+1,h); } xerror(message) char *message; { printf("expire: %s.\n", message); fflush(stdout); exit(1); } mkdir(groupdir) register char *groupdir; { char buf[BUFLEN]; register struct passwd *pw; extern char *NEWSU; int rc; if (access(OLDNEWS, 2) < 0) return -1; sprintf(buf, "mkdir %s/%s", OLDNEWS, groupdir); rc = system(buf); sprintf(buf, "%s/%s", OLDNEWS, groupdir); if (verbose) printf("mkdir %s, rc %d\n", buf, rc); chmod(buf, 0755); if ((pw = getpwnam(NEWSU)) != NULL) chown(buf, pw->pw_uid, pw->pw_gid); return rc; }