1 | |
---|
2 | /* |
---|
3 | * send.c -- send a composed message |
---|
4 | * |
---|
5 | * $Id: send.c,v 1.1.1.1 1999-02-07 18:14:16 danw Exp $ |
---|
6 | */ |
---|
7 | |
---|
8 | #include <h/mh.h> |
---|
9 | #include <fcntl.h> |
---|
10 | #include <errno.h> |
---|
11 | #include <signal.h> |
---|
12 | |
---|
13 | |
---|
14 | static struct swit switches[] = { |
---|
15 | #define ALIASW 0 |
---|
16 | { "alias aliasfile", 0 }, |
---|
17 | #define DEBUGSW 1 |
---|
18 | { "debug", -5 }, |
---|
19 | #define DRAFTSW 2 |
---|
20 | { "draft", 0 }, |
---|
21 | #define DFOLDSW 3 |
---|
22 | { "draftfolder +folder", 6 }, |
---|
23 | #define DMSGSW 4 |
---|
24 | { "draftmessage msg", 6 }, |
---|
25 | #define NDFLDSW 5 |
---|
26 | { "nodraftfolder", 0 }, |
---|
27 | #define FILTSW 6 |
---|
28 | { "filter filterfile", 0 }, |
---|
29 | #define NFILTSW 7 |
---|
30 | { "nofilter", 0 }, |
---|
31 | #define FRMTSW 8 |
---|
32 | { "format", 0 }, |
---|
33 | #define NFRMTSW 9 |
---|
34 | { "noformat", 0 }, |
---|
35 | #define FORWSW 10 |
---|
36 | { "forward", 0 }, |
---|
37 | #define NFORWSW 11 |
---|
38 | { "noforward", 0 }, |
---|
39 | #define MIMESW 12 |
---|
40 | { "mime", 0 }, |
---|
41 | #define NMIMESW 13 |
---|
42 | { "nomime", 0 }, |
---|
43 | #define MSGDSW 14 |
---|
44 | { "msgid", 0 }, |
---|
45 | #define NMSGDSW 15 |
---|
46 | { "nomsgid", 0 }, |
---|
47 | #define PUSHSW 16 |
---|
48 | { "push", 0 }, |
---|
49 | #define NPUSHSW 17 |
---|
50 | { "nopush", 0 }, |
---|
51 | #define SPLITSW 18 |
---|
52 | { "split seconds", 0 }, |
---|
53 | #define UNIQSW 19 |
---|
54 | { "unique", -6 }, |
---|
55 | #define NUNIQSW 20 |
---|
56 | { "nounique", -8 }, |
---|
57 | #define VERBSW 21 |
---|
58 | { "verbose", 0 }, |
---|
59 | #define NVERBSW 22 |
---|
60 | { "noverbose", 0 }, |
---|
61 | #define WATCSW 23 |
---|
62 | { "watch", 0 }, |
---|
63 | #define NWATCSW 24 |
---|
64 | { "nowatch", 0 }, |
---|
65 | #define WIDTHSW 25 |
---|
66 | { "width columns", 0 }, |
---|
67 | #define VERSIONSW 26 |
---|
68 | { "version", 0 }, |
---|
69 | #define HELPSW 27 |
---|
70 | { "help", 4 }, |
---|
71 | #define BITSTUFFSW 28 |
---|
72 | { "dashstuffing", -12 }, |
---|
73 | #define NBITSTUFFSW 29 |
---|
74 | { "nodashstuffing", -14 }, |
---|
75 | #define MAILSW 30 |
---|
76 | { "mail", -4 }, |
---|
77 | #define SAMLSW 31 |
---|
78 | { "saml", -4 }, |
---|
79 | #define SENDSW 32 |
---|
80 | { "send", -4 }, |
---|
81 | #define SOMLSW 33 |
---|
82 | { "soml", -4 }, |
---|
83 | #define CLIESW 34 |
---|
84 | { "client host", -6 }, |
---|
85 | #define SERVSW 35 |
---|
86 | { "server host", -6 }, |
---|
87 | #define SNOOPSW 36 |
---|
88 | { "snoop", -5 }, |
---|
89 | { NULL, 0 } |
---|
90 | }; |
---|
91 | |
---|
92 | static struct swit anyl[] = { |
---|
93 | #define NOSW 0 |
---|
94 | { "no", 0 }, |
---|
95 | #define YESW 1 |
---|
96 | { "yes", 0 }, |
---|
97 | #define LISTDSW 2 |
---|
98 | { "list", 0 }, |
---|
99 | { NULL, 0 } |
---|
100 | }; |
---|
101 | |
---|
102 | extern int debugsw; /* from sendsbr.c */ |
---|
103 | extern int forwsw; |
---|
104 | extern int inplace; |
---|
105 | extern int pushsw; |
---|
106 | extern int splitsw; |
---|
107 | extern int unique; |
---|
108 | extern int verbsw; |
---|
109 | |
---|
110 | extern char *altmsg; /* .. */ |
---|
111 | extern char *annotext; |
---|
112 | extern char *distfile; |
---|
113 | |
---|
114 | extern int errno; |
---|
115 | |
---|
116 | int |
---|
117 | main (int argc, char **argv) |
---|
118 | { |
---|
119 | int msgp = 0, distsw = 0, vecp = 1; |
---|
120 | int isdf = 0, mime = 0; |
---|
121 | int msgnum, status; |
---|
122 | char *cp, *dfolder = NULL, *maildir = NULL; |
---|
123 | char buf[BUFSIZ], **ap, **argp, **arguments; |
---|
124 | char *msgs[MAXARGS], *vec[MAXARGS]; |
---|
125 | struct msgs *mp; |
---|
126 | struct stat st; |
---|
127 | #ifdef UCI |
---|
128 | FILE *fp; |
---|
129 | #endif /* UCI */ |
---|
130 | |
---|
131 | #ifdef LOCALE |
---|
132 | setlocale(LC_ALL, ""); |
---|
133 | #endif |
---|
134 | invo_name = r1bindex (argv[0], '/'); |
---|
135 | |
---|
136 | /* read user profile/context */ |
---|
137 | context_read(); |
---|
138 | |
---|
139 | arguments = getarguments (invo_name, argc, argv, 1); |
---|
140 | argp = arguments; |
---|
141 | |
---|
142 | vec[vecp++] = "-library"; |
---|
143 | vec[vecp++] = getcpy (m_maildir ("")); |
---|
144 | |
---|
145 | while ((cp = *argp++)) { |
---|
146 | if (*cp == '-') { |
---|
147 | switch (smatch (++cp, switches)) { |
---|
148 | case AMBIGSW: |
---|
149 | ambigsw (cp, switches); |
---|
150 | done (1); |
---|
151 | case UNKWNSW: |
---|
152 | adios (NULL, "-%s unknown\n", cp); |
---|
153 | |
---|
154 | case HELPSW: |
---|
155 | snprintf (buf, sizeof(buf), "%s [file] [switches]", invo_name); |
---|
156 | print_help (buf, switches, 1); |
---|
157 | done (1); |
---|
158 | case VERSIONSW: |
---|
159 | print_version(invo_name); |
---|
160 | done (1); |
---|
161 | |
---|
162 | case DRAFTSW: |
---|
163 | msgs[msgp++] = draft; |
---|
164 | continue; |
---|
165 | |
---|
166 | case DFOLDSW: |
---|
167 | if (dfolder) |
---|
168 | adios (NULL, "only one draft folder at a time!"); |
---|
169 | if (!(cp = *argp++) || *cp == '-') |
---|
170 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
171 | dfolder = path (*cp == '+' || *cp == '@' ? cp + 1 : cp, |
---|
172 | *cp != '@' ? TFOLDER : TSUBCWF); |
---|
173 | continue; |
---|
174 | case DMSGSW: |
---|
175 | if (!(cp = *argp++) || *cp == '-') |
---|
176 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
177 | msgs[msgp++] = cp; |
---|
178 | continue; |
---|
179 | case NDFLDSW: |
---|
180 | dfolder = NULL; |
---|
181 | isdf = NOTOK; |
---|
182 | continue; |
---|
183 | |
---|
184 | case PUSHSW: |
---|
185 | pushsw++; |
---|
186 | continue; |
---|
187 | case NPUSHSW: |
---|
188 | pushsw = 0; |
---|
189 | continue; |
---|
190 | |
---|
191 | case SPLITSW: |
---|
192 | if (!(cp = *argp++) || sscanf (cp, "%d", &splitsw) != 1) |
---|
193 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
194 | continue; |
---|
195 | |
---|
196 | case UNIQSW: |
---|
197 | unique++; |
---|
198 | continue; |
---|
199 | case NUNIQSW: |
---|
200 | unique = 0; |
---|
201 | continue; |
---|
202 | |
---|
203 | case FORWSW: |
---|
204 | forwsw++; |
---|
205 | continue; |
---|
206 | case NFORWSW: |
---|
207 | forwsw = 0; |
---|
208 | continue; |
---|
209 | |
---|
210 | case VERBSW: |
---|
211 | verbsw++; |
---|
212 | vec[vecp++] = --cp; |
---|
213 | continue; |
---|
214 | case NVERBSW: |
---|
215 | verbsw = 0; |
---|
216 | vec[vecp++] = --cp; |
---|
217 | continue; |
---|
218 | |
---|
219 | case MIMESW: |
---|
220 | mime++; |
---|
221 | vec[vecp++] = --cp; |
---|
222 | continue; |
---|
223 | case NMIMESW: |
---|
224 | mime = 0; |
---|
225 | vec[vecp++] = --cp; |
---|
226 | continue; |
---|
227 | |
---|
228 | case DEBUGSW: |
---|
229 | debugsw++; /* fall */ |
---|
230 | case NFILTSW: |
---|
231 | case FRMTSW: |
---|
232 | case NFRMTSW: |
---|
233 | case BITSTUFFSW: |
---|
234 | case NBITSTUFFSW: |
---|
235 | case MSGDSW: |
---|
236 | case NMSGDSW: |
---|
237 | case WATCSW: |
---|
238 | case NWATCSW: |
---|
239 | case MAILSW: |
---|
240 | case SAMLSW: |
---|
241 | case SENDSW: |
---|
242 | case SOMLSW: |
---|
243 | case SNOOPSW: |
---|
244 | vec[vecp++] = --cp; |
---|
245 | continue; |
---|
246 | |
---|
247 | case ALIASW: |
---|
248 | case FILTSW: |
---|
249 | case WIDTHSW: |
---|
250 | case CLIESW: |
---|
251 | case SERVSW: |
---|
252 | vec[vecp++] = --cp; |
---|
253 | if (!(cp = *argp++) || *cp == '-') |
---|
254 | adios (NULL, "missing argument to %s", argp[-2]); |
---|
255 | vec[vecp++] = cp; |
---|
256 | continue; |
---|
257 | } |
---|
258 | } else { |
---|
259 | msgs[msgp++] = cp; |
---|
260 | } |
---|
261 | } |
---|
262 | |
---|
263 | /* |
---|
264 | * check for "Aliasfile:" profile entry |
---|
265 | */ |
---|
266 | if ((cp = context_find ("Aliasfile"))) { |
---|
267 | char *dp = NULL; |
---|
268 | |
---|
269 | for (ap = brkstring(dp = getcpy(cp), " ", "\n"); ap && *ap; ap++) { |
---|
270 | vec[vecp++] = "-alias"; |
---|
271 | vec[vecp++] = *ap; |
---|
272 | } |
---|
273 | } |
---|
274 | |
---|
275 | if (dfolder == NULL) { |
---|
276 | if (msgp == 0) { |
---|
277 | #ifdef WHATNOW |
---|
278 | if ((cp = getenv ("mhdraft")) && *cp) { |
---|
279 | msgs[msgp++] = cp; |
---|
280 | goto go_to_it; |
---|
281 | } |
---|
282 | #endif /* WHATNOW */ |
---|
283 | msgs[msgp++] = getcpy (m_draft (NULL, NULL, 1, &isdf)); |
---|
284 | if (stat (msgs[0], &st) == NOTOK) |
---|
285 | adios (msgs[0], "unable to stat draft file"); |
---|
286 | cp = concat ("Use \"", msgs[0], "\"? ", NULL); |
---|
287 | for (status = LISTDSW; status != YESW;) { |
---|
288 | if (!(argp = getans (cp, anyl))) |
---|
289 | done (1); |
---|
290 | switch (status = smatch (*argp, anyl)) { |
---|
291 | case NOSW: |
---|
292 | done (0); |
---|
293 | case YESW: |
---|
294 | break; |
---|
295 | case LISTDSW: |
---|
296 | showfile (++argp, msgs[0]); |
---|
297 | break; |
---|
298 | default: |
---|
299 | advise (NULL, "say what?"); |
---|
300 | break; |
---|
301 | } |
---|
302 | } |
---|
303 | } else { |
---|
304 | for (msgnum = 0; msgnum < msgp; msgnum++) |
---|
305 | msgs[msgnum] = getcpy (m_maildir (msgs[msgnum])); |
---|
306 | } |
---|
307 | } else { |
---|
308 | if (!context_find ("path")) |
---|
309 | free (path ("./", TFOLDER)); |
---|
310 | |
---|
311 | if (!msgp) |
---|
312 | msgs[msgp++] = "cur"; |
---|
313 | maildir = m_maildir (dfolder); |
---|
314 | |
---|
315 | if (chdir (maildir) == NOTOK) |
---|
316 | adios (maildir, "unable to change directory to"); |
---|
317 | |
---|
318 | /* read folder and create message structure */ |
---|
319 | if (!(mp = folder_read (dfolder))) |
---|
320 | adios (NULL, "unable to read folder %s", dfolder); |
---|
321 | |
---|
322 | /* check for empty folder */ |
---|
323 | if (mp->nummsg == 0) |
---|
324 | adios (NULL, "no messages in %s", dfolder); |
---|
325 | |
---|
326 | /* parse all the message ranges/sequences and set SELECTED */ |
---|
327 | for (msgnum = 0; msgnum < msgp; msgnum++) |
---|
328 | if (!m_convert (mp, msgs[msgnum])) |
---|
329 | done (1); |
---|
330 | seq_setprev (mp); /* set the previous-sequence */ |
---|
331 | |
---|
332 | for (msgp = 0, msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { |
---|
333 | if (is_selected (mp, msgnum)) { |
---|
334 | msgs[msgp++] = getcpy (m_name (msgnum)); |
---|
335 | unset_exists (mp, msgnum); |
---|
336 | } |
---|
337 | } |
---|
338 | |
---|
339 | mp->msgflags |= SEQMOD; |
---|
340 | seq_save (mp); |
---|
341 | } |
---|
342 | |
---|
343 | #ifdef WHATNOW |
---|
344 | go_to_it: |
---|
345 | #endif /* WHATNOW */ |
---|
346 | |
---|
347 | if ((cp = getenv ("SIGNATURE")) == NULL || *cp == 0) |
---|
348 | if ((cp = context_find ("signature")) && *cp) |
---|
349 | m_putenv ("SIGNATURE", cp); |
---|
350 | #ifdef UCI |
---|
351 | else { |
---|
352 | snprintf (buf, sizeof(buf), "%s/.signature", mypath); |
---|
353 | if ((fp = fopen (buf, "r")) != NULL |
---|
354 | && fgets (buf, sizeof buf, fp) != NULL) { |
---|
355 | fclose (fp); |
---|
356 | if (cp = strchr (buf, '\n')) |
---|
357 | *cp = 0; |
---|
358 | m_putenv ("SIGNATURE", buf); |
---|
359 | } |
---|
360 | } |
---|
361 | #endif /* UCI */ |
---|
362 | |
---|
363 | for (msgnum = 0; msgnum < msgp; msgnum++) |
---|
364 | if (stat (msgs[msgnum], &st) == NOTOK) |
---|
365 | adios (msgs[msgnum], "unable to stat draft file"); |
---|
366 | |
---|
367 | if ((annotext = getenv ("mhannotate")) == NULL || *annotext == 0) |
---|
368 | annotext = NULL; |
---|
369 | if (annotext && ((cp = getenv ("mhinplace")) != NULL && *cp != 0)) |
---|
370 | inplace = atoi (cp); |
---|
371 | if ((altmsg = getenv ("mhaltmsg")) == NULL || *altmsg == 0) |
---|
372 | altmsg = NULL; /* used by dist interface - see below */ |
---|
373 | |
---|
374 | if ((cp = getenv ("mhdist")) |
---|
375 | && *cp |
---|
376 | && (distsw = atoi (cp)) |
---|
377 | && altmsg) { |
---|
378 | vec[vecp++] = "-dist"; |
---|
379 | distfile = getcpy (m_scratch (altmsg, invo_name)); |
---|
380 | if (link (altmsg, distfile) == NOTOK) { |
---|
381 | if (errno != EXDEV |
---|
382 | #ifdef EISREMOTE |
---|
383 | && errno != EISREMOTE |
---|
384 | #endif /* EISREMOTE */ |
---|
385 | ) |
---|
386 | adios (distfile, "unable to link %s to", altmsg); |
---|
387 | free (distfile); |
---|
388 | distfile = getcpy (m_tmpfil (invo_name)); |
---|
389 | { |
---|
390 | int in, out; |
---|
391 | struct stat st; |
---|
392 | |
---|
393 | if ((in = open (altmsg, O_RDONLY)) == NOTOK) |
---|
394 | adios (altmsg, "unable to open"); |
---|
395 | fstat(in, &st); |
---|
396 | if ((out = creat (distfile, (int) st.st_mode & 0777)) == NOTOK) |
---|
397 | adios (distfile, "unable to write"); |
---|
398 | cpydata (in, out, altmsg, distfile); |
---|
399 | close (in); |
---|
400 | close (out); |
---|
401 | } |
---|
402 | } |
---|
403 | } else { |
---|
404 | distfile = NULL; |
---|
405 | } |
---|
406 | |
---|
407 | if (altmsg == NULL || stat (altmsg, &st) == NOTOK) { |
---|
408 | st.st_mtime = 0; |
---|
409 | st.st_dev = 0; |
---|
410 | st.st_ino = 0; |
---|
411 | } |
---|
412 | if (pushsw) |
---|
413 | push (); |
---|
414 | |
---|
415 | status = 0; |
---|
416 | vec[0] = r1bindex (postproc, '/'); |
---|
417 | closefds (3); |
---|
418 | |
---|
419 | for (msgnum = 0; msgnum < msgp; msgnum++) { |
---|
420 | switch (sendsbr (vec, vecp, msgs[msgnum], &st, 1)) { |
---|
421 | case DONE: |
---|
422 | done (++status); |
---|
423 | case NOTOK: |
---|
424 | status++; /* fall */ |
---|
425 | case OK: |
---|
426 | break; |
---|
427 | } |
---|
428 | } |
---|
429 | |
---|
430 | context_save (); /* save the context file */ |
---|
431 | done (status); |
---|
432 | } |
---|