📄 mf.c
字号:
/* mf.c - mail filter subroutines */#ifndef lintstatic char ident[] = "@(#)$Id: mf.c,v 1.10 1992/12/15 00:20:22 jromine Exp $";#endif /* lint */#include "mf.h"#include <ctype.h>#include <stdio.h>static int isat(), parse_address(), phrase();static int route_addr(), local_part(), domain(), route();static int my_lex();static void compress();/* */static char *getcpy (s)register char *s;{ register char *p;if (!s) { _cleanup(); abort(); for(;;) pause();} if ((p = malloc ((unsigned) (strlen (s) + 2))) != NULL) (void) strcpy (p, s); return p;}static char *add (s1, s2)register char *s1, *s2;{ register char *p; if (s2 == NULL) return getcpy (s1); if ((p = malloc ((unsigned) (strlen (s1) + strlen (s2) + 2))) != NULL) (void) sprintf (p, "%s%s", s2, s1); free (s2); return p;}/* */int isfrom (string)register char *string;{ return (strncmp (string, "From ", 5) == 0 || strncmp (string, ">From ", 6) == 0);}int lequal (a, b)register char *a, *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; if (c1 != c2) return FALSE; } return (*b == 0);}/* *//* * * 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 (addrs)register char *addrs;{ static int state = CHKADR; register char *cp; register struct adrx *adrxp; if (state == CHKADR) for (state = UNIXDR, cp = addrs; *cp; cp++) if (index (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 (addrs)register 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 = index (cp, ',')) == NULL) if ((wp = index (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 = index (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 = rindex (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 (fp, tp)register char *fp, *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 (p)register char *p;{ return (strncmp (p, " AT ", 4) && strncmp (p, " At ", 4) && strncmp (p, " aT ", 4) && strncmp (p, " at ", 4) ? FALSE : TRUE);}/* *//* * * getadrx() implements a partial 822-style address parser. The parser * is neither complete nor correct. It does however recognize nearly all * of the 822 address syntax. In addition it handles the majority of the * 733 syntax as well. Most problems arise from trying to accomodate both. * * In terms of 822, the route-specification in * * "<" [route] local-part "@" domain ">" * * is parsed and returned unchanged. Multiple at-signs are compressed * via source-routing. Recursive groups are not allowed as per the * standard. * * In terms of 733, " at " is recognized as equivalent to "@". * * In terms of both the parser will not complain about missing hosts. * * ----- * * We should not allow addresses like * * Marshall T. Rose <MRose@UCI> * * but should insist on * * "Marshall T. Rose" <MRose@UCI> * * Unfortunately, a lot of mailers stupidly let people get away with this. * * ----- * * We should not allow addresses like * * <MRose@UCI> * * but should insist on * * MRose@UCI * * Unfortunately, a lot of mailers stupidly let people's UAs get away with * this. * * ----- * * We should not allow addresses like * * @UCI:MRose@UCI-750a * * but should insist on * * Marshall Rose <@UCI:MRose@UCI-750a> * * Unfortunately, a lot of mailers stupidly do this. * *//* */#define QUOTE '\\'#define LX_END 0#define LX_ERR 1#define LX_ATOM 2#define LX_QSTR 3#define LX_DLIT 4#define LX_SEMI 5#define LX_COMA 6#define LX_LBRK 7#define LX_RBRK 8#define LX_COLN 9#define LX_DOT 10#define LX_AT 11static struct { char lx_chr; int lx_val;} special[] = { ';', LX_SEMI, ',', LX_COMA, '<', LX_LBRK, '>', LX_RBRK, ':', LX_COLN, '.', LX_DOT, '@', LX_AT, '(', LX_ERR, ')', LX_ERR, QUOTE, LX_ERR, '"', LX_ERR, '[', LX_ERR, ']', LX_ERR, 0, 0};/* */static int glevel = 0;static int ingrp = 0;static int last_lex = LX_END;static char *dp = NULL;static char *cp = NULL;static char *ap = NULL;static char *pers = NULL;static char *mbox = NULL;static char *host = NULL;static char *path = NULL;static char *grp = NULL;static char *note = NULL;static char err[BUFSIZ];static char adr[BUFSIZ];static struct adrx adrxs2;/* */struct adrx *getadrx (addrs)register char *addrs;{ register char *bp; register struct adrx *adrxp = &adrxs2; if (pers) free (pers); if (mbox) free (mbox); if (host) free (host); if (path) free (path); if (grp) free (grp); if (note) free (note); pers = mbox = host = path = grp = note = NULL; err[0] = 0; if (dp == NULL) { dp = cp = getcpy (addrs ? addrs : ""); glevel = 0; } else if (cp == NULL) { free (dp); dp = NULL; return NULL; } switch (parse_address ()) { case DONE: free (dp); dp = cp = NULL; return NULL; case OK: switch (last_lex) { case LX_COMA: case LX_END: break; default: /* catch trailing comments */ bp = cp; (void) my_lex (adr); cp = bp; break; } break; default: break; } if (err[0]) for (;;) { switch (last_lex) { case LX_COMA: case LX_END: break; default: (void) my_lex (adr); continue; } break; } while (isspace (*ap)) ap++; if (cp) (void) sprintf (adr, "%.*s", cp - ap, ap); else (void) strcpy (adr, ap); bp = adr + strlen (adr) - 1; if (*bp == ',' || *bp == ';' || *bp == '\n') *bp = 0;/* */ adrxp -> text = adr; adrxp -> pers = pers; adrxp -> mbox = mbox; adrxp -> host = host; adrxp -> path = path; adrxp -> grp = grp; adrxp -> ingrp = ingrp; adrxp -> note = note; adrxp -> err = err[0] ? err : NULL; return adrxp;}/* */static int parse_address () { char buffer[BUFSIZ];again: ; ap = cp; switch (my_lex (buffer)) { case LX_ATOM: case LX_QSTR: pers = getcpy (buffer); break; case LX_SEMI: if (glevel-- <= 0) { (void) strcpy (err, "extraneous semi-colon"); return NOTOK; } case LX_COMA: if (note) { free (note); note = NULL; } goto again; case LX_END: return DONE; case LX_LBRK: /* sigh (2) */ goto get_addr; case LX_AT: /* sigh (3) */ cp = ap; if (route_addr (buffer) == NOTOK) return NOTOK; return OK; /* why be choosy? */ default: (void) sprintf (err, "illegal address construct (%s)", buffer); return NOTOK; }/* */ switch (my_lex (buffer)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -