From 0503a6e9be34f24858b55b555a5c948182b9f24b Mon Sep 17 00:00:00 2001 From: markus schnalke Date: Thu, 22 Mar 2012 17:07:25 +0100 Subject: [PATCH] Merged mhbuildsbr.c into mhbuild.c, cause it is not used elsewhere. --- create-deps.sh | 1 + deps.png | Bin 0 -> 88393 bytes h/mhparse.h | 2 +- makedeps2dot | 44 ++ uip/Makefile.in | 6 +- uip/mhbuild.c | 1698 +++++++++++++++++++++++++++++++++++++++++++++++++++- uip/mhbuildsbr.c | 1732 ------------------------------------------------------ uip/mhcachesbr.c | 4 +- 8 files changed, 1745 insertions(+), 1742 deletions(-) create mode 100644 create-deps.sh create mode 100644 deps.png create mode 100644 makedeps2dot delete mode 100644 uip/mhbuildsbr.c diff --git a/create-deps.sh b/create-deps.sh new file mode 100644 index 0000000..79f2c0e --- /dev/null +++ b/create-deps.sh @@ -0,0 +1 @@ +cat `find . -name Makefile.in` | awk -f makedeps2dot | dot -Tpng -o /tmp/deps.png diff --git a/deps.png b/deps.png new file mode 100644 index 0000000000000000000000000000000000000000..bb42a9a9d704c82b6541a0d16f2da5251b909d4e GIT binary patch literal 88393 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 \"" $1 "\";" + } + print "" +} + +END { + print "}" +} diff --git a/uip/Makefile.in b/uip/Makefile.in index d81985f..a5ecae8 100644 --- a/uip/Makefile.in +++ b/uip/Makefile.in @@ -66,7 +66,7 @@ SCMDS = inc SRCS = ali.c aliasbr.c anno.c annosbr.c ap.c burst.c comp.c \ conflict.c dist.c distsbr.c dp.c dropsbr.c flist.c fmtdump.c \ folder.c forw.c inc.c mmh.sh mark.c md5.c mhbuild.c \ - mhbuildsbr.c mhcachesbr.c mhfree.c mhl.c mhlist.c mhlistsbr.c \ + mhcachesbr.c mhfree.c mhl.c mhlist.c mhlistsbr.c \ mhmail.c mhmisc.c mhoutsbr.c mhparam.c mhparse.c \ mhpath.c mhshow.c mhshowsbr.c mhstore.c mhstoresbr.c mhtest.c \ msgchk.c new.c packf.c pick.c print-mimetype.sh \ @@ -133,8 +133,8 @@ mmh: mmh.sh mark: mark.o $(LOCALLIBS) $(LINK) mark.o $(LINKLIBS) -mhbuild: mhbuild.o mhbuildsbr.o mhcachesbr.o mhlistsbr.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o termsbr.o md5.o $(LOCALLIBS) - $(LINK) mhbuild.o mhbuildsbr.o mhcachesbr.o mhlistsbr.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o md5.o $(LINKLIBS) $(TERMLIB) +mhbuild: mhbuild.o mhcachesbr.o mhlistsbr.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o termsbr.o md5.o $(LOCALLIBS) + $(LINK) mhbuild.o mhcachesbr.o mhlistsbr.o mhoutsbr.o mhmisc.o mhfree.o mhparse.o md5.o $(LINKLIBS) $(TERMLIB) mhl: mhl.o termsbr.o $(LOCALLIBS) $(LINK) mhl.o termsbr.o $(LINKLIBS) $(TERMLIB) diff --git a/uip/mhbuild.c b/uip/mhbuild.c index 63d7be2..3432ccc 100644 --- a/uip/mhbuild.c +++ b/uip/mhbuild.c @@ -6,6 +6,13 @@ ** complete copyright information. */ +/* +** This code was originally part of mhn.c. I split it into +** a separate program (mhbuild.c). But the code still has some of +** the mhn.c code in it. This program needs additional +** streamlining and removal of unneeded code. +*/ + #include #include #include @@ -18,6 +25,17 @@ #include #include +#ifdef TIME_WITH_SYS_TIME +# include +# include +#else +# ifdef TM_IN_SYS_TIME +# include +# else +# include +# endif +#endif + #ifdef HAVE_SYS_WAIT_H # include #endif @@ -69,8 +87,50 @@ static struct swit switches[] = { }; -/* mhbuildsbr.c */ -extern char *tmp; /* directory to place temp files */ +/* +** Directory to place tmp files. This must +** be set before these routines are called. +*/ +char *tmp; + +pid_t xpid = 0; + +static char prefix[] = "----- =_aaaaaaaaaa"; + + +/* +** prototypes +*/ + +/* mhmisc.c */ +int make_intermediates(char *); +void content_error(char *, CT, char *, ...); + +/* mhcachesbr.c */ +int find_cache(CT, int, int *, char *, char *, int); + +/* ftpsbr.c */ +int ftp_get(char *, char *, char *, char *, char *, char *, int, int); + +/* mhfree.c */ +void free_content(CT); +void free_ctinfo(CT); +void free_encoding(CT, int); + +/* +** static prototypes +*/ +static int init_decoded_content(CT); +static char *fgetstr(char *, int, FILE *); +static int user_content(FILE *, char *, char *, CT *); +static void set_id(CT, int); +static int compose_content(CT); +static int scan_content(CT); +static int build_headers(CT); +static char *calculate_digest(CT, int); +static CT build_mime(char *); + + /* mhcachesbr.c */ extern int rcachesw; @@ -97,8 +157,7 @@ static int unlink_outfile = 0; static void unlink_done(int) NORETURN; -/* mhbuildsbr.c */ -CT build_mime(char *); +/* mhoutsbr.c */ int output_message(CT, char *); int output_message_fp(CT, FILE *, char*); @@ -399,3 +458,1634 @@ unlink_done(int status) exit(status); } + +/* +** Main routine for translating composition file +** into valid MIME message. It translates the draft +** into a content structure (actually a tree of content +** structures). This message then can be manipulated +** in various ways, including being output via +** output_message(). +*/ +static CT +build_mime(char *infile) +{ + int compnum, state; + char buf[BUFSIZ], name[NAMESZ]; + char *cp, *np, *vp; + struct multipart *m; + struct part **pp; + CT ct; + FILE *in; + + umask(~m_gmprot()); + + /* open the composition draft */ + if ((in = fopen(infile, "r")) == NULL) + adios(infile, "unable to open for reading"); + + /* + ** Allocate space for primary (outside) content + */ + if ((ct = (CT) calloc(1, sizeof(*ct))) == NULL) + adios(NULL, "out of memory"); + + /* + ** Allocate structure for handling decoded content + ** for this part. We don't really need this, but + ** allocate it to remain consistent. + */ + init_decoded_content(ct); + + /* + ** Parse some of the header fields in the composition + ** draft into the linked list of header fields for + ** the new MIME message. + */ + for (compnum = 1, state = FLD;;) { + switch (state = m_getfld(state, name, buf, sizeof(buf), in)) { + case FLD: + case FLDPLUS: + case FLDEOF: + compnum++; + + /* abort if draft has Mime-Version header field */ + if (!mh_strcasecmp(name, VRSN_FIELD)) + adios(NULL, "draft shouldn't contain %s: field", VRSN_FIELD); + + /* + ** abort if draft has Content-Transfer-Encoding + ** header field + */ + if (!mh_strcasecmp(name, ENCODING_FIELD)) + adios(NULL, "draft shouldn't contain %s: field", ENCODING_FIELD); + + /* ignore any Content-Type fields in the header */ + if (!mh_strcasecmp(name, TYPE_FIELD)) { + while (state == FLDPLUS) + state = m_getfld(state, name, buf, + sizeof(buf), in); + goto finish_field; + } + + /* get copies of the buffers */ + np = getcpy(name); + vp = getcpy(buf); + + /* if necessary, get rest of field */ + while (state == FLDPLUS) { + state = m_getfld(state, name, buf, + sizeof(buf), in); + vp = add(buf, vp); /* add to prev value */ + } + + /* Now add the header data to the list */ + add_header(ct, np, vp); + +finish_field: + /* if this wasn't the last hdr field, then continue */ + if (state != FLDEOF) + continue; + /* else fall... */ + + case FILEEOF: + adios(NULL, "draft has empty body -- no directives!"); + /* NOTREACHED */ + + case BODY: + case BODYEOF: + fseek(in, (long) (-strlen(buf)), SEEK_CUR); + break; + + case LENERR: + case FMTERR: + adios(NULL, "message format error in component #%d", + compnum); + + default: + adios(NULL, "getfld() returned %d", state); + } + break; + } + + /* + ** Now add the MIME-Version header field + ** to the list of header fields. + */ + np = getcpy(VRSN_FIELD); + vp = concat(" ", VRSN_VALUE, "\n", NULL); + add_header(ct, np, vp); + + /* + ** We initally assume we will find multiple contents in the + ** draft. So create a multipart/mixed content to hold everything. + ** We can remove this later, if it is not needed. + */ + if (get_ctinfo("multipart/mixed", ct, 0) == NOTOK) + done(1); + ct->c_type = CT_MULTIPART; + ct->c_subtype = MULTI_MIXED; + ct->c_file = getcpy(infile); + + if ((m = (struct multipart *) calloc(1, sizeof(*m))) == NULL) + adios(NULL, "out of memory"); + ct->c_ctparams = (void *) m; + pp = &m->mp_parts; + + /* + ** read and parse the composition file + ** and the directives it contains. + */ + while (fgetstr(buf, sizeof(buf) - 1, in)) { + struct part *part; + CT p; + + if (user_content(in, infile, buf, &p) == DONE) { + admonish(NULL, "ignoring spurious #end"); + continue; + } + if (!p) + continue; + + if ((part = (struct part *) calloc(1, sizeof(*part))) == NULL) + adios(NULL, "out of memory"); + *pp = part; + pp = &part->mp_next; + part->mp_part = p; + } + + /* + ** close the composition draft since + ** it's not needed any longer. + */ + fclose(in); + + /* check if any contents were found */ + if (!m->mp_parts) + adios(NULL, "no content directives found"); + + /* + ** If only one content was found, then remove and + ** free the outer multipart content. + */ + if (!m->mp_parts->mp_next) { + CT p; + + p = m->mp_parts->mp_part; + m->mp_parts->mp_part = NULL; + + /* move header fields */ + p->c_first_hf = ct->c_first_hf; + p->c_last_hf = ct->c_last_hf; + ct->c_first_hf = NULL; + ct->c_last_hf = NULL; + + free_content(ct); + ct = p; + } else { + set_id(ct, 1); + } + + /* + ** Fill out, or expand directives. Parse and execute + ** commands specified by profile composition strings. + */ + compose_content(ct); + + if ((cp = strchr(prefix, 'a')) == NULL) + adios(NULL, "internal error(4)"); + + /* + ** Scan the contents. Choose a transfer encoding, and + ** check if prefix for multipart boundary clashes with + ** any of the contents. + */ + while (scan_content(ct) == NOTOK) { + if (*cp < 'z') { + (*cp)++; + } else { + if (*++cp == 0) + adios(NULL, "giving up trying to find a unique delimiter string"); + else + (*cp)++; + } + } + + /* Build the rest of the header field structures */ + build_headers(ct); + + return ct; +} + + +/* +** Set up structures for placing unencoded +** content when building parts. +*/ + +static int +init_decoded_content(CT ct) +{ + CE ce; + + if ((ce = (CE) calloc(1, sizeof(*ce))) == NULL) + adios(NULL, "out of memory"); + + ct->c_cefile = ce; + ct->c_ceopenfnx = open7Bit; /* since unencoded */ + ct->c_ceclosefnx = close_encoding; + ct->c_cesizefnx = NULL; /* since unencoded */ + + return OK; +} + + +static char * +fgetstr(char *s, int n, FILE *stream) +{ + char *cp, *ep; + + for (ep = (cp = s) + n; cp < ep; ) { + int i; + + if (!fgets(cp, n, stream)) + return (cp != s ? s : NULL); + if (cp == s && *cp != '#') + return s; + + cp += (i = strlen(cp)) - 1; + if (i <= 1 || *cp-- != '\n' || *cp != '\\') + break; + *cp = '\0'; + n -= (i - 2); + } + + return s; +} + + +/* +** Parse the composition draft for text and directives. +** Do initial setup of Content structure. +*/ + +static int +user_content(FILE *in, char *file, char *buf, CT *ctp) +{ + int extrnal, vrsn; + unsigned char *cp; + char **ap; + char buffer[BUFSIZ]; + struct multipart *m; + struct part **pp; + struct stat st; + struct str2init *s2i; + CI ci; + CT ct; + CE ce; + + if (buf[0] == '\n' || strcmp(buf, "#\n") == 0) { + *ctp = NULL; + return OK; + } + + /* allocate basic Content structure */ + if ((ct = (CT) calloc(1, sizeof(*ct))) == NULL) + adios(NULL, "out of memory"); + *ctp = ct; + + /* allocate basic structure for handling decoded content */ + init_decoded_content(ct); + ce = ct->c_cefile; + + ci = &ct->c_ctinfo; + set_id(ct, 0); + + /* + ** Handle inline text. Check if line + ** is one of the following forms: + ** + ** 1) doesn't begin with '#' (implicit directive) + ** 2) begins with "##" (implicit directive) + ** 3) begins with "#<" + */ + if (buf[0] != '#' || buf[1] == '#' || buf[1] == '<') { + int headers; + int inlineD; + long pos; + char content[BUFSIZ]; + FILE *out; + char *cp; + + cp = m_mktemp2(NULL, invo_name, NULL, &out); + if (cp == NULL) + adios("mhbuild", "unable to create temporary file"); + + /* use a temp file to collect the plain text lines */ + ce->ce_file = getcpy(cp); + ce->ce_unlink = 1; + + if (buf[0] == '#' && buf[1] == '<') { + strncpy(content, buf + 2, sizeof(content)); + inlineD = 1; + goto rock_and_roll; + } else { + inlineD = 0; + } + + /* the directive is implicit */ + strncpy(content, "text/plain", sizeof(content)); + headers = 0; + strncpy(buffer, buf[0] != '#' ? buf : buf + 1, sizeof(buffer)); + for (;;) { + int i; + + if (headers >= 0 && uprf(buffer, DESCR_FIELD) && + buffer[i=strlen(DESCR_FIELD)] == ':') { + headers = 1; + +again_descr: + ct->c_descr = add(buffer + i + 1, ct->c_descr); + if (!fgetstr(buffer, sizeof(buffer) - 1, in)) + adios(NULL, "end-of-file after %s: field in plaintext", DESCR_FIELD); + switch (buffer[0]) { + case ' ': + case '\t': + i = -1; + goto again_descr; + + case '#': + adios(NULL, "#-directive after %s: field in plaintext", DESCR_FIELD); + /* NOTREACHED */ + + default: + break; + } + } + + if (headers >= 0 && uprf(buffer, DISPO_FIELD) + && buffer[i = strlen(DISPO_FIELD)] == ':') { + headers = 1; + +again_dispo: + ct->c_dispo = add(buffer + i + 1, ct->c_dispo); + if (!fgetstr(buffer, sizeof(buffer) - 1, in)) + adios(NULL, "end-of-file after %s: field in plaintext", DISPO_FIELD); + switch (buffer[0]) { + case ' ': + case '\t': + i = -1; + goto again_dispo; + + case '#': + adios(NULL, "#-directive after %s: field in plaintext", DISPO_FIELD); + /* NOTREACHED */ + + default: + break; + } + } + + if (headers != 1 || buffer[0] != '\n') + fputs(buffer, out); + +rock_and_roll: + headers = -1; + pos = ftell(in); + if ((cp = fgetstr(buffer, sizeof(buffer) - 1, in)) + == NULL) + break; + if (buffer[0] == '#') { + char *bp; + + if (buffer[1] != '#') + break; + for (cp = (bp = buffer) + 1; *cp; cp++) + *bp++ = *cp; + *bp = '\0'; + } + } + + if (listsw) + ct->c_end = ftell(out); + fclose(out); + + /* parse content type */ + if (get_ctinfo(content, ct, inlineD) == NOTOK) + done(1); + + for (s2i = str2cts; s2i->si_key; s2i++) + if (!mh_strcasecmp(ci->ci_type, s2i->si_key)) + break; + if (!s2i->si_key && !uprf(ci->ci_type, "X-")) + s2i++; + + /* + ** check type specified (possibly implicitly) + */ + switch (ct->c_type = s2i->si_val) { + case CT_MESSAGE: + if (!mh_strcasecmp(ci->ci_subtype, "rfc822")) { + ct->c_encoding = CE_7BIT; + goto call_init; + } + /* else fall... */ + case CT_MULTIPART: + adios(NULL, "it doesn't make sense to define an in-line %s content", + ct->c_type == CT_MESSAGE ? "message" : + "multipart"); + /* NOTREACHED */ + + default: +call_init: + if ((ct->c_ctinitfnx = s2i->si_init)) + (*ct->c_ctinitfnx) (ct); + break; + } + + if (cp) + fseek(in, pos, SEEK_SET); + return OK; + } + + /* + ** If we've reached this point, the next line + ** must be some type of explicit directive. + */ + + /* check if directive is external-type */ + extrnal = (buf[1] == '@'); + + /* parse directive */ + if (get_ctinfo(buf + (extrnal ? 2 : 1), ct, 1) == NOTOK) + done(1); + + /* check directive against the list of MIME types */ + for (s2i = str2cts; s2i->si_key; s2i++) + if (!mh_strcasecmp(ci->ci_type, s2i->si_key)) + break; + + /* + ** Check if the directive specified a valid type. + ** This will happen if it was one of the following forms: + ** + ** #type/subtype (or) + ** #@type/subtype + */ + if (s2i->si_key) { + if (!ci->ci_subtype) + adios(NULL, "missing subtype in \"#%s\"", ci->ci_type); + + switch (ct->c_type = s2i->si_val) { + case CT_MULTIPART: + adios(NULL, "use \"#begin ... #end\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); + /* NOTREACHED */ + + case CT_MESSAGE: + if (!mh_strcasecmp(ci->ci_subtype, "partial")) + adios(NULL, "sorry, \"#%s/%s\" isn't supported", ci->ci_type, ci->ci_subtype); + if (!mh_strcasecmp(ci->ci_subtype, "external-body")) + adios(NULL, "use \"#@type/subtype ... [] ...\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); +use_forw: + adios(NULL, "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); + /* NOTREACHED */ + + default: + if ((ct->c_ctinitfnx = s2i->si_init)) + (*ct->c_ctinitfnx) (ct); + break; + } + + /* + ** #@type/subtype (external types directive) + */ + if (extrnal) { + struct exbody *e; + CT p; + + if (!ci->ci_magic) + adios(NULL, "need external information for \"#@%s/%s\"", ci->ci_type, ci->ci_subtype); + p = ct; + + snprintf(buffer, sizeof(buffer), "message/external-body; %s", ci->ci_magic); + free(ci->ci_magic); + ci->ci_magic = NULL; + + /* + ** Since we are using the current Content structure to + ** hold information about the type of the external + ** reference, we need to create another Content + ** structure for the message/external-body to wrap + ** it in. + */ + if ((ct = (CT) calloc(1, sizeof(*ct))) == NULL) + adios(NULL, "out of memory"); + *ctp = ct; + ci = &ct->c_ctinfo; + if (get_ctinfo(buffer, ct, 0) == NOTOK) + done(1); + ct->c_type = CT_MESSAGE; + ct->c_subtype = MESSAGE_EXTERNAL; + + if ((e = (struct exbody *) + calloc(1, sizeof(*e))) == NULL) + adios(NULL, "out of memory"); + ct->c_ctparams = (void *) e; + + e->eb_parent = ct; + e->eb_content = p; + p->c_ctexbody = e; + + if (params_external(ct, 1) == NOTOK) + done(1); + + return OK; + } + + /* Handle [file] argument */ + if (ci->ci_magic) { + /* check if specifies command to execute */ + if (*ci->ci_magic == '|' || *ci->ci_magic == '!') { + for (cp = ci->ci_magic + 1; isspace(*cp); cp++) + continue; + if (!*cp) + adios(NULL, "empty pipe command for #%s directive", ci->ci_type); + cp = getcpy(cp); + free(ci->ci_magic); + ci->ci_magic = cp; + } else { + /* record filename of decoded contents */ + ce->ce_file = ci->ci_magic; + if (access(ce->ce_file, R_OK) == NOTOK) + adios("reading", "unable to access %s for", ce->ce_file); + if (listsw && stat(ce->ce_file, &st) != NOTOK) + ct->c_end = (long) st.st_size; + ci->ci_magic = NULL; + } + return OK; + } + + /* + ** No [file] argument, so check profile for + ** method to compose content. + */ + snprintf(buffer, sizeof(buffer), "%s-compose-%s/%s", + invo_name, ci->ci_type, ci->ci_subtype); + if ((cp = context_find(buffer)) == NULL || *cp == '\0') { + snprintf(buffer, sizeof(buffer), "%s-compose-%s", + invo_name, ci->ci_type); + if ((cp = context_find(buffer)) == NULL || + *cp == '\0') { + content_error(NULL, ct, "don't know how to compose content"); + done(1); + } + } + ci->ci_magic = getcpy(cp); + return OK; + } + + if (extrnal) + adios(NULL, "external definition not allowed for \"#%s\"", + ci->ci_type); + + /* + ** Message directive + ** #forw [+folder] [msgs] + */ + if (!mh_strcasecmp(ci->ci_type, "forw")) { + int msgnum; + char *folder, *arguments[MAXARGS]; + struct msgs *mp; + + if (ci->ci_magic) { + ap = brkstring(ci->ci_magic, " ", "\n"); + copyip(ap, arguments, MAXARGS); + } else { + arguments[0] = seq_cur; + arguments[1] = NULL; + } + folder = NULL; + + /* search the arguments for a folder name */ + for (ap = arguments; *ap; ap++) { + cp = *ap; + if (*cp == '+' || *cp == '@') { + if (folder) + adios(NULL, "only one folder per #forw directive"); + else + folder = getcpy(expandfol(cp)); + } + } + + /* else, use the current folder */ + if (!folder) + folder = getcpy(getcurfol()); + + if (!(mp = folder_read(folder))) + adios(NULL, "unable to read folder %s", folder); + for (ap = arguments; *ap; ap++) { + cp = *ap; + if (*cp != '+' && *cp != '@') + if (!m_convert(mp, cp)) + done(1); + } + free(folder); + free_ctinfo(ct); + + /* + ** If there is more than one message to include, make this + ** a content of type "multipart/digest" and insert each message + ** as a subpart. If there is only one message, then make this + ** a content of type "message/rfc822". + */ + if (mp->numsel > 1) { + /* we are forwarding multiple messages */ + if (get_ctinfo("multipart/digest", ct, 0) == NOTOK) + done(1); + ct->c_type = CT_MULTIPART; + ct->c_subtype = MULTI_DIGEST; + + if ((m = (struct multipart *) + calloc(1, sizeof(*m))) == NULL) + adios(NULL, "out of memory"); + ct->c_ctparams = (void *) m; + pp = &m->mp_parts; + + for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { + if (is_selected(mp, msgnum)) { + struct part *part; + CT p; + CE pe; + + if ((p = (CT) calloc(1, sizeof(*p))) + == NULL) + adios(NULL, "out of memory"); + init_decoded_content(p); + pe = p->c_cefile; + if (get_ctinfo("message/rfc822", p, 0) + == NOTOK) + done(1); + p->c_type = CT_MESSAGE; + p->c_subtype = MESSAGE_RFC822; + + snprintf(buffer, sizeof(buffer), + "%s/%d", mp->foldpath, + msgnum); + pe->ce_file = getcpy(buffer); + if (listsw && stat(pe->ce_file, &st) + != NOTOK) + p->c_end = (long) st.st_size; + + if ((part = (struct part *) calloc(1, sizeof(*part))) == NULL) + adios(NULL, "out of memory"); + *pp = part; + pp = &part->mp_next; + part->mp_part = p; + } + } + } else { + /* we are forwarding one message */ + if (get_ctinfo("message/rfc822", ct, 0) == NOTOK) + done(1); + ct->c_type = CT_MESSAGE; + ct->c_subtype = MESSAGE_RFC822; + + msgnum = mp->lowsel; + snprintf(buffer, sizeof(buffer), "%s/%d", + mp->foldpath, msgnum); + ce->ce_file = getcpy(buffer); + if (listsw && stat(ce->ce_file, &st) != NOTOK) + ct->c_end = (long) st.st_size; + } + + folder_free(mp); /* free folder/message structure */ + return OK; + } + + /* + ** #end + */ + if (!mh_strcasecmp(ci->ci_type, "end")) { + free_content(ct); + *ctp = NULL; + return DONE; + } + + /* + ** #begin [ alternative | parallel ] + */ + if (!mh_strcasecmp(ci->ci_type, "begin")) { + if (!ci->ci_magic) { + vrsn = MULTI_MIXED; + cp = SubMultiPart[vrsn - 1].kv_key; + } else if (!mh_strcasecmp(ci->ci_magic, "alternative")) { + vrsn = MULTI_ALTERNATE; + cp = SubMultiPart[vrsn - 1].kv_key; + } else if (!mh_strcasecmp(ci->ci_magic, "parallel")) { + vrsn = MULTI_PARALLEL; + cp = SubMultiPart[vrsn - 1].kv_key; + } else if (uprf(ci->ci_magic, "digest")) { + goto use_forw; + } else { + vrsn = MULTI_UNKNOWN; + cp = ci->ci_magic; + } + + free_ctinfo(ct); + snprintf(buffer, sizeof(buffer), "multipart/%s", cp); + if (get_ctinfo(buffer, ct, 0) == NOTOK) + done(1); + ct->c_type = CT_MULTIPART; + ct->c_subtype = vrsn; + + if ((m = (struct multipart *) calloc(1, sizeof(*m))) == NULL) + adios(NULL, "out of memory"); + ct->c_ctparams = (void *) m; + + pp = &m->mp_parts; + while (fgetstr(buffer, sizeof(buffer) - 1, in)) { + struct part *part; + CT p; + + if (user_content(in, file, buffer, &p) == DONE) { + if (!m->mp_parts) + adios(NULL, "empty \"#begin ... #end\" sequence"); + return OK; + } + if (!p) + continue; + + if ((part = (struct part *) + calloc(1, sizeof(*part))) == NULL) + adios(NULL, "out of memory"); + *pp = part; + pp = &part->mp_next; + part->mp_part = p; + } + admonish(NULL, "premature end-of-file, missing #end"); + return OK; + } + + /* + ** Unknown directive + */ + adios(NULL, "unknown directive \"#%s\"", ci->ci_type); + return NOTOK; /* NOT REACHED */ +} + + +static void +set_id(CT ct, int top) +{ + char msgid[BUFSIZ]; + static int partno; + static time_t clock = 0; + static char *msgfmt; + + if (clock == 0) { + time(&clock); + snprintf(msgid, sizeof(msgid), "<%d.%ld.%%d@%s>\n", + (int) getpid(), (long) clock, LocalName()); + partno = 0; + msgfmt = getcpy(msgid); + } + snprintf(msgid, sizeof(msgid), msgfmt, top ? 0 : ++partno); + ct->c_id = getcpy(msgid); +} + + +static char ebcdicsafe[0x100] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, + 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + + +/* +** Fill out, or expand the various contents in the composition +** draft. Read-in any necessary files. Parse and execute any +** commands specified by profile composition strings. +*/ + +static int +compose_content(CT ct) +{ + CE ce = ct->c_cefile; + + switch (ct->c_type) { + case CT_MULTIPART: + { + int partnum; + char *pp; + char partnam[BUFSIZ]; + struct multipart *m = (struct multipart *) ct->c_ctparams; + struct part *part; + + if (ct->c_partno) { + snprintf(partnam, sizeof(partnam), "%s.", + ct->c_partno); + pp = partnam + strlen(partnam); + } else { + pp = partnam; + } + + /* first, we call compose_content on all the subparts */ + for (part = m->mp_parts, partnum = 1; part; + part = part->mp_next, partnum++) { + CT p = part->mp_part; + + sprintf(pp, "%d", partnum); + p->c_partno = getcpy(partnam); + if (compose_content(p) == NOTOK) + return NOTOK; + } + + /* + ** If the -rfc934mode switch is given, then check all + ** the subparts of a multipart/digest. If they are all + ** message/rfc822, then mark this content and all + ** subparts with the rfc934 compatibility mode flag. + */ + if (rfc934sw && ct->c_subtype == MULTI_DIGEST) { + int is934 = 1; + + for (part = m->mp_parts; part; part = part->mp_next) { + CT p = part->mp_part; + + if (p->c_subtype != MESSAGE_RFC822) { + is934 = 0; + break; + } + } + ct->c_rfc934 = is934; + for (part = m->mp_parts; part; part = part->mp_next) { + CT p = part->mp_part; + + if ((p->c_rfc934 = is934)) + p->c_end++; + } + } + + if (listsw) { + ct->c_end = (partnum = strlen(prefix) + 2) + 2; + if (ct->c_rfc934) + ct->c_end += 1; + + for (part = m->mp_parts; part; part = part->mp_next) + ct->c_end += part->mp_part->c_end + partnum; + } + } + break; + + case CT_MESSAGE: + /* Nothing to do for type message */ + break; + + /* + ** Discrete types (text/application/audio/image/video) + */ + default: + if (!ce->ce_file) { + pid_t child_id; + int xstdout, len, buflen; + char *bp, **ap, *cp; + char *vec[4], buffer[BUFSIZ]; + FILE *out; + CI ci = &ct->c_ctinfo; + char *tfile = NULL; + + if (!(cp = ci->ci_magic)) + adios(NULL, "internal error(5)"); + + tfile = m_mktemp2(NULL, invo_name, NULL, NULL); + if (tfile == NULL) { + adios("mhbuild", "unable to create temporary file"); + } + ce->ce_file = getcpy(tfile); + ce->ce_unlink = 1; + + xstdout = 0; + + /* Get buffer ready to go */ + bp = buffer; + bp[0] = '\0'; + buflen = sizeof(buffer); + + /* + ** Parse composition string into buffer + */ + for ( ; *cp; cp++) { + if (*cp == '%') { + switch (*++cp) { + case 'a': + { + /* + ** insert parameters from + ** directive + */ + char **ep; + char *s = ""; + + for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { + snprintf(bp, buflen, "%s%s=\"%s\"", s, *ap, *ep); + len = strlen(bp); + bp += len; + buflen -= len; + s = " "; + } + } + break; + + case 'F': + /* %f, and stdout is not-redirected */ + xstdout = 1; + /* and fall... */ + + case 'f': + /* + ** insert temporary filename + ** where content should be + ** written + */ + snprintf(bp, buflen, "%s", ce->ce_file); + break; + + case 's': + /* insert content subtype */ + strncpy(bp, ci->ci_subtype, buflen); + break; + + case '%': + /* insert character % */ + goto raw; + + default: + *bp++ = *--cp; + *bp = '\0'; + buflen--; + continue; + } + len = strlen(bp); + bp += len; + buflen -= len; + } else { +raw: + *bp++ = *cp; + *bp = '\0'; + buflen--; + } + } + + if (verbosw) + printf("composing content %s/%s from command\n\t%s\n", ci->ci_type, ci->ci_subtype, buffer); + + fflush(stdout); /* not sure if need for -noverbose */ + + vec[0] = "/bin/sh"; + vec[1] = "-c"; + vec[2] = buffer; + vec[3] = NULL; + + if ((out = fopen(ce->ce_file, "w")) == NULL) + adios(ce->ce_file, "unable to open for writing"); + + switch (child_id = fork()) { + case NOTOK: + adios("fork", "unable to fork"); + /* NOTREACHED */ + + case OK: + if (!xstdout) + dup2(fileno(out), 1); + close(fileno(out)); + execvp("/bin/sh", vec); + fprintf(stderr, "unable to exec "); + perror("/bin/sh"); + _exit(-1); + /* NOTREACHED */ + + default: + fclose(out); + if (pidXwait(child_id, NULL)) + done(1); + break; + } + } + + /* Check size of file */ + if (listsw && ct->c_end == 0L) { + struct stat st; + + if (stat(ce->ce_file, &st) != NOTOK) + ct->c_end = (long) st.st_size; + } + break; + } + + return OK; +} + + +/* +** Scan the content. +** +** 1) choose a transfer encoding. +** 2) check for clashes with multipart boundary string. +** 3) for text content, figure out which character set is being used. +** +** If there is a clash with one of the contents and the multipart boundary, +** this function will exit with NOTOK. This will cause the scanning process +** to be repeated with a different multipart boundary. It is possible +** (although highly unlikely) that this scan will be repeated multiple times. +*/ + +static int +scan_content(CT ct) +{ + int len; + int check8bit = 0, contains8bit = 0; /* check if contains 8bit data */ + int checklinelen = 0, linelen = 0; /* check for long lines */ + int checkboundary = 0, boundaryclash = 0; /* check if clashes with multipart boundary */ + int checklinespace = 0, linespace = 0; /* check if any line ends with space */ + int checkebcdic = 0, ebcdicunsafe = 0; /* check if contains ebcdic unsafe characters */ + unsigned char *cp = NULL, buffer[BUFSIZ]; + struct text *t = NULL; + FILE *in = NULL; + CE ce = ct->c_cefile; + + /* + ** handle multipart by scanning all subparts + ** and then checking their encoding. + */ + if (ct->c_type == CT_MULTIPART) { + struct multipart *m = (struct multipart *) ct->c_ctparams; + struct part *part; + + /* initially mark the domain of enclosing multipart as 7bit */ + ct->c_encoding = CE_7BIT; + + for (part = m->mp_parts; part; part = part->mp_next) { + CT p = part->mp_part; + + if (scan_content(p) == NOTOK) { + /* choose encoding for subpart */ + return NOTOK; + } + + /* + ** if necessary, enlarge encoding for enclosing + ** multipart + */ + if (p->c_encoding == CE_BINARY) + ct->c_encoding = CE_BINARY; + if (p->c_encoding == CE_8BIT && + ct->c_encoding != CE_BINARY) + ct->c_encoding = CE_8BIT; + } + + return OK; + } + + /* + ** Decide what to check while scanning this content. + */ + switch (ct->c_type) { + case CT_TEXT: + check8bit = 1; + checkboundary = 1; + if (ct->c_subtype == TEXT_PLAIN) { + checkebcdic = 0; + checklinelen = 0; + checklinespace = 0; + } else { + checkebcdic = ebcdicsw; + checklinelen = 1; + checklinespace = 1; + } + break; + + case CT_APPLICATION: + check8bit = 1; + checkebcdic = ebcdicsw; + checklinelen = 1; + checklinespace = 1; + checkboundary = 1; + break; + + case CT_MESSAGE: + check8bit = 0; + checkebcdic = 0; + checklinelen = 0; + checklinespace = 0; + + /* don't check anything for message/external */ + if (ct->c_subtype == MESSAGE_EXTERNAL) + checkboundary = 0; + else + checkboundary = 1; + break; + + case CT_AUDIO: + case CT_IMAGE: + case CT_VIDEO: + /* + ** Don't check anything for these types, + ** since we are forcing use of base64. + */ + check8bit = 0; + checkebcdic = 0; + checklinelen = 0; + checklinespace = 0; + checkboundary = 0; + break; + } + + /* + ** Scan the unencoded content + */ + if (check8bit || checklinelen || checklinespace || checkboundary) { + if ((in = fopen(ce->ce_file, "r")) == NULL) + adios(ce->ce_file, "unable to open for reading"); + len = strlen(prefix); + + while (fgets(buffer, sizeof(buffer) - 1, in)) { + /* + ** Check for 8bit data. + */ + if (check8bit) { + for (cp = buffer; *cp; cp++) { + if (!isascii(*cp)) { + contains8bit = 1; + /* no need to keep checking */ + check8bit = 0; + } + /* + ** Check if character is ebcdic-safe. + ** We only check this if also checking + ** for 8bit data. + */ + if (checkebcdic && !ebcdicsafe[*cp & 0xff]) { + ebcdicunsafe = 1; + /* no need to keep checking */ + checkebcdic = 0; + } + } + } + + /* + ** Check line length. + */ + if (checklinelen && (strlen(buffer) > CPERLIN + 1)) { + linelen = 1; + checklinelen = 0; /* no need to keep checking */ + } + + /* + ** Check if line ends with a space. + */ + if (checklinespace && + (cp = buffer + strlen(buffer) - 2) > + buffer && isspace(*cp)) { + linespace = 1; + /* no need to keep checking */ + checklinespace = 0; + } + + /* + ** Check if content contains a line that clashes + ** with our standard boundary for multipart messages. + */ + if (checkboundary && buffer[0] == '-' && + buffer[1] == '-') { + for (cp = buffer + strlen(buffer) - 1; + cp >= buffer; cp--) + if (!isspace(*cp)) + break; + *++cp = '\0'; + if (strncmp(buffer + 2, prefix, len)==0 && + isdigit(buffer[2 + len])) { + boundaryclash = 1; + /* no need to keep checking */ + checkboundary = 0; + } + } + } + fclose(in); + } + + /* + ** Decide which transfer encoding to use. + */ + switch (ct->c_type) { + case CT_TEXT: + /* + ** If the text content didn't specify a character + ** set, we need to figure out which one was used. + */ + t = (struct text *) ct->c_ctparams; + if (t->tx_charset == CHARSET_UNSPECIFIED) { + CI ci = &ct->c_ctinfo; + char **ap, **ep; + + for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) + continue; + + if (contains8bit) { + t->tx_charset = CHARSET_UNKNOWN; + *ap = concat("charset=", write_charset_8bit(), + NULL); + } else { + t->tx_charset = CHARSET_USASCII; + *ap = getcpy("charset=us-ascii"); + } + + cp = strchr(*ap++, '='); + *ap = NULL; + *cp++ = '\0'; + *ep = cp; + } + + if (contains8bit || ebcdicunsafe || linelen || linespace || + checksw) + ct->c_encoding = CE_QUOTED; + else + ct->c_encoding = CE_7BIT; + break; + + case CT_APPLICATION: + /* For application type, use base64, except when postscript */ + if (contains8bit || ebcdicunsafe || linelen || linespace || + checksw) + ct->c_encoding = (ct->c_subtype == + APPLICATION_POSTSCRIPT) ? + CE_QUOTED : CE_BASE64; + else + ct->c_encoding = CE_7BIT; + break; + + case CT_MESSAGE: + ct->c_encoding = CE_7BIT; + break; + + case CT_AUDIO: + case CT_IMAGE: + case CT_VIDEO: + /* For audio, image, and video contents, just use base64 */ + ct->c_encoding = CE_BASE64; + break; + } + + return (boundaryclash ? NOTOK : OK); +} + + +/* +** Scan the content structures, and build header +** fields that will need to be output into the +** message. +*/ + +static int +build_headers(CT ct) +{ + int cc, mailbody, len; + char **ap, **ep; + char *np, *vp, buffer[BUFSIZ]; + CI ci = &ct->c_ctinfo; + + /* + ** If message is type multipart, then add the multipart + ** boundary to the list of attribute/value pairs. + */ + if (ct->c_type == CT_MULTIPART) { + char *cp; + static int level = 0; /* store nesting level */ + + ap = ci->ci_attrs; + ep = ci->ci_values; + snprintf(buffer, sizeof(buffer), "boundary=%s%d", + prefix, level++); + cp = strchr(*ap++ = getcpy(buffer), '='); + *ap = NULL; + *cp++ = '\0'; + *ep = cp; + } + + /* + ** Skip the output of Content-Type, parameters, content + ** description and disposition, and Content-ID if the + ** content is of type "message" and the rfc934 compatibility + ** flag is set (which means we are inside multipart/digest + ** and the switch -rfc934mode was given). + */ + if (ct->c_type == CT_MESSAGE && ct->c_rfc934) + goto skip_headers; + + /* + ** output the content type and subtype + */ + np = getcpy(TYPE_FIELD); + vp = concat(" ", ci->ci_type, "/", ci->ci_subtype, NULL); + + /* keep track of length of line */ + len = strlen(TYPE_FIELD) + strlen(ci->ci_type) + + strlen(ci->ci_subtype) + 3; + + mailbody = ct->c_type == CT_MESSAGE && + ct->c_subtype == MESSAGE_EXTERNAL && + ((struct exbody *) ct->c_ctparams)->eb_body; + + /* + ** Append the attribute/value pairs to + ** the end of the Content-Type line. + */ + for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { + if (mailbody && !mh_strcasecmp(*ap, "body")) + continue; + + vp = add(";", vp); + len++; + + snprintf(buffer, sizeof(buffer), "%s=\"%s\"", *ap, *ep); + if (len + 1 + (cc = strlen(buffer)) >= CPERLIN) { + vp = add("\n\t", vp); + len = 8; + } else { + vp = add(" ", vp); + len++; + } + vp = add(buffer, vp); + len += cc; + } + + /* + ** Append any RFC-822 comment to the end of + ** the Content-Type line. + */ + if (ci->ci_comment) { + snprintf(buffer, sizeof(buffer), "(%s)", ci->ci_comment); + if (len + 1 + (cc = 2 + strlen(ci->ci_comment)) >= CPERLIN) { + vp = add("\n\t", vp); + len = 8; + } else { + vp = add(" ", vp); + len++; + } + vp = add(buffer, vp); + len += cc; + } + vp = add("\n", vp); + add_header(ct, np, vp); + + /* + ** output the Content-ID, unless disabled by -nocontentid + */ + if (contentidsw && ct->c_id) { + np = getcpy(ID_FIELD); + vp = concat(" ", ct->c_id, NULL); + add_header(ct, np, vp); + } + + /* + ** output the Content-Description + */ + if (ct->c_descr) { + np = getcpy(DESCR_FIELD); + vp = concat(" ", ct->c_descr, NULL); + add_header(ct, np, vp); + } + + /* + ** output the Content-Disposition + */ + if (ct->c_dispo) { + np = getcpy(DISPO_FIELD); + vp = concat(" ", ct->c_dispo, NULL); + add_header(ct, np, vp); + } + +skip_headers: + /* + ** If this is the internal content structure for a + ** "message/external", then we are done with the + ** headers (since it has no body). + */ + if (ct->c_ctexbody) + return OK; + + /* + ** output the Content-MD5 + */ + if (checksw) { + np = getcpy(MD5_FIELD); + vp = calculate_digest(ct, (ct->c_encoding == CE_QUOTED) ? + 1 : 0); + add_header(ct, np, vp); + } + + /* + ** output the Content-Transfer-Encoding + */ + switch (ct->c_encoding) { + case CE_7BIT: + /* Nothing to output */ + break; + + case CE_8BIT: + if (ct->c_type == CT_MESSAGE) + adios(NULL, "internal error, invalid encoding"); + + np = getcpy(ENCODING_FIELD); + vp = concat(" ", "8bit", "\n", NULL); + add_header(ct, np, vp); + break; + + case CE_QUOTED: + if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) + adios(NULL, "internal error, invalid encoding"); + + np = getcpy(ENCODING_FIELD); + vp = concat(" ", "quoted-printable", "\n", NULL); + add_header(ct, np, vp); + break; + + case CE_BASE64: + if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) + adios(NULL, "internal error, invalid encoding"); + + np = getcpy(ENCODING_FIELD); + vp = concat(" ", "base64", "\n", NULL); + add_header(ct, np, vp); + break; + + case CE_BINARY: + if (ct->c_type == CT_MESSAGE) + adios(NULL, "internal error, invalid encoding"); + + np = getcpy(ENCODING_FIELD); + vp = concat(" ", "binary", "\n", NULL); + add_header(ct, np, vp); + break; + + default: + adios(NULL, "unknown transfer encoding in content"); + break; + } + + /* + ** Additional content specific header processing + */ + switch (ct->c_type) { + case CT_MULTIPART: + { + struct multipart *m; + struct part *part; + + m = (struct multipart *) ct->c_ctparams; + for (part = m->mp_parts; part; part = part->mp_next) { + CT p; + + p = part->mp_part; + build_headers(p); + } + } + break; + + case CT_MESSAGE: + if (ct->c_subtype == MESSAGE_EXTERNAL) { + struct exbody *e; + + e = (struct exbody *) ct->c_ctparams; + build_headers(e->eb_content); + } + break; + + default: + /* Nothing to do */ + break; + } + + return OK; +} + + +static char nib2b64[0x40+1] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + +static char * +calculate_digest(CT ct, int asciiP) +{ + int cc; + char buffer[BUFSIZ], *vp, *op; + unsigned char *dp; + unsigned char digest[16]; + unsigned char outbuf[25]; + FILE *in; + MD5_CTX mdContext; + CE ce = ct->c_cefile; + + /* open content */ + if ((in = fopen(ce->ce_file, "r")) == NULL) + adios(ce->ce_file, "unable to open for reading"); + + /* Initialize md5 context */ + MD5Init(&mdContext); + + /* calculate md5 message digest */ + if (asciiP) { + while (fgets(buffer, sizeof(buffer) - 1, in)) { + char c, *cp; + + cp = buffer + strlen(buffer) - 1; + if ((c = *cp) == '\n') + *cp = '\0'; + + MD5Update(&mdContext, (unsigned char *) buffer, + (unsigned int) strlen(buffer)); + + if (c == '\n') + MD5Update(&mdContext, (unsigned char *) "\r\n", + 2); + } + } else { + while ((cc = fread(buffer, sizeof(*buffer), sizeof(buffer), + in)) > 0) + MD5Update(&mdContext, (unsigned char *) buffer, + (unsigned int) cc); + } + + /* md5 finalization. Write digest and zero md5 context */ + MD5Final(digest, &mdContext); + + /* close content */ + fclose(in); + + /* print debugging info */ + if (debugsw) { + unsigned char *ep; + + fprintf(stderr, "MD5 digest="); + for (ep = (dp = digest) + sizeof(digest) / sizeof(digest[0]); + dp < ep; dp++) + fprintf(stderr, "%02x", *dp & 0xff); + fprintf(stderr, "\n"); + } + + /* encode the digest using base64 */ + for (dp = digest, op = outbuf, cc = sizeof(digest) / sizeof(digest[0]); + cc > 0; cc -= 3, op += 4) { + unsigned long bits; + char *bp; + + bits = (*dp++ & 0xff) << 16; + if (cc > 1) { + bits |= (*dp++ & 0xff) << 8; + if (cc > 2) + bits |= *dp++ & 0xff; + } + + for (bp = op + 4; bp > op; bits >>= 6) + *--bp = nib2b64[bits & 0x3f]; + if (cc < 3) { + *(op + 3) = '='; + if (cc < 2) + *(op + 2) = '='; + } + } + + /* null terminate string */ + outbuf[24] = '\0'; + + /* now make copy and return string */ + vp = concat(" ", outbuf, "\n", NULL); + return vp; +} diff --git a/uip/mhbuildsbr.c b/uip/mhbuildsbr.c deleted file mode 100644 index efbb8ac..0000000 --- a/uip/mhbuildsbr.c +++ /dev/null @@ -1,1732 +0,0 @@ -/* -** mhbuildsbr.c -- routines to 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. -*/ - -/* -** This code was originally part of mhn.c. I split it into -** a separate program (mhbuild.c) and then later split it -** again (mhbuildsbr.c). But the code still has some of -** the mhn.c code in it. This program needs additional -** streamlining and removal of unneeded code. -*/ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#ifdef TIME_WITH_SYS_TIME -# include -# include -#else -# ifdef TM_IN_SYS_TIME -# include -# else -# include -# endif -#endif - -#ifdef HAVE_SYS_WAIT_H -# include -#endif - - -extern int debugsw; -extern int verbosw; - -extern int ebcdicsw; -extern int listsw; -extern int rfc934sw; -extern int contentidsw; - -extern int endian; /* mhmisc.c */ - -/* cache policies */ -extern int rcachesw; /* mhcachesbr.c */ -extern int wcachesw; /* mhcachesbr.c */ - -/* -** Directory to place tmp files. This must -** be set before these routines are called. -*/ -char *tmp; - -pid_t xpid = 0; - -static char prefix[] = "----- =_aaaaaaaaaa"; - - -/* mhmisc.c */ -int make_intermediates(char *); -void content_error(char *, CT, char *, ...); - -/* mhcachesbr.c */ -int find_cache(CT, int, int *, char *, char *, int); - -/* ftpsbr.c */ -int ftp_get(char *, char *, char *, char *, char *, char *, int, int); - -/* mhfree.c */ -void free_content(CT); -void free_ctinfo(CT); -void free_encoding(CT, int); - -/* -** prototypes -*/ -CT build_mime(char *); - -/* -** static prototypes -*/ -static int init_decoded_content(CT); -static char *fgetstr(char *, int, FILE *); -static int user_content(FILE *, char *, char *, CT *); -static void set_id(CT, int); -static int compose_content(CT); -static int scan_content(CT); -static int build_headers(CT); -static char *calculate_digest(CT, int); - - -/* -** Main routine for translating composition file -** into valid MIME message. It translates the draft -** into a content structure (actually a tree of content -** structures). This message then can be manipulated -** in various ways, including being output via -** output_message(). -*/ - -CT -build_mime(char *infile) -{ - int compnum, state; - char buf[BUFSIZ], name[NAMESZ]; - char *cp, *np, *vp; - struct multipart *m; - struct part **pp; - CT ct; - FILE *in; - - umask(~m_gmprot()); - - /* open the composition draft */ - if ((in = fopen(infile, "r")) == NULL) - adios(infile, "unable to open for reading"); - - /* - ** Allocate space for primary (outside) content - */ - if ((ct = (CT) calloc(1, sizeof(*ct))) == NULL) - adios(NULL, "out of memory"); - - /* - ** Allocate structure for handling decoded content - ** for this part. We don't really need this, but - ** allocate it to remain consistent. - */ - init_decoded_content(ct); - - /* - ** Parse some of the header fields in the composition - ** draft into the linked list of header fields for - ** the new MIME message. - */ - for (compnum = 1, state = FLD;;) { - switch (state = m_getfld(state, name, buf, sizeof(buf), in)) { - case FLD: - case FLDPLUS: - case FLDEOF: - compnum++; - - /* abort if draft has Mime-Version header field */ - if (!mh_strcasecmp(name, VRSN_FIELD)) - adios(NULL, "draft shouldn't contain %s: field", VRSN_FIELD); - - /* - ** abort if draft has Content-Transfer-Encoding - ** header field - */ - if (!mh_strcasecmp(name, ENCODING_FIELD)) - adios(NULL, "draft shouldn't contain %s: field", ENCODING_FIELD); - - /* ignore any Content-Type fields in the header */ - if (!mh_strcasecmp(name, TYPE_FIELD)) { - while (state == FLDPLUS) - state = m_getfld(state, name, buf, - sizeof(buf), in); - goto finish_field; - } - - /* get copies of the buffers */ - np = getcpy(name); - vp = getcpy(buf); - - /* if necessary, get rest of field */ - while (state == FLDPLUS) { - state = m_getfld(state, name, buf, - sizeof(buf), in); - vp = add(buf, vp); /* add to prev value */ - } - - /* Now add the header data to the list */ - add_header(ct, np, vp); - -finish_field: - /* if this wasn't the last hdr field, then continue */ - if (state != FLDEOF) - continue; - /* else fall... */ - - case FILEEOF: - adios(NULL, "draft has empty body -- no directives!"); - /* NOTREACHED */ - - case BODY: - case BODYEOF: - fseek(in, (long) (-strlen(buf)), SEEK_CUR); - break; - - case LENERR: - case FMTERR: - adios(NULL, "message format error in component #%d", - compnum); - - default: - adios(NULL, "getfld() returned %d", state); - } - break; - } - - /* - ** Now add the MIME-Version header field - ** to the list of header fields. - */ - np = getcpy(VRSN_FIELD); - vp = concat(" ", VRSN_VALUE, "\n", NULL); - add_header(ct, np, vp); - - /* - ** We initally assume we will find multiple contents in the - ** draft. So create a multipart/mixed content to hold everything. - ** We can remove this later, if it is not needed. - */ - if (get_ctinfo("multipart/mixed", ct, 0) == NOTOK) - done(1); - ct->c_type = CT_MULTIPART; - ct->c_subtype = MULTI_MIXED; - ct->c_file = getcpy(infile); - - if ((m = (struct multipart *) calloc(1, sizeof(*m))) == NULL) - adios(NULL, "out of memory"); - ct->c_ctparams = (void *) m; - pp = &m->mp_parts; - - /* - ** read and parse the composition file - ** and the directives it contains. - */ - while (fgetstr(buf, sizeof(buf) - 1, in)) { - struct part *part; - CT p; - - if (user_content(in, infile, buf, &p) == DONE) { - admonish(NULL, "ignoring spurious #end"); - continue; - } - if (!p) - continue; - - if ((part = (struct part *) calloc(1, sizeof(*part))) == NULL) - adios(NULL, "out of memory"); - *pp = part; - pp = &part->mp_next; - part->mp_part = p; - } - - /* - ** close the composition draft since - ** it's not needed any longer. - */ - fclose(in); - - /* check if any contents were found */ - if (!m->mp_parts) - adios(NULL, "no content directives found"); - - /* - ** If only one content was found, then remove and - ** free the outer multipart content. - */ - if (!m->mp_parts->mp_next) { - CT p; - - p = m->mp_parts->mp_part; - m->mp_parts->mp_part = NULL; - - /* move header fields */ - p->c_first_hf = ct->c_first_hf; - p->c_last_hf = ct->c_last_hf; - ct->c_first_hf = NULL; - ct->c_last_hf = NULL; - - free_content(ct); - ct = p; - } else { - set_id(ct, 1); - } - - /* - ** Fill out, or expand directives. Parse and execute - ** commands specified by profile composition strings. - */ - compose_content(ct); - - if ((cp = strchr(prefix, 'a')) == NULL) - adios(NULL, "internal error(4)"); - - /* - ** Scan the contents. Choose a transfer encoding, and - ** check if prefix for multipart boundary clashes with - ** any of the contents. - */ - while (scan_content(ct) == NOTOK) { - if (*cp < 'z') { - (*cp)++; - } else { - if (*++cp == 0) - adios(NULL, "giving up trying to find a unique delimiter string"); - else - (*cp)++; - } - } - - /* Build the rest of the header field structures */ - build_headers(ct); - - return ct; -} - - -/* -** Set up structures for placing unencoded -** content when building parts. -*/ - -static int -init_decoded_content(CT ct) -{ - CE ce; - - if ((ce = (CE) calloc(1, sizeof(*ce))) == NULL) - adios(NULL, "out of memory"); - - ct->c_cefile = ce; - ct->c_ceopenfnx = open7Bit; /* since unencoded */ - ct->c_ceclosefnx = close_encoding; - ct->c_cesizefnx = NULL; /* since unencoded */ - - return OK; -} - - -static char * -fgetstr(char *s, int n, FILE *stream) -{ - char *cp, *ep; - - for (ep = (cp = s) + n; cp < ep; ) { - int i; - - if (!fgets(cp, n, stream)) - return (cp != s ? s : NULL); - if (cp == s && *cp != '#') - return s; - - cp += (i = strlen(cp)) - 1; - if (i <= 1 || *cp-- != '\n' || *cp != '\\') - break; - *cp = '\0'; - n -= (i - 2); - } - - return s; -} - - -/* -** Parse the composition draft for text and directives. -** Do initial setup of Content structure. -*/ - -static int -user_content(FILE *in, char *file, char *buf, CT *ctp) -{ - int extrnal, vrsn; - unsigned char *cp; - char **ap; - char buffer[BUFSIZ]; - struct multipart *m; - struct part **pp; - struct stat st; - struct str2init *s2i; - CI ci; - CT ct; - CE ce; - - if (buf[0] == '\n' || strcmp(buf, "#\n") == 0) { - *ctp = NULL; - return OK; - } - - /* allocate basic Content structure */ - if ((ct = (CT) calloc(1, sizeof(*ct))) == NULL) - adios(NULL, "out of memory"); - *ctp = ct; - - /* allocate basic structure for handling decoded content */ - init_decoded_content(ct); - ce = ct->c_cefile; - - ci = &ct->c_ctinfo; - set_id(ct, 0); - - /* - ** Handle inline text. Check if line - ** is one of the following forms: - ** - ** 1) doesn't begin with '#' (implicit directive) - ** 2) begins with "##" (implicit directive) - ** 3) begins with "#<" - */ - if (buf[0] != '#' || buf[1] == '#' || buf[1] == '<') { - int headers; - int inlineD; - long pos; - char content[BUFSIZ]; - FILE *out; - char *cp; - - cp = m_mktemp2(NULL, invo_name, NULL, &out); - if (cp == NULL) - adios("mhbuildsbr", "unable to create temporary file"); - - /* use a temp file to collect the plain text lines */ - ce->ce_file = getcpy(cp); - ce->ce_unlink = 1; - - if (buf[0] == '#' && buf[1] == '<') { - strncpy(content, buf + 2, sizeof(content)); - inlineD = 1; - goto rock_and_roll; - } else { - inlineD = 0; - } - - /* the directive is implicit */ - strncpy(content, "text/plain", sizeof(content)); - headers = 0; - strncpy(buffer, buf[0] != '#' ? buf : buf + 1, sizeof(buffer)); - for (;;) { - int i; - - if (headers >= 0 && uprf(buffer, DESCR_FIELD) && - buffer[i=strlen(DESCR_FIELD)] == ':') { - headers = 1; - -again_descr: - ct->c_descr = add(buffer + i + 1, ct->c_descr); - if (!fgetstr(buffer, sizeof(buffer) - 1, in)) - adios(NULL, "end-of-file after %s: field in plaintext", DESCR_FIELD); - switch (buffer[0]) { - case ' ': - case '\t': - i = -1; - goto again_descr; - - case '#': - adios(NULL, "#-directive after %s: field in plaintext", DESCR_FIELD); - /* NOTREACHED */ - - default: - break; - } - } - - if (headers >= 0 && uprf(buffer, DISPO_FIELD) - && buffer[i = strlen(DISPO_FIELD)] == ':') { - headers = 1; - -again_dispo: - ct->c_dispo = add(buffer + i + 1, ct->c_dispo); - if (!fgetstr(buffer, sizeof(buffer) - 1, in)) - adios(NULL, "end-of-file after %s: field in plaintext", DISPO_FIELD); - switch (buffer[0]) { - case ' ': - case '\t': - i = -1; - goto again_dispo; - - case '#': - adios(NULL, "#-directive after %s: field in plaintext", DISPO_FIELD); - /* NOTREACHED */ - - default: - break; - } - } - - if (headers != 1 || buffer[0] != '\n') - fputs(buffer, out); - -rock_and_roll: - headers = -1; - pos = ftell(in); - if ((cp = fgetstr(buffer, sizeof(buffer) - 1, in)) - == NULL) - break; - if (buffer[0] == '#') { - char *bp; - - if (buffer[1] != '#') - break; - for (cp = (bp = buffer) + 1; *cp; cp++) - *bp++ = *cp; - *bp = '\0'; - } - } - - if (listsw) - ct->c_end = ftell(out); - fclose(out); - - /* parse content type */ - if (get_ctinfo(content, ct, inlineD) == NOTOK) - done(1); - - for (s2i = str2cts; s2i->si_key; s2i++) - if (!mh_strcasecmp(ci->ci_type, s2i->si_key)) - break; - if (!s2i->si_key && !uprf(ci->ci_type, "X-")) - s2i++; - - /* - ** check type specified (possibly implicitly) - */ - switch (ct->c_type = s2i->si_val) { - case CT_MESSAGE: - if (!mh_strcasecmp(ci->ci_subtype, "rfc822")) { - ct->c_encoding = CE_7BIT; - goto call_init; - } - /* else fall... */ - case CT_MULTIPART: - adios(NULL, "it doesn't make sense to define an in-line %s content", - ct->c_type == CT_MESSAGE ? "message" : - "multipart"); - /* NOTREACHED */ - - default: -call_init: - if ((ct->c_ctinitfnx = s2i->si_init)) - (*ct->c_ctinitfnx) (ct); - break; - } - - if (cp) - fseek(in, pos, SEEK_SET); - return OK; - } - - /* - ** If we've reached this point, the next line - ** must be some type of explicit directive. - */ - - /* check if directive is external-type */ - extrnal = (buf[1] == '@'); - - /* parse directive */ - if (get_ctinfo(buf + (extrnal ? 2 : 1), ct, 1) == NOTOK) - done(1); - - /* check directive against the list of MIME types */ - for (s2i = str2cts; s2i->si_key; s2i++) - if (!mh_strcasecmp(ci->ci_type, s2i->si_key)) - break; - - /* - ** Check if the directive specified a valid type. - ** This will happen if it was one of the following forms: - ** - ** #type/subtype (or) - ** #@type/subtype - */ - if (s2i->si_key) { - if (!ci->ci_subtype) - adios(NULL, "missing subtype in \"#%s\"", ci->ci_type); - - switch (ct->c_type = s2i->si_val) { - case CT_MULTIPART: - adios(NULL, "use \"#begin ... #end\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); - /* NOTREACHED */ - - case CT_MESSAGE: - if (!mh_strcasecmp(ci->ci_subtype, "partial")) - adios(NULL, "sorry, \"#%s/%s\" isn't supported", ci->ci_type, ci->ci_subtype); - if (!mh_strcasecmp(ci->ci_subtype, "external-body")) - adios(NULL, "use \"#@type/subtype ... [] ...\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); -use_forw: - adios(NULL, "use \"#forw [+folder] [msgs]\" instead of \"#%s/%s\"", ci->ci_type, ci->ci_subtype); - /* NOTREACHED */ - - default: - if ((ct->c_ctinitfnx = s2i->si_init)) - (*ct->c_ctinitfnx) (ct); - break; - } - - /* - ** #@type/subtype (external types directive) - */ - if (extrnal) { - struct exbody *e; - CT p; - - if (!ci->ci_magic) - adios(NULL, "need external information for \"#@%s/%s\"", ci->ci_type, ci->ci_subtype); - p = ct; - - snprintf(buffer, sizeof(buffer), "message/external-body; %s", ci->ci_magic); - free(ci->ci_magic); - ci->ci_magic = NULL; - - /* - ** Since we are using the current Content structure to - ** hold information about the type of the external - ** reference, we need to create another Content - ** structure for the message/external-body to wrap - ** it in. - */ - if ((ct = (CT) calloc(1, sizeof(*ct))) == NULL) - adios(NULL, "out of memory"); - *ctp = ct; - ci = &ct->c_ctinfo; - if (get_ctinfo(buffer, ct, 0) == NOTOK) - done(1); - ct->c_type = CT_MESSAGE; - ct->c_subtype = MESSAGE_EXTERNAL; - - if ((e = (struct exbody *) - calloc(1, sizeof(*e))) == NULL) - adios(NULL, "out of memory"); - ct->c_ctparams = (void *) e; - - e->eb_parent = ct; - e->eb_content = p; - p->c_ctexbody = e; - - if (params_external(ct, 1) == NOTOK) - done(1); - - return OK; - } - - /* Handle [file] argument */ - if (ci->ci_magic) { - /* check if specifies command to execute */ - if (*ci->ci_magic == '|' || *ci->ci_magic == '!') { - for (cp = ci->ci_magic + 1; isspace(*cp); cp++) - continue; - if (!*cp) - adios(NULL, "empty pipe command for #%s directive", ci->ci_type); - cp = getcpy(cp); - free(ci->ci_magic); - ci->ci_magic = cp; - } else { - /* record filename of decoded contents */ - ce->ce_file = ci->ci_magic; - if (access(ce->ce_file, R_OK) == NOTOK) - adios("reading", "unable to access %s for", ce->ce_file); - if (listsw && stat(ce->ce_file, &st) != NOTOK) - ct->c_end = (long) st.st_size; - ci->ci_magic = NULL; - } - return OK; - } - - /* - ** No [file] argument, so check profile for - ** method to compose content. - */ - snprintf(buffer, sizeof(buffer), "%s-compose-%s/%s", - invo_name, ci->ci_type, ci->ci_subtype); - if ((cp = context_find(buffer)) == NULL || *cp == '\0') { - snprintf(buffer, sizeof(buffer), "%s-compose-%s", - invo_name, ci->ci_type); - if ((cp = context_find(buffer)) == NULL || - *cp == '\0') { - content_error(NULL, ct, "don't know how to compose content"); - done(1); - } - } - ci->ci_magic = getcpy(cp); - return OK; - } - - if (extrnal) - adios(NULL, "external definition not allowed for \"#%s\"", - ci->ci_type); - - /* - ** Message directive - ** #forw [+folder] [msgs] - */ - if (!mh_strcasecmp(ci->ci_type, "forw")) { - int msgnum; - char *folder, *arguments[MAXARGS]; - struct msgs *mp; - - if (ci->ci_magic) { - ap = brkstring(ci->ci_magic, " ", "\n"); - copyip(ap, arguments, MAXARGS); - } else { - arguments[0] = seq_cur; - arguments[1] = NULL; - } - folder = NULL; - - /* search the arguments for a folder name */ - for (ap = arguments; *ap; ap++) { - cp = *ap; - if (*cp == '+' || *cp == '@') { - if (folder) - adios(NULL, "only one folder per #forw directive"); - else - folder = getcpy(expandfol(cp)); - } - } - - /* else, use the current folder */ - if (!folder) - folder = getcpy(getcurfol()); - - if (!(mp = folder_read(folder))) - adios(NULL, "unable to read folder %s", folder); - for (ap = arguments; *ap; ap++) { - cp = *ap; - if (*cp != '+' && *cp != '@') - if (!m_convert(mp, cp)) - done(1); - } - free(folder); - free_ctinfo(ct); - - /* - ** If there is more than one message to include, make this - ** a content of type "multipart/digest" and insert each message - ** as a subpart. If there is only one message, then make this - ** a content of type "message/rfc822". - */ - if (mp->numsel > 1) { - /* we are forwarding multiple messages */ - if (get_ctinfo("multipart/digest", ct, 0) == NOTOK) - done(1); - ct->c_type = CT_MULTIPART; - ct->c_subtype = MULTI_DIGEST; - - if ((m = (struct multipart *) - calloc(1, sizeof(*m))) == NULL) - adios(NULL, "out of memory"); - ct->c_ctparams = (void *) m; - pp = &m->mp_parts; - - for (msgnum = mp->lowsel; msgnum <= mp->hghsel; msgnum++) { - if (is_selected(mp, msgnum)) { - struct part *part; - CT p; - CE pe; - - if ((p = (CT) calloc(1, sizeof(*p))) - == NULL) - adios(NULL, "out of memory"); - init_decoded_content(p); - pe = p->c_cefile; - if (get_ctinfo("message/rfc822", p, 0) - == NOTOK) - done(1); - p->c_type = CT_MESSAGE; - p->c_subtype = MESSAGE_RFC822; - - snprintf(buffer, sizeof(buffer), - "%s/%d", mp->foldpath, - msgnum); - pe->ce_file = getcpy(buffer); - if (listsw && stat(pe->ce_file, &st) - != NOTOK) - p->c_end = (long) st.st_size; - - if ((part = (struct part *) calloc(1, sizeof(*part))) == NULL) - adios(NULL, "out of memory"); - *pp = part; - pp = &part->mp_next; - part->mp_part = p; - } - } - } else { - /* we are forwarding one message */ - if (get_ctinfo("message/rfc822", ct, 0) == NOTOK) - done(1); - ct->c_type = CT_MESSAGE; - ct->c_subtype = MESSAGE_RFC822; - - msgnum = mp->lowsel; - snprintf(buffer, sizeof(buffer), "%s/%d", - mp->foldpath, msgnum); - ce->ce_file = getcpy(buffer); - if (listsw && stat(ce->ce_file, &st) != NOTOK) - ct->c_end = (long) st.st_size; - } - - folder_free(mp); /* free folder/message structure */ - return OK; - } - - /* - ** #end - */ - if (!mh_strcasecmp(ci->ci_type, "end")) { - free_content(ct); - *ctp = NULL; - return DONE; - } - - /* - ** #begin [ alternative | parallel ] - */ - if (!mh_strcasecmp(ci->ci_type, "begin")) { - if (!ci->ci_magic) { - vrsn = MULTI_MIXED; - cp = SubMultiPart[vrsn - 1].kv_key; - } else if (!mh_strcasecmp(ci->ci_magic, "alternative")) { - vrsn = MULTI_ALTERNATE; - cp = SubMultiPart[vrsn - 1].kv_key; - } else if (!mh_strcasecmp(ci->ci_magic, "parallel")) { - vrsn = MULTI_PARALLEL; - cp = SubMultiPart[vrsn - 1].kv_key; - } else if (uprf(ci->ci_magic, "digest")) { - goto use_forw; - } else { - vrsn = MULTI_UNKNOWN; - cp = ci->ci_magic; - } - - free_ctinfo(ct); - snprintf(buffer, sizeof(buffer), "multipart/%s", cp); - if (get_ctinfo(buffer, ct, 0) == NOTOK) - done(1); - ct->c_type = CT_MULTIPART; - ct->c_subtype = vrsn; - - if ((m = (struct multipart *) calloc(1, sizeof(*m))) == NULL) - adios(NULL, "out of memory"); - ct->c_ctparams = (void *) m; - - pp = &m->mp_parts; - while (fgetstr(buffer, sizeof(buffer) - 1, in)) { - struct part *part; - CT p; - - if (user_content(in, file, buffer, &p) == DONE) { - if (!m->mp_parts) - adios(NULL, "empty \"#begin ... #end\" sequence"); - return OK; - } - if (!p) - continue; - - if ((part = (struct part *) - calloc(1, sizeof(*part))) == NULL) - adios(NULL, "out of memory"); - *pp = part; - pp = &part->mp_next; - part->mp_part = p; - } - admonish(NULL, "premature end-of-file, missing #end"); - return OK; - } - - /* - ** Unknown directive - */ - adios(NULL, "unknown directive \"#%s\"", ci->ci_type); - return NOTOK; /* NOT REACHED */ -} - - -static void -set_id(CT ct, int top) -{ - char msgid[BUFSIZ]; - static int partno; - static time_t clock = 0; - static char *msgfmt; - - if (clock == 0) { - time(&clock); - snprintf(msgid, sizeof(msgid), "<%d.%ld.%%d@%s>\n", - (int) getpid(), (long) clock, LocalName()); - partno = 0; - msgfmt = getcpy(msgid); - } - snprintf(msgid, sizeof(msgid), msgfmt, top ? 0 : ++partno); - ct->c_id = getcpy(msgid); -} - - -static char ebcdicsafe[0x100] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, - 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, - 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - - -/* -** Fill out, or expand the various contents in the composition -** draft. Read-in any necessary files. Parse and execute any -** commands specified by profile composition strings. -*/ - -static int -compose_content(CT ct) -{ - CE ce = ct->c_cefile; - - switch (ct->c_type) { - case CT_MULTIPART: - { - int partnum; - char *pp; - char partnam[BUFSIZ]; - struct multipart *m = (struct multipart *) ct->c_ctparams; - struct part *part; - - if (ct->c_partno) { - snprintf(partnam, sizeof(partnam), "%s.", - ct->c_partno); - pp = partnam + strlen(partnam); - } else { - pp = partnam; - } - - /* first, we call compose_content on all the subparts */ - for (part = m->mp_parts, partnum = 1; part; - part = part->mp_next, partnum++) { - CT p = part->mp_part; - - sprintf(pp, "%d", partnum); - p->c_partno = getcpy(partnam); - if (compose_content(p) == NOTOK) - return NOTOK; - } - - /* - ** If the -rfc934mode switch is given, then check all - ** the subparts of a multipart/digest. If they are all - ** message/rfc822, then mark this content and all - ** subparts with the rfc934 compatibility mode flag. - */ - if (rfc934sw && ct->c_subtype == MULTI_DIGEST) { - int is934 = 1; - - for (part = m->mp_parts; part; part = part->mp_next) { - CT p = part->mp_part; - - if (p->c_subtype != MESSAGE_RFC822) { - is934 = 0; - break; - } - } - ct->c_rfc934 = is934; - for (part = m->mp_parts; part; part = part->mp_next) { - CT p = part->mp_part; - - if ((p->c_rfc934 = is934)) - p->c_end++; - } - } - - if (listsw) { - ct->c_end = (partnum = strlen(prefix) + 2) + 2; - if (ct->c_rfc934) - ct->c_end += 1; - - for (part = m->mp_parts; part; part = part->mp_next) - ct->c_end += part->mp_part->c_end + partnum; - } - } - break; - - case CT_MESSAGE: - /* Nothing to do for type message */ - break; - - /* - ** Discrete types (text/application/audio/image/video) - */ - default: - if (!ce->ce_file) { - pid_t child_id; - int xstdout, len, buflen; - char *bp, **ap, *cp; - char *vec[4], buffer[BUFSIZ]; - FILE *out; - CI ci = &ct->c_ctinfo; - char *tfile = NULL; - - if (!(cp = ci->ci_magic)) - adios(NULL, "internal error(5)"); - - tfile = m_mktemp2(NULL, invo_name, NULL, NULL); - if (tfile == NULL) { - adios("mhbuildsbr", "unable to create temporary file"); - } - ce->ce_file = getcpy(tfile); - ce->ce_unlink = 1; - - xstdout = 0; - - /* Get buffer ready to go */ - bp = buffer; - bp[0] = '\0'; - buflen = sizeof(buffer); - - /* - ** Parse composition string into buffer - */ - for ( ; *cp; cp++) { - if (*cp == '%') { - switch (*++cp) { - case 'a': - { - /* - ** insert parameters from - ** directive - */ - char **ep; - char *s = ""; - - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - snprintf(bp, buflen, "%s%s=\"%s\"", s, *ap, *ep); - len = strlen(bp); - bp += len; - buflen -= len; - s = " "; - } - } - break; - - case 'F': - /* %f, and stdout is not-redirected */ - xstdout = 1; - /* and fall... */ - - case 'f': - /* - ** insert temporary filename - ** where content should be - ** written - */ - snprintf(bp, buflen, "%s", ce->ce_file); - break; - - case 's': - /* insert content subtype */ - strncpy(bp, ci->ci_subtype, buflen); - break; - - case '%': - /* insert character % */ - goto raw; - - default: - *bp++ = *--cp; - *bp = '\0'; - buflen--; - continue; - } - len = strlen(bp); - bp += len; - buflen -= len; - } else { -raw: - *bp++ = *cp; - *bp = '\0'; - buflen--; - } - } - - if (verbosw) - printf("composing content %s/%s from command\n\t%s\n", ci->ci_type, ci->ci_subtype, buffer); - - fflush(stdout); /* not sure if need for -noverbose */ - - vec[0] = "/bin/sh"; - vec[1] = "-c"; - vec[2] = buffer; - vec[3] = NULL; - - if ((out = fopen(ce->ce_file, "w")) == NULL) - adios(ce->ce_file, "unable to open for writing"); - - switch (child_id = fork()) { - case NOTOK: - adios("fork", "unable to fork"); - /* NOTREACHED */ - - case OK: - if (!xstdout) - dup2(fileno(out), 1); - close(fileno(out)); - execvp("/bin/sh", vec); - fprintf(stderr, "unable to exec "); - perror("/bin/sh"); - _exit(-1); - /* NOTREACHED */ - - default: - fclose(out); - if (pidXwait(child_id, NULL)) - done(1); - break; - } - } - - /* Check size of file */ - if (listsw && ct->c_end == 0L) { - struct stat st; - - if (stat(ce->ce_file, &st) != NOTOK) - ct->c_end = (long) st.st_size; - } - break; - } - - return OK; -} - - -/* -** Scan the content. -** -** 1) choose a transfer encoding. -** 2) check for clashes with multipart boundary string. -** 3) for text content, figure out which character set is being used. -** -** If there is a clash with one of the contents and the multipart boundary, -** this function will exit with NOTOK. This will cause the scanning process -** to be repeated with a different multipart boundary. It is possible -** (although highly unlikely) that this scan will be repeated multiple times. -*/ - -static int -scan_content(CT ct) -{ - int len; - int check8bit = 0, contains8bit = 0; /* check if contains 8bit data */ - int checklinelen = 0, linelen = 0; /* check for long lines */ - int checkboundary = 0, boundaryclash = 0; /* check if clashes with multipart boundary */ - int checklinespace = 0, linespace = 0; /* check if any line ends with space */ - int checkebcdic = 0, ebcdicunsafe = 0; /* check if contains ebcdic unsafe characters */ - unsigned char *cp = NULL, buffer[BUFSIZ]; - struct text *t = NULL; - FILE *in = NULL; - CE ce = ct->c_cefile; - - /* - ** handle multipart by scanning all subparts - ** and then checking their encoding. - */ - if (ct->c_type == CT_MULTIPART) { - struct multipart *m = (struct multipart *) ct->c_ctparams; - struct part *part; - - /* initially mark the domain of enclosing multipart as 7bit */ - ct->c_encoding = CE_7BIT; - - for (part = m->mp_parts; part; part = part->mp_next) { - CT p = part->mp_part; - - if (scan_content(p) == NOTOK) { - /* choose encoding for subpart */ - return NOTOK; - } - - /* - ** if necessary, enlarge encoding for enclosing - ** multipart - */ - if (p->c_encoding == CE_BINARY) - ct->c_encoding = CE_BINARY; - if (p->c_encoding == CE_8BIT && - ct->c_encoding != CE_BINARY) - ct->c_encoding = CE_8BIT; - } - - return OK; - } - - /* - ** Decide what to check while scanning this content. - */ - switch (ct->c_type) { - case CT_TEXT: - check8bit = 1; - checkboundary = 1; - if (ct->c_subtype == TEXT_PLAIN) { - checkebcdic = 0; - checklinelen = 0; - checklinespace = 0; - } else { - checkebcdic = ebcdicsw; - checklinelen = 1; - checklinespace = 1; - } - break; - - case CT_APPLICATION: - check8bit = 1; - checkebcdic = ebcdicsw; - checklinelen = 1; - checklinespace = 1; - checkboundary = 1; - break; - - case CT_MESSAGE: - check8bit = 0; - checkebcdic = 0; - checklinelen = 0; - checklinespace = 0; - - /* don't check anything for message/external */ - if (ct->c_subtype == MESSAGE_EXTERNAL) - checkboundary = 0; - else - checkboundary = 1; - break; - - case CT_AUDIO: - case CT_IMAGE: - case CT_VIDEO: - /* - ** Don't check anything for these types, - ** since we are forcing use of base64. - */ - check8bit = 0; - checkebcdic = 0; - checklinelen = 0; - checklinespace = 0; - checkboundary = 0; - break; - } - - /* - ** Scan the unencoded content - */ - if (check8bit || checklinelen || checklinespace || checkboundary) { - if ((in = fopen(ce->ce_file, "r")) == NULL) - adios(ce->ce_file, "unable to open for reading"); - len = strlen(prefix); - - while (fgets(buffer, sizeof(buffer) - 1, in)) { - /* - ** Check for 8bit data. - */ - if (check8bit) { - for (cp = buffer; *cp; cp++) { - if (!isascii(*cp)) { - contains8bit = 1; - /* no need to keep checking */ - check8bit = 0; - } - /* - ** Check if character is ebcdic-safe. - ** We only check this if also checking - ** for 8bit data. - */ - if (checkebcdic && !ebcdicsafe[*cp & 0xff]) { - ebcdicunsafe = 1; - /* no need to keep checking */ - checkebcdic = 0; - } - } - } - - /* - ** Check line length. - */ - if (checklinelen && (strlen(buffer) > CPERLIN + 1)) { - linelen = 1; - checklinelen = 0; /* no need to keep checking */ - } - - /* - ** Check if line ends with a space. - */ - if (checklinespace && - (cp = buffer + strlen(buffer) - 2) > - buffer && isspace(*cp)) { - linespace = 1; - /* no need to keep checking */ - checklinespace = 0; - } - - /* - ** Check if content contains a line that clashes - ** with our standard boundary for multipart messages. - */ - if (checkboundary && buffer[0] == '-' && - buffer[1] == '-') { - for (cp = buffer + strlen(buffer) - 1; - cp >= buffer; cp--) - if (!isspace(*cp)) - break; - *++cp = '\0'; - if (strncmp(buffer + 2, prefix, len)==0 && - isdigit(buffer[2 + len])) { - boundaryclash = 1; - /* no need to keep checking */ - checkboundary = 0; - } - } - } - fclose(in); - } - - /* - ** Decide which transfer encoding to use. - */ - switch (ct->c_type) { - case CT_TEXT: - /* - ** If the text content didn't specify a character - ** set, we need to figure out which one was used. - */ - t = (struct text *) ct->c_ctparams; - if (t->tx_charset == CHARSET_UNSPECIFIED) { - CI ci = &ct->c_ctinfo; - char **ap, **ep; - - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) - continue; - - if (contains8bit) { - t->tx_charset = CHARSET_UNKNOWN; - *ap = concat("charset=", write_charset_8bit(), - NULL); - } else { - t->tx_charset = CHARSET_USASCII; - *ap = getcpy("charset=us-ascii"); - } - - cp = strchr(*ap++, '='); - *ap = NULL; - *cp++ = '\0'; - *ep = cp; - } - - if (contains8bit || ebcdicunsafe || linelen || linespace || - checksw) - ct->c_encoding = CE_QUOTED; - else - ct->c_encoding = CE_7BIT; - break; - - case CT_APPLICATION: - /* For application type, use base64, except when postscript */ - if (contains8bit || ebcdicunsafe || linelen || linespace || - checksw) - ct->c_encoding = (ct->c_subtype == - APPLICATION_POSTSCRIPT) ? - CE_QUOTED : CE_BASE64; - else - ct->c_encoding = CE_7BIT; - break; - - case CT_MESSAGE: - ct->c_encoding = CE_7BIT; - break; - - case CT_AUDIO: - case CT_IMAGE: - case CT_VIDEO: - /* For audio, image, and video contents, just use base64 */ - ct->c_encoding = CE_BASE64; - break; - } - - return (boundaryclash ? NOTOK : OK); -} - - -/* -** Scan the content structures, and build header -** fields that will need to be output into the -** message. -*/ - -static int -build_headers(CT ct) -{ - int cc, mailbody, len; - char **ap, **ep; - char *np, *vp, buffer[BUFSIZ]; - CI ci = &ct->c_ctinfo; - - /* - ** If message is type multipart, then add the multipart - ** boundary to the list of attribute/value pairs. - */ - if (ct->c_type == CT_MULTIPART) { - char *cp; - static int level = 0; /* store nesting level */ - - ap = ci->ci_attrs; - ep = ci->ci_values; - snprintf(buffer, sizeof(buffer), "boundary=%s%d", - prefix, level++); - cp = strchr(*ap++ = getcpy(buffer), '='); - *ap = NULL; - *cp++ = '\0'; - *ep = cp; - } - - /* - ** Skip the output of Content-Type, parameters, content - ** description and disposition, and Content-ID if the - ** content is of type "message" and the rfc934 compatibility - ** flag is set (which means we are inside multipart/digest - ** and the switch -rfc934mode was given). - */ - if (ct->c_type == CT_MESSAGE && ct->c_rfc934) - goto skip_headers; - - /* - ** output the content type and subtype - */ - np = getcpy(TYPE_FIELD); - vp = concat(" ", ci->ci_type, "/", ci->ci_subtype, NULL); - - /* keep track of length of line */ - len = strlen(TYPE_FIELD) + strlen(ci->ci_type) + - strlen(ci->ci_subtype) + 3; - - mailbody = ct->c_type == CT_MESSAGE && - ct->c_subtype == MESSAGE_EXTERNAL && - ((struct exbody *) ct->c_ctparams)->eb_body; - - /* - ** Append the attribute/value pairs to - ** the end of the Content-Type line. - */ - for (ap = ci->ci_attrs, ep = ci->ci_values; *ap; ap++, ep++) { - if (mailbody && !mh_strcasecmp(*ap, "body")) - continue; - - vp = add(";", vp); - len++; - - snprintf(buffer, sizeof(buffer), "%s=\"%s\"", *ap, *ep); - if (len + 1 + (cc = strlen(buffer)) >= CPERLIN) { - vp = add("\n\t", vp); - len = 8; - } else { - vp = add(" ", vp); - len++; - } - vp = add(buffer, vp); - len += cc; - } - - /* - ** Append any RFC-822 comment to the end of - ** the Content-Type line. - */ - if (ci->ci_comment) { - snprintf(buffer, sizeof(buffer), "(%s)", ci->ci_comment); - if (len + 1 + (cc = 2 + strlen(ci->ci_comment)) >= CPERLIN) { - vp = add("\n\t", vp); - len = 8; - } else { - vp = add(" ", vp); - len++; - } - vp = add(buffer, vp); - len += cc; - } - vp = add("\n", vp); - add_header(ct, np, vp); - - /* - ** output the Content-ID, unless disabled by -nocontentid - */ - if (contentidsw && ct->c_id) { - np = getcpy(ID_FIELD); - vp = concat(" ", ct->c_id, NULL); - add_header(ct, np, vp); - } - - /* - ** output the Content-Description - */ - if (ct->c_descr) { - np = getcpy(DESCR_FIELD); - vp = concat(" ", ct->c_descr, NULL); - add_header(ct, np, vp); - } - - /* - ** output the Content-Disposition - */ - if (ct->c_dispo) { - np = getcpy(DISPO_FIELD); - vp = concat(" ", ct->c_dispo, NULL); - add_header(ct, np, vp); - } - -skip_headers: - /* - ** If this is the internal content structure for a - ** "message/external", then we are done with the - ** headers (since it has no body). - */ - if (ct->c_ctexbody) - return OK; - - /* - ** output the Content-MD5 - */ - if (checksw) { - np = getcpy(MD5_FIELD); - vp = calculate_digest(ct, (ct->c_encoding == CE_QUOTED) ? - 1 : 0); - add_header(ct, np, vp); - } - - /* - ** output the Content-Transfer-Encoding - */ - switch (ct->c_encoding) { - case CE_7BIT: - /* Nothing to output */ - break; - - case CE_8BIT: - if (ct->c_type == CT_MESSAGE) - adios(NULL, "internal error, invalid encoding"); - - np = getcpy(ENCODING_FIELD); - vp = concat(" ", "8bit", "\n", NULL); - add_header(ct, np, vp); - break; - - case CE_QUOTED: - if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) - adios(NULL, "internal error, invalid encoding"); - - np = getcpy(ENCODING_FIELD); - vp = concat(" ", "quoted-printable", "\n", NULL); - add_header(ct, np, vp); - break; - - case CE_BASE64: - if (ct->c_type == CT_MESSAGE || ct->c_type == CT_MULTIPART) - adios(NULL, "internal error, invalid encoding"); - - np = getcpy(ENCODING_FIELD); - vp = concat(" ", "base64", "\n", NULL); - add_header(ct, np, vp); - break; - - case CE_BINARY: - if (ct->c_type == CT_MESSAGE) - adios(NULL, "internal error, invalid encoding"); - - np = getcpy(ENCODING_FIELD); - vp = concat(" ", "binary", "\n", NULL); - add_header(ct, np, vp); - break; - - default: - adios(NULL, "unknown transfer encoding in content"); - break; - } - - /* - ** Additional content specific header processing - */ - switch (ct->c_type) { - case CT_MULTIPART: - { - struct multipart *m; - struct part *part; - - m = (struct multipart *) ct->c_ctparams; - for (part = m->mp_parts; part; part = part->mp_next) { - CT p; - - p = part->mp_part; - build_headers(p); - } - } - break; - - case CT_MESSAGE: - if (ct->c_subtype == MESSAGE_EXTERNAL) { - struct exbody *e; - - e = (struct exbody *) ct->c_ctparams; - build_headers(e->eb_content); - } - break; - - default: - /* Nothing to do */ - break; - } - - return OK; -} - - -static char nib2b64[0x40+1] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -static char * -calculate_digest(CT ct, int asciiP) -{ - int cc; - char buffer[BUFSIZ], *vp, *op; - unsigned char *dp; - unsigned char digest[16]; - unsigned char outbuf[25]; - FILE *in; - MD5_CTX mdContext; - CE ce = ct->c_cefile; - - /* open content */ - if ((in = fopen(ce->ce_file, "r")) == NULL) - adios(ce->ce_file, "unable to open for reading"); - - /* Initialize md5 context */ - MD5Init(&mdContext); - - /* calculate md5 message digest */ - if (asciiP) { - while (fgets(buffer, sizeof(buffer) - 1, in)) { - char c, *cp; - - cp = buffer + strlen(buffer) - 1; - if ((c = *cp) == '\n') - *cp = '\0'; - - MD5Update(&mdContext, (unsigned char *) buffer, - (unsigned int) strlen(buffer)); - - if (c == '\n') - MD5Update(&mdContext, (unsigned char *) "\r\n", - 2); - } - } else { - while ((cc = fread(buffer, sizeof(*buffer), sizeof(buffer), - in)) > 0) - MD5Update(&mdContext, (unsigned char *) buffer, - (unsigned int) cc); - } - - /* md5 finalization. Write digest and zero md5 context */ - MD5Final(digest, &mdContext); - - /* close content */ - fclose(in); - - /* print debugging info */ - if (debugsw) { - unsigned char *ep; - - fprintf(stderr, "MD5 digest="); - for (ep = (dp = digest) + sizeof(digest) / sizeof(digest[0]); - dp < ep; dp++) - fprintf(stderr, "%02x", *dp & 0xff); - fprintf(stderr, "\n"); - } - - /* encode the digest using base64 */ - for (dp = digest, op = outbuf, cc = sizeof(digest) / sizeof(digest[0]); - cc > 0; cc -= 3, op += 4) { - unsigned long bits; - char *bp; - - bits = (*dp++ & 0xff) << 16; - if (cc > 1) { - bits |= (*dp++ & 0xff) << 8; - if (cc > 2) - bits |= *dp++ & 0xff; - } - - for (bp = op + 4; bp > op; bits >>= 6) - *--bp = nib2b64[bits & 0x3f]; - if (cc < 3) { - *(op + 3) = '='; - if (cc < 2) - *(op + 2) = '='; - } - } - - /* null terminate string */ - outbuf[24] = '\0'; - - /* now make copy and return string */ - vp = concat(" ", outbuf, "\n", NULL); - return vp; -} diff --git a/uip/mhcachesbr.c b/uip/mhcachesbr.c index c6f0603..7bd4cfb 100644 --- a/uip/mhcachesbr.c +++ b/uip/mhcachesbr.c @@ -36,7 +36,7 @@ extern int debugsw; -extern pid_t xpid; /* mhshowsbr.c or mhbuildsbr.c */ +extern pid_t xpid; /* mhshowsbr.c or mhbuild.c */ /* cache policies */ int rcachesw = CACHE_ASK; @@ -50,7 +50,7 @@ char *cache_public; char *cache_private; -/* mhparse.c (OR) mhbuildsbr.c */ +/* mhparse.c (OR) mhbuild.c */ int pidcheck (int); /* mhmisc.c */ -- 1.7.10.4