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