+ return status;
+}
+
+/*
+ * Compile our format string and save any parameters we care about.
+ */
+
+#define DEFAULT_HEADER "[ Message %{folder}%<{folder}:%>%(msg) ]"
+#define DEFAULT_MARKER "[ part %{part} - %{content-type} - " \
+ "%<{description}%{description}" \
+ "%?{cdispo-filename}%{cdispo-filename}" \
+ "%|%{ctype-name}%> " \
+ "%(kilo(size))B %<(unseen)\\(suppressed\\)%> ]"
+
+static struct format *
+compile_header(char *form)
+{
+ struct format *fmt;
+ char *fmtstring;
+ struct comp *comp = NULL;
+ unsigned int bucket;
+
+ fmtstring = new_fs(form, NULL, DEFAULT_HEADER);
+
+ (void) fmt_compile(fmtstring, &fmt, 1);
+ free_fs();
+
+ while ((comp = fmt_nextcomp(comp, &bucket)) != NULL) {
+ if (strcasecmp(comp->c_name, "folder") == 0) {
+ folder_comp = comp;
+ }
+ }
+
+ return fmt;
+}
+
+static struct format *
+compile_marker(char *form)
+{
+ struct format *fmt;
+ char *fmtstring;
+ struct comp *comp = NULL;
+ unsigned int bucket;
+ struct param_comp_list *pc_entry;
+
+ fmtstring = new_fs(form, NULL, DEFAULT_MARKER);
+
+ (void) fmt_compile(fmtstring, &fmt, 1);
+ free_fs();
+
+ /*
+ * Things we care about:
+ *
+ * part - Part name (e.g., 1.1)
+ * content-type - Content-Type
+ * description - Content-Description
+ * disposition - Content-Disposition (inline, attachment)
+ * ctype-<param> - Content-Type parameter
+ * cdispo-<param> - Content-Disposition parameter
+ */
+
+ while ((comp = fmt_nextcomp(comp, &bucket)) != NULL) {
+ if (strcasecmp(comp->c_name, "part") == 0) {
+ part_comp = comp;
+ } else if (strcasecmp(comp->c_name, "content-type") == 0) {
+ ctype_comp = comp;
+ } else if (strcasecmp(comp->c_name, "description") == 0) {
+ description_comp = comp;
+ } else if (strcasecmp(comp->c_name, "disposition") == 0) {
+ dispo_comp = comp;
+ } else if (strncasecmp(comp->c_name, "ctype-", 6) == 0 &&
+ strlen(comp->c_name) > 6) {
+ NEW(pc_entry);
+ pc_entry->param = mh_xstrdup(comp->c_name + 6);
+ pc_entry->comp = comp;
+ pc_entry->next = ctype_pc_list;
+ ctype_pc_list = pc_entry;
+ } else if (strncasecmp(comp->c_name, "cdispo-", 7) == 0 &&
+ strlen(comp->c_name) > 7) {
+ NEW(pc_entry);
+ pc_entry->param = mh_xstrdup(comp->c_name + 7);
+ pc_entry->comp = comp;
+ pc_entry->next = dispo_pc_list;
+ dispo_pc_list = pc_entry;
+ }
+ }
+
+ return fmt;
+}
+
+/*
+ * Output on stdout an appropriate marker for this content, using mh-format
+ */
+
+static void
+output_header(CT ct, struct format *fmt)
+{
+ charstring_t outbuf = charstring_create (BUFSIZ);
+ int dat[5] = { 0 };
+ char *endp;
+ int message = 0;
+
+ if (folder_comp)
+ folder_comp->c_text = getcpy(folder);
+
+ if (ct->c_file && *ct->c_file) {
+ message = strtol(ct->c_file, &endp, 10);
+ if (*endp) message = 0;
+ dat[0] = message;
+ }
+
+ /* it would be nice to populate dat[2], for %(size) here,
+ * but it's not available. it might also be nice to know
+ * if the message originally had any mime parts or not -- but
+ * there's also no record of that. (except for MIME-version:)
+ */
+
+ fmt_scan(fmt, outbuf, BUFSIZ, dat, NULL);
+
+ fputs(charstring_buffer (outbuf), stdout);
+ charstring_free (outbuf);
+
+ fmt_freecomptext();
+}
+
+static void
+output_marker(CT ct, struct format *fmt, int hidden)
+{
+ charstring_t outbuf = charstring_create (BUFSIZ);
+ struct param_comp_list *pcentry;
+ int partsize;
+ int message = 0;
+ char *endp;
+ int dat[5] = { 0 };
+
+ /*
+ * Grab any items we care about.
+ */
+
+ if (ctype_comp && ct->c_ctinfo.ci_type) {
+ ctype_comp->c_text = concat(ct->c_ctinfo.ci_type, "/",
+ ct->c_ctinfo.ci_subtype, NULL);
+ }
+
+ if (part_comp && ct->c_partno) {
+ part_comp->c_text = mh_xstrdup(ct->c_partno);
+ }
+
+ if (description_comp && ct->c_descr) {
+ description_comp->c_text = mh_xstrdup(ct->c_descr);
+ }
+
+ if (dispo_comp && ct->c_dispo_type) {
+ dispo_comp->c_text = mh_xstrdup(ct->c_dispo_type);
+ }
+
+ for (pcentry = ctype_pc_list; pcentry != NULL; pcentry = pcentry->next) {
+ pcentry->comp->c_text = get_param(ct->c_ctinfo.ci_first_pm,
+ pcentry->param, '?', 0);
+ }
+
+ for (pcentry = dispo_pc_list; pcentry != NULL; pcentry = pcentry->next) {
+ pcentry->comp->c_text = get_param(ct->c_dispo_first,
+ pcentry->param, '?', 0);
+ }
+
+ if (ct->c_cesizefnx)
+ partsize = (*ct->c_cesizefnx) (ct);
+ else
+ partsize = ct->c_end - ct->c_begin;
+
+ if (ct->c_file && *ct->c_file) {
+ message = strtol(ct->c_file, &endp, 10);
+ if (*endp) message = 0;
+ dat[0] = message;
+ }
+ dat[2] = partsize;
+
+ /* make the part's hidden aspect available by overloading the
+ * %(unseen) function. make the part's size available via %(size).
+ * see comments in h/fmt_scan.h.
+ */
+ dat[4] = hidden;
+
+ fmt_scan(fmt, outbuf, BUFSIZ, dat, NULL);
+
+ fputs(charstring_buffer (outbuf), stdout);
+ charstring_free (outbuf);
+
+ fmt_freecomptext();
+}
+
+/*
+ * Reset (and free) any of the saved marker text
+ */
+
+static void
+free_markercomps(void)
+{
+ struct param_comp_list *pc_entry, *pc2;
+
+ folder_comp = NULL;
+ part_comp = NULL;
+ ctype_comp = NULL;
+ description_comp = NULL;
+ dispo_comp = NULL;
+
+ for (pc_entry = ctype_pc_list; pc_entry != NULL; ) {
+ free(pc_entry->param);
+ pc2 = pc_entry->next;
+ free(pc_entry);
+ pc_entry = pc2;
+ }
+
+ for (pc_entry = dispo_pc_list; pc_entry != NULL; ) {
+ free(pc_entry->param);
+ pc2 = pc_entry->next;
+ free(pc_entry);
+ pc_entry = pc2;
+ }