comparison uip/scansbr.c @ 0:bce86c4163a3

Initial revision
author kono
date Mon, 18 Apr 2005 23:46:02 +0900
parents
children 441a2190cfae
comparison
equal deleted inserted replaced
-1:000000000000 0:bce86c4163a3
1 /* scansbr.c - routines to help scan along... */
2 #ifndef lint
3 static char ident[] = "@(#)$Id$";
4 #endif /* lint */
5
6 #include "../h/mh.h"
7 #include "../h/addrsbr.h"
8 #include "../h/formatsbr.h"
9 #include "../h/scansbr.h"
10 #include "../zotnet/tws.h"
11 #include <stdio.h>
12 #include <ctype.h>
13 #include <sys/types.h>
14 #include <sys/stat.h>
15
16 #ifdef FILE__PTR
17 #define _ptr __ptr
18 #define _cnt __cnt
19 #endif
20
21 #ifdef _FSTDIO
22 #define _ptr _p /* Gag */
23 #define _cnt _w /* Wretch */
24 #endif
25
26 #define MAXSCANL 256 /* longest possible scan line */
27 #define SBUFSIZ 512 /* buffer size for content part of header
28 * fields. We want this to be large
29 * enough so that we don't do a lot of
30 * extra FLDPLUS calls on m_getfld but
31 * small enough so that we don't snarf
32 * the entire message body when we're
33 * only going to display 30 characters
34 * of it.
35 */
36
37 /* */
38
39 static struct format *fmt;
40 #ifdef JLR
41 static struct format *fmt_top;
42 #endif /* JLR */
43
44 static struct comp *datecomp; /* pntr to "date" comp */
45 static struct comp *bodycomp; /* pntr to "body" pseudo-comp
46 * (if referenced) */
47 static int ncomps = 0; /* # of interesting components */
48 static char **compbuffers = 0; /* buffers for component text */
49 static struct comp **used_buf = 0; /* stack for comp that use buffers */
50
51 char *scanl = 0; /* text of most recent scanline */
52
53 static int dat[5]; /* aux. data for format routine */
54
55 #ifdef RPATHS
56 char *unixline (); /* info from UNIX From: line */
57 #endif /* RPATHS */
58
59 #define FPUTS(buf) {\
60 if (mh_fputs(buf,scnout) == EOF)\
61 adios (scnmsg, "write error on");\
62 }
63
64 /* */
65
66 /* ARGSUSED */
67
68 int scan (inb, innum, outnum, nfs, width, curflg, unseen,
69 hdrflg, folder, size, noisy)
70 char *nfs,
71 *folder;
72 int innum,
73 outnum,
74 width,
75 curflg,
76 unseen,
77 hdrflg,
78 noisy;
79 long size;
80 register FILE *inb;
81 {
82 int compnum,
83 encrypted,
84 state;
85 register int i;
86 register char *cp;
87 register struct comp *cptr;
88 register char *tmpbuf;
89 register char **nxtbuf;
90 register struct comp **savecomp;
91 char *scnmsg;
92 FILE *scnout;
93 char name[NAMESZ];
94 static int rlwidth,
95 slwidth;
96
97 /* first-time only initialization */
98 if (scanl == NULLCP) {
99 int bigwid;
100
101 if (width == 0) {
102 if ((width = sc_width ()) < WIDTH/2)
103 width = WIDTH/2;
104 else if (width > MAXSCANL)
105 width = MAXSCANL;
106 }
107 dat[3] = slwidth = width;
108 if ((scanl = (char *)malloc( (unsigned) (slwidth + 2) )) == (char *)0)
109 adios (NULLCP, "unable to malloc scan line (%d bytes)", slwidth+2);
110 if (outnum)
111 (void) umask( ~ m_gmprot() );
112
113 ncomps = fmt_compile (nfs, &fmt) + 1;
114 #ifdef JLR
115 fmt_top = fmt;
116 #endif /* JLR */
117 FINDCOMP(bodycomp, "body");
118 FINDCOMP(datecomp, "date");
119 FINDCOMP(cptr, "folder");
120 if (cptr && folder) {
121 cptr->c_text = folder;
122 cptr->c_flags = hdrflg;
123 }
124 FINDCOMP(cptr, "encrypted");
125 if (!cptr)
126 if (cptr = (struct comp *) calloc (1, sizeof *cptr)) {
127 cptr -> c_name = "encrypted";
128 cptr -> c_next = wantcomp[i = CHASH (cptr -> c_name)];
129 wantcomp[i] = cptr;
130 ncomps++;
131 }
132 FINDCOMP (cptr, "dtimenow");
133 if (cptr)
134 cptr->c_text = getcpy(dtimenow ());
135 nxtbuf = compbuffers = (char **)calloc((unsigned) ncomps,
136 sizeof(char *));
137 if (nxtbuf == NULL)
138 adios (NULLCP, "unable to allocate component buffers");
139 used_buf = (struct comp **)calloc((unsigned) (ncomps+1),
140 sizeof(struct comp *));
141 if (used_buf == NULL)
142 adios (NULLCP, "unable to allocate component buffer stack");
143 used_buf += ncomps+1; *--used_buf = 0;
144 rlwidth = bodycomp && (width > SBUFSIZ) ? width : SBUFSIZ;
145 for (i = ncomps; i--; )
146 if ((*nxtbuf++ = malloc( rlwidth )) == NULL)
147 adios (NULLCP, "unable to allocate component buffer");
148 }
149 /* each-message initialization */
150 nxtbuf = compbuffers;
151 savecomp = used_buf;
152 tmpbuf = *nxtbuf++;
153 dat[0] = innum ? innum : outnum;
154 dat[1] = curflg;
155 dat[4] = unseen;
156
157 /*
158 * get the first field. If the msg is non-empty and we're doing
159 * an "inc", open the output file.
160 */
161 if ((state = m_getfld (FLD, name, tmpbuf, rlwidth, inb)) == FILEEOF)
162 if (ferror(inb)) {
163 advise("read", "unable to"); /* "read error" */
164 return SCNFAT;
165 } else
166 return SCNEOF;
167
168 if (outnum) {
169 if (outnum > 0) { /* Fix from Van -- I'm not sure why... */
170 scnmsg = m_name (outnum);
171 if (*scnmsg == '?') /* msg num out of range */
172 return SCNNUM;
173 }
174 else
175 scnmsg = "/dev/null";
176 if ((scnout = fopen (scnmsg, "w")) == NULL)
177 adios (scnmsg, "unable to write");
178 #ifdef RPATHS
179 if ((cp = unixline ()) && *cp != '\n') {
180 FPUTS ("Return-Path: ");
181 FPUTS (cp);
182 }
183 #endif /* RPATHS */
184 }
185
186 /* scan - main loop */
187 for (compnum = 1; ; state = m_getfld (state, name, tmpbuf, rlwidth, inb)) {
188 switch (state) {
189 case FLD:
190 case FLDPLUS:
191 compnum++;
192 if (outnum) {
193 FPUTS (name);
194 if (putc (':', scnout) == EOF)
195 adios (scnmsg, "write error on");
196 FPUTS (tmpbuf);
197 }
198 /*
199 * if we're interested in this component, save a pointer
200 * to the component text, then start using our next free
201 * buffer as the component temp buffer (buffer switching
202 * saves an extra copy of the component text).
203 */
204 if (cptr = wantcomp[CHASH(name)])
205 do {
206 if (uleq(name, cptr->c_name)) {
207 if (! cptr->c_text) {
208 #ifdef JAPAN
209 (void) ml_conv(tmpbuf);
210 #endif /* JAPAN */
211 cptr->c_text = tmpbuf;
212 for (cp = tmpbuf + strlen (tmpbuf) - 1;
213 cp >= tmpbuf; cp--)
214 if (isspace (*cp & 0xff))
215 *cp = 0;
216 else
217 break;
218 *--savecomp = cptr;
219 tmpbuf = *nxtbuf++;
220 }
221 break;
222 }
223 } while (cptr = cptr->c_next);
224
225 while (state == FLDPLUS) {
226 state = m_getfld (state, name, tmpbuf, rlwidth, inb);
227 if (outnum)
228 FPUTS (tmpbuf);
229 }
230 break;
231
232 case BODY:
233 compnum = -1;
234 if (! outnum) {
235 state = FILEEOF; /* stop now if scan cmd */
236 goto finished;
237 }
238 if (putc ('\n', scnout) == EOF)
239 adios (scnmsg, "write error on");
240 FPUTS (tmpbuf);
241 /*
242 * performance hack: some people like to run "inc" on
243 * things like net.sources or large digests. We do a
244 * copy directly into the output buffer rather than
245 * going through an intermediate buffer.
246 *
247 * We need the amount of data m_getfld found & don't
248 * want to do a strlen on the long buffer so there's
249 * a hack in m_getfld to save the amount of data it
250 * returned in the global "msg_count".
251 */
252 body: ;
253 while (state == BODY) {
254 #ifdef _STDIO_USES_IOSTREAM
255 if (scnout->_IO_write_ptr == scnout->_IO_write_end) {
256 #else
257 if (scnout->_cnt <= 0) {
258 #endif
259 if (fflush(scnout) == EOF)
260 adios (scnmsg, "write error on");
261 }
262 #ifdef _STDIO_USES_IOSTREAM
263 state = m_getfld(state, name, scnout->_IO_write_ptr,
264 (long)scnout->_IO_write_ptr-(long)scnout->_IO_write_end,
265 inb);
266 scnout->_IO_write_ptr += msg_count;
267 #else
268 state = m_getfld( state, name, scnout->_ptr,
269 -(scnout->_cnt), inb );
270 scnout->_cnt -= msg_count;
271 scnout->_ptr += msg_count;
272 #endif
273 }
274 goto finished;
275
276 case LENERR:
277 case FMTERR:
278 fprintf (stderr,
279 innum ? "??Format error (message %d) in "
280 : "??Format error in ",
281 outnum ? outnum : innum);
282 fprintf (stderr, "component %d\n", compnum);
283
284 if (outnum) {
285 FPUTS ("\n\nBAD MSG:\n");
286 FPUTS (name);
287 if (putc ('\n', scnout) == EOF)
288 adios (scnmsg, "write error on");
289 state = BODY;
290 goto body;
291 }
292 /* fall through */
293
294 case FILEEOF:
295 goto finished;
296
297 default:
298 adios (NULLCP, "getfld() returned %d", state);
299 }
300 }
301 /*
302 * format and output the scan line.
303 */
304 finished:
305 if (ferror(inb)) {
306 advise("read", "unable to"); /* "read error" */
307 return SCNFAT;
308 }
309 {
310 char *saved_c_text;
311
312 if (bodycomp) {
313 /* Save and restore buffer so we don't trash our dynamic pool! */
314 saved_c_text = bodycomp->c_text;
315 #ifdef JAPAN
316 (void) ml_conv(tmpbuf);
317 #endif /* JAPAN */
318 bodycomp->c_text = tmpbuf;
319 }
320
321 if (size)
322 dat[2] = size;
323 else if (outnum > 0)
324 if ((dat[2] = ftell(scnout)) == EOF)
325 adios (scnmsg, "write error on");
326
327 if ( (datecomp && ! datecomp->c_text) || (!size && !outnum)) {
328 struct stat st;
329 (void) fstat (fileno(inb), &st);
330 if (!size && !outnum)
331 dat[2] = st.st_size;
332 if (datecomp) {
333 if (! datecomp->c_text) {
334 if (datecomp->c_tws == NULL)
335 datecomp->c_tws = (struct tws *)
336 calloc((unsigned) 1, sizeof(*datecomp->c_tws));
337 if (datecomp->c_tws == NULL)
338 adios (NULLCP, "unable to allocate tws buffer");
339 *datecomp->c_tws = *dlocaltime ((time_t *) &st.st_mtime);
340 datecomp->c_flags = -1;
341 } else {
342 datecomp->c_flags = 0;
343 }
344 }
345 }
346 #ifndef JLR
347 (void) fmtscan (fmt, scanl, slwidth, dat);
348 #else /* JLR */
349 fmt = fmtscan (fmt, scanl, slwidth, dat);
350 if (!fmt)
351 fmt = fmt_top; /* reset for old format files */
352 #endif /* JLR */
353
354 if (bodycomp)
355 bodycomp->c_text = saved_c_text;
356 }
357 if (noisy)
358 #ifdef JAPAN
359 ml_fputs (scanl, stdout);
360 #else /* JAPAN */
361 (void) fputs (scanl, stdout);
362 #endif /* JAPAN */
363
364 FINDCOMP (cptr, "encrypted");
365 encrypted = cptr && cptr -> c_text;
366 /* return dynamically allocated buffers to pool */
367 while ( cptr = *savecomp++ ) {
368 *--nxtbuf = cptr->c_text;
369 cptr->c_text = NULLCP;
370 }
371 *--nxtbuf = tmpbuf;
372
373 if (outnum && fclose (scnout) == EOF)
374 adios (scnmsg, "write error on");
375
376 return (state != FILEEOF ? SCNERR : encrypted ? SCNENC : SCNMSG);
377 }
378
379 /* */
380
381 /* Cheat: we are loaded with adrparse, which wants a routine called
382 OfficialName(). We call adrparse:getm() with the correct arguments
383 to prevent OfficialName() from being called. Hence, the following
384 is to keep the loader happy.
385 */
386
387 char *OfficialName (name)
388 register char *name;
389 {
390 return name;
391 }
392
393 mh_fputs(s, stream)
394 char *s;
395 FILE *stream;
396 {
397 char c;
398 while(c = *s++)
399 if(putc(c,stream) == EOF )
400 return(EOF);
401 return(0);
402 }