.RB [ \-list " | " \-nolist ]
.RB [ \-realsize " | " \-norealsize ]
.RB [ \-headers " | " \-noheaders ]
+.RB [ \-directives " | " \-nodirectives ]
.RB [ \-ebcdicsafe " | " \-noebcdicsafe ]
.RB [ \-rfc934mode " | " \-norfc934mode ]
.RB [ \-contentid " | " \-nocontentid ]
.fi
.RE
.PP
-There are four kinds of directives: \*(lqtype\*(rq directives, which
+There are five kinds of directives: \*(lqtype\*(rq directives, which
name the type and subtype of the content; \*(lqexternal-type\*(rq
directives, which also name the type and subtype of the content; the
\*(lqmessage\*(rq directive (#forw), which is used to forward one or
-more messages; and, the \*(lqbegin\*(rq directive (#begin), which is
-used to create a multipart content.
+more messages; the \*(lqbegin\*(rq directive (#begin), which is
+used to create a multipart content; and the \*(lqon/off/pop\*(rq
+directives (#on, #off, #pop) which control whether any other
+directives are honored at all.
+.PP
+The
+.B \-directives
+switch allows control over whether mhbuild will honor any of the
+\*(lq#\*(rq-directives. This can also be affected with the #on or
+#off directives, and #pop, which restores the state of processing to
+that preceding the most recent #on or #off. (The #on, #off, and #pop
+directives are always honored, of course.) This allows inclusion of
+plain text which looks like mhbuild directives, without causing
+errors:
+.PP
+.RS 5
+.nf
+#off
+#include <stdio.h>
+
+printf("Hello, World!);
+#pop
+.fi
+.RE
+.PP
+Currently the stack depth for the #on/off/pop directives is 32.
.PP
The \*(lqtype\*(rq directive is used to directly specify the type and
subtype of a content. You may only specify discrete types in this manner
{ "check", 0 },
#define NCHECKSW 1
{ "nocheck", 0 },
-#define EBCDICSW 2
+#define DIRECTIVES 2
+ { "directives", 0 },
+#define NDIRECTIVES 3
+ { "nodirectives", 0 },
+#define EBCDICSW 4
{ "ebcdicsafe", 0 },
-#define NEBCDICSW 3
+#define NEBCDICSW 5
{ "noebcdicsafe", 0 },
-#define HEADSW 4
+#define HEADSW 6
{ "headers", 0 },
-#define NHEADSW 5
+#define NHEADSW 7
{ "noheaders", 0 },
-#define LISTSW 6
+#define LISTSW 8
{ "list", 0 },
-#define NLISTSW 7
+#define NLISTSW 9
{ "nolist", 0 },
-#define SIZESW 8
+#define SIZESW 10
{ "realsize", 0 },
-#define NSIZESW 9
+#define NSIZESW 11
{ "norealsize", 0 },
-#define RFC934SW 10
+#define RFC934SW 12
{ "rfc934mode", 0 },
-#define NRFC934SW 11
+#define NRFC934SW 13
{ "norfc934mode", 0 },
-#define VERBSW 12
+#define VERBSW 14
{ "verbose", 0 },
-#define NVERBSW 13
+#define NVERBSW 15
{ "noverbose", 0 },
-#define RCACHESW 14
+#define RCACHESW 16
{ "rcache policy", 0 },
-#define WCACHESW 15
+#define WCACHESW 17
{ "wcache policy", 0 },
-#define CONTENTIDSW 16
+#define CONTENTIDSW 18
{ "contentid", 0 },
-#define NCONTENTIDSW 17
+#define NCONTENTIDSW 19
{ "nocontentid", 0 },
-#define VERSIONSW 18
+#define VERSIONSW 20
{ "version", 0 },
-#define HELPSW 19
+#define HELPSW 21
{ "help", 0 },
-#define DEBUGSW 20
+#define DEBUGSW 22
{ "debug", -5 },
{ NULL, 0 }
};
static void unlink_done (int) NORETURN;
/* mhbuildsbr.c */
-CT build_mime (char *);
+CT build_mime (char *, int);
int output_message (CT, char *);
int output_message_fp (CT, FILE *, char*);
int
main (int argc, char **argv)
{
- int sizesw = 1, headsw = 1;
+ int sizesw = 1, headsw = 1, directives = 1;
int *icachesw;
char *cp, buf[BUFSIZ];
char buffer[BUFSIZ], *compfile = NULL;
headsw = 0;
continue;
+ case DIRECTIVES:
+ directives = 1;
+ continue;
+ case NDIRECTIVES:
+ directives = 0;
+ continue;
+
case LISTSW:
listsw++;
continue;
unlink_infile = 1;
/* build the content structures for MIME message */
- ct = build_mime (infile);
+ ct = build_mime (infile, directives);
cts[0] = ct;
cts[1] = NULL;
*/
/* build the content structures for MIME message */
- ct = build_mime (compfile);
+ ct = build_mime (compfile, directives);
cts[0] = ct;
cts[1] = NULL;
/*
* prototypes
*/
-CT build_mime (char *);
+CT build_mime (char *, int);
/*
* static prototypes
static char *calculate_digest (CT, int);
+static unsigned char directives_stack[32];
+static unsigned int directives_index;
+
+static int do_direct(void)
+{
+ return directives_stack[directives_index];
+}
+
+static void directive_onoff(int onoff)
+{
+ if (directives_index >= sizeof(directives_stack)) {
+ fprintf(stderr, "mhbuild: #on/off overflow, continuing\n");
+ return;
+ }
+ directives_stack[++directives_index] = onoff;
+}
+
+static void directive_init(int onoff)
+{
+ directives_index = 0;
+ directives_stack[0] = onoff;
+}
+
+static void directive_pop(void)
+{
+ if (directives_index > 0)
+ directives_index--;
+ else
+ fprintf(stderr, "mhbuild: #pop underflow, continuing\n");
+}
+
/*
* Main routine for translating composition file
* into valid MIME message. It translates the draft
*/
CT
-build_mime (char *infile)
+build_mime (char *infile, int directives)
{
int compnum, state;
char buf[BUFSIZ], name[NAMESZ];
CT ct;
FILE *in;
+ directive_init(directives);
+
umask (~m_gmprot ());
/* open the composition draft */
fgetstr (char *s, int n, FILE *stream)
{
char *cp, *ep;
+ int o_n = n;
+
+ while(1) {
+ for (ep = (cp = s) + o_n; cp < ep; ) {
+ int i;
- for (ep = (cp = s) + n; cp < ep; ) {
- int i;
+ if (!fgets (cp, n, stream))
+ return (cp != s ? s : NULL);
- if (!fgets (cp, n, stream))
- return (cp != s ? s : NULL);
- if (cp == s && *cp != '#')
- return s;
+ if (cp == s && *cp != '#')
+ return s;
- cp += (i = strlen (cp)) - 1;
- if (i <= 1 || *cp-- != '\n' || *cp != '\\')
+ cp += (i = strlen (cp)) - 1;
+ if (i <= 1 || *cp-- != '\n' || *cp != '\\')
+ break;
+ *cp = '\0';
+ n -= (i - 2);
+ }
+
+ if (strcmp(s, "#on\n") == 0) {
+ directive_onoff(1);
+ } else if (strcmp(s, "#off\n") == 0) {
+ directive_onoff(0);
+ } else if (strcmp(s, "#pop\n") == 0) {
+ directive_pop();
+ } else {
break;
- *cp = '\0';
- n -= (i - 2);
+ }
}
return s;
CT ct;
CE ce;
- if (buf[0] == '\n' || strcmp (buf, "#\n") == 0) {
+ if (buf[0] == '\n' || (do_direct() && strcmp (buf, "#\n") == 0)) {
*ctp = NULL;
return OK;
}
* 2) begins with "##" (implicit directive)
* 3) begins with "#<"
*/
- if (buf[0] != '#' || buf[1] == '#' || buf[1] == '<') {
+ if (!do_direct() || buf[0] != '#' || buf[1] == '#' || buf[1] == '<') {
int headers;
int inlineD;
long pos;
ce->ce_file = add (cp, NULL);
ce->ce_unlink = 1;
- if (buf[0] == '#' && buf[1] == '<') {
+ if (do_direct() && (buf[0] == '#' && buf[1] == '<')) {
strncpy (content, buf + 2, sizeof(content));
inlineD = 1;
goto rock_and_roll;
/* the directive is implicit */
strncpy (content, "text/plain", sizeof(content));
headers = 0;
- strncpy (buffer, buf[0] != '#' ? buf : buf + 1, sizeof(buffer));
+ strncpy (buffer, (!do_direct() || buf[0] != '#') ? buf : buf + 1, sizeof(buffer));
for (;;) {
int i;
- if (headers >= 0 && uprf (buffer, DESCR_FIELD)
+ if (headers >= 0 && do_direct() && uprf (buffer, DESCR_FIELD)
&& buffer[i = strlen (DESCR_FIELD)] == ':') {
headers = 1;
}
}
- if (headers >= 0 && uprf (buffer, DISPO_FIELD)
+ if (headers >= 0 && do_direct() && uprf (buffer, DISPO_FIELD)
&& buffer[i = strlen (DISPO_FIELD)] == ':') {
headers = 1;
pos = ftell (in);
if ((cp = fgetstr (buffer, sizeof(buffer) - 1, in)) == NULL)
break;
- if (buffer[0] == '#') {
+ if (do_direct() && buffer[0] == '#') {
char *bp;
if (buffer[1] != '#')