Eliminated compilation warnings.
[mmh] / uip / send.c
1
2 /*
3  * send.c -- send a composed message
4  *
5  * $Id$
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     return done (status);
432 }