mhmail: Don't invoke inc when called without arguments.
[mmh] / uip / mhmail.c
1 /*
2 ** mhmail.c -- simple mail program
3 **
4 ** This code is Copyright (c) 2002, by the authors of nmh.  See the
5 ** COPYRIGHT file in the root directory of the nmh distribution for
6 ** complete copyright information.
7 */
8
9 #include <h/mh.h>
10 #include <h/signals.h>
11 #include <h/utils.h>
12 #include <signal.h>
13
14 static struct swit switches[] = {
15 #define BODYSW  0
16         { "body text", 0 },
17 #define CCSW  1
18         { "cc addrs ...", 0 },
19 #define FROMSW  2
20         { "from addr", 0 },
21 #define SUBJSW  3
22         { "subject text", 0 },
23 #define VERSIONSW  4
24         { "version", 0 },
25 #define HELPSW  5
26         { "help", 0 },
27 #define RESNDSW  6
28         { "resent", -6 },
29 #define QUEUESW  7
30         { "queued", -6 },
31         { NULL, 0 }
32 };
33
34 static char tmpfil[BUFSIZ];
35
36 /*
37 ** static prototypes
38 */
39 static RETSIGTYPE intrser(int);
40
41
42 int
43 main(int argc, char **argv)
44 {
45         pid_t child_id;
46         int status, i, iscc = 0, nvec;
47         int queued = 0, resent = 0, somebody;
48         char *cp, *tolist = NULL, *cclist = NULL, *subject = NULL;
49         char *from = NULL, *body = NULL, **argp, **arguments;
50         char *vec[5], buf[BUFSIZ];
51         FILE *out;
52         char *tfile = NULL;
53
54 #ifdef LOCALE
55         setlocale(LC_ALL, "");
56 #endif
57         invo_name = mhbasename(argv[0]);
58
59         /* foil search of user profile/context */
60         if (context_foil(NULL) == -1)
61                 done(1);
62
63         /* Without arguments, exit. */
64         if (argc == 1) {
65                 adios(NULL, "no interactive mail shell. Use inc/scan/show instead.");
66         }
67
68         arguments = getarguments(invo_name, argc, argv, 0);
69         argp = arguments;
70
71         while ((cp = *argp++)) {
72                 if (*cp == '-') {
73                         switch (smatch(++cp, switches)) {
74                         case AMBIGSW:
75                                 ambigsw(cp, switches);
76                                 done(1);
77                         case UNKWNSW:
78                                 adios(NULL, "-%s unknown", cp);
79
80                         case HELPSW:
81                                 snprintf(buf, sizeof(buf),
82                                                 "%s addrs... [switches]",
83                                                 invo_name);
84                                 print_help(buf, switches, 0);
85                                 done(1);
86                         case VERSIONSW:
87                                 print_version(invo_name);
88                                 done(1);
89
90                         case FROMSW:
91                                 if (!(from = *argp++) || *from == '-')
92                                         adios(NULL, "missing argument to %s",
93                                                         argp[-2]);
94                                 continue;
95
96                         case BODYSW:
97                                 if (!(body = *argp++) || *body == '-')
98                                         adios(NULL, "missing argument to %s",
99                                                         argp[-2]);
100                                 continue;
101
102                         case CCSW:
103                                 iscc++;
104                                 continue;
105
106                         case SUBJSW:
107                                 if (!(subject = *argp++) || *subject == '-')
108                                         adios(NULL, "missing argument to %s",
109                                                         argp[-2]);
110                                 continue;
111
112                         case RESNDSW:
113                                 resent++;
114                                 continue;
115
116                         case QUEUESW:
117                                 queued++;
118                                 continue;
119                         }
120                 }
121                 if (iscc)
122                         cclist = cclist ? add(cp, add(", ", cclist)) :
123                                         getcpy(cp);
124                 else
125                         tolist = tolist ? add(cp, add(", ", tolist)) :
126                                         getcpy(cp);
127         }
128
129         if (tolist == NULL)
130                 adios(NULL, "usage: %s addrs ... [switches]", invo_name);
131
132         tfile = m_mktemp2("/tmp/", invo_name, NULL, &out);
133         if (tfile == NULL)
134                 adios("mhmail", "unable to create temporary file");
135         chmod(tfile, 0600);
136         strncpy(tmpfil, tfile, sizeof(tmpfil));
137
138         SIGNAL2(SIGINT, intrser);
139
140         fprintf(out, "%sTo: %s\n", resent ? "Resent-" : "", tolist);
141         if (cclist)
142                 fprintf(out, "%sCc: %s\n", resent ? "Resent-" : "", cclist);
143         if (subject)
144                 fprintf(out, "%sSubject: %s\n", resent ? "Resent-" : "", subject);
145         if (from)
146                 fprintf(out, "%sFrom: %s\n", resent ? "Resent-" : "", from);
147         if (!resent)
148                 fputs("\n", out);
149
150         if (body) {
151                 fprintf(out, "%s", body);
152                 if (*body && *(body + strlen(body) - 1) != '\n')
153                         fputs("\n", out);
154         } else {
155                 for (somebody = 0; (i = fread(buf, sizeof(*buf), sizeof(buf),
156                                 stdin)) > 0; somebody++)
157                         if (fwrite(buf, sizeof(*buf), i, out) != i)
158                                 adios(tmpfil, "error writing");
159                 if (!somebody) {
160                         unlink(tmpfil);
161                         done(1);
162                 }
163         }
164         fclose(out);
165
166         nvec = 0;
167         vec[nvec++] = mhbasename(postproc);
168         vec[nvec++] = tmpfil;
169         if (resent)
170                 vec[nvec++] = "-dist";
171         if (queued)
172                 vec[nvec++] = "-queued";
173         vec[nvec] = NULL;
174
175         if ((child_id = fork()) == NOTOK) {
176                 /* report failure and then send it */
177                 adios(NULL, "unable to fork");
178         } else if (child_id) {
179                 /* parent process */
180                 if ((status = pidXwait(child_id, postproc))) {
181                         fprintf(stderr, "Letter saved in dead.letter\n");
182                         execl("/bin/mv", "mv", tmpfil, "dead.letter", NULL);
183                         execl("/usr/bin/mv", "mv", tmpfil, "dead.letter",
184                                         NULL);
185                         perror("mv");
186                         _exit(-1);
187                 }
188                 unlink(tmpfil);
189                 done(status ? 1 : 0);
190         } else {
191                 /* child process */
192                 execvp(postproc, vec);
193                 fprintf(stderr, "unable to exec ");
194                 perror(postproc);
195                 _exit(-1);
196         }
197
198         return 0;  /* dead code to satisfy the compiler */
199 }
200
201
202 static RETSIGTYPE
203 intrser(int i)
204 {
205 #ifndef RELIABLE_SIGNALS
206         if (i)
207                 SIGNAL(i, SIG_IGN);
208 #endif
209
210         unlink(tmpfil);
211         done(i != 0 ? 1 : 0);
212 }
213