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