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