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