]> diplodocus.org Git - nmh/blob - uip/viamail.c
c6dfb2dc275cf80cc71ea0e11edebea139865087
[nmh] / uip / viamail.c
1
2 /*
3 * viamail.c -- send multiple files in a MIME message
4 *
5 * This code is Copyright (c) 2002, by the authors of nmh. See the
6 * COPYRIGHT file in the root directory of the nmh distribution for
7 * complete copyright information.
8 */
9
10 #include <h/mh.h>
11 #include <fcntl.h>
12 #include <h/signals.h>
13 #include <h/md5.h>
14 #include <signal.h>
15 #include <h/mts.h>
16 #include <h/tws.h>
17 #include <h/mime.h>
18 #include <h/mhparse.h>
19
20 #define VIAMAIL_SWITCHES \
21 X("to mailpath", 0, TOSW) \
22 X("from mailpath", 0, FROMSW) \
23 X("subject subject", 0, SUBJECTSW) \
24 X("parameters arguments", 0, PARAMSW) \
25 X("description text", 0, DESCRIPTSW) \
26 X("comment text", 0, COMMENTSW) \
27 X("delay seconds", 0, DELAYSW) \
28 X("verbose", 0, VERBSW) \
29 X("noverbose", 0, NVERBSW) \
30 X("version", 0, VERSIONSW) \
31 X("help", 0, HELPSW) \
32 X("debug", -5, DEBUGSW) \
33
34 #define X(sw, minchars, id) id,
35 DEFINE_SWITCH_ENUM(VIAMAIL);
36 #undef X
37
38 #define X(sw, minchars, id) { sw, minchars, id },
39 DEFINE_SWITCH_ARRAY(VIAMAIL, switches);
40 #undef X
41
42 extern int debugsw;
43 extern int splitsw;
44 extern int verbsw;
45
46 /*
47 * static prototypes
48 */
49 static int via_mail (char *, char *, char *, char *, char *, int, char *);
50
51
52 int
53 main (int argc, char **argv)
54 {
55 int delay = 0;
56 char *f1 = NULL, *f2 = NULL, *f3 = NULL;
57 char *f4 = NULL, *f5 = NULL, *f7 = NULL;
58 static char postpath[PATH_MAX];
59 char *cp, buf[BUFSIZ];
60 char **argp, **arguments;
61
62 #ifdef LOCALE
63 setlocale(LC_ALL, "");
64 #endif
65 invo_name = r1bindex (argv[0], '/');
66
67 /* foil search of user profile/context */
68 if (context_foil (NULL) == -1)
69 done (1);
70
71 arguments = getarguments (invo_name, argc, argv, 0);
72 argp = arguments;
73
74 while ((cp = *argp++)) {
75 if (*cp == '-') {
76 switch (smatch (++cp, switches)) {
77 case AMBIGSW:
78 ambigsw (cp, switches);
79 done (1);
80 case UNKWNSW:
81 adios (NULL, "-%s unknown", cp);
82
83 case HELPSW:
84 snprintf (buf, sizeof(buf), "%s [switches]", invo_name);
85 print_help (buf, switches, 1);
86 done (0);
87 case VERSIONSW:
88 print_version(invo_name);
89 done (0);
90
91 case TOSW:
92 if (!(f1 = *argp++))
93 adios (NULL, "missing argument to %s", argp[-2]);
94 continue;
95 case SUBJECTSW:
96 if (!(f2 = *argp++))
97 adios (NULL, "missing argument to %s", argp[-2]);
98 continue;
99 case PARAMSW:
100 if (!(f3 = *argp++))
101 adios (NULL, "missing argument to %s", argp[-2]);
102 continue;
103 case DESCRIPTSW:
104 if (!(f4 = *argp++))
105 adios (NULL, "missing argument to %s", argp[-2]);
106 continue;
107 case COMMENTSW:
108 if (!(f5 = *argp++))
109 adios (NULL, "missing argument to %s", argp[-2]);
110 continue;
111 case DELAYSW:
112 if (!(cp = *argp++) || *cp == '-')
113 adios (NULL, "missing argument to %s", argp[-2]);
114
115 /*
116 * If there is an error, just reset the delay parameter
117 * to -1. We will set a default delay later.
118 */
119 if (sscanf (cp, "%d", &delay) != 1)
120 delay = -1;
121 continue;
122 case FROMSW:
123 if (!(f7 = *argp++))
124 adios (NULL, "missing argument to %s", argp[-2]);
125 continue;
126
127 case VERBSW:
128 verbsw = 1;
129 continue;
130 case NVERBSW:
131 verbsw = 0;
132 continue;
133
134 case DEBUGSW:
135 debugsw = 1;
136 continue;
137 }
138 }
139 }
140
141 if (!f1)
142 adios (NULL, "missing -viamail \"mailpath\" switch");
143
144 /* viamail doesn't read the context and postproc isn't always what
145 we want, such as when running make distcheck. If we have the
146 absolute path, set postproc to point to post in the same
147 directory as this executable.
148 This could be generalized to handle relative paths (by
149 converting to absolute), to find the full path from PATH given
150 just the basename, and to squash out ../ but it's only needed
151 here. viamail is typically called from sendfiles, which
152 provides the absolute path.
153 */
154 if (argv[0] && argv[0][0] == '/' &&
155 strlen(argv[0]) - 3 < sizeof postpath) {
156 strncpy (postpath, argv[0], sizeof postpath - 1);
157 postpath[sizeof postpath - 1] = '\0';
158 if ((cp = strrchr (postpath, '/'))) {
159 struct stat st;
160
161 *(cp + 1) = '\0';
162 /* strlen ("post") <= sizeof postpath - (cp - postpath) - 2
163 but use strncat just in case the code above changes. */
164 strncat (postpath, "post", sizeof postpath - (cp - postpath) - 2);
165
166 if (stat (postpath, &st) == OK) {
167 postproc = postpath;
168 }
169 }
170 }
171
172 via_mail (f1, f2, f3, f4, f5, delay, f7);
173 return 0; /* dead code to satisfy the compiler */
174 }
175
176
177 /*
178 * VIAMAIL
179 */
180
181 static int
182 via_mail (char *mailsw, char *subjsw, char *parmsw, char *descsw,
183 char *cmntsw, int delay, char *fromsw)
184 {
185 int status, vecp;
186 char tmpfil[BUFSIZ], *program;
187 char **vec;
188 struct stat st;
189 FILE *fp;
190 char *tfile = NULL;
191
192 umask (~m_gmprot ());
193
194 tfile = m_mktemp2(NULL, invo_name, NULL, &fp);
195 if (tfile == NULL) adios("viamail", "unable to create temporary file");
196 chmod(tfile, 0600);
197 strncpy (tmpfil, tfile, sizeof(tmpfil));
198
199 if (!strchr(mailsw, '@'))
200 mailsw = concat (mailsw, "@", LocalName (0), NULL);
201 fprintf (fp, "To: %s\n", mailsw);
202
203 if (subjsw)
204 fprintf (fp, "Subject: %s\n", subjsw);
205
206 if (fromsw) {
207 if (!strchr(fromsw, '@'))
208 fromsw = concat (fromsw, "@", LocalName (0), NULL);
209 fprintf (fp, "From: %s\n", fromsw);
210 }
211
212 fprintf (fp, "%s: %s\n", VRSN_FIELD, VRSN_VALUE);
213 fprintf (fp, "%s: application/octet-stream", TYPE_FIELD);
214
215 if (parmsw)
216 fprintf (fp, "; %s", parmsw);
217
218 if (cmntsw)
219 fprintf (fp, "\n\t(%s)", cmntsw);
220
221 if (descsw)
222 fprintf (fp, "\n%s: %s", DESCR_FIELD, descsw);
223
224 fprintf (fp, "\n%s: %s\n\n", ENCODING_FIELD, "base64");
225
226 if (fflush (fp))
227 adios (tmpfil, "error writing to");
228
229 writeBase64aux (stdin, fp);
230 if (fflush (fp))
231 adios (tmpfil, "error writing to");
232
233 if (fstat (fileno (fp), &st) == NOTOK)
234 adios ("failed", "fstat of %s", tmpfil);
235
236 if (delay < 0)
237 splitsw = 10;
238 else
239 splitsw = delay;
240
241 status = 0;
242
243 vec = argsplit(postproc, &program, &vecp);
244 if (verbsw)
245 vec[vecp++] = "-verbose";
246
247 switch (sendsbr (vec, vecp, program, tmpfil, &st, 0, (char *)0, 0)) {
248 case DONE:
249 case NOTOK:
250 status++;
251 break;
252 case OK:
253 break;
254 }
255
256 fclose (fp);
257 if (unlink (tmpfil) == -1)
258 advise (NULL, "unable to remove temp file %s", tmpfil);
259 done (status);
260 return 1;
261 }