Path: utzoo!attcan!utgpu!jarvis.csri.toronto.edu!rutgers!network!ucsd!usc!cs.utexas.edu!fletcher From: fletcher@cs.utexas.edu (Fletcher Mattox) Newsgroups: news.software.b Subject: C expire + B news Message-ID: <6703@cs.utexas.edu> Date: 14 Aug 89 14:34:32 GMT Organization: U. Texas CS Dept., Austin, Texas Lines: 449 Here's what I did to shoehorn C expire into 2.11 news. My motivation was not just speed, but the desire to keep expire from locking up news for hours while our 20 NNTP neighbors filled up /usr/spool/news/.rnews with duplicate articles. File locking is provided only for UNIXes with flock(2), though it shouldn't be difficult to accommodate other locking primitives. Fletcher # This is a shell archive. Remove anything before this line, # then unpack it by saving it in a file and typing "sh file". # # Wrapped by cs.utexas.edu!fletcher on Mon Aug 14 09:11:47 CDT 1989 # Contents: README Patch.bnews Patch.cnews flock.c echo x - README sed 's/^@//' > "README" <<'@//E*O*F README//' It was easy to get C news expire to work with B news. Here's what I did. Apply Patch.bnews and Patch.cnews. Arrange for CEXPIRE to be defined in B news and for BNEWS to be defined in expire.c. I chose to keep the B news date format in the history file (I have local scripts which parse this field), so that a typical history line looks like: <644@uakari.primate.wisc.edu> 08/04/89 15:59~- comp.terminals/1661 You can make expire faster (and perhaps make history more aesthetic, depending on your point of view) by converting the date to seconds. Also, I gratuitously changed expire to ignore malformed history lines rather than to quit when it found one. Regarding message-id case: B news converts ids to lower case before writing the dbm file. C news does not. I chose to go with B news' convention. If you ever have to rebuild the history file from scratch, with C news' mkhistory, you'll need to add a strlower() to mkdbm.c. Rhetorical questions: Why does B news downcase message ids? Why doesn't C news? (Actually I think I know the answer to the second question). Regarding locking: Rather than drag all the B news #ifdefs into C news, I just brought over the 4BSD flocking code--that's all I needed. If you can't use that, you'll have to write your own newslock() and newsunlock(). C expire only needs to lock the news system during its last read(2) of the history file--less than one second. Where you *really* need locking is during upact, which can take many minutes. I used flock.c for that, i.e. my doexpire looks something like: cd $NEWSLIB ./expire -v explist ./flock active upact rnews -U Fletcher @//E*O*F README// chmod u=rw,g=rw,o=r README echo x - Patch.bnews sed 's/^@//' > "Patch.bnews" <<'@//E*O*F Patch.bnews//' *** inews.c.OLD Thu Aug 3 16:22:31 1989 --- inews.c Fri Jul 28 17:46:31 1989 *************** *** 949,954 int is_invalid = FALSE; int exitcode = 0; long now; #ifdef DOXREFS register char *nextref = header.xref; #endif /* DOXREFS */ --- 949,955 ----- int is_invalid = FALSE; int exitcode = 0; long now; + char ebuf[DATELEN+2]; #ifdef DOXREFS register char *nextref = header.xref; #endif /* DOXREFS */ *************** *** 964,969 (void) time(&now); tm = gmtime(&now); if (header.expdate[0]) addhist(" "); #ifdef USG --- 965,974 ----- (void) time(&now); tm = gmtime(&now); + #ifdef CEXPIRE + sprintf(ebuf, "~%s", header.expdate[0] ? header.expdate : "-"); + #else + ebuf[0] = '\0'; if (header.expdate[0]) addhist(" "); #endif /* CEXPIRE */ *************** *** 966,971 tm = gmtime(&now); if (header.expdate[0]) addhist(" "); #ifdef USG sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d\t", #else /* !USG */ --- 971,977 ----- ebuf[0] = '\0'; if (header.expdate[0]) addhist(" "); + #endif /* CEXPIRE */ #ifdef USG sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d%s\t", #else /* !USG */ *************** *** 967,973 if (header.expdate[0]) addhist(" "); #ifdef USG ! sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d\t", #else /* !USG */ sprintf(bfr,"%02d/%02d/%d %02d:%02d\t", #endif /* !USG */ --- 973,979 ----- addhist(" "); #endif /* CEXPIRE */ #ifdef USG ! sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d%s\t", #else /* !USG */ sprintf(bfr,"%02d/%02d/%d %02d:%02d%s\t", #endif /* !USG */ *************** *** 969,975 #ifdef USG sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d\t", #else /* !USG */ ! sprintf(bfr,"%02d/%02d/%d %02d:%02d\t", #endif /* !USG */ tm->tm_mon+1, tm->tm_mday, tm->tm_year,tm->tm_hour, tm->tm_min); addhist(bfr); --- 975,981 ----- #ifdef USG sprintf(bfr,"%2.2d/%2.2d/%d %2.2d:%2.2d%s\t", #else /* !USG */ ! sprintf(bfr,"%02d/%02d/%d %02d:%02d%s\t", #endif /* !USG */ tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour, tm->tm_min, ebuf); *************** *** 971,977 #else /* !USG */ sprintf(bfr,"%02d/%02d/%d %02d:%02d\t", #endif /* !USG */ ! tm->tm_mon+1, tm->tm_mday, tm->tm_year,tm->tm_hour, tm->tm_min); addhist(bfr); log("%s %s ng %s subj '%s' from %s", spool_news != DONT_SPOOL ? "queued" : (mode==PROC ? "received" : "posted"), --- 977,984 ----- #else /* !USG */ sprintf(bfr,"%02d/%02d/%d %02d:%02d%s\t", #endif /* !USG */ ! tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour, ! tm->tm_min, ebuf); addhist(bfr); log("%s %s ng %s subj '%s' from %s", spool_news != DONT_SPOOL ? "queued" : (mode==PROC ? "received" : "posted"), *** control.c.OLD Thu Aug 3 16:25:39 1989 --- control.c Fri Jul 28 17:44:25 1989 *************** *** 626,631 char whatsisname[BUFLEN], nfilename[BUFLEN]; time_t t; int su = 0; #ifndef u370 struct hbuf htmp; #endif /* !u370 */ --- 626,632 ----- char whatsisname[BUFLEN], nfilename[BUFLEN]; time_t t; int su = 0; + char ebuf[3]; #ifndef u370 struct hbuf htmp; #endif /* !u370 */ *************** *** 640,645 log("Can't cancel %s: non-existent", argv[1]); (void) time(&t); tm = localtime(&t); #ifdef USG sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled", #else /* !USG */ --- 641,651 ----- log("Can't cancel %s: non-existent", argv[1]); (void) time(&t); tm = localtime(&t); + #ifdef CEXPIRE + strcpy(ebuf, "~-"); + #else + ebuf[0] = '\0'; + #endif /* CEXPIRE */ #ifdef USG sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d%s\tcancelled", #else /* !USG */ *************** *** 641,647 (void) time(&t); tm = localtime(&t); #ifdef USG ! sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled", #else /* !USG */ sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled", #endif /* !USG */ --- 647,653 ----- ebuf[0] = '\0'; #endif /* CEXPIRE */ #ifdef USG ! sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d%s\tcancelled", #else /* !USG */ sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d%s\tcancelled", #endif /* !USG */ *************** *** 643,649 #ifdef USG sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d\tcancelled", #else /* !USG */ ! sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled", #endif /* !USG */ argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour, tm->tm_min); --- 649,655 ----- #ifdef USG sprintf(bfr,"%s\t%2.2d/%2.2d/%d %2.2d:%2.2d%s\tcancelled", #else /* !USG */ ! sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d%s\tcancelled", #endif /* !USG */ argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour, tm->tm_min, ebuf); *************** *** 646,652 sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d\tcancelled", #endif /* !USG */ argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour, ! tm->tm_min); savehist(bfr); return -1; } --- 652,658 ----- sprintf(bfr,"%s\t%02d/%02d/%d %02d:%02d%s\tcancelled", #endif /* !USG */ argv[1], tm->tm_mon+1, tm->tm_mday, tm->tm_year, tm->tm_hour, ! tm->tm_min, ebuf); savehist(bfr); return -1; } @//E*O*F Patch.bnews// chmod u=rw,g=rw,o=r Patch.bnews echo x - Patch.cnews sed 's/^@//' > "Patch.cnews" <<'@//E*O*F Patch.cnews//' *** expire.c.OLD Thu Aug 3 18:51:46 1989 --- expire.c Thu Aug 3 18:41:52 1989 *************** *** 425,430 datum lhs; datum rhs; register int ret; cd(ctlfile((char *)NULL)); old = open("history", 0); --- 425,431 ----- datum lhs; datum rhs; register int ret; + char name[512]; /* should be plenty of room for a msg-id */ cd(ctlfile((char *)NULL)); old = open("history", 0); *************** *** 449,455 nameend = strchr(line, '\t'); if (nameend == NULL) { errno = 0; ! fail("bad return from doline(): `%.75s'", line); } /* make the DBM entry */ --- 450,457 ----- nameend = strchr(line, '\t'); if (nameend == NULL) { errno = 0; ! warning("bad return from doline(): `%.75s'", line); ! continue; } /* make the DBM entry */ *************** *** 454,460 /* make the DBM entry */ *nameend = '\0'; - lhs.dptr = line; lhs.dsize = strlen(line)+1; here = ftell(new); rhs.dptr = (char *)&here; --- 456,461 ----- /* make the DBM entry */ *nameend = '\0'; lhs.dsize = strlen(line)+1; #ifdef BNEWS if (lhs.dsize > sizeof name) { *************** *** 456,461 *nameend = '\0'; lhs.dptr = line; lhs.dsize = strlen(line)+1; here = ftell(new); rhs.dptr = (char *)&here; rhs.dsize = sizeof(here); --- 457,473 ----- /* make the DBM entry */ *nameend = '\0'; lhs.dsize = strlen(line)+1; + #ifdef BNEWS + if (lhs.dsize > sizeof name) { + warning("message id too long: `%.75s'", line); + continue; + } + strcpy(name,line); + strlower(name); + lhs.dptr = name; + #else + lhs.dptr = line; + # endif here = ftell(new); rhs.dptr = (char *)&here; rhs.dsize = sizeof(here); *************** *** 1274,1276 return(result); } --- 1286,1325 ----- return(result); } + + #ifdef BNEWS + + /* + * Lock the system, B news style. + */ + + #include+ #include + static int fd; + + static + void + newslock() + { + char *active = ctlfile("active"); + + openlog(progname, 0, LOG_NEWS); + if ((fd = open(active, 2)) < 0) { + perror(active); + exit(1); + } + if (flock(fd, LOCK_EX) < 0) { + perror("expire can't flock the active file"); + exit(1); + } + syslog(LOG_INFO, "%s: locked", active); + } + + static + void + newsunlock() + { + (void) close(fd); + syslog(LOG_INFO, "%s: active file unlocked"); + } + #endif /* BNEWS*/ @//E*O*F Patch.cnews// chmod u=rw,g=rw,o=r Patch.cnews echo x - flock.c sed 's/^@//' > "flock.c" <<'@//E*O*F flock.c//' #include #include main(argc, argv) char **argv; { char *file; int i; int fd; if (argc < 3) { fprintf(stderr, "Usage: %s file_to_lock command [args]\n", argv[0]); exit(1); } file = argv[1]; if ((fd = open(file, 2)) < 0) { perror(file); exit(1); } if (flock(fd, LOCK_EX) < 0) { perror("flock"); exit(1); } argv += 2; #ifdef debug for (i = 0; argv[i] && argv[i][0]; i++) printf("argv[%d]= %s\n", i, argv[i]); #endif debug execvp(argv[0], argv); perror(argv[0]); exit(1); } @//E*O*F flock.c// chmod u=rw,g=rw,o=r flock.c exit 0