1 /* rcvdist.c - a rcvmail program to distribute messages */
3 static char ident[] = "@(#)$Id: rcvdist.c,v 1.10 1992/12/15 00:20:22 jromine Exp $";
7 #include "../h/formatsbr.h"
8 #include "../h/rcvmail.h"
9 #include "../zotnet/tws.h"
17 static struct swit switches[] = {
29 static char backup[BUFSIZ] = "";
30 static char drft[BUFSIZ] = "";
31 static char tmpfil[BUFSIZ] = "";
56 setlocale(LC_ALL, "");
58 invo_name = r1bindex (argv[0], '/');
60 if ((cp = m_find (invo_name)) != NULL) {
61 ap = brkstring (cp = getcpy (cp), " ", "\n");
62 ap = copyip (ap, arguments);
66 (void) copyip (argv + 1, ap);
71 while (cp = *argp++) {
73 switch (smatch (++cp, switches)) {
75 ambigsw (cp, switches);
82 "%s [switches] [switches for postproc] address ...",
88 if (!(form = *argp++) || *form == '-')
89 adios (NULLCP, "missing argument to %s", argp[-2]);
92 addrs = addrs ? add (cp, add (", ", addrs)) : getcpy (cp);
98 adios (NULLCP, "usage: %s [switches] [switches for postproc] address ...",
101 (void) umask (~m_gmprot ());
102 (void) strcpy (tmpfil, m_tmpfil (invo_name));
103 if ((fp = fopen (tmpfil, "w+")) == NULL)
104 adios (tmpfil, "unable to create");
105 (void) cpydata (fileno (stdin), fileno (fp), "message", tmpfil);
106 (void) fseek (fp, 0L, 0);
107 (void) strcpy (drft, m_tmpfil (invo_name));
108 rcvdistout (fp, form, addrs);
111 if (distout (drft, tmpfil, backup) == NOTOK)
114 vec[0] = r1bindex (postproc, '/');
115 vec[vecp++] = "-dist";
119 for (i = 0; (child_id = fork ()) == NOTOK && i < 5; i++)
123 admonish (NULLCP, "unable to fork");/* fall */
125 execvp (postproc, vec);
126 fprintf (stderr, "unable to exec ");
131 done (pidXwait (child_id, postproc));
138 /* very similar to routine in replsbr.c */
142 static int outputlinelen = OUTPUTLINELEN;
144 static struct format *fmt;
146 static int ncomps = 0;
147 static char **compbuffers = 0;
148 static struct comp **used_buf = 0;
152 static char *addrcomps[] = {
169 static rcvdistout (inb, form, addrs)
174 register int char_read = 0,
178 register char *tmpbuf,
184 register struct comp *cptr,
188 if ((out = fopen (drft, "w")) == NULL)
189 adios (drft, "unable to create");
191 cp = new_fs (form ? form : rcvdistcomps, NULLCP, NULLCP);
192 format_len = strlen (cp);
193 ncomps = fmt_compile (cp, &fmt) + 1;
194 if ((nxtbuf = compbuffers = (char **)
195 calloc ((unsigned) ncomps, sizeof (char *)))
197 adios (NULLCP, "unable to allocate component buffers");
198 if ((savecomp = used_buf = (struct comp **)
199 calloc ((unsigned) (ncomps + 1), sizeof (struct comp *)))
200 == (struct comp **) NULL)
201 adios (NULLCP, "unable to allocate component buffer stack");
202 savecomp += ncomps + 1;
205 for (i = ncomps; i--;)
206 if ((*nxtbuf++ = malloc (SBUFSIZ)) == NULL)
207 adios (NULLCP, "unable to allocate component buffer");
208 nxtbuf = compbuffers;
211 for (ap = addrcomps; *ap; ap++) {
212 FINDCOMP (cptr, *ap);
214 cptr -> c_type |= CT_ADDR;
217 FINDCOMP (cptr, "addresses");
219 cptr -> c_text = addrs;
221 for (state = FLD;;) {
222 switch (state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb)) {
225 if (cptr = wantcomp[CHASH (name)])
227 if (uleq (name, cptr -> c_name)) {
228 char_read += msg_count;
229 if (!cptr -> c_text) {
230 cptr -> c_text = tmpbuf;
235 i = strlen (cp = cptr -> c_text) - 1;
237 if (cptr -> c_type & CT_ADDR) {
239 cp = add (",\n\t", cp);
243 cptr -> c_text = add (tmpbuf, cp);
245 while (state == FLDPLUS) {
246 state = m_getfld (state, name, tmpbuf,
248 cptr -> c_text = add (tmpbuf, cptr -> c_text);
249 char_read += msg_count;
253 } while (cptr = cptr -> c_next);
255 while (state == FLDPLUS)
256 state = m_getfld (state, name, tmpbuf, SBUFSIZ, inb);
266 adios (NULLCP, "m_getfld() returned %d", state);
271 i = format_len + char_read + 256;
272 scanl = malloc ((unsigned) i + 2);
273 dat[0] = dat[1] = dat[2] = dat[4] = 0;
274 dat[3] = outputlinelen;
275 (void) fmtscan (fmt, scanl, i, dat);
279 adios (drft, "error writing");
283 for (nxtbuf = compbuffers, i = ncomps; cptr = *savecomp++; nxtbuf++, i--)
284 free (cptr -> c_text);
287 free ((char *) compbuffers);
288 free ((char *) used_buf);
297 (void) unlink (backup);
299 (void) unlink (drft);
301 (void) unlink (tmpfil);
303 exit (status ? RCV_MBX : RCV_MOK);