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