]> diplodocus.org Git - nmh/blob - uip/mhbuild.c
fbe2b2c6c5a86fe1efac1542c6b77fab661cf533
[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 char *tmp; /* directory to place temp files */
78
79 /* mhcachesbr.c */
80 extern int rcachesw;
81 extern int wcachesw;
82 extern char *cache_public;
83 extern char *cache_private;
84
85 int debugsw = 0;
86 int verbosw = 0;
87
88 int ebcdicsw = 0;
89 int listsw = 0;
90 int rfc934sw = 0;
91 int contentidsw = 1;
92
93 /*
94 * Temporary files
95 */
96 static char infile[BUFSIZ];
97 static int unlink_infile = 0;
98
99 static char outfile[BUFSIZ];
100 static int unlink_outfile = 0;
101
102 static void unlink_done (int) NORETURN;
103
104 /* mhbuildsbr.c */
105 CT build_mime (char *);
106 int output_message (CT, char *);
107 int output_message_fp (CT, FILE *, 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 = NULL;
129 FILE *fp_out = NULL;
130
131 done=unlink_done;
132
133 #ifdef LOCALE
134 setlocale(LC_ALL, "");
135 #endif
136 invo_name = r1bindex (argv[0], '/');
137
138 /* read user profile/context */
139 context_read();
140
141 arguments = getarguments (invo_name, argc, argv, 1);
142 argp = arguments;
143
144 while ((cp = *argp++)) {
145 if (cp[0] == '-' && cp[1] == '\0') {
146 if (compfile)
147 adios (NULL, "cannot specify both standard input and a file");
148 else
149 compfile = cp;
150 listsw = 0; /* turn off -list if using standard in/out */
151 verbosw = 0; /* turn off -verbose listings */
152 break;
153 }
154 if (*cp == '-') {
155 switch (smatch (++cp, switches)) {
156 case AMBIGSW:
157 ambigsw (cp, switches);
158 done (1);
159 case UNKWNSW:
160 adios (NULL, "-%s unknown", cp);
161
162 case HELPSW:
163 snprintf (buf, sizeof(buf), "%s [switches] file", invo_name);
164 print_help (buf, switches, 1);
165 done (1);
166 case VERSIONSW:
167 print_version(invo_name);
168 done (1);
169
170 case RCACHESW:
171 icachesw = &rcachesw;
172 goto do_cache;
173 case WCACHESW:
174 icachesw = &wcachesw;
175 do_cache: ;
176 if (!(cp = *argp++) || *cp == '-')
177 adios (NULL, "missing argument to %s", argp[-2]);
178 switch (*icachesw = smatch (cp, caches)) {
179 case AMBIGSW:
180 ambigsw (cp, caches);
181 done (1);
182 case UNKWNSW:
183 adios (NULL, "%s unknown", cp);
184 default:
185 break;
186 }
187 continue;
188
189 case CHECKSW:
190 checksw++;
191 continue;
192 case NCHECKSW:
193 checksw = 0;
194 continue;
195
196 case EBCDICSW:
197 ebcdicsw++;
198 continue;
199 case NEBCDICSW:
200 ebcdicsw = 0;
201 continue;
202
203 case HEADSW:
204 headsw++;
205 continue;
206 case NHEADSW:
207 headsw = 0;
208 continue;
209
210 case LISTSW:
211 listsw++;
212 continue;
213 case NLISTSW:
214 listsw = 0;
215 continue;
216
217 case RFC934SW:
218 rfc934sw++;
219 continue;
220 case NRFC934SW:
221 rfc934sw = 0;
222 continue;
223
224 case SIZESW:
225 sizesw++;
226 continue;
227 case NSIZESW:
228 sizesw = 0;
229 continue;
230
231 case CONTENTIDSW:
232 contentidsw = 1;
233 continue;
234 case NCONTENTIDSW:
235 contentidsw = 0;
236 continue;
237
238 case VERBSW:
239 verbosw++;
240 continue;
241 case NVERBSW:
242 verbosw = 0;
243 continue;
244 case DEBUGSW:
245 debugsw = 1;
246 continue;
247 }
248 }
249 if (compfile)
250 adios (NULL, "only one composition file allowed");
251 else
252 compfile = cp;
253 }
254
255 set_endian ();
256
257 if ((cp = getenv ("MM_NOASK")) && !strcmp (cp, "1"))
258 listsw = 0;
259
260 /*
261 * Check if we've specified an additional profile
262 */
263 if ((cp = getenv ("MHBUILD"))) {
264 if ((fp = fopen (cp, "r"))) {
265 readconfig ((struct node **) 0, fp, cp, 0);
266 fclose (fp);
267 } else {
268 admonish ("", "unable to read $MHBUILD profile (%s)", cp);
269 }
270 }
271
272 /*
273 * Read the standard profile setup
274 */
275 if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) {
276 readconfig ((struct node **) 0, fp, cp, 0);
277 fclose (fp);
278 }
279
280 /* Check for public cache location */
281 if ((cache_public = context_find (nmhcache)) && *cache_public != '/')
282 cache_public = NULL;
283
284 /* Check for private cache location */
285 if (!(cache_private = context_find (nmhprivcache)))
286 cache_private = ".cache";
287 cache_private = getcpy (m_maildir (cache_private));
288
289 /*
290 * Check for storage directory. If defined, we
291 * will store temporary files there. Else we
292 * store them in standard nmh directory.
293 */
294 if ((cp = context_find (nmhstorage)) && *cp)
295 tmp = concat (cp, "/", invo_name, NULL);
296 else
297 tmp = add (m_maildir (invo_name), NULL);
298
299 if (!context_find ("path"))
300 free (path ("./", TFOLDER));
301
302 /* Check if we have a file to process */
303 if (!compfile)
304 adios (NULL, "need to specify a %s composition file", invo_name);
305
306 /*
307 * Process the composition file from standard input.
308 */
309 if (compfile[0] == '-' && compfile[1] == '\0') {
310 /* copy standard input to temporary file */
311 strncpy (infile, m_mktemp(invo_name, NULL, &fp), sizeof(infile));
312 while (fgets (buffer, BUFSIZ, stdin))
313 fputs (buffer, fp);
314 fclose (fp);
315 unlink_infile = 1;
316
317 /* build the content structures for MIME message */
318 ct = build_mime (infile);
319 cts[0] = ct;
320 cts[1] = NULL;
321
322 /* output MIME message to this temporary file */
323 strncpy (outfile, m_mktemp(invo_name, NULL, &fp_out), sizeof(outfile));
324 unlink_outfile = 1;
325
326 /* output the message */
327 output_message_fp (ct, fp_out, outfile);
328 fclose(fp_out);
329
330 /* output the temp file to standard output */
331 if ((fp = fopen (outfile, "r")) == NULL)
332 adios (outfile, "unable to open");
333 while (fgets (buffer, BUFSIZ, fp))
334 fputs (buffer, stdout);
335 fclose (fp);
336
337 unlink (infile);
338 unlink_infile = 0;
339
340 unlink (outfile);
341 unlink_outfile = 0;
342
343 free_content (ct);
344 done (0);
345 }
346
347 /*
348 * Process the composition file from a file.
349 */
350
351 /* build the content structures for MIME message */
352 ct = build_mime (compfile);
353 cts[0] = ct;
354 cts[1] = NULL;
355
356 /* output MIME message to this temporary file */
357 strncpy(outfile, m_mktemp2(compfile, invo_name, NULL, &fp_out),
358 sizeof(outfile));
359 unlink_outfile = 1;
360
361 /* output the message */
362 output_message_fp (ct, fp_out, outfile);
363 fclose(fp_out);
364
365 /*
366 * List the message info
367 */
368 if (listsw)
369 list_all_messages (cts, headsw, sizesw, verbosw, debugsw);
370
371 /* Rename composition draft */
372 snprintf (buffer, sizeof(buffer), "%s.orig", m_backup (compfile));
373 if (rename (compfile, buffer) == NOTOK) {
374 adios (compfile, "unable to rename comp draft %s to", buffer);
375 }
376
377 /* Rename output file to take its place */
378 if (rename (outfile, compfile) == NOTOK) {
379 advise (outfile, "unable to rename output %s to", compfile);
380 rename (buffer, compfile);
381 done (1);
382 }
383 unlink_outfile = 0;
384
385 free_content (ct);
386 done (0);
387 return 1;
388 }
389
390
391 static void
392 unlink_done (int status)
393 {
394 /*
395 * Check if we need to remove stray
396 * temporary files.
397 */
398 if (unlink_infile)
399 unlink (infile);
400 if (unlink_outfile)
401 unlink (outfile);
402
403 exit (status);
404 }