--- sbr/readconfig.c 2002/11/17 17:11:03 0.0 +++ sbr/readconfig.c 2002/11/17 17:11:42 0.1 @@ -45,9 +45,10 @@ void readconfig (struct node **npp, FILE *ib, char *file, int ctx) { - register int state; + register int state, line; register char *cp; char name[NAMESZ], field[BUFSIZ]; + char *fname; register struct node *np; register struct procstr *ps; @@ -56,7 +57,10 @@ return; } + fname = getcpy (file); + line = 0; for (state = FLD;;) { + line++; switch (state = m_getfld (state, name, field, sizeof(field), ib)) { case FLD: case FLDPLUS: @@ -69,6 +73,7 @@ if (state == FLDPLUS) { cp = getcpy (field); while (state == FLDPLUS) { + line++; state = m_getfld (state, name, field, sizeof(field), ib); cp = add (field, cp); } @@ -78,6 +83,8 @@ np->n_field = trimcpy (field); } np->n_context = ctx; + np->n_lineno = line; + np->n_filename = fname; /* * Now scan the list of `procs' and link in the --- h/mh.h 2002/12/02 19:50:02 0.0 +++ h/mh.h 2002/12/02 19:51:12 0.1 @@ -33,10 +33,12 @@ * user context/profile structure */ struct node { - char *n_name; /* key */ - char *n_field; /* value */ - char n_context; /* context, not profile */ - struct node *n_next; /* next entry */ + char *n_name; /* key */ + char *n_field; /* value */ + boolean n_context; /* context, not profile */ + short n_lineno; /* approx line # in file */ + char *n_filename; /* file name */ + struct node *n_next; /* next entry */ }; /* --- /dev/null Mon Dec 2 14:40:23 2002 +++ sbr/context_get.c Mon Dec 2 14:38:12 2002 @@ -0,0 +1,84 @@ + +/* + * context_get.c -- iterate through entries in the context/profile list + * + * $Id: context_get.c,v 0.0 2002/12/02 19:37:33 jepeway Exp $ + */ + +#include <h/mh.h> + +/* + * Starting with np, find the next node + * that has a name with a prefix of str + */ +static struct node * +context_node_pfx (char *str, struct node *np) +{ + int l; + + /* sanity check - check that context has been read */ + if (defpath == NULL) + adios (NULL, "oops, context hasn't been read yet"); + + l = strlen (str); + while (np) { + if (!strncasecmp (np->n_name, str, l) && + strlen(np->n_name) >= l) /* n_name not a prefix of str */ + return (np); + np = np->n_next; + } + + return (NULL); +} + +/* + * Return first entry that has a prefix of str + */ +void * +context_get (char *str) +{ + return ((void *) context_node_pfx (str, m_defs)); +} + +/* + * Return next entry after v that has a prefix of str + */ +void * +context_getnext (char *str, void *v) +{ + struct node *np = (struct node *) v; + return (np == NULL ? NULL : (void *) context_node_pfx (str, np->n_next)); +} + +/* + * Return the name of a context entry + */ +char * +context_name (void *v) +{ + struct node *np = (struct node *) v; + + return (np == NULL ? NULL : np->n_name); +} + +/* + * Return the line number of a context entry + */ +int +context_lineno (void *v) +{ + struct node *np = (struct node *) v; + + return (np == NULL ? NULL : np->n_lineno); +} + +/* + * Return the file name of a context entry + */ +char * +context_filename (void *v) +{ + struct node *np = (struct node *) v; + + return (np == NULL ? NULL : np->n_filename); +} --- sbr/Makefile.in 2002/11/17 17:07:09 0.0 +++ sbr/Makefile.in 2002/12/02 19:43:32 0.1 @@ -38,7 +38,7 @@ # source for library functions SRCS = add.c addrsbr.c ambigsw.c atooi.c brkstring.c check_charset.c \ closefds.c concat.c context_del.c context_find.c context_foil.c \ - context_read.c context_replace.c context_save.c copy.c \ + context_get.c context_read.c context_replace.c context_save.c copy.c \ copyip.c cpydata.c cpydgst.c discard.c done.c error.c \ fdcompare.c folder_addmsg.c folder_delmsgs.c folder_free.c \ folder_pack.c folder_read.c folder_realloc.c gans.c \ @@ -59,7 +59,7 @@ OBJS = add.o addrsbr.o ambigsw.o atooi.o brkstring.o check_charset.o \ closefds.o concat.o context_del.o context_find.o context_foil.o \ - context_read.o context_replace.o context_save.o copy.o \ + context_get.o context_read.o context_replace.o context_save.o copy.o \ copyip.o cpydata.o cpydgst.o discard.o done.o error.o \ fdcompare.o folder_addmsg.o folder_delmsgs.o folder_free.o \ folder_pack.o folder_read.o folder_realloc.o gans.o \ --- h/prototypes.h 2002/12/02 19:26:28 0.0 +++ h/prototypes.h 2002/12/02 20:16:58 0.1 @@ -38,6 +38,11 @@ char *concat (char *, ...); int context_del (char *); char *context_find (char *); +void *context_get (char *); +void *context_getnext (char *, void *); +char *context_name (void *); +char *context_filename (void *); +int context_line (char *); int context_foil (char *); void context_read (void); void context_replace (char *, char *); --- uip/mhshowsbr.c 2002/11/17 16:46:41 0.0 +++ uip/mhshowsbr.c 2002/12/02 19:19:08 @@ -33,6 +33,8 @@ extern int errno; extern int debugsw; +extern char *types[NTYPES + 1]; +extern int ntype; int pausesw = 1; int serialsw = 0; @@ -44,6 +46,10 @@ int nomore = 0; char *formsw = NULL; +/* list of types in order of preference when displaying multipart/alternative */ +static char *preferred_types[NTYPES+1]; +static char **pref_types = NULL; + pid_t xpid = 0; static sigjmp_buf intrenv; @@ -87,6 +93,8 @@ static int show_partial (CT, int, int); static int show_external (CT, int, int); static RETSIGTYPE intrser (int); +static void sort_alt_parts (struct multipart *, char **); +static char **get_pref_types(char **); /* @@ -111,6 +119,12 @@ if (!strcmp (formsw, "mhl.null")) formsw = NULL; + /* + * Build preferences for types in multipart/alternative + */ + if (pref_types == NULL) + pref_types = get_pref_types(preferred_types); + for (ctp = cts; *ctp; ctp++) { ct = *ctp; @@ -285,6 +299,32 @@ return 0; /* NOT REACHED */ } +/* + * Build list of preferred types by from + * all *-show-type/subtype entries in config + */ +static char ** +get_pref_types (char **pt) +{ + char *s, buffer[BUFSIZ]; + char **t = pt; + void *ctx; + int len; + + strcpy(buffer, invo_name); + strcat(buffer, "-show-"); + len = strlen(buffer); + + /* Iterate over all aux show procs, adding them to *pt */ + for (ctx = context_get(buffer); + ctx; + ctx = context_getnext(buffer, ctx)) { + *t++ = context_name(ctx) + len; + } + + *t = NULL; + return pt; +} /* * Generic method for displaying content @@ -687,6 +727,70 @@ return NOTOK; } +/* + * sort a msg's alternate parts according to their + * order of appearance in the type_prefs array + */ +static void +sort_alt_parts (struct multipart *m, char **type_prefs) +{ + struct part **hd, *p, *next, *prev; + char **t; + char buffer[BUFSIZ]; + CI ci; + + if (type_prefs == NULL) + return; + + if (debugsw) { + fputs("types are:\n", stderr); + for (t = type_prefs; *t; t++) + fprintf(stderr, "\t\n", *t); + fputs("order was:\n", stderr); + for (p = m->mp_parts; p; p = p->mp_next) { + ci = &p->mp_part->c_ctinfo; + fprintf(stderr, "\t0 -> /\n", p, ci->ci_type, ci->ci_subtype); + } + } + + hd = &m->mp_parts; + t = type_prefs; + while (*t && *hd) { + /* drag all msg parts of type *t to front of list */ + prev = NULL; + for (p = *hd; p; prev = p, p = p->mp_next) { + ci = &p->mp_part->c_ctinfo; + snprintf (buffer, sizeof(buffer), + "/", ci->ci_type, ci->ci_subtype); + if (strcasecmp (*t, ci->ci_type) && strcasecmp (*t, buffer)) + continue; + + /* move p to front of list */ + if (prev != NULL) { + /* remove p */ + prev->mp_next = p->mp_next; + + /* insert p at head */ + next = *hd; + *hd = p; + (*hd)->mp_next = next; + } + + /* skip past new head, as we never want to move it again */ + hd = &(*hd)->mp_next; + } + + t++; + } + + if (debugsw) { + fputs("order is:\n", stderr); + for (p = m->mp_parts; p; p = p->mp_next) { + ci = &p->mp_part->c_ctinfo; + fprintf(stderr, "\t0 -> /\n", p, ci->ci_type, ci->ci_subtype); + } + } +} /* * show message body of subtypes of multipart that @@ -708,6 +812,11 @@ if (ct->c_subtype == MULTI_PARALLEL) { nowserial = serialsw; } else if (ct->c_subtype == MULTI_ALTERNATE) { + /* sort according to mhn.defaults... */ + sort_alt_parts(m, pref_types); + /* ...but types on cmd-line take precedence */ + sort_alt_parts(m, types); + nowalternate = 1; alternating = 1; nowserial = serial;