X-Git-Url: https://diplodocus.org/git/nmh/blobdiff_plain/f65f8722914d9cfba9317439d9712957719a35b4..ea855e72d026c72658d43f993fc62cfcf2de2ca3:/sbr/mf.c diff --git a/sbr/mf.c b/sbr/mf.c index c7959103..d99d2b38 100644 --- a/sbr/mf.c +++ b/sbr/mf.c @@ -2,20 +2,18 @@ /* * mf.c -- mail filter subroutines * - * $Id$ + * 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. */ #include -#include -#include +#include /* * static prototypes */ -static char *getcpy (char *); -static char *add (char *, char *); -static void compress (char *, char *); -static int isat (char *); +static int isat (const char *); static int parse_address (void); static int phrase (char *); static int route_addr (char *); @@ -25,41 +23,8 @@ static int route (char *); static int my_lex (char *); -static char * -getcpy (char *s) -{ - register char *p; - - if (!s) { -/* causes compiles to blow up because the symbol _cleanup is undefined - where did this ever come from? */ - /* _cleanup(); */ - abort(); - for(;;) - pause(); - } - if ((p = malloc ((size_t) (strlen (s) + 2)))) - strcpy (p, s); - return p; -} - - -static char * -add (char *s1, char *s2) -{ - register char *p; - - if (!s2) - return getcpy (s1); - - if ((p = malloc ((size_t) (strlen (s1) + strlen (s2) + 2)))) - sprintf (p, "%s%s", s2, s1); - free (s2); - return p; -} - int -isfrom(char *string) +isfrom(const char *string) { return (strncmp (string, "From ", 5) == 0 || strncmp (string, ">From ", 6) == 0); @@ -67,14 +32,16 @@ isfrom(char *string) int -lequal (char *a, char *b) +lequal (const char *a, const char *b) { for (; *a; a++, b++) if (*b == 0) return FALSE; else { - char c1 = islower (*a) ? toupper (*a) : *a; - char c2 = islower (*b) ? toupper (*b) : *b; + char c1 = islower ((unsigned char) *a) ? + toupper ((unsigned char) *a) : *a; + char c2 = islower ((unsigned char) *b) ? + toupper ((unsigned char) *b) : *b; if (c1 != c2) return FALSE; } @@ -83,158 +50,8 @@ lequal (char *a, char *b) } -/* - * seekadrx() is tricky. We want to cover both UUCP-style and ARPA-style - * addresses, so for each list of addresses we see if we can find some - * character to give us a hint. - */ - - -#define CHKADR 0 /* undertermined address style */ -#define UNIXDR 1 /* UNIX-style address */ -#define ARPADR 2 /* ARPAnet-style address */ - - -static char *punctuators = ";<>.()[]"; -static char *vp = NULL; -static char *tp = NULL; - -static struct adrx adrxs1; - - -struct adrx * -seekadrx (char *addrs) -{ - static int state = CHKADR; - register char *cp; - register struct adrx *adrxp; - - if (state == CHKADR) - for (state = UNIXDR, cp = addrs; *cp; cp++) - if (strchr(punctuators, *cp)) { - state = ARPADR; - break; - } - - switch (state) { - case UNIXDR: - adrxp = uucpadrx (addrs); - break; - - case ARPADR: - default: - adrxp = getadrx (addrs); - break; - } - - if (adrxp == NULL) - state = CHKADR; - - return adrxp; -} - - -/* - * uucpadrx() implements a partial UUCP-style address parser. It's based - * on the UUCP notion that addresses are separated by spaces or commas. - */ - - -struct adrx * -uucpadrx (char *addrs) -{ - register char *cp, *wp, *xp, *yp, *zp; - register struct adrx *adrxp = &adrxs1; - - if (vp == NULL) { - vp = tp = getcpy (addrs); - compress (addrs, vp); - } - else - if (tp == NULL) { - free (vp); - vp = NULL; - return NULL; - } - - for (cp = tp; isspace (*cp); cp++) - continue; - if (*cp == 0) { - free (vp); - vp = tp = NULL; - return NULL; - } - - if ((wp = strchr(cp, ',')) == NULL) { - if ((wp = strchr(cp, ' ')) != NULL) { - xp = wp; - while (isspace (*xp)) - xp++; - if (*xp != 0 && isat (--xp)) { - yp = xp + 4; - while (isspace (*yp)) - yp++; - if (*yp != 0) { - if ((zp = strchr(yp, ' ')) != NULL) - *zp = 0, tp = ++zp; - else - tp = NULL; - } - else - *wp = 0, tp = ++wp; - } - else - *wp = 0, tp = ++wp; - } - else - tp = NULL; - } - else - *wp = 0, tp = ++wp; - - if (adrxp->text) - free (adrxp->text); - adrxp->text = getcpy (cp); - adrxp->mbox = cp; - adrxp->host = adrxp->path = NULL; - if ((wp = strrchr(cp, '@')) != NULL) { - *wp++ = 0; - adrxp->host = *wp ? wp : NULL; - } - else - for (wp = cp + strlen (cp) - 4; wp >= cp; wp--) - if (isat (wp)) { - *wp++ = 0; - adrxp->host = wp + 3; - } - - adrxp->pers = adrxp->grp = adrxp->note = adrxp->err = NULL; - adrxp->ingrp = 0; - - return adrxp; -} - - -static void -compress (char *fp, char *tp) -{ - register char c, *cp; - - for (c = ' ', cp = tp; (*tp = *fp++) != 0;) - if (isspace (*tp)) { - if (c != ' ') - *tp++ = c = ' '; - } - else - c = *tp++; - - if (c == ' ' && cp < tp) - *--tp = 0; -} - - static int -isat (char *p) +isat (const char *p) { return (strncmp (p, " AT ", 4) && strncmp (p, " At ", 4) @@ -358,7 +175,7 @@ static struct adrx adrxs2; struct adrx * -getadrx (char *addrs) +getadrx (const char *addrs) { register char *bp; register struct adrx *adrxp = &adrxs2; @@ -379,7 +196,7 @@ getadrx (char *addrs) err[0] = 0; if (dp == NULL) { - dp = cp = getcpy (addrs ? addrs : ""); + dp = cp = strdup (addrs ? addrs : ""); glevel = 0; } else @@ -413,6 +230,15 @@ getadrx (char *addrs) break; } + /* + * Reject the address if key fields contain 8bit characters + */ + + if (contains8bit(mbox, NULL) || contains8bit(host, NULL) || + contains8bit(path, NULL) || contains8bit(grp, NULL)) { + strcpy(err, "Address contains 8-bit characters"); + } + if (err[0]) for (;;) { switch (last_lex) { @@ -426,10 +252,10 @@ getadrx (char *addrs) } break; } - while (isspace (*ap)) + while (isspace ((unsigned char) *ap)) ap++; if (cp) - sprintf (adr, "%.*s", cp - ap, ap); + sprintf (adr, "%.*s", (int)(cp - ap), ap); else strcpy (adr, ap); bp = adr + strlen (adr) - 1; @@ -460,7 +286,7 @@ again: ; switch (my_lex (buffer)) { case LX_ATOM: case LX_QSTR: - pers = getcpy (buffer); + pers = strdup (buffer); break; case LX_SEMI: @@ -714,7 +540,7 @@ domain (char *buffer) static int route (char *buffer) { - path = getcpy ("@"); + path = strdup ("@"); for (;;) { switch (my_lex (buffer)) { @@ -767,8 +593,12 @@ route (char *buffer) static int my_lex (char *buffer) { + /* buffer should be at least BUFSIZ bytes long */ int i, gotat = 0; - register char c, *bp; + char c, *bp; + +/* Add C to the buffer bp. After use of this macro *bp is guaranteed to be within the buffer. */ +#define ADDCHR(C) do { *bp++ = (C); if ((bp - buffer) == (BUFSIZ-1)) goto my_lex_buffull; } while (0) bp = buffer; *bp = 0; @@ -777,91 +607,97 @@ my_lex (char *buffer) gotat = isat (cp); c = *cp++; - while (isspace (c)) + while (isspace ((unsigned char) c)) c = *cp++; if (c == 0) { cp = NULL; return (last_lex = LX_END); } - if (c == '(') - for (*bp++ = c, i = 0;;) + if (c == '(') { + ADDCHR(c); + for (i = 0;;) switch (c = *cp++) { case 0: cp = NULL; return (last_lex = LX_ERR); case QUOTE: - *bp++ = c; + ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; return (last_lex = LX_ERR); } - *bp++ = c; + ADDCHR(c); continue; case '(': i++; default: - *bp++ = c; + ADDCHR(c); continue; case ')': - *bp++ = c; + ADDCHR(c); if (--i < 0) { *bp = 0; note = note ? add (buffer, add (" ", note)) - : getcpy (buffer); + : strdup (buffer); return my_lex (buffer); } } + } - if (c == '"') - for (*bp++ = c;;) + if (c == '"') { + ADDCHR(c); + for (;;) switch (c = *cp++) { case 0: cp = NULL; return (last_lex = LX_ERR); case QUOTE: - *bp++ = c; + ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; return (last_lex = LX_ERR); } default: - *bp++ = c; + ADDCHR(c); continue; case '"': - *bp++ = c; + ADDCHR(c); *bp = 0; return (last_lex = LX_QSTR); } - - if (c == '[') - for (*bp++ = c;;) + } + + if (c == '[') { + ADDCHR(c); + for (;;) switch (c = *cp++) { case 0: cp = NULL; return (last_lex = LX_ERR); case QUOTE: - *bp++ = c; + ADDCHR(c); if ((c = *cp++) == 0) { cp = NULL; return (last_lex = LX_ERR); } default: - *bp++ = c; + ADDCHR(c); continue; case ']': - *bp++ = c; + ADDCHR(c); *bp = 0; return (last_lex = LX_DLIT); } - - *bp++ = c; + } + + ADDCHR(c); *bp = 0; for (i = 0; special[i].lx_chr != 0; i++) if (c == special[i].lx_chr) return (last_lex = special[i].lx_val); - if (iscntrl (c)) + if (iscntrl ((unsigned char) c)) return (last_lex = LX_ERR); for (;;) { @@ -870,9 +706,9 @@ my_lex (char *buffer) for (i = 0; special[i].lx_chr != 0; i++) if (c == special[i].lx_chr) goto got_atom; - if (iscntrl (c) || isspace (c)) + if (iscntrl ((unsigned char) c) || isspace ((unsigned char) c)) break; - *bp++ = c; + ADDCHR(c); } got_atom: ; if (c == 0) @@ -883,18 +719,23 @@ got_atom: ; last_lex = !gotat || cp == NULL || strchr(cp, '<') != NULL ? LX_ATOM : LX_AT; return last_lex; + + my_lex_buffull: + /* Out of buffer space. *bp is the last byte in the buffer */ + *bp = 0; + return (last_lex = LX_ERR); } char * -legal_person (char *p) +legal_person (const char *p) { int i; - register char *cp; + register const char *cp; static char buffer[BUFSIZ]; if (*p == '"') - return p; + return (char *) p; for (cp = p; *cp; cp++) for (i = 0; special[i].lx_chr; i++) if (*cp == special[i].lx_chr) { @@ -902,7 +743,7 @@ legal_person (char *p) return buffer; } - return p; + return (char *) p; } @@ -915,8 +756,7 @@ mfgets (FILE *in, char **bp) static char *pp = NULL; if (pp == NULL) - if (!(pp = malloc ((size_t) (len = BUFSIZ)))) - return NOTOK; + pp = mh_xmalloc ((size_t) (len = BUFSIZ)); for (ep = (cp = pp) + len - 2;;) { switch (i = getc (in)) { @@ -956,13 +796,8 @@ mfgets (FILE *in, char **bp) break; } if (cp >= ep) { - if (!(dp = realloc (pp, (size_t) (len += BUFSIZ)))) { - free (pp); - pp = NULL; - return NOTOK; - } - else - cp += dp - pp, ep = (pp = cp) + len - 2; + dp = mh_xrealloc (pp, (size_t) (len += BUFSIZ)); + cp += dp - pp, ep = (pp = cp) + len - 2; } } }