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