{ NULL, 0 }
};
+char *version=VERSION;
+
#define NOCOMPONENT 0x000001 /* don't show component name */
#define UPPERCASE 0x000002 /* display in all upper case */
#define CENTER 0x000004 /* center line */
#define INIT 0x000800 /* initialize component */
#define SPLIT 0x001000 /* split headers (don't concatenate) */
#define NONEWLINE 0x002000 /* don't write trailing newline */
-#define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07LEFTADJUST\010COMPRESS\011ADDRFMT\012DATEFMT\013FORMAT\014INIT\015SPLIT\016NONEWLINE"
+#define RTRIM 0x004000 /* trim trailing whitespace */
+#define RAW 0x008000 /* print the raw input */
+#define LBITS "\020\01NOCOMPONENT\02UPPERCASE\03CENTER\04CLEARTEXT\05EXTRA\06HDROUTPUT\07LEFTADJUST\010COMPRESS\011ADDRFMT\012DATEFMT\013FORMAT\014INIT\015SPLIT\016NONEWLINE\017RTRIM\020RAW"
#define GFLAGS (NOCOMPONENT | UPPERCASE | CENTER | LEFTADJUST | COMPRESS | SPLIT)
struct mcomp {
static struct triple triples[] = {
{ "nocomponent", NOCOMPONENT, 0 },
- { "uppercase", UPPERCASE, 0 },
+ { "uppercase", UPPERCASE, RAW },
{ "nouppercase", 0, UPPERCASE },
- { "center", CENTER, 0 },
+ { "center", CENTER, RAW },
{ "nocenter", 0, CENTER },
- { "leftadjust", LEFTADJUST, 0 },
+ { "leftadjust", LEFTADJUST, RAW },
{ "noleftadjust", 0, LEFTADJUST },
- { "compress", COMPRESS, 0 },
+ { "compress", COMPRESS, RAW },
{ "nocompress", 0, COMPRESS },
{ "split", SPLIT, 0 },
{ "nosplit", 0, SPLIT },
- { "addrfield", ADDRFMT, DATEFMT },
- { "datefield", DATEFMT, ADDRFMT },
- { "newline", 0, NONEWLINE },
+ { "rtrim", RTRIM, RAW },
+ { "nortrim", 0, RTRIM },
+ { "raw", RAW|SPLIT|NOCOMPONENT|NONEWLINE, UPPERCASE|CENTER|LEFTADJUST|COMPRESS|DATEFMT|ADDRFMT },
+ { "addrfield", ADDRFMT, DATEFMT|RAW },
+ { "datefield", DATEFMT, ADDRFMT|RAW },
+ { "newline", 0, NONEWLINE|RAW },
{ "nonewline", NONEWLINE, 0 },
{ NULL, 0, 0 }
};
c1->c_flags &= ~HDROUTPUT;
}
+static boolean
+simplematch(char *pattern, char *b)
+{
+ char *match = strrchr(pattern, '*');
+ char repl;
+ boolean ret;
+
+ /* check if pattern ends with a * and is not escaped witch a \ */
+ if (!match || match[1] || (match > pattern && match[-1] == '\\')) {
+ if (!match || match[1]) {
+ return mh_strcasecmp(pattern, b) == 0;
+ }
+ match[0] = '\0';
+ match[-1] = '*';
+ ret = mh_strcasecmp(pattern, b)==0;
+ match[-1] = '\\';
+ match[0] = '*';
+ return ret;
+ }
+
+ repl = b[match-pattern];
+ b[match-pattern] = '\0';
+ *match = '\0';
+ ret = (mh_strcasecmp(pattern, b) == 0);
+ b[match-pattern] = repl;
+ *match = '*';
+ return ret;
+}
static void
mhlfile(FILE *fp, char *mname, int ofilen, int ofilec)
{
- int state;
+ enum state state;
+ struct field f = {{0}};
struct mcomp *c1, *c2, *c3;
- char **ip, name[NAMESZ], buf[BUFSIZ];
+ char **ip;
if (forwall) {
printf("\n-------");
- if (ofilen == 1)
+ if (ofilen == 1) {
printf(" Forwarded Message%s", ofilec > 1 ? "s" : "");
- else
+ } else {
printf(" Message %d", ofilen);
+ }
printf("\n\n");
} else if (ofilec > 1) {
if (ofilen > 1) {
printf(">>> %s\n\n", mname);
}
- for (state = FLD;!eflag;) {
- switch (state = m_getfld(state, name, buf, sizeof(buf), fp)) {
- case FLD:
- case FLDPLUS:
+ for (state = FLD2; !eflag; ) {
+ switch (state = m_getfld2(state, &f, fp)) {
+ case FLD2:
for (ip = ignores; *ip; ip++)
- if (!mh_strcasecmp(name, *ip)) {
- while (state == FLDPLUS)
- state = m_getfld(state, name, buf, sizeof(buf), fp);
+ if (simplematch(*ip, f.name)) {
break;
}
- if (*ip)
+ if (*ip) {
continue;
+ }
for (c2 = fmthd; c2; c2 = c2->c_next)
- if (!mh_strcasecmp(c2->c_name, name))
+ if (mh_strcasecmp(c2->c_name, f.name)==0) {
break;
+ }
c1 = NULL;
if (!((c3 = c2 ? c2 : &global)->c_flags & SPLIT))
for (c1 = msghd; c1; c1 = c1->c_next)
- if (!mh_strcasecmp(c1->c_name,
- c3->c_name)) {
- c1->c_text = mcomp_add(c1->c_flags, buf, c1->c_text);
+ if (mh_strcasecmp(c1->c_name,
+ c3->c_name)==0) {
+ c1->c_text = mcomp_add(c1->c_flags, f.value, c1->c_text);
break;
}
- if (c1 == NULL)
- c1 = add_queue(&msghd, &msgtl, name, buf, 0);
- while (state == FLDPLUS) {
- state = m_getfld(state, name, buf,
- sizeof(buf), fp);
- c1->c_text = add(buf, c1->c_text);
+ if (c1 == NULL) {
+ c1 = add_queue(&msghd, &msgtl, f.name, f.value, 0);
}
- if (c2 == NULL)
+ if (c2 == NULL) {
c1->c_flags |= EXTRA;
+ }
continue;
- case BODY:
- case FILEEOF:
+ case BODY2:
+ case FILEEOF2:
column = 0;
for (c1 = fmthd; c1; c1 = c1->c_next) {
if (c1->c_flags & CLEARTEXT) {
putcomp(c1, c1, ONECOMP);
continue;
}
- if (!mh_strcasecmp(c1->c_name, "messagename")) {
+ if (mh_strcasecmp(c1->c_name, "messagename")==0) {
holder.c_text = concat("(Message ",
mname, ")\n", NULL);
putcomp(c1, &holder, ONECOMP);
mh_free0(&(holder.c_text));
continue;
}
- if (!mh_strcasecmp(c1->c_name, "extras")) {
- for (c2 = msghd; c2; c2 = c2->c_next)
- if (c2->c_flags & EXTRA)
+ if (mh_strcasecmp(c1->c_name, "extras")==0) {
+ for (c2 = msghd; c2; c2 = c2->c_next) {
+ if (c2->c_flags & EXTRA) {
putcomp(c1, c2, TWOCOMP);
+ }
+ }
continue;
}
- if (dobody && !mh_strcasecmp(c1->c_name, "body")) {
- holder.c_text = mh_xcalloc(sizeof(buf), sizeof(char));
- strncpy(holder.c_text, buf, sizeof(buf));
- while (state == BODY) {
+ if (dobody && mh_strcasecmp(c1->c_name, "body")==0) {
+ holder.c_text = mh_xstrdup(f.value);
+ while (state == BODY2) {
putcomp(c1, &holder, BODYCOMP);
- state = m_getfld(state, name, holder.c_text, sizeof(buf), fp);
+ state = m_getfld2(state, &f, fp);
+ free(holder.c_text);
+ holder.c_text = mh_xstrdup(f.value);
}
mh_free0(&(holder.c_text));
continue;
}
- for (c2 = msghd; c2; c2 = c2->c_next)
- if (!mh_strcasecmp(c2->c_name,
- c1->c_name)) {
+ for (c2 = msghd; c2; c2 = c2->c_next) {
+ if (mh_strcasecmp(c2->c_name,
+ c1->c_name)==0) {
putcomp(c1, c2, ONECOMP);
- if (!(c1->c_flags & SPLIT))
+ if (!(c1->c_flags & SPLIT)) {
break;
+ }
}
+ }
}
return;
- case LENERR:
- case FMTERR:
+ case LENERR2:
+ case FMTERR2:
+ case IOERR2:
advise(NULL, "format error in message %s", mname);
exitstat++;
return;
*head = *tail = NULL;
}
-
static void
putcomp(struct mcomp *c1, struct mcomp *c2, int flag)
{
int count, cchdr;
unsigned char *cp;
+ char trimmed_prefix[BUFSIZ];
+ strncpy(trimmed_prefix, c1->c_text ? c1->c_text : c1->c_name, sizeof(trimmed_prefix) - 1);
+ rtrim(trimmed_prefix);
cchdr = 0;
lm = 0;
wid = c1->c_width ? c1->c_width : global.c_width;
onelp = NULL;
if (c1->c_flags & CLEARTEXT) {
- putstr(c1->c_text);
+ putstr((c1->c_flags & RTRIM) ? rtrim(c1->c_text) : c1->c_text);
putstr("\n");
return;
}
+ if (c1->c_flags & RAW) {
+ switch (flag) {
+ case ONECOMP:
+ printf("%s:%s", c1->c_name, c1->c_text);
+ break;
+ case TWOCOMP:
+ printf("%s:%s", c2->c_name, c2->c_text);
+ break;
+ case BODYCOMP:
+ fputs(c2->c_text, stdout);
+ break;
+ default:
+ adios(EX_SOFTWARE, NULL, "BUG: putcomp() is called with a unknown flag");
+ }
+ return;
+ }
+
if (c1->c_fstr && (c1->c_flags & (ADDRFMT | DATEFMT | FORMAT)))
mcomp_format(c1, c2);
for (cp = (c1->c_text ? c1->c_text : c1->c_name); *cp; cp++)
if (islower(*cp))
*cp = toupper(*cp);
- putstr(c1->c_text ? c1->c_text : c1->c_name);
+ if (*c2->c_text && *c2->c_text != '\n' && *c2->c_text != '\r') {
+ putstr(c1->c_text ? c1->c_text : c1->c_name);
+ } else {
+ putstr(trimmed_prefix);
+ }
if (flag != BODYCOMP) {
putstr(": ");
if (!(c1->c_flags & SPLIT))
}
count += c1->c_offset;
- if ((cp = oneline(c2->c_text, c1->c_flags)))
- putstr(cp);
+ if ((cp = oneline(c2->c_text, c1->c_flags))) {
+ putstr((c1->c_flags & RTRIM) ? rtrim(cp) : cp);
+ }
if (term == '\n')
putstr("\n");
while ((cp = oneline(c2->c_text, c1->c_flags))) {
lm = count;
- if (flag == BODYCOMP && !(c1->c_flags & NOCOMPONENT))
- putstr(c1->c_text ? c1->c_text : c1->c_name);
+ if (flag == BODYCOMP && !(c1->c_flags & NOCOMPONENT)) {
+ if (*cp) {
+ putstr(c1->c_text ? c1->c_text : c1->c_name);
+ } else {
+ putstr(trimmed_prefix);
+ }
+ }
if (*cp)
- putstr(cp);
+ putstr((c1->c_flags & RTRIM) ? rtrim(cp) : cp);
+
if (term == '\n')
putstr("\n");
}
c1->c_flags &= ~HDROUTPUT; /* Buffer ended on a newline */
}
-
static char *
oneline(char *stuff, long flags)
{
return ret;
}
-
static void
putstr(char *string)
{