|
|
1.1 root 1: /* down!honey 4/84 */
2: /* article msg-id [ ... msg-id ] */
3: * where message-id is usually of the form [email protected],
4: * and the domain in the message-id is optional.
5: *
6: * BUGS:
7: * Cannot handle all domains, for instance, BERKELEY.EDU.
8: */
9:
10: #define HISTORY "/usr/lib/news/history"
11: #define NEWSDIR "/usr/spool/news"
12:
13: char *formats[] = { /* add as appropriate */
14: "<%s.uucp>",
15: "<%s>",
16: "<%s.arpa>",
17: "<%s.oz>",
18: 0
19: };
20:
21: #include <stdio.h>
22: #include <sysexits.h>
23: #include <ctype.h>
24:
25: typedef struct {
26: char *dptr;
27: int dsize;
28: } datum;
29:
30: #if defined(USG_INDEX)
31: /* S3 or S5 both call strchr() what 4.X BSD calls index */
32: #define index strchr
33: #endif
34:
35: long lseek();
36: char *index();
37: datum fetch(), dofetch();
38:
39: main(argc, argv)
40: char **argv;
41: {
42: int fd;
43: char buf[BUFSIZ], *ptr1, *ptr2;
44: datum content;
45:
46: if ((fd = open(HISTORY, 0)) < 0) {
47: perror(HISTORY);
48: exit(EX_UNAVAILABLE);
49: }
50: if (dbminit(HISTORY) < 0) {
51: fprintf(stderr, "dbm error\n");
52: exit(EX_UNAVAILABLE);
53: }
54: for (--argc, argv++; argc; --argc, argv++) {
55: long foff; /* file offset */
56: content = dofetch(*argv);
57: if (content.dptr == 0) {
58: printf("%s: No such key\n", *argv);
59: continue;
60: }
61:
62: /* Correct a machine dependent bug here, caused */
63: /* because the lseek offset pointed to by dptr might */
64: /* not be long-aligned. */
65: /* Guy Harris suggested bug fix to prevent core drop. */
66: /* This bug was written up in net.bugs.4bsd and */
67: /* cross-posted to net.news.b */
68: bcopy(content.dptr, (char *)&foff, sizeof foff);
69:
70: if (lseek(fd, foff, 0) < 0)
71: continue;
72: if (read(fd, buf, sizeof buf) <= 0)
73: continue;
74:
75: /*
76: * To understand this piece of code, you must understand
77: * that the format of lines in the history file are either:
78: * <msg-id>TAB<date>SPACE<time>TABthenNL
79: * <msg-id>TAB<date>SPACE<time>TAB<spoolpathname>NL
80: * <msg-id>TAB<date>SPACE<time>TAB<spoolpathname>SPACE...
81: * The first format occurs when expired,
82: * the second form occurs when exactly one pathname,
83: * and the third occurs when cross-postings.
84: */
85: *
86:
87: /* remove end of line */
88: if ((ptr2 = index(buf, '\n')) == 0)
89: continue;
90: *ptr2 = '\0';
91:
92: /* The 4th field contains the article file name */
93:
94: if ((ptr1 = index(buf, '\t')) == 0)
95: continue;
96: ptr1++;
97:
98: /* ptr1 now at begin of field 2 - the date field */
99:
100: if ((ptr1 = index(ptr1, '\t')) == 0)
101: continue;
102: ptr1++;
103:
104: /* ptr1 now at begin of field 4 - the article spool pathname */
105: /* or the newline that has been converted to a NULL */
106:
107: /* change net.unix/231 to net/unix/231 */
108: for (ptr2 = ptr1; ptr2 = index(ptr2, '.'); *ptr2 = '/')
109: ;
110:
111: /* terminate after the first pathname, if any */
112: if ((ptr2 = index(ptr1, ' ')) != NULL)
113: *ptr2 = '\0';
114:
115: if (*ptr1 == '\0')
116: printf("expired\n");
117: else
118: printf("%s/%s\n", NEWSDIR, ptr1);
119: }
120: exit(EX_OK);
121: }
122:
123: datum
124: dofetch(str)
125: char *str;
126: {
127: datum key, content;
128: char buf[BUFSIZ], **fmt;
129: register char *rcp;
130:
131: for (fmt = formats; *fmt; fmt++) {
132: sprintf(buf, *fmt, str);
133: rcp = buf - 1;
134: while (*++rcp)
135: if (isupper(*rcp))
136: *rcp = tolower(*rcp);
137: key.dptr = buf;
138: key.dsize = strlen(buf) + 1;
139: content = fetch(key);
140: if (content.dptr)
141: break;
142: }
143: return(content);
144: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.