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 "util.h"
20: #include "server.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: int eoo; /* End of server output */
186: char ser_line[256];
187: #endif
188:
189: #ifdef CACHESUBJ
190: if (!subj_list) {
191: register ART_NUM i;
192:
193:
194: #ifndef lint
195: subj_list =
196: (char**)safemalloc((MEM_SIZE)((OFFSET(lastart)+2)*sizeof(char *)));
197: #endif lint
198: for (i=0; i<=OFFSET(lastart); i++)
199: subj_list[i] = Nullch;
200: }
201: if (!artnum || artnum > lastart)
202: s = nullstr;
203: else
204: s = subj_list[OFFSET(artnum)];
205: #endif
206: if (s == Nullch) {
207: if (current_subject) {
208: s = fetchlines(artnum,SUBJ_LINE);
209: #ifdef CACHESUBJ
210: subj_list[OFFSET(artnum)] = s;
211: #endif
212: }
213: else {
214: s = safemalloc((MEM_SIZE)256);
215: *s = '\0';
216: #ifdef SERVER
217: sprintf(ser_line, "HEAD %d", artnum);
218: put_server(ser_line);
219: eoo = 0;
220: if (get_server(ser_line, 256) >= 0 && ser_line[0] == CHAR_OK) {
221: do {
222: if (get_server(s, 256) < 0 || (*s == '.')) {
223: strcpy(s, "Title: \n");
224: eoo = 1;
225: }
226: #else /* not SERVER */
227: if (artopen(artnum) != Nullfp) {
228: do {
229: if (fgets(s,256,artfp) == Nullch)
230: strcpy(s, "Title: \n");
231: #endif /* SERVER */
232: } while (strnNE(s,"Title:",6) && strnNE(s,"Subject:",8));
233: #ifdef SERVER
234: if (!eoo)
235: while (get_server(ser_line, sizeof (ser_line)) >= 0 &&
236: ser_line[0] != '.');
237: #endif
238: #ifndef SERVER
239: s[strlen(s)-1] = '\0';
240: #endif
241: t = index(s,':')+1;
242: while (*t == ' ') t++;
243: strcpy(s, t);
244: }
245: s = saferealloc(s, (MEM_SIZE)strlen(s)+1);
246: #ifdef CACHESUBJ
247: subj_list[OFFSET(artnum)] = s;
248: #endif
249: }
250: }
251: #ifdef CACHESUBJ
252: if (copy) {
253: t = savestr(s);
254: return t;
255: }
256: else
257: return s;
258: #else
259: if (copy)
260: return s;
261: else {
262: safecpy(cmd_buf,s,CBUFLEN); /* hope this is okay--we're */
263: free(s);
264: return cmd_buf; /* really scraping for space here */
265: }
266: #endif
267: }
268:
269: /* get header lines from an article */
270:
271: char *
272: fetchlines(artnum,which_line)
273: ART_NUM artnum; /* article to get line from */
274: int which_line; /* type of line desired */
275: {
276: char *newbuf, *t, tmp_buf[LBUFLEN];
277: register ART_POS curpos;
278: int size;
279: register ART_POS firstpos;
280: register ART_POS lastpos;
281:
282: #ifdef ASYNC_PARSE
283: if (parse_maybe(artnum))
284: artnum = 0;
285: #endif
286: firstpos = htype[which_line].ht_minpos;
287: lastpos = htype[which_line].ht_maxpos;
288: if (!artnum || firstpos < 0 || artopen(artnum) == Nullfp) {
289: newbuf = safemalloc((unsigned int)1);
290: *newbuf = '\0';
291: return newbuf;
292: }
293: #ifndef lint
294: size = lastpos - firstpos + 1;
295: #else
296: size = Null(int);
297: #endif lint
298: #ifdef DEBUGGING
299: if (debug && (size < 1 || size > 1000)) {
300: printf("Firstpos = %ld, lastpos = %ld\n",(long)firstpos,(long)lastpos);
301: gets(tmp_buf);
302: }
303: #endif
304: newbuf = safemalloc((unsigned int)size);
305: *newbuf = '\0';
306: fseek(artfp,firstpos,0);
307: for (curpos = firstpos; curpos < lastpos; curpos = ftell(artfp)) {
308: if (fgets(tmp_buf,LBUFLEN,artfp) == Nullch)
309: break;
310: if (*tmp_buf == ' ' || *tmp_buf == '\t')
311: t = tmp_buf;
312: else
313: t = index(tmp_buf,':')+1;
314: if (t == Nullch)
315: break;
316: else {
317: while (*t == ' ' || *t == '\t') t++;
318: safecat(newbuf,t,size);
319: }
320: }
321: return newbuf;
322: }