]>
diplodocus.org Git - nmh/blob - docs/historical/mh-6.8.5/uip/scansbr.c
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
)