Mercurial > hg > Applications > mh
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 } |