1: /* $Header: head.c,v 4.3.1.2 85/05/10 13:47:25 lwall Exp $
2: *
3: * $Log: head.c,v $
4: * Revision 4.3.1.2 85/05/10 13:47:25 lwall
5: * Added debugging stuff.
6: *
7: * Revision 4.3.1.1 85/05/10 11:32:30 lwall
8: * Branch for patches.
9: *
10: * Revision 4.3 85/05/01 11:38:21 lwall
11: * Baseline for release with 4.3bsd.
12: *
13: */
14:
15: #include "EXTERN.h"
16: #include "common.h"
17: #include "artio.h"
18: #include "bits.h"
19: #include "server.h"
20: #include "util.h"
21: #include "INTERN.h"
22: #include "head.h"
23:
24: bool first_one; /* is this the 1st occurance of this header line? */
25:
26: static char htypeix[26] =
27: {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
28:
29: void
30: head_init()
31: {
32: register int i;
33:
34: for (i=HEAD_FIRST+1; i<HEAD_LAST; i++)
35: htypeix[*htype[i].ht_name - 'a'] = i;
36: }
37:
38: #ifdef DEBUGGING
39: (where)
40: char *where;
41: {
42: register int i;
43:
44: printf("header: %d %s", parsed_art, where);
45:
46: for (i=0; i<HEAD_LAST; i++) {
47: printf("%15s %4d %4d %03o\n",htype[i].ht_name,
48: htype[i].ht_minpos,
49: htype[i].ht_maxpos,
50: htype[i].ht_flags) FLUSH;
51: }
52: }
53: #endif
54:
55: int
56: set_line_type(bufptr,colon)
57: char *bufptr;
58: register char *colon;
59: {
60: char lc[LONGKEY+3];
61: register char *t, *f;
62: register int i, len;
63:
64: for (t=lc,f=bufptr; f<colon; f++, t++) {
65: if (isspace(*f))
66: /* guard against space before : */
67: break;
68: *t = isupper(*f) ? tolower(*f) : *f;
69: }
70: *t = '\0';
71: f = lc; /* get lc into register */
72: len = t - f;
73:
74: /* now scan the headtype table, backwards so we don't have to supply an
75: * extra terminating value, using first letter as index, and length as
76: * optimization to avoid calling subroutine strEQ unnecessarily. Hauls.
77: */
78:
79: if (islower(*f)) {
80: for (i = htypeix[*f - 'a']; *htype[i].ht_name == *f; --i) {
81: if (len == htype[i].ht_length && strEQ(f, htype[i].ht_name)) {
82: return i;
83: }
84: }
85: }
86: return SOME_LINE;
87: }
88:
89:
90: start_header(artnum)
91: ART_NUM artnum;
92: {
93: register int i;
94:
95: #ifdef DEBUGGING
96: if (debug & 4)
97: dumpheader("start_header\n");
98: #endif
99: for (i=0; i<HEAD_LAST; i++) {
100: htype[i].ht_minpos = -1;
101: htype[i].ht_maxpos = 0;
102: }
103: in_header = SOME_LINE;
104: first_one = FALSE;
105: #ifdef ASYNC_PARSE
106: parsed_art = artnum;
107: #endif
108: }
109:
110: bool
111: parseline(art_buf,newhide,oldhide)
112: char *art_buf;
113: int newhide, oldhide;
114: {
115: if (*art_buf == ' ' || *art_buf == '\t')
116: /* header continuation line? */
117: return oldhide;
118: else { /* maybe another header line */
119: char *s;
120:
121: if (first_one) { /* did we just pass 1st occurance? */
122: first_one = FALSE;
123: htype[in_header].ht_maxpos = artpos;
124: /* remember where line left off */
125: }
126: s = index(art_buf,':');
127: if (s == Nullch || s-art_buf > LONGKEY+2) {
128: /* is it the end of the header? */
129: htype[PAST_HEADER].ht_minpos =
130: (*art_buf == '\n') ? ftell(artfp) : artpos;
131: /* remember where body starts */
132: in_header = PAST_HEADER;
133: }
134: else { /* it is a new header line */
135: in_header = set_line_type(art_buf,s);
136: first_one = (htype[in_header].ht_minpos < 0);
137: if (first_one)
138: htype[in_header].ht_minpos = artpos;
139: #ifdef DEBUGGING
140: if (debug & 4)
141: dumpheader(art_buf);
142: #endif
143: if (htype[in_header].ht_flags & HT_HIDE)
144: return newhide;
145: }
146: }
147: return FALSE; /* don't hide this line */
148: }
149:
150: #ifdef ASYNC_PARSE
151: int
152: parse_maybe(artnum)
153: ART_NUM artnum;
154: {
155: char tmpbuf[LBUFLEN];
156:
157: if (parsed_art == artnum)
158: return 0;
159: /* no maybe about it now */
160: if (artopen(artnum) == Nullfp) {
161: return -1;
162: }
163: start_header(artnum);
164: while (in_header) {
165: artpos = ftell(artfp);
166: if (fgets(tmpbuf,LBUFLEN,artfp) == Nullch)
167: break;
168: parseline(tmpbuf,FALSE,FALSE);
169: }
170: in_header = PAST_HEADER;
171: return 0;
172: }
173: #endif
174:
175: /* get the subject line for an article */
176:
177: char *
178: fetchsubj(artnum,current_subject,copy)
179: ART_NUM artnum; /* article to get subject from */
180: bool current_subject; /* is it in a parsed header? */
181: bool copy; /* do you want it savestr()ed? */
182: {
183: char *s = Nullch, *t;
184: #ifdef SERVER
185: static int xhdr = 1; /* Can we use xhdr command? */
186: int eoo; /* End of server output */
187: char ser_line[256];
188: #endif SERVER
189:
190: #ifdef CACHESUBJ
191: if (!subj_list) {
192: register ART_NUM i;
193:
194:
195: #ifndef lint
196: subj_list =
197: (char**)safemalloc((MEM_SIZE)((OFFSET(lastart)+2)*sizeof(char *)));
198: #endif lint
199: for (i=0; i<=OFFSET(lastart); i++)
200: subj_list[i] = Nullch;
201: }
202: if (!artnum || artnum > lastart)
203: s = nullstr;
204: else
205: s = subj_list[OFFSET(artnum)];
206: #endif
207: if (s == Nullch) {
208: if (current_subject) {
209: s = fetchlines(artnum,SUBJ_LINE);
210: #ifdef CACHESUBJ
211: subj_list[OFFSET(artnum)] = s;
212: #endif
213: }
214: else {
215: s = safemalloc((MEM_SIZE)256);
216: *s = '\0';
217: #ifdef SERVER
218: if (xhdr) {
219: sprintf(ser_line, "XHDR subject %ld", artnum);
220: put_server(ser_line);
221: if (get_server(ser_line, sizeof (ser_line)) >= 0) {
222: if (ser_line[0] == CHAR_FATAL) {
223: xhdr = 0;
224: } else {
225: while (get_server(ser_line, sizeof (ser_line)) >= 0) {
226: if (ser_line[0] == '.')
227: break;
228: else {
229: t = index(ser_line, ' ');
230: if (t++) {
231: strcpy(s, t);
232: if (t = index(s, '\r'))
233: *t = '\0';
234: }
235: }
236: }
237: }
238: } else {
239: fprintf(stderr,
240: "rrn: Unexpected close of server socket.\n");
241: finalize(1);
242: }
243: }
244:
245: if (!xhdr) {
246: sprintf(ser_line, "HEAD %ld", artnum);
247: put_server(ser_line);
248: eoo = 0;
249: if (get_server(ser_line, 256) >= 0 && ser_line[0] == CHAR_OK) {
250: do {
251: if (get_server(s, 256) < 0 || (*s == '.')) {
252: strcpy(s, "Title: \n");
253: eoo = 1;
254: }
255: } while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
256:
257: if (!eoo)
258: while (get_server(ser_line, sizeof (ser_line)) >= 0 &&
259: ser_line[0] != '.');
260: t = index(s,':')+1;
261: while (*t == ' ') t++;
262: strcpy(s, t);
263: }
264: }
265: #else not SERVER
266: if (artopen(artnum) != Nullfp) {
267: do {
268: if (fgets(s,256,artfp) == Nullch)
269: strcpy(s, "Title: \n");
270: } while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
271:
272: s[strlen(s)-1] = '\0';
273: t = index(s,':')+1;
274: while (*t == ' ') t++;
275: strcpy(s, t);
276: }
277: #endif
278: s = saferealloc(s, (MEM_SIZE)strlen(s)+1);
279: #ifdef CACHESUBJ
280: subj_list[OFFSET(artnum)] = s;
281: #endif
282: }
283: }
284: #ifdef CACHESUBJ
285: if (copy) {
286: t = savestr(s);
287: return t;
288: }
289: else
290: return s;
291: #else
292: if (copy)
293: return s;
294: else {
295: safecpy(cmd_buf,s,CBUFLEN); /* hope this is okay--we're */
296: free(s);
297: return cmd_buf; /* really scraping for space here */
298: }
299: #endif
300: }
301:
302: /* get header lines from an article */
303:
304: char *
305: fetchlines(artnum,which_line)
306: ART_NUM artnum; /* article to get line from */
307: int which_line; /* type of line desired */
308: {
309: char *newbuf, *t, tmp_buf[LBUFLEN];
310: register ART_POS curpos;
311: int size;
312: register ART_POS firstpos;
313: register ART_POS lastpos;
314:
315: #ifdef ASYNC_PARSE
316: if (parse_maybe(artnum))
317: artnum = 0;
318: #endif
319: firstpos = htype[which_line].ht_minpos;
320: lastpos = htype[which_line].ht_maxpos;
321: if (!artnum || firstpos < 0 || artopen(artnum) == Nullfp) {
322: newbuf = safemalloc((unsigned int)1);
323: *newbuf = '\0';
324: return newbuf;
325: }
326: #ifndef lint
327: size = lastpos - firstpos + 1;
328: #else
329: size = Null(int);
330: #endif lint
331: #ifdef DEBUGGING
332: if (debug && (size < 1 || size > 1000)) {
333: printf("Firstpos = %ld, lastpos = %ld\n",(long)firstpos,(long)lastpos);
334: gets(tmp_buf);
335: }
336: #endif
337: newbuf = safemalloc((unsigned int)size);
338: *newbuf = '\0';
339: fseek(artfp,firstpos,0);
340: for (curpos = firstpos; curpos < lastpos; curpos = ftell(artfp)) {
341: if (fgets(tmp_buf,LBUFLEN,artfp) == Nullch)
342: break;
343: if (*tmp_buf == ' ' || *tmp_buf == '\t')
344: t = tmp_buf;
345: else
346: t = index(tmp_buf,':')+1;
347: if (t == Nullch)
348: break;
349: else {
350: while (*t == ' ' || *t == '\t') t++;
351: safecat(newbuf,t,size);
352: }
353: }
354: return newbuf;
355: }