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