source: trunk/third/nmh/uip/scansbr.c @ 12455

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