1 /* scansbr.c - routines to help scan along... */
3 static char ident[] = "@(#)$Id: scansbr.c,v 1.16 1994/04/21 18:20:50 jromine Exp $";
7 #include "../h/addrsbr.h"
8 #include "../h/formatsbr.h"
9 #include "../h/scansbr.h"
10 #include "../zotnet/tws.h"
13 #include <sys/types.h>
17 #define _ptr _p /* Gag */
18 #define _cnt _w /* Wretch */
21 #define MAXSCANL 256 /* longest possible scan line */
22 #define SBUFSIZ 512 /* buffer size for content part of header
23 * fields. We want this to be large
24 * enough so that we don't do a lot of
25 * extra FLDPLUS calls on m_getfld but
26 * small enough so that we don't snarf
27 * the entire message body when we're
28 * only going to display 30 characters
34 static struct format *fmt;
36 static struct format *fmt_top;
39 static struct comp *datecomp; /* pntr to "date" comp */
40 static struct comp *bodycomp; /* pntr to "body" pseudo-comp
42 static int ncomps = 0; /* # of interesting components */
43 static char **compbuffers = 0; /* buffers for component text */
44 static struct comp **used_buf = 0; /* stack for comp that use buffers */
46 char *scanl = 0; /* text of most recent scanline */
48 static int dat[5]; /* aux. data for format routine */
51 char *unixline (); /* info from UNIX From: line */
55 if (mh_fputs(buf,scnout) == EOF)\
56 adios (scnmsg, "write error on");\
63 int scan (inb, innum, outnum, nfs, width, curflg, unseen,
64 hdrflg, folder, size, noisy)
82 register struct comp *cptr;
83 register char *tmpbuf;
84 register char **nxtbuf;
85 register struct comp **savecomp;
92 /* first-time only initialization */
93 if (scanl == NULLCP) {
97 if ((width = sc_width ()) < WIDTH/2)
99 else if (width > MAXSCANL)
102 dat[3] = slwidth = width;
103 if ((scanl = (char *)malloc( (unsigned) (slwidth + 2) )) == (char *)0)
104 adios (NULLCP, "unable to malloc scan line (%d bytes)", slwidth+2);
106 (void) umask( ~ m_gmprot() );
108 ncomps = fmt_compile (nfs, &fmt) + 1;
112 FINDCOMP(bodycomp, "body");
113 FINDCOMP(datecomp, "date");
114 FINDCOMP(cptr, "folder");
115 if (cptr && folder) {
116 cptr->c_text = folder;
117 cptr->c_flags = hdrflg;
119 FINDCOMP(cptr, "encrypted");
121 if (cptr = (struct comp *) calloc (1, sizeof *cptr)) {
122 cptr -> c_name = "encrypted";
123 cptr -> c_next = wantcomp[i = CHASH (cptr -> c_name)];
127 FINDCOMP (cptr, "dtimenow");
129 cptr->c_text = getcpy(dtimenow ());
130 nxtbuf = compbuffers = (char **)calloc((unsigned) ncomps,
133 adios (NULLCP, "unable to allocate component buffers");
134 used_buf = (struct comp **)calloc((unsigned) (ncomps+1),
135 sizeof(struct comp *));
136 if (used_buf == NULL)
137 adios (NULLCP, "unable to allocate component buffer stack");
138 used_buf += ncomps+1; *--used_buf = 0;
139 rlwidth = bodycomp && (width > SBUFSIZ) ? width : SBUFSIZ;
140 for (i = ncomps; i--; )
141 if ((*nxtbuf++ = malloc( rlwidth )) == NULL)
142 adios (NULLCP, "unable to allocate component buffer");
144 /* each-message initialization */
145 nxtbuf = compbuffers;
148 dat[0] = innum ? innum : outnum;
153 * get the first field. If the msg is non-empty and we're doing
154 * an "inc", open the output file.
156 if ((state = m_getfld (FLD, name, tmpbuf, rlwidth, inb)) == FILEEOF)
158 advise("read", "unable to"); /* "read error" */
164 if (outnum > 0) { /* Fix from Van -- I'm not sure why... */
165 scnmsg = m_name (outnum);
166 if (*scnmsg == '?') /* msg num out of range */
170 scnmsg = "/dev/null";
171 if ((scnout = fopen (scnmsg, "w")) == NULL)
172 adios (scnmsg, "unable to write");
174 if ((cp = unixline ()) && *cp != '\n') {
175 FPUTS ("Return-Path: ");
181 /* scan - main loop */
182 for (compnum = 1; ; state = m_getfld (state, name, tmpbuf, rlwidth, inb)) {
189 (void) putc (':', scnout);
193 * if we're interested in this component, save a pointer
194 * to the component text, then start using our next free
195 * buffer as the component temp buffer (buffer switching
196 * saves an extra copy of the component text).
198 if (cptr = wantcomp[CHASH(name)])
200 if (uleq(name, cptr->c_name)) {
201 if (! cptr->c_text) {
202 cptr->c_text = tmpbuf;
203 for (cp = tmpbuf + strlen (tmpbuf) - 1;
214 } while (cptr = cptr->c_next);
216 while (state == FLDPLUS) {
217 state = m_getfld (state, name, tmpbuf, rlwidth, inb);
226 state = FILEEOF; /* stop now if scan cmd */
229 (void) putc ('\n', scnout);
232 * performance hack: some people like to run "inc" on
233 * things like net.sources or large digests. We do a
234 * copy directly into the output buffer rather than
235 * going through an intermediate buffer.
237 * We need the amount of data m_getfld found & don't
238 * want to do a strlen on the long buffer so there's
239 * a hack in m_getfld to save the amount of data it
240 * returned in the global "msg_count".
243 while (state == BODY) {
244 if (scnout->_cnt <= 0) {
245 if (fflush(scnout) == EOF)
246 adios (scnmsg, "write error on");
248 state = m_getfld( state, name, scnout->_ptr,
249 -(scnout->_cnt), inb );
250 scnout->_cnt -= msg_count;
251 scnout->_ptr += msg_count;
258 innum ? "??Format error (message %d) in "
259 : "??Format error in ",
260 outnum ? outnum : innum);
261 fprintf (stderr, "component %d\n", compnum);
264 FPUTS ("\n\nBAD MSG:\n");
266 (void) putc ('\n', scnout);
276 adios (NULLCP, "getfld() returned %d", state);
280 * format and output the scan line.
284 advise("read", "unable to"); /* "read error" */
291 /* Save and restore buffer so we don't trash our dynamic pool! */
292 saved_c_text = bodycomp->c_text;
293 bodycomp->c_text = tmpbuf;
299 dat[2] = ftell(scnout);
301 if ( (datecomp && ! datecomp->c_text) || (!size && !outnum)) {
303 (void) fstat (fileno(inb), &st);
304 if (!size && !outnum)
307 if (! datecomp->c_text) {
308 if (datecomp->c_tws == NULL)
309 datecomp->c_tws = (struct tws *)
310 calloc((unsigned) 1, sizeof(*datecomp->c_tws));
311 if (datecomp->c_tws == NULL)
312 adios (NULLCP, "unable to allocate tws buffer");
313 *datecomp->c_tws = *dlocaltime ((long *) &st.st_mtime);
314 datecomp->c_flags = -1;
316 datecomp->c_flags = 0;
321 (void) fmtscan (fmt, scanl, slwidth, dat);
323 fmt = fmtscan (fmt, scanl, slwidth, dat);
325 fmt = fmt_top; /* reset for old format files */
329 bodycomp->c_text = saved_c_text;
332 (void) fputs (scanl, stdout);
334 FINDCOMP (cptr, "encrypted");
335 encrypted = cptr && cptr -> c_text;
336 /* return dynamically allocated buffers to pool */
337 while ( cptr = *savecomp++ ) {
338 *--nxtbuf = cptr->c_text;
339 cptr->c_text = NULLCP;
343 if (outnum && fclose (scnout) == EOF)
344 adios (scnmsg, "write error on");
346 return (state != FILEEOF ? SCNERR : encrypted ? SCNENC : SCNMSG);
351 /* Cheat: we are loaded with adrparse, which wants a routine called
352 OfficialName(). We call adrparse:getm() with the correct arguments
353 to prevent OfficialName() from being called. Hence, the following
354 is to keep the loader happy.
357 char *OfficialName (name)
369 if(putc(c,stream) == EOF )