Refactor: Use if for two-way branching; Compare against 0 explicitly
[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 #include <fcntl.h>
14
15
16 static struct swit switches[] = {
17 #define BODYSW  0
18         { "bodytext text", 0 },
19 #define CCSW  1
20         { "cc addrs ...", 0 },
21 #define FROMSW  2
22         { "from addr", 0 },
23 #define SUBJSW  3
24         { "subject text", 0 },
25 #define VERSIONSW  4
26         { "Version", 0 },
27 #define HELPSW  5
28         { "help", 0 },
29         { NULL, 0 }
30 };
31
32 static char tmpfil[BUFSIZ];
33
34 /*
35 ** static prototypes
36 */
37 static void intrser(int);
38
39
40 int
41 main(int argc, char **argv)
42 {
43         int status, iscc = 0, nvec;
44         char *cp, *tolist = NULL, *cclist = NULL, *subject = NULL;
45         char *from = NULL, *body = NULL, **argp, **arguments;
46         char *vec[5], buf[BUFSIZ];
47         FILE *out;
48         char *tfile = NULL;
49
50         setlocale(LC_ALL, "");
51         invo_name = mhbasename(argv[0]);
52
53         /* Without arguments, exit. */
54         if (argc == 1) {
55                 adios(NULL, "no interactive mail shell. Use inc/scan/show instead.");
56         }
57
58         context_read();
59
60         arguments = getarguments(invo_name, argc, argv, 0);
61         argp = arguments;
62
63         while ((cp = *argp++)) {
64                 if (*cp == '-') {
65                         switch (smatch(++cp, switches)) {
66                         case AMBIGSW:
67                                 ambigsw(cp, switches);
68                                 done(1);
69                         case UNKWNSW:
70                                 adios(NULL, "-%s unknown", cp);
71
72                         case HELPSW:
73                                 snprintf(buf, sizeof(buf),
74                                                 "%s addrs... [switches]",
75                                                 invo_name);
76                                 print_help(buf, switches, 0);
77                                 done(1);
78                         case VERSIONSW:
79                                 print_version(invo_name);
80                                 done(1);
81
82                         case FROMSW:
83                                 if (!(from = *argp++) || *from == '-')
84                                         adios(NULL, "missing argument to %s",
85                                                         argp[-2]);
86                                 continue;
87
88                         case BODYSW:
89                                 if (!(body = *argp++) || *body == '-')
90                                         adios(NULL, "missing argument to %s",
91                                                         argp[-2]);
92                                 continue;
93
94                         case CCSW:
95                                 iscc++;
96                                 continue;
97
98                         case SUBJSW:
99                                 if (!(subject = *argp++) || *subject == '-')
100                                         adios(NULL, "missing argument to %s",
101                                                         argp[-2]);
102                                 continue;
103                         }
104                 }
105                 if (iscc)
106                         cclist = cclist ? add(cp, add(", ", cclist)) :
107                                         getcpy(cp);
108                 else
109                         tolist = tolist ? add(cp, add(", ", tolist)) :
110                                         getcpy(cp);
111         }
112
113         if (tolist == NULL)
114                 adios(NULL, "usage: %s addrs ... [switches]", invo_name);
115
116         tfile = m_mktemp2("/tmp/", invo_name, NULL, &out);
117         if (tfile == NULL)
118                 adios("mhmail", "unable to create temporary file");
119         chmod(tfile, 0600);
120         strncpy(tmpfil, tfile, sizeof(tmpfil));
121
122         SIGNAL2(SIGINT, intrser);
123
124         fprintf(out, "To: %s\n", tolist);
125         if (cclist)
126                 fprintf(out, "Cc: %s\n", cclist);
127         if (subject)
128                 fprintf(out, "Subject: %s\n", subject);
129         if (from)
130                 fprintf(out, "From: %s\n", from);
131         fputs("\n", out);
132
133         if (body) {
134                 fprintf(out, "%s", body);
135                 if (*body && body[strlen(body) - 1] != '\n')
136                         fputs("\n", out);
137         } else {
138                 int empty = 1;
139
140                 while (fgets(buf, sizeof buf, stdin)) {
141                         if (buf[0]=='.' && buf[1]=='\n') {
142                                 /* A period alone on a line means EOF. */
143                                 break;
144                         }
145                         empty = 0;
146                         if (fputs(buf, out) == EOF) {
147                                 adios(tmpfil, "error writing");
148                         }
149                 }
150                 if (empty) {
151                         unlink(tmpfil);
152                         adios(NULL, "not sending message with empty body");
153                 }
154         }
155         fclose(out);
156
157         nvec = 0;
158         vec[nvec++] = "spost";
159         vec[nvec++] = tmpfil;
160         vec[nvec] = NULL;
161
162         if ((status = execprog(*vec, vec))) {
163                 /* spost failed, save draft as dead.letter */
164                 int in, out;
165
166                 in = open(tmpfil, O_RDONLY);
167                 out = creat("dead.letter", 0600);
168                 if (in == -1 || out == -1) {
169                         fprintf(stderr, "Letter left at %s.\n",
170                                         tmpfil);
171                         done(status ? 1 : 0);
172                 }
173                 cpydata(in, out, tmpfil, "dead.letter");
174                 close(in);
175                 close(out);
176                 fprintf(stderr, "Letter saved in dead.letter\n");
177         }
178         unlink(tmpfil);
179         done(status ? 1 : 0);
180         return 0;  /* dead code to satisfy the compiler */
181 }
182
183
184 static void
185 intrser(int i)
186 {
187         unlink(tmpfil);
188         done(i != 0 ? 1 : 0);
189 }
190