-
/*
- * mhbuild.c -- expand/translate MIME composition files
- *
- * $Id$
- *
- * This code is Copyright (c) 2002, by the authors of nmh. See the
- * COPYRIGHT file in the root directory of the nmh distribution for
- * complete copyright information.
- */
+** mhbuild.c -- expand/translate MIME composition files
+**
+** This code is Copyright (c) 2002, by the authors of nmh. See the
+** COPYRIGHT file in the root directory of the nmh distribution for
+** complete copyright information.
+*/
#include <h/mh.h>
#include <fcntl.h>
#include <h/mime.h>
#include <h/mhparse.h>
#include <h/mhcachesbr.h>
+#include <h/utils.h>
#ifdef HAVE_SYS_WAIT_H
# include <sys/wait.h>
#endif
static struct swit switches[] = {
-#define CHECKSW 0
- { "check", 0 },
-#define NCHECKSW 1
- { "nocheck", 0 },
-#define EBCDICSW 2
- { "ebcdicsafe", 0 },
-#define NEBCDICSW 3
- { "noebcdicsafe", 0 },
-#define HEADSW 4
- { "headers", 0 },
-#define NHEADSW 5
- { "noheaders", 0 },
-#define LISTSW 6
- { "list", 0 },
-#define NLISTSW 7
- { "nolist", 0 },
-#define SIZESW 8
- { "realsize", 0 },
-#define NSIZESW 9
- { "norealsize", 0 },
-#define RFC934SW 10
- { "rfc934mode", 0 },
-#define NRFC934SW 11
- { "norfc934mode", 0 },
-#define VERBSW 12
- { "verbose", 0 },
-#define NVERBSW 13
- { "noverbose", 0 },
-#define RCACHESW 14
- { "rcache policy", 0 },
-#define WCACHESW 15
- { "wcache policy", 0 },
-#define VERSIONSW 16
- { "version", 0 },
-#define HELPSW 17
- { "help", 0 },
-#define DEBUGSW 18
- { "debug", -5 },
- { NULL, 0 }
+#define CHECKSW 0
+ { "check", 0 },
+#define NCHECKSW 1
+ { "nocheck", 0 },
+#define EBCDICSW 2
+ { "ebcdicsafe", 0 },
+#define NEBCDICSW 3
+ { "noebcdicsafe", 0 },
+#define HEADSW 4
+ { "headers", 0 },
+#define NHEADSW 5
+ { "noheaders", 0 },
+#define LISTSW 6
+ { "list", 0 },
+#define NLISTSW 7
+ { "nolist", 0 },
+#define SIZESW 8
+ { "realsize", 0 },
+#define NSIZESW 9
+ { "norealsize", 0 },
+#define RFC934SW 10
+ { "rfc934mode", 0 },
+#define NRFC934SW 11
+ { "norfc934mode", 0 },
+#define VERBSW 12
+ { "verbose", 0 },
+#define NVERBSW 13
+ { "noverbose", 0 },
+#define RCACHESW 14
+ { "rcache policy", 0 },
+#define WCACHESW 15
+ { "wcache policy", 0 },
+#define CONTENTIDSW 16
+ { "contentid", 0 },
+#define NCONTENTIDSW 17
+ { "nocontentid", 0 },
+#define VERSIONSW 18
+ { "version", 0 },
+#define HELPSW 19
+ { "help", 0 },
+#define DEBUGSW 20
+ { "debug", -5 },
+ { NULL, 0 }
};
/* mhbuildsbr.c */
-extern int checksw;
-extern char *tmp; /* directory to place temp files */
+extern char *tmp; /* directory to place temp files */
/* mhcachesbr.c */
extern int rcachesw;
int ebcdicsw = 0;
int listsw = 0;
int rfc934sw = 0;
+int contentidsw = 1;
/*
- * Temporary files
- */
+** Temporary files
+*/
static char infile[BUFSIZ];
static int unlink_infile = 0;
static char outfile[BUFSIZ];
static int unlink_outfile = 0;
+static void unlink_done(int) NORETURN;
/* mhbuildsbr.c */
-CT build_mime (char *);
-int output_message (CT, char *);
+CT build_mime(char *);
+int output_message(CT, char *);
+int output_message_fp(CT, FILE *, char*);
/* mhlistsbr.c */
-int list_all_messages (CT *, int, int, int, int);
+int list_all_messages(CT *, int, int, int, int);
/* mhmisc.c */
-void set_endian (void);
+void set_endian(void);
/* mhfree.c */
-void free_content (CT);
+void free_content(CT);
int
-main (int argc, char **argv)
+main(int argc, char **argv)
{
- int sizesw = 1, headsw = 1;
- int *icachesw;
- char *cp, buf[BUFSIZ];
- char buffer[BUFSIZ], *compfile = NULL;
- char **argp, **arguments;
- CT ct, cts[2];
- FILE *fp;
+ int sizesw = 1, headsw = 1;
+ int *icachesw;
+ char *cp, buf[BUFSIZ];
+ char buffer[BUFSIZ], *compfile = NULL;
+ char **argp, **arguments;
+ CT ct, cts[2];
+ FILE *fp = NULL;
+ FILE *fp_out = NULL;
+
+ done = unlink_done;
#ifdef LOCALE
- setlocale(LC_ALL, "");
+ setlocale(LC_ALL, "");
#endif
- invo_name = r1bindex (argv[0], '/');
-
- /* read user profile/context */
- context_read();
-
- arguments = getarguments (invo_name, argc, argv, 1);
- argp = arguments;
-
- while ((cp = *argp++)) {
- if (cp[0] == '-' && cp[1] == '\0') {
- if (compfile)
- adios (NULL, "cannot specify both standard input and a file");
- else
- compfile = cp;
- listsw = 0; /* turn off -list if using standard in/out */
- verbosw = 0; /* turn off -verbose listings */
- break;
+ invo_name = mhbasename(argv[0]);
+
+ /* read user profile/context */
+ context_read();
+
+ arguments = getarguments(invo_name, argc, argv, 1);
+ argp = arguments;
+
+ while ((cp = *argp++)) {
+ if (cp[0] == '-' && cp[1] == '\0') {
+ if (compfile)
+ adios(NULL, "cannot specify both standard input and a file");
+ else
+ compfile = cp;
+ listsw = 0; /* turn off -list if using std in/out */
+ verbosw = 0; /* turn off -verbose listings */
+ break;
+ }
+ if (*cp == '-') {
+ switch (smatch(++cp, switches)) {
+ case AMBIGSW:
+ ambigsw(cp, switches);
+ done(1);
+ case UNKWNSW:
+ adios(NULL, "-%s unknown", cp);
+
+ case HELPSW:
+ snprintf(buf, sizeof(buf), "%s [switches] file", invo_name);
+ print_help(buf, switches, 1);
+ done(1);
+ case VERSIONSW:
+ print_version(invo_name);
+ done(1);
+
+ case RCACHESW:
+ icachesw = &rcachesw;
+ goto do_cache;
+ case WCACHESW:
+ icachesw = &wcachesw;
+ do_cache: ;
+ if (!(cp = *argp++) || *cp == '-')
+ adios(NULL, "missing argument to %s",
+ argp[-2]);
+ switch (*icachesw = smatch(cp, caches)) {
+ case AMBIGSW:
+ ambigsw(cp, caches);
+ done(1);
+ case UNKWNSW:
+ adios(NULL, "%s unknown", cp);
+ default:
+ break;
+ }
+ continue;
+
+ case CHECKSW:
+ checksw++;
+ continue;
+ case NCHECKSW:
+ checksw = 0;
+ continue;
+
+ case EBCDICSW:
+ ebcdicsw++;
+ continue;
+ case NEBCDICSW:
+ ebcdicsw = 0;
+ continue;
+
+ case HEADSW:
+ headsw++;
+ continue;
+ case NHEADSW:
+ headsw = 0;
+ continue;
+
+ case LISTSW:
+ listsw++;
+ continue;
+ case NLISTSW:
+ listsw = 0;
+ continue;
+
+ case RFC934SW:
+ rfc934sw++;
+ continue;
+ case NRFC934SW:
+ rfc934sw = 0;
+ continue;
+
+ case SIZESW:
+ sizesw++;
+ continue;
+ case NSIZESW:
+ sizesw = 0;
+ continue;
+
+ case CONTENTIDSW:
+ contentidsw = 1;
+ continue;
+ case NCONTENTIDSW:
+ contentidsw = 0;
+ continue;
+
+ case VERBSW:
+ verbosw++;
+ continue;
+ case NVERBSW:
+ verbosw = 0;
+ continue;
+ case DEBUGSW:
+ debugsw = 1;
+ continue;
+ }
+ }
+ if (compfile)
+ adios(NULL, "only one composition file allowed");
+ else
+ compfile = cp;
}
- if (*cp == '-') {
- switch (smatch (++cp, switches)) {
- case AMBIGSW:
- ambigsw (cp, switches);
- done (1);
- case UNKWNSW:
- adios (NULL, "-%s unknown", cp);
-
- case HELPSW:
- snprintf (buf, sizeof(buf), "%s [switches] file", invo_name);
- print_help (buf, switches, 1);
- done (1);
- case VERSIONSW:
- print_version(invo_name);
- done (1);
-
- case RCACHESW:
- icachesw = &rcachesw;
- goto do_cache;
- case WCACHESW:
- icachesw = &wcachesw;
- do_cache: ;
- if (!(cp = *argp++) || *cp == '-')
- adios (NULL, "missing argument to %s", argp[-2]);
- switch (*icachesw = smatch (cp, caches)) {
- case AMBIGSW:
- ambigsw (cp, caches);
- done (1);
- case UNKWNSW:
- adios (NULL, "%s unknown", cp);
- default:
- break;
+
+ set_endian();
+
+ if ((cp = getenv("MM_NOASK")) && !strcmp(cp, "1"))
+ listsw = 0;
+
+ /*
+ ** Check if we've specified an additional profile
+ */
+ if ((cp = getenv("MHBUILD"))) {
+ if ((fp = fopen(cp, "r"))) {
+ readconfig((struct node **) 0, fp, cp, 0);
+ fclose(fp);
+ } else {
+ admonish("", "unable to read $MHBUILD profile (%s)",
+ cp);
}
- continue;
-
- case CHECKSW:
- checksw++;
- continue;
- case NCHECKSW:
- checksw = 0;
- continue;
-
- case EBCDICSW:
- ebcdicsw++;
- continue;
- case NEBCDICSW:
- ebcdicsw = 0;
- continue;
-
- case HEADSW:
- headsw++;
- continue;
- case NHEADSW:
- headsw = 0;
- continue;
-
- case LISTSW:
- listsw++;
- continue;
- case NLISTSW:
- listsw = 0;
- continue;
-
- case RFC934SW:
- rfc934sw++;
- continue;
- case NRFC934SW:
- rfc934sw = 0;
- continue;
-
- case SIZESW:
- sizesw++;
- continue;
- case NSIZESW:
- sizesw = 0;
- continue;
-
- case VERBSW:
- verbosw++;
- continue;
- case NVERBSW:
- verbosw = 0;
- continue;
- case DEBUGSW:
- debugsw = 1;
- continue;
- }
}
- if (compfile)
- adios (NULL, "only one composition file allowed");
+
+ /*
+ ** Read the standard profile setup
+ */
+ if ((fp = fopen(cp = etcpath("mhn.defaults"), "r"))) {
+ readconfig((struct node **) 0, fp, cp, 0);
+ fclose(fp);
+ }
+
+ /* Check for public cache location */
+ if ((cache_public = context_find(nmhcache)) && *cache_public != '/')
+ cache_public = NULL;
+
+ /* Check for private cache location */
+ if (!(cache_private = context_find(nmhprivcache)))
+ cache_private = ".cache";
+ cache_private = getcpy(toabsdir(cache_private));
+
+ /*
+ ** Check for storage directory. If defined, we
+ ** will store temporary files there. Else we
+ ** store them in standard nmh directory.
+ */
+ if ((cp = context_find(nmhstorage)) && *cp)
+ tmp = concat(cp, "/", invo_name, NULL);
else
- compfile = cp;
- }
-
- set_endian ();
-
- if ((cp = getenv ("MM_NOASK")) && !strcmp (cp, "1"))
- listsw = 0;
-
- /*
- * Check if we've specified an additional profile
- */
- if ((cp = getenv ("MHBUILD"))) {
- if ((fp = fopen (cp, "r"))) {
- readconfig ((struct node **) 0, fp, cp, 0);
- fclose (fp);
- } else {
- admonish ("", "unable to read $MHBUILD profile (%s)", cp);
+ tmp = getcpy(toabsdir(invo_name));
+
+ /* Check if we have a file to process */
+ if (!compfile)
+ adios(NULL, "need to specify a %s composition file",
+ invo_name);
+
+ /*
+ ** Process the composition file from standard input.
+ */
+ if (compfile[0] == '-' && compfile[1] == '\0') {
+ /* copy standard input to temporary file */
+ strncpy(infile, m_mktemp(invo_name, NULL, &fp),
+ sizeof(infile));
+ while (fgets(buffer, BUFSIZ, stdin))
+ fputs(buffer, fp);
+ fclose(fp);
+ unlink_infile = 1;
+
+ /* build the content structures for MIME message */
+ ct = build_mime(infile);
+ cts[0] = ct;
+ cts[1] = NULL;
+
+ /* output MIME message to this temporary file */
+ strncpy(outfile, m_mktemp(invo_name, NULL, &fp_out),
+ sizeof(outfile));
+ unlink_outfile = 1;
+
+ /* output the message */
+ output_message_fp(ct, fp_out, outfile);
+ fclose(fp_out);
+
+ /* output the temp file to standard output */
+ if ((fp = fopen(outfile, "r")) == NULL)
+ adios(outfile, "unable to open");
+ while (fgets(buffer, BUFSIZ, fp))
+ fputs(buffer, stdout);
+ fclose(fp);
+
+ unlink(infile);
+ unlink_infile = 0;
+
+ unlink(outfile);
+ unlink_outfile = 0;
+
+ free_content(ct);
+ done(0);
}
- }
-
- /*
- * Read the standard profile setup
- */
- if ((fp = fopen (cp = etcpath ("mhn.defaults"), "r"))) {
- readconfig ((struct node **) 0, fp, cp, 0);
- fclose (fp);
- }
-
- /* Check for public cache location */
- if ((cache_public = context_find (nmhcache)) && *cache_public != '/')
- cache_public = NULL;
-
- /* Check for private cache location */
- if (!(cache_private = context_find (nmhprivcache)))
- cache_private = ".cache";
- cache_private = getcpy (m_maildir (cache_private));
-
- /*
- * Check for storage directory. If defined, we
- * will store temporary files there. Else we
- * store them in standard nmh directory.
- */
- if ((cp = context_find (nmhstorage)) && *cp)
- tmp = concat (cp, "/", invo_name, NULL);
- else
- tmp = add (m_maildir (invo_name), NULL);
-
- if (!context_find ("path"))
- free (path ("./", TFOLDER));
-
- /* Check if we have a file to process */
- if (!compfile)
- adios (NULL, "need to specify a %s composition file", invo_name);
-
- /*
- * Process the composition file from standard input.
- */
- if (compfile[0] == '-' && compfile[1] == '\0') {
-
- /* copy standard input to temporary file */
- strncpy (infile, m_scratch ("", invo_name), sizeof(infile));
- if ((fp = fopen (infile, "w")) == NULL)
- adios (infile, "unable to open");
- while (fgets (buffer, BUFSIZ, stdin))
- fputs (buffer, fp);
- fclose (fp);
- unlink_infile = 1;
+
+ /*
+ ** Process the composition file from a file.
+ */
/* build the content structures for MIME message */
- ct = build_mime (infile);
+ ct = build_mime(compfile);
cts[0] = ct;
cts[1] = NULL;
/* output MIME message to this temporary file */
- strncpy (outfile, m_scratch ("", invo_name), sizeof(outfile));
+ strncpy(outfile, m_mktemp2(compfile, invo_name, NULL, &fp_out),
+ sizeof(outfile));
unlink_outfile = 1;
/* output the message */
- output_message (ct, outfile);
-
- /* output the temp file to standard output */
- if ((fp = fopen (outfile, "r")) == NULL)
- adios (outfile, "unable to open");
- while (fgets (buffer, BUFSIZ, fp))
- fputs (buffer, stdout);
- fclose (fp);
-
- unlink (infile);
- unlink_infile = 0;
+ output_message_fp(ct, fp_out, outfile);
+ fclose(fp_out);
+
+ /*
+ ** List the message info
+ */
+ if (listsw)
+ list_all_messages(cts, headsw, sizesw, verbosw, debugsw);
+
+ /* Rename composition draft */
+ snprintf(buffer, sizeof(buffer), "%s.orig", m_backup(compfile));
+ if (rename(compfile, buffer) == NOTOK) {
+ adios(compfile, "unable to rename comp draft %s to", buffer);
+ }
- unlink (outfile);
+ /* Rename output file to take its place */
+ if (rename(outfile, compfile) == NOTOK) {
+ advise(outfile, "unable to rename output %s to", compfile);
+ rename(buffer, compfile);
+ done(1);
+ }
unlink_outfile = 0;
- free_content (ct);
- done (0);
- }
-
- /*
- * Process the composition file from a file.
- */
-
- /* build the content structures for MIME message */
- ct = build_mime (compfile);
- cts[0] = ct;
- cts[1] = NULL;
-
- /* output MIME message to this temporary file */
- strncpy (outfile, m_scratch (compfile, invo_name), sizeof(outfile));
- unlink_outfile = 1;
-
- /* output the message */
- output_message (ct, outfile);
-
- /*
- * List the message info
- */
- if (listsw)
- list_all_messages (cts, headsw, sizesw, verbosw, debugsw);
-
- /* Rename composition draft */
- snprintf (buffer, sizeof(buffer), "%s.orig", m_backup (compfile));
- if (rename (compfile, buffer) == NOTOK)
- adios (compfile, "unable to rename %s to", buffer);
-
- /* Rename output file to take its place */
- if (rename (outfile, compfile) == NOTOK) {
- advise (outfile, "unable to rename %s to", compfile);
- rename (buffer, compfile);
- done (1);
- }
- unlink_outfile = 0;
-
- free_content (ct);
- return done (0);
+ free_content(ct);
+ done(0);
+ return 1;
}
-int
-done (int status)
+static void
+unlink_done(int status)
{
- /*
- * Check if we need to remove stray
- * temporary files.
- */
- if (unlink_infile)
- unlink (infile);
- if (unlink_outfile)
- unlink (outfile);
-
- exit (status);
- return 1; /* dead code to satisfy the compiler */
+ /*
+ ** Check if we need to remove stray temporary files.
+ */
+ if (unlink_infile)
+ unlink(infile);
+ if (unlink_outfile)
+ unlink(outfile);
+
+ exit(status);
}