|
|
1.1 root 1: /* scansbr.c - routines to help scan along... */
2:
3: #include "../h/mh.h"
4: #include "../h/addrsbr.h"
5: #include "../h/formatsbr.h"
6: #include "../h/scansbr.h"
7: #include "../zotnet/tws.h"
8: #include <stdio.h>
9: #include <ctype.h>
10: #include <sys/types.h>
11: #include <sys/stat.h>
12:
13:
14: #define MAXSCANL 510 /* longest possible scan line */
15: #define SBUFSIZ 256
16: /* buffer size for content part of header
17: * fields. We want this to be large
18: * enough so that we don't do a lot of
19: * extra FLDPLUS calls on m_getfld but
20: * small enough so that we don't snarf
21: * the entire message body when we're
22: * only going to display 30 characters
23: * of it.
24: */
25:
26: /* */
27:
28: static struct format *fmt;
29:
30: static struct comp *datecomp; /* pntr to "date" comp */
31: static struct comp *bodycomp; /* pntr to "body" pseudo-comp (if referenced) */
32: static int ncomps = 0; /* # of interesting components */
33: static char **compbuffers = 0; /* buffers for component text */
34: static struct comp **used_buf = 0; /* stack for comp that use buffers */
35:
36: char *scanl = 0; /* text of most recent scanline */
37:
38: static int dat[4]; /* aux. data for format routine */
39:
40: #ifdef RPATHS
41: char *unixline(); /* info from UNIX From: line */
42: #endif RPATHS
43:
44: #define FPUTS(buf) {\
45: if (fputs(buf,scnout) == EOF)\
46: adios (scnmsg, "write error on");\
47: }
48:
49: /* */
50:
51: /* ARGSUSED */
52:
53: scan(inb, innum, outnum, nfs, width, curflg, header, size, noisy, aud)
54: register FILE *inb;
55: char *nfs;
56: int innum, outnum, width, curflg, header;
57: long size;
58: int noisy, aud;
59: {
60: int compnum, encrypted, state;
61: register int i;
62: register struct comp *cptr;
63: register char *tmpbuf;
64: register char **nxtbuf;
65: register struct comp **savecomp;
66: char *scnmsg;
67: FILE *scnout;
68: char name[NAMESZ];
69: static int slwidth;
70: #ifdef RPATHS
71: char *cp;
72: #endif RPATHS
73:
74: /* first-time only initialization */
75: if (scanl == NULLCP) {
76: if (width == 0) {
77: if ((width = sc_width()) < WIDTH / 2)
78: width = WIDTH / 2;
79: else if (width > MAXSCANL)
80: width = MAXSCANL;
81: }
82: dat[3] = slwidth = width;
83: scanl = (char *) malloc((unsigned)MAXSCANL+2);
84: if (outnum)
85: (void) umask(~m_gmprot());
86:
87: ncomps = fmt_compile(nfs, &fmt) + 1;
88: FINDCOMP(bodycomp, "body");
89: FINDCOMP(datecomp, "date");
90: FINDCOMP(cptr, "encrypted");
91: if (!cptr)
92: if (cptr = (struct comp *) calloc(1, sizeof *cptr)) {
93: cptr->c_name = "encrypted";
94: cptr->c_next =
95: wantcomp[i = CHASH(cptr->c_name)];
96: wantcomp[i] = cptr;
97: ncomps++;
98: }
99: nxtbuf = compbuffers = (char **)
100: calloc((unsigned) ncomps, sizeof(char *));
101: if (nxtbuf == NULL)
102: adios(NULLCP, "unable to allocate component buffers");
103: used_buf = (struct comp **)
104: calloc((unsigned) (ncomps + 1), sizeof(struct comp *));
105: if (used_buf == NULL)
106: adios(NULLCP, "unable to allocate component buffer stack");
107: used_buf += ncomps + 1;
108: *--used_buf = 0;
109: for (i = ncomps; i--;)
110: if ((*nxtbuf++ = malloc(SBUFSIZ)) == NULL)
111: adios(NULLCP,
112: "unable to allocate component buffer");
113: }
114: /* each-message initialization */
115: nxtbuf = compbuffers;
116: savecomp = used_buf;
117: tmpbuf = *nxtbuf++;
118: dat[0] = innum ? innum : outnum;
119: dat[1] = curflg;
120:
121: /*
122: * get the first field. If the msg is non-empty and we're doing
123: * an "inc", open the output file.
124: */
125: if ((state = m_getfld(FLD, name, tmpbuf, SBUFSIZ, inb)) == FILEEOF)
126: return SCNEOF;
127:
128: if (outnum) {
129: if (outnum > 0) {
130: scnmsg = m_name(outnum);
131: if (*scnmsg == '?') /* msg num out of range */
132: return SCNNUM;
133: } else
134: scnmsg = "/dev/null";
135: if ((scnout = fopen(scnmsg, "w")) == NULL)
136: adios(scnmsg, "unable to write");
137: #ifdef RPATHS
138: if ((cp = unixline()) && *cp != '\n') {
139: FPUTS("Return-Path: ");
140: FPUTS(cp);
141: }
142: #endif RPATHS
143: }
144: /* scan - main loop */
145: for (compnum = 1;;
146: state = m_getfld(state, name, tmpbuf, SBUFSIZ, inb)) {
147: switch (state) {
148: case FLD:
149: case FLDPLUS:
150: compnum++;
151: if (outnum) {
152: FPUTS(name);
153: (void) putc(':', scnout);
154: FPUTS(tmpbuf);
155: }
156: /*
157: * If we're interested in this component, save a
158: * pointer to the component text, then start using
159: * our next free buffer as the component temp buffer
160: * (buffer switching saves an extra copy of the
161: * component text).
162: */
163: if (cptr = wantcomp[CHASH(name)])
164: do {
165: if (uleq(name, cptr->c_name)) {
166: if (!cptr->c_text) {
167: cptr->c_text = tmpbuf;
168: *--savecomp = cptr;
169: tmpbuf = *nxtbuf++;
170: }
171: break;
172: }
173: } while (cptr = cptr->c_next);
174:
175: while (state == FLDPLUS) {
176: state =
177: m_getfld(state, name, tmpbuf, SBUFSIZ, inb);
178: if (outnum)
179: FPUTS(tmpbuf);
180: }
181: break;
182:
183: case BODY:
184: compnum = -1;
185: if (!outnum) {
186: state = FILEEOF; /* stop now if scan cmd */
187: goto finished;
188: }
189: (void) putc('\n', scnout);
190: FPUTS(tmpbuf);
191: /*
192: * Performance hack: some people like to run "inc" on
193: * things like net.sources or large digests. We do a
194: * copy directly into the output buffer rather than
195: * going through an intermediate buffer.
196: *
197: * We need the amount of data m_getfld found & don't
198: * want to do a strlen on the long buffer so there's
199: * a hack in m_getfld to save the amount of data it
200: * returned in the global "msg_count".
201: */
202: body:
203: while (state == BODY) {
204: if (scnout->_cnt <= 0) {
205: if (fflush(scnout) == EOF)
206: adios(scnmsg, "write error on");
207: }
208: state = m_getfld(state, name,
209: scnout->_ptr, -(scnout->_cnt), inb);
210: scnout->_cnt -= msg_count;
211: scnout->_ptr += msg_count;
212: }
213: goto finished;
214:
215: case LENERR:
216: case FMTERR:
217: fprintf(stderr,
218: innum ? "??Format error (message %d) in "
219: : "??Format error in ",
220: outnum ? outnum : innum);
221: fprintf(stderr, "component %d\n", compnum);
222:
223: if (outnum) {
224: FPUTS("\n\nBAD MSG:\n");
225: FPUTS(name);
226: (void) putc('\n', scnout);
227: state = BODY;
228: goto body;
229: }
230: /* fall through */
231:
232: case FILEEOF:
233: goto finished;
234:
235: default:
236: adios(NULLCP, "getfld() returned %d", state);
237: }
238: }
239: /* format and output the scan line. */
240: finished:
241: if (noisy || aud) {
242: char *saved_c_text;
243:
244: if (bodycomp) {
245: /* Save and restore buffer so we don't trash our
246: dynamic pool! */
247: saved_c_text = bodycomp->c_text;
248: bodycomp->c_text = tmpbuf;
249: }
250: if (size)
251: dat[2] = size;
252: else if (outnum > 0)
253: dat[2] = ftell(scnout);
254:
255: if ((datecomp && !datecomp->c_text) || (!size && !outnum)) {
256: struct stat st;
257: (void) fstat(fileno(inb), &st);
258: if (!size && !outnum)
259: dat[2] = st.st_size;
260: if (datecomp) {
261: if (!datecomp->c_text) {
262: if (datecomp->c_tws == NULL)
263: datecomp->c_tws = (struct tws *)
264: calloc((unsigned) 1,
265: sizeof(*datecomp->c_tws));
266: if (datecomp->c_tws == NULL)
267: adios(NULLCP,
268: "unable to allocate tws buffer");
269: *datecomp->c_tws =
270: *dlocaltime((long *) &st.st_mtime);
271: datecomp->c_flags = -1;
272: } else {
273: datecomp->c_flags = 0;
274: }
275: }
276: }
277: (void) fmtscan(fmt, scanl, slwidth, dat);
278: if (aud)
279: (void) fputs(scanl, aud);
280: if (noisy)
281: (void) fputs(scanl, stdout);
282:
283: if (bodycomp)
284: bodycomp->c_text = saved_c_text;
285: }
286: FINDCOMP(cptr, "encrypted");
287: encrypted = cptr && cptr->c_text;
288: /* return dynamically allocated buffers to pool */
289: while (cptr = *savecomp++) {
290: *--nxtbuf = cptr->c_text;
291: cptr->c_text = NULLCP;
292: }
293: *--nxtbuf = tmpbuf;
294:
295: if (outnum && fclose(scnout) == EOF)
296: adios(scnmsg, "write error on");
297:
298: return (state != FILEEOF ? SCNERR : encrypted ? SCNENC : SCNMSG);
299: }
300:
301: /* */
302:
303: /*
304: * Cheat: we are loaded with adrparse, which wants a routine called
305: * OfficialName(). We call adrparse:getm() with the correct arguments
306: * to prevent OfficialName() from being called. Hence, the following
307: * is to keep the loader happy.
308: */
309:
310: /* XXX don't bother if linking with the shared library */
311: #ifndef SHARED
312: char *
313: OfficialName(name)
314: register char *name;
315: {
316: return name;
317: }
318:
319: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.