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