/* * This part was written by Harald Kipp * * Bug reports should be sent to * * harald@os2point.ping.de * harald@sesam.com * Fido: 2:2448/434 * * Purging articles by reading the active file. * */ #include #include #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "expire.h" static int AddArt2Hist(DBM *db, char *id, time_t atim, long asiz, char *ng, long anum); /************************************************************************/ /* */ /************************************************************************/ int PurgeByActive(void) { int result = 1; FILE *fpact; char *line; long maxart, minart; char *ngname; char *ngdir; char *artpath; int lineno = 0; long *art_array; int num_arts; int i; char mc; char *cp; DBM *ndb = NULL; char *msgid; time_t hex_time; if((fpact = xopen(cfg.activefile, "rt")) == NULL) { perror(cfg.activefile); lperror(cfg.activefile); return(0); } if(cfg.dorebuild) { /* * Remove leftovers and open new history */ if(del_history(cfg.newhistfile)) lprintf("Removed from previous exec: %s", cfg.newhistfile); del_history(cfg.oldhistfile); if((ndb = dbm_open(cfg.newhistfile, O_RDWR | O_CREAT, 0666)) == NULL) { perror(cfg.newhistfile); fclose(fpact); lprintf("Cannot open %s", cfg.newhistfile); return(0); } } line = malloc(BUFSIZ); ngname = malloc(BUFSIZ); ngdir = malloc(_MAX_PATH); while(fgets(line, BUFSIZ, fpact)) { if(sscanf(line, "%s %ld %ld %c", ngname, &maxart, &minart, &mc) < 4) { lprintf("Line %d in active file invalid: %s", lineno, line); continue; } lineno++; /* * Process specified newsgroups only */ if(!ngmatch(ngname, cfg.groups)) { if(DOLOG(LOG_EXPIRE)) lprintf("Group %s not in list, ignored", ngname); continue; } /* * Ignore empty groups */ if(minart > maxart) { if(DOLOG(LOG_EXPIRE)) lprintf("Group %s is empty, ignored", ngname); continue; } /* * Allocate an array to hold all article numbers in this group */ if((maxart - minart) > 16000) maxart = minart + 16000; num_arts = (int)(maxart - minart); if(DOLOG(LOG_EXPIRE)) lprintf("Processing group %s with %u articles", ngname, num_arts); art_array = malloc(sizeof(long) * 16000); /* * Build path to the newsgroup and scan directory */ strcpy(ngdir, cfg.newsdir); strcat(ngdir, "\\"); cp = strchr(ngdir, '\0'); strcpy(cp, ngname); while(*cp) { if(*cp == '.') *cp = '\\'; cp++; } if(DOLOG(LOG_EXPIRE)) lprintf("Scanning %s", ngdir); num_arts = scan_dir(ngdir, 0, 0, art_array, 16000); if(DOLOG(LOG_EXPIRE)) lprintf("%u articles found in %s", num_arts, ngdir); /* * Process each article found */ artpath = malloc(_MAX_PATH); msgid = malloc(128); for(i = 0; i < num_arts; i++) { struct stat ast; FILE *fpart; sprintf(artpath, "%s\\%lu", ngdir, art_array[i]); if(stat(artpath, &ast)) { lprintf("Failed to get status of %s\n", artpath); continue; } if((fpart = xopen(artpath, "rt")) == NULL) { lperror(artpath); continue; } hex_time = get_id_expire(fpart, msgid); fclose(fpart); if(DOLOG(LOG_EXPIRE)) { if(hex_time) lprintf("Expire line found in %lu: %.*s", art_array[i], strlen(ctime(&hex_time)) - 1, ctime(&hex_time)); else lprintf("Article %lu received at %.*s", art_array[i], strlen(ctime(&ast.st_ctime)) - 1, ctime(&ast.st_ctime)); } if(hex_time == 0) hex_time = cfg.expiretime; if(ast.st_ctime < hex_time) { if(DOLOG(LOG_EXPIRE)) lprintf("Article %lu expired", art_array[i]); if(cfg.dorebuild && ast.st_ctime > cfg.forgettime) { if(DOLOG(LOG_EXPIRE)) lprintf("Remember article %lu", art_array[i]); if(AddArt2Hist(ndb, msgid, ast.st_ctime, 0, NULL, 0)) ids_kept++; } arts_deleted++; bytes_deleted += ast.st_size; if(DOLOG(LOG_TESTMODE)) lprintf("Would delete %s", artpath); else if(unlink(artpath)) { lperror(artpath); arts_deleted--; bytes_deleted -= ast.st_size; } } else { if(cfg.dorebuild) { if(AddArt2Hist(ndb, msgid, ast.st_ctime, ast.st_size, ngname, art_array[i])) ids_kept++; } arts_kept++; bytes_kept += ast.st_size; } } free(artpath); free(art_array); } fclose(fpact); if(cfg.dorebuild) { dbm_close(ndb); if(result) { if(DOLOG(LOG_TESTMODE)) { lprintf("Would rename %s to %s", cfg.historyfile, cfg.oldhistfile); lprintf("Would rename %s to %s", cfg.newhistfile, cfg.historyfile); } else { rename_history(cfg.historyfile, cfg.oldhistfile); if(rename_history(cfg.newhistfile, cfg.historyfile)) result = 0; } } } free(ngname); free(ngdir); free(line); return(arts_deleted != 0); } /************************************************************************/ /* */ /************************************************************************/ static int AddArt2Hist(DBM *db, char *id, time_t atim, long asiz, char *ng, long anum) { int result = 1; datum key, val; char *line = malloc(1024); key.dptr = id; key.dsize = strlen(key.dptr) + 1; val = dbm_fetch(db, key); if (val.dptr == NULL) { if(asiz) sprintf(line, "%ld %ld %s:%lu", local_to_gmt(atim), asiz, ng, anum); else sprintf(line, "%ld", local_to_gmt(atim)); key.dptr = id; key.dsize = strlen(key.dptr) + 1; val.dptr = line; val.dsize = strlen(val.dptr) + 1; } else { if(asiz) sprintf(line, "%s,%s:%lu", val.dptr, ng, anum); else *line = '\0'; } if(*line) { key.dptr = id; key.dsize = strlen(key.dptr) + 1; val.dptr = line; val.dsize = strlen(val.dptr) + 1; if(DOLOG(LOG_EXPIRE)) lprintf("Add history: %s %s", id, line); if(dbm_store(db, key, val, DBM_REPLACE)) { lprintf("Failed to add %s", id); result = 0; } } free(line); return(result); }