/* * 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 history file. * */ #include #include #include #include #include #include #include #include #include #include #include "config.h" #include "expire.h" #define MAX_SKIPPED 100 /************************************************************************/ /* */ /************************************************************************/ int PurgeByHistory(void) { int result = 1; int histcount; char *histlist[20]; char *ngp; char *cp; char *histrec; char *line; datum key, val; FILE *hfp; DBM *ndb; time_t art_time; time_t hex_time = 0; long art_size; int skipped = 0; int i; char *path; /* * Remove leftovers from previous exec */ if(del_history(cfg.newhistfile)) lprintf("Removed from previous exec: %s", cfg.newhistfile); del_history(cfg.oldhistfile); /* * Open current history in sequential mode */ if((hfp = fopen(cfg.historyfile, "r")) == NULL) { char *histpag = malloc(strlen(cfg.historyfile) + 5); strcat(strcpy(histpag, cfg.historyfile), ".pag"); hfp = fopen(histpag, "r"); free(histpag); } if(hfp == NULL) { perror(cfg.historyfile); lperror(cfg.historyfile); return(0); } /* * Open new history in dbm mode */ if((ndb = dbm_open(cfg.newhistfile, O_RDWR | O_CREAT, 0666)) == NULL) { perror(cfg.newhistfile); fclose(hfp); lprintf("Cannot open %s", cfg.newhistfile); return(0); } line = malloc(BUFSIZ); path = malloc(_MAX_PATH); while(fgets(line, BUFSIZ, hfp)) { if((cp = strchr(line, '\n')) == NULL) { if(DOLOG(LOG_EXPIRE)) lprintf("Skipped bad history line: %s", line); if(++skipped >= MAX_SKIPPED) break; continue; } *cp = '\0'; if((histrec = strchr(line, ' ')) == NULL) { if(DOLOG(LOG_EXPIRE)) lprintf("Skipped bad history line: %s", line); if(++skipped >= MAX_SKIPPED) break; continue; } *histrec++ = '\0'; if((art_time = atol(histrec)) == 0) { if(DOLOG(LOG_EXPIRE)) lprintf("Skipped bad history line: %s", line); if(++skipped >= MAX_SKIPPED) break; continue; } if ((cp = strchr(histrec, ' ')) != NULL) { art_size = atol(cp); if ((cp = strchr(cp + 1, ' ')) == NULL) { if(DOLOG(LOG_EXPIRE)) lprintf("Skipped bad history line: %s", line); if(++skipped >= MAX_SKIPPED) break; continue; } if (*(++cp) == '\0') { if(DOLOG(LOG_EXPIRE)) lprintf("Skipped bad history line: %s", line); if(++skipped >= MAX_SKIPPED) break; continue; } ngp = strdup(cp); if((histcount = get_histlist(histlist, ngp)) == 0) { if(DOLOG(LOG_EXPIRE)) lprintf("Skipped bad history line: %s", line); if(++skipped >= MAX_SKIPPED) break; free(ngp); continue; } /* * Ignore unmatched groups */ for(i = 0; i < histcount; i++) { char *cp1 = strchr(histlist[i], ':'); if(cp1) { *cp1 = '\0'; if(!ngmatch(histlist[i], cfg.groups)) break; *cp1 = ':'; } } if(i < histcount) { key.dptr = line; key.dsize = strlen(key.dptr) + 1; val.dptr = histrec; val.dsize = strlen(val.dptr) + 1; if(DOLOG(LOG_EXPIRE)) lprintf("Keep %s in %s", line, histlist[i]); if (dbm_store(ndb, key, val, DBM_REPLACE)) lprintf("Failed to keep unmatched %s", line); else { arts_kept += histcount; bytes_kept += art_size; ids_kept++; } free(ngp); continue; } } else { /* * Article already expired but kept to remember msg id */ if(DOLOG(LOG_EXPIRE)) lprintf("Remembered article already expired: %s", line); art_size = 0; ngp = NULL; histcount = 0; } /*--------------------------------------------------------------*/ /* At this point we have the following results. */ /* */ /* histcount: number of linked articles */ /* hislist : array of linked articles (news.group:) */ /* art_time : Time when article was received */ /* line : Pointer to history key (message id) */ /* histrec : Pointer to history data */ /*--------------------------------------------------------------*/ /* * Build path to first newsgroup with this article * to read the expire date from it's header */ if(cfg.ignorexp == 0 && histcount) { char *cp1; strcpy(path, cfg.newsdir); strcat(path, "\\"); cp1 = strchr(path, '\0'); strcat(path, histlist[0]); while(cp1) { if((cp = strchr(cp1, '.')) != NULL) *(cp1 = cp) = '\\'; else if((cp1 = strchr(cp1, ':')) != NULL) { FILE *fpart; *cp1 = '\\'; if((fpart = xopen(path, "rt")) != NULL) { hex_time = get_id_expire(fpart, NULL); fclose(fpart); } else { /* * If we can't open the article then it * may be lost. We should forget it in * the hope that it might be offered * to us again some time. */ art_time = cfg.forgettime - 1; lperror(path); } } } } else hex_time = cfg.expiretime; if(hex_time == 0) hex_time = cfg.expiretime; if(art_time < hex_time) { /* * Remember article */ if(art_time > cfg.forgettime) { cp = histrec; while(*cp && *cp != ' ' && *cp != '\t') cp++; while(*cp) *cp++ = ' '; key.dptr = line; key.dsize = strlen(key.dptr) + 1; val.dptr = histrec; val.dsize = strlen(val.dptr) + 1; if(DOLOG(LOG_EXPIRE)) lprintf("Remember article %s", line); if (dbm_store(ndb, key, val, DBM_REPLACE)) lprintf("Failed to remember %s", line); else ids_kept++; } /* * Expire article */ for(i = 0; i < histcount; i++) { cp = histlist[i]; if(DOLOG(LOG_EXPIRE)) lprintf("Expire %s", cp); while((cp = strchr(cp, '.')) != NULL) *cp = '\\'; cp = histlist[i]; if((cp = strchr(cp, ':')) != NULL) { *cp = '\\'; strcpy(path, cfg.newsdir); strcat(path, "\\"); strcat(path, histlist[i]); arts_deleted++; bytes_deleted += art_size; if(DOLOG(LOG_TESTMODE)) lprintf("Would delete %s", path); else if(unlink(path)) { lperror(path); arts_deleted--; bytes_deleted -= art_size; } } else skipped++; } ids_deleted++; } /* * Keep article */ else { key.dptr = line; key.dsize = strlen(key.dptr) + 1; val.dptr = histrec; val.dsize = strlen(val.dptr) + 1; if(DOLOG(LOG_EXPIRE)) lprintf("Keep article %s", line); if (dbm_store(ndb, key, val, DBM_REPLACE)) lprintf("Failed to keep %s", line); else { arts_kept += histcount; bytes_kept += art_size; ids_kept++; } } if(ngp) free(ngp); } dbm_close(ndb); fclose(hfp); if(skipped >= MAX_SKIPPED) { lprintf("Too many bad lines in history file"); result = 0; } if(result) { if(DOLOG(LOG_TESTMODE)) lprintf("Would rename %s to %s", cfg.historyfile, cfg.oldhistfile); else if(rename_history(cfg.historyfile, cfg.oldhistfile)) result = 0; } if(result) { if(DOLOG(LOG_TESTMODE)) lprintf("Would rename %s to %s", cfg.newhistfile, cfg.historyfile); else if(rename_history(cfg.newhistfile, cfg.historyfile)) result = 0; } free(line); free(path); return(arts_deleted != 0); }