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

Revision 12455, 6.1 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 * rcvdist.c -- asynchronously redistribute messages
4 *
5 * $Id: rcvdist.c,v 1.1.1.1 1999-02-07 18:14:16 danw Exp $
6 */
7
8#include <h/mh.h>
9#include <h/fmt_scan.h>
10#include <h/rcvmail.h>
11#include <zotnet/tws/tws.h>
12
13static struct swit switches[] = {
14#define FORMSW       0
15    { "form formfile",  4 },
16#define VERSIONSW    1
17    { "version", 0 },
18#define HELPSW       2
19    { "help", 4 },
20    { NULL, 0 }
21};
22
23static char backup[BUFSIZ] = "";
24static char drft[BUFSIZ] = "";
25static char tmpfil[BUFSIZ] = "";
26
27/*
28 * prototypes
29 */
30static void rcvdistout (FILE *, char *, char *);
31void done (int);
32
33
34int
35main (int argc, char **argv)
36{
37    pid_t child_id;
38    int i, vecp = 1;
39    char *addrs = NULL, *cp, *form = NULL, buf[BUFSIZ];
40    char **argp, **arguments, *vec[MAXARGS];
41    register FILE *fp;
42
43#ifdef LOCALE
44    setlocale(LC_ALL, "");
45#endif
46    invo_name = r1bindex (argv[0], '/');
47
48    /* read user profile/context */
49    context_read();
50
51    mts_init (invo_name);
52    arguments = getarguments (invo_name, argc, argv, 1);
53    argp = arguments;
54
55    while ((cp = *argp++)) {
56        if (*cp == '-') {
57            switch (smatch (++cp, switches)) {
58                case AMBIGSW:
59                    ambigsw (cp, switches);
60                    done (1);
61                case UNKWNSW:
62                    vec[vecp++] = --cp;
63                    continue;
64
65                case HELPSW:
66                    snprintf (buf, sizeof(buf),
67                        "%s [switches] [switches for postproc] address ...",
68                        invo_name);
69                    print_help (buf, switches, 1);
70                    done (1);
71                case VERSIONSW:
72                    print_version(invo_name);
73                    done (1);
74
75                case FORMSW:
76                    if (!(form = *argp++) || *form == '-')
77                        adios (NULL, "missing argument to %s", argp[-2]);
78                    continue;
79            }
80        }
81        addrs = addrs ? add (cp, add (", ", addrs)) : getcpy (cp);
82    }
83
84    if (addrs == NULL)
85        adios (NULL, "usage: %s [switches] [switches for postproc] address ...",
86            invo_name);
87
88    umask (~m_gmprot ());
89    strncpy (tmpfil, m_tmpfil (invo_name), sizeof(tmpfil));
90    if ((fp = fopen (tmpfil, "w+")) == NULL)
91        adios (tmpfil, "unable to create");
92    cpydata (fileno (stdin), fileno (fp), "message", tmpfil);
93    fseek (fp, 0L, SEEK_SET);
94    strncpy (drft, m_tmpfil (invo_name), sizeof(drft));
95    rcvdistout (fp, form, addrs);
96    fclose (fp);
97
98    if (distout (drft, tmpfil, backup) == NOTOK)
99        done (1);
100
101    vec[0] = r1bindex (postproc, '/');
102    vec[vecp++] = "-dist";
103    vec[vecp++] = drft;
104    vec[vecp] = NULL;
105
106    for (i = 0; (child_id = fork()) == NOTOK && i < 5; i++)
107        sleep (5);
108    switch (child_id) {
109        case NOTOK:
110            admonish (NULL, "unable to fork");/* fall */
111        case OK:
112            execvp (postproc, vec);
113            fprintf (stderr, "unable to exec ");
114            perror (postproc);
115            _exit (1);
116
117        default:
118            done (pidXwait(child_id, postproc));
119    }
120/* NOTREACHED */
121}
122
123/* very similar to routine in replsbr.c */
124
125#define SBUFSIZ 256
126
127static int outputlinelen = OUTPUTLINELEN;
128
129static struct format *fmt;
130
131static int ncomps = 0;
132static char **compbuffers = 0;
133static struct comp **used_buf = 0;
134
135static int dat[5];
136
137static char *addrcomps[] = {
138    "from",
139    "sender",
140    "reply-to",
141    "to",
142    "cc",
143    "bcc",
144    "resent-from",
145    "resent-sender",
146    "resent-reply-to",
147    "resent-to",
148    "resent-cc",
149    "resent-bcc",
150    NULL
151};
152
153
154static void
155rcvdistout (FILE *inb, char *form, char *addrs)
156{
157    register int char_read = 0, format_len, i, state;
158    register char *tmpbuf, **nxtbuf, **ap;
159    char *cp, *scanl, name[NAMESZ];
160    register struct comp *cptr, **savecomp;
161    FILE *out;
162
163    if (!(out = fopen (drft, "w")))
164        adios (drft, "unable to create");
165
166    /* get new format string */
167    cp = new_fs (form ? form : rcvdistcomps, NULL, NULL);
168    format_len = strlen (cp);
169    ncomps = fmt_compile (cp, &fmt) + 1;
170    if (!(nxtbuf = compbuffers = (char **) calloc ((size_t) ncomps, sizeof(char *))))
171        adios (NULL, "unable to allocate component buffers");
172    if (!(savecomp = used_buf = (struct comp **) calloc ((size_t) (ncomps + 1), sizeof(struct comp *))))
173        adios (NULL, "unable to allocate component buffer stack");
174    savecomp += ncomps + 1;
175    *--savecomp = 0;
176
177    for (i = ncomps; i--;)
178        if (!(*nxtbuf++ = malloc (SBUFSIZ)))
179            adios (NULL, "unable to allocate component buffer");
180    nxtbuf = compbuffers;
181    tmpbuf = *nxtbuf++;
182
183    for (ap = addrcomps; *ap; ap++) {
184        FINDCOMP (cptr, *ap);
185        if (cptr)
186            cptr->c_type |= CT_ADDR;
187    }
188
189    FINDCOMP (cptr, "addresses");
190    if (cptr)
191        cptr->c_text = addrs;
192
193    for (state = FLD;;) {
194        switch (state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb)) {
195            case FLD:
196            case FLDPLUS:
197                if ((cptr = wantcomp[CHASH (name)]))
198                    do {
199                        if (!strcasecmp (name, cptr->c_name)) {
200                            char_read += msg_count;
201                            if (!cptr->c_text) {
202                                cptr->c_text = tmpbuf;
203                                *--savecomp = cptr;
204                                tmpbuf = *nxtbuf++;
205                            }
206                            else {
207                                i = strlen (cp = cptr->c_text) - 1;
208                                if (cp[i] == '\n')
209                                    if (cptr->c_type & CT_ADDR) {
210                                        cp[i] = 0;
211                                        cp = add (",\n\t", cp);
212                                    }
213                                    else
214                                        cp = add ("\t", cp);
215                                cptr->c_text = add (tmpbuf, cp);
216                            }
217                            while (state == FLDPLUS) {
218                                state = m_getfld (state, name, tmpbuf,
219                                                  SBUFSIZ, inb);
220                                cptr->c_text = add (tmpbuf, cptr->c_text);
221                                char_read += msg_count;
222                            }
223                            break;
224                        }
225                    } while ((cptr = cptr->c_next));
226
227                while (state == FLDPLUS)
228                    state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
229                break;
230
231            case LENERR:
232            case FMTERR:
233            case BODY:
234            case FILEEOF:
235                goto finished;
236
237            default:
238                adios (NULL, "m_getfld() returned %d", state);
239        }
240    }
241finished: ;
242
243    i = format_len + char_read + 256;
244    scanl = malloc ((size_t) i + 2);
245    dat[0] = dat[1] = dat[2] = dat[4] = 0;
246    dat[3] = outputlinelen;
247    fmt_scan (fmt, scanl, i, dat);
248    fputs (scanl, out);
249
250    if (ferror (out))
251        adios (drft, "error writing");
252    fclose (out);
253
254    free (scanl);
255    for (nxtbuf = compbuffers, i = ncomps; cptr = *savecomp++; nxtbuf++, i--)
256        free (cptr->c_text);
257    while (i-- > 0)
258        free (*nxtbuf++);
259    free ((char *) compbuffers);
260    free ((char *) used_buf);
261}
262
263
264void
265done (int status)
266{
267    if (backup[0])
268        unlink (backup);
269    if (drft[0])
270        unlink (drft);
271    if (tmpfil[0])
272        unlink (tmpfil);
273
274    exit (status ? RCV_MBX : RCV_MOK);
275}
Note: See TracBrowser for help on using the repository browser.