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 | |
---|
13 | static 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 | |
---|
23 | static char backup[BUFSIZ] = ""; |
---|
24 | static char drft[BUFSIZ] = ""; |
---|
25 | static char tmpfil[BUFSIZ] = ""; |
---|
26 | |
---|
27 | /* |
---|
28 | * prototypes |
---|
29 | */ |
---|
30 | static void rcvdistout (FILE *, char *, char *); |
---|
31 | void done (int); |
---|
32 | |
---|
33 | |
---|
34 | int |
---|
35 | main (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 | |
---|
127 | static int outputlinelen = OUTPUTLINELEN; |
---|
128 | |
---|
129 | static struct format *fmt; |
---|
130 | |
---|
131 | static int ncomps = 0; |
---|
132 | static char **compbuffers = 0; |
---|
133 | static struct comp **used_buf = 0; |
---|
134 | |
---|
135 | static int dat[5]; |
---|
136 | |
---|
137 | static 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 | |
---|
154 | static void |
---|
155 | rcvdistout (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 | } |
---|
241 | finished: ; |
---|
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 | |
---|
264 | void |
---|
265 | done (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 | } |
---|