]> diplodocus.org Git - nmh/blob - uip/mhbuild.c
Cope with sasl_decode64() returning SASL_CONTINUE as well as SASL_OK.
[nmh] / uip / mhbuild.c
1
2 /*
3 * mhbuild.c -- expand/translate MIME composition files
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 #include <h/mhcachesbr.h>
23 #include <h/utils.h>
24
25 #ifdef HAVE_SYS_WAIT_H
26 # include <sys/wait.h>
27 #endif
28
29 static struct swit switches[] = {
30 #define CHECKSW 0
31 { "check", 0 },
32 #define NCHECKSW 1
33 { "nocheck", 0 },
34 #define EBCDICSW 2
35 { "ebcdicsafe", 0 },
36 #define NEBCDICSW 3
37 { "noebcdicsafe", 0 },
38 #define HEADSW 4
39 { "headers", 0 },
40 #define NHEADSW 5
41 { "noheaders", 0 },
42 #define LISTSW 6
43 { "list", 0 },
44 #define NLISTSW 7
45 { "nolist", 0 },
46 #define SIZESW 8
47 { "realsize", 0 },
48 #define NSIZESW 9
49 { "norealsize", 0 },
50 #define RFC934SW 10
51 { "rfc934mode", 0 },
52 #define NRFC934SW 11
53 { "norfc934mode", 0 },
54 #define VERBSW 12
55 { "verbose", 0 },
56 #define NVERBSW 13
57 { "noverbose", 0 },
58 #define RCACHESW 14
59 { "rcache policy", 0 },
60 #define WCACHESW 15
61 { "wcache policy", 0 },
62 #define CONTENTIDSW 16
63 { "contentid", 0 },
64 #define NCONTENTIDSW 17
65 { "nocontentid", 0 },
66 #define VERSIONSW 18
67 { "version", 0 },
68 #define HELPSW 19
69 { "help", 0 },
70 #define DEBUGSW 20
71 { "debug", -5 },
72 { NULL, 0 }
73 };
74
75
76 /* mhbuildsbr.c */
77 extern int checksw;
78 extern char *tmp; /* directory to place temp files */
79
80 /* mhcachesbr.c */
81 extern int rcachesw;
82 extern int wcachesw;
83 extern char *cache_public;
84 extern char *cache_private;
85
86 int debugsw = 0;
87 int verbosw = 0;
88
89 int ebcdicsw = 0;
90 int listsw = 0;
91 int rfc934sw = 0;
92 int contentidsw = 1;
93
94 /*
95 * Temporary files
96 */
97 static char infile[BUFSIZ];
98 static int unlink_infile = 0;
99
100 static char outfile[BUFSIZ];
101 static int unlink_outfile = 0;
102
103 static void unlink_done (int);
104
105 /* mhbuildsbr.c */
106 CT build_mime (char *);
107 int output_message (CT, char *);
108
109 /* mhlistsbr.c */
110 int list_all_messages (CT *, int, int, int, int);
111
112 /* mhmisc.c */
113 void set_endian (void);
114
115 /* mhfree.c */
116 void free_content (CT);
117
118
119 int
120 main (int argc, char **argv)
121 {
122 int sizesw = 1, headsw = 1;
123 int *icachesw;
124 char *cp, buf[BUFSIZ];
125 char buffer[BUFSIZ], *compfile = NULL;
126 char **argp, **arguments;
127 CT ct, cts[2];
128 FILE *fp;
129
130 done=unlink_done;
131
132 #ifdef LOCALE
133 setlocale(LC_ALL, "");
134 #endif
135 invo_name = r1bindex (argv[0], '/');
136
137 /* read user profile/context */
138 context_read();
139
140 arguments = getarguments (invo_name, argc, argv, 1);
141 argp = arguments;
142
143 while ((cp = *argp++)) {
144 if (cp[0] == '-' && cp[1] == '\0') {
145 if (compfile)
146 adios (NULL, "cannot specify both standard input and a file");
147 else
148 compfile = cp;
149 listsw = 0; /* turn off -list if using standard in/out */
150 verbosw = 0; /* turn off -verbose listings */
151 break;
152 }
153 if (*cp == '-') {
154 switch (smatch (++cp, switches)) {
155 case AMBIGSW:
156 ambigsw (cp, switches);
157 done (1);
158 case UNKWNSW:
159 adios (NULL, "-%s unknown", cp);
160
161 case HELPSW:
162 snprintf (buf, sizeof(buf), "%s [switches] file", invo_name);
163 print_help (buf, switches, 1);
164 done (1);
165 case VERSIONSW:
166 print_version(invo_name);
167 done (1);
168
169 case RCACHESW:
170 icachesw = &rcachesw;
171 goto do_cache;
172 case WCACHESW:
173 icachesw = &wcachesw;
174 do_cache: ;
175 if (!(cp = *argp++) || *cp == '-')
176 adios (NULL, "missing argument to %s", argp[-2]);
177 switch (*icachesw = smatch (cp, caches)) {
178 case AMBIGSW:
179 ambigsw (cp, caches);
180 done (1);
181 case UNKWNSW:
182 adios (NULL, "%s unknown", cp);
183 default:
184 break;
185 }
186 continue;
187
188 case CHECKSW:
189 checksw++;
190 continue;
191 case NCHECKSW:
192 checksw = 0;
193 continue;
194
195 case EBCDICSW:
196 ebcdicsw++;
197 continue;
198 case NEBCDICSW:
199 ebcdicsw = 0;
200 continue;
201
202 case HEADSW:
203 headsw++;
204 continue;
205 case NHEADSW:
206 headsw = 0;
207 continue;
208
209 case LISTSW:
210 listsw++;
211 continue;
212 case NLISTSW:
213 listsw = 0;
214 continue;
215
216 case RFC934SW:
217 rfc934sw++;
218 continue;
219 case NRFC934SW:
220 rfc934sw = 0;
221 continue;
222
223 case SIZESW:
224 sizesw++;
225 continue;
226 case NSIZESW:
227 sizesw = 0;
228 continue;
229
230 case CONTENTIDSW:
231 contentidsw = 1;
232 continue;
233 case NCONTENTIDSW:
234 contentidsw = 0;
235 continue;
236
237 case VERBSW:
238 verbosw++;
239 continue;
240 case NVERBSW:
241 verbosw = 0;
242 continue;
243 case DEBUGSW:
244 debugsw = 1;
245 continue;
246 }
247 }
248 if (compfile)
249 adios (NULL, "only one composition file allowed");
250 else
251 compfile = cp;
252 }
253
254 set_endian ();
255
256 if ((cp = getenv ("MM_NOASK")) && !strcmp (cp, "1"))
257 listsw = 0;
258
259 /*
260 * Check if we've specified an additional profile
261 */
262 if ((cp = getenv ("MHBUILD"))) {
263 if ((fp = fopen (cp, "r"))) {
264 readconfig ((struct node **) 0, fp, cp, 0);
265 fclose (fp);
266 } else {
267 admonish ("", "unable to read $MHBUILD profile (%s)", cp);
268 }
269 }
270
271 /*
272 * Read the standard profile setup
273 */
274 if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) {
275 readconfig ((struct node **) 0, fp, cp, 0);
276 fclose (fp);
277 }
278
279 /* Check for public cache location */
280 if ((cache_public = context_find (nmhcache)) && *cache_public != '/')
281 cache_public = NULL;
282
283 /* Check for private cache location */
284 if (!(cache_private = context_find (nmhprivcache)))
285 cache_private = ".cache";
286 cache_private = getcpy (m_maildir (cache_private));
287
288 /*
289 * Check for storage directory. If defined, we
290 * will store temporary files there. Else we
291 * store them in standard nmh directory.
292 */
293 if ((cp = context_find (nmhstorage)) && *cp)
294 tmp = concat (cp, "/", invo_name, NULL);
295 else
296 tmp = add (m_maildir (invo_name), NULL);
297
298 if (!context_find ("path"))
299 free (path ("./", TFOLDER));
300
301 /* Check if we have a file to process */
302 if (!compfile)
303 adios (NULL, "need to specify a %s composition file", invo_name);
304
305 /*
306 * Process the composition file from standard input.
307 */
308 if (compfile[0] == '-' && compfile[1] == '\0') {
309
310 /* copy standard input to temporary file */
311 strncpy (infile, m_scratch ("", invo_name), sizeof(infile));
312 if ((fp = fopen (infile, "w")) == NULL)
313 adios (infile, "unable to open");
314 while (fgets (buffer, BUFSIZ, stdin))
315 fputs (buffer, fp);
316 fclose (fp);
317 unlink_infile = 1;
318
319 /* build the content structures for MIME message */
320 ct = build_mime (infile);
321 cts[0] = ct;
322 cts[1] = NULL;
323
324 /* output MIME message to this temporary file */
325 strncpy (outfile, m_scratch ("", invo_name), sizeof(outfile));
326 unlink_outfile = 1;
327
328 /* output the message */
329 output_message (ct, outfile);
330
331 /* output the temp file to standard output */
332 if ((fp = fopen (outfile, "r")) == NULL)
333 adios (outfile, "unable to open");
334 while (fgets (buffer, BUFSIZ, fp))
335 fputs (buffer, stdout);
336 fclose (fp);
337
338 unlink (infile);
339 unlink_infile = 0;
340
341 unlink (outfile);
342 unlink_outfile = 0;
343
344 free_content (ct);
345 done (0);
346 }
347
348 /*
349 * Process the composition file from a file.
350 */
351
352 /* build the content structures for MIME message */
353 ct = build_mime (compfile);
354 cts[0] = ct;
355 cts[1] = NULL;
356
357 /* output MIME message to this temporary file */
358 strncpy (outfile, m_scratch (compfile, invo_name), sizeof(outfile));
359 unlink_outfile = 1;
360
361 /* output the message */
362 output_message (ct, outfile);
363
364 /*
365 * List the message info
366 */
367 if (listsw)
368 list_all_messages (cts, headsw, sizesw, verbosw, debugsw);
369
370 /* Rename composition draft */
371 snprintf (buffer, sizeof(buffer), "%s.orig", m_backup (compfile));
372 if (rename (compfile, buffer) == NOTOK)
373 adios (compfile, "unable to rename %s to", buffer);
374
375 /* Rename output file to take its place */
376 if (rename (outfile, compfile) == NOTOK) {
377 advise (outfile, "unable to rename %s to", compfile);
378 rename (buffer, compfile);
379 done (1);
380 }
381 unlink_outfile = 0;
382
383 free_content (ct);
384 done (0);
385 return 1;
386 }
387
388
389 static void
390 unlink_done (int status)
391 {
392 /*
393 * Check if we need to remove stray
394 * temporary files.
395 */
396 if (unlink_infile)
397 unlink (infile);
398 if (unlink_outfile)
399 unlink (outfile);
400
401 exit (status);
402 }