📄 parseaddr.c
字号:
setstat(ep->ec_code); } tv++; } else setstat(EX_UNAVAILABLE); if ((**tv & 0377) != CANONUSER) syserr("554 buildaddr: error: no user"); cataddr(++tv, NULL, buf, sizeof buf, ' '); stripquotes(buf); if (isascii(buf[0]) && isdigit(buf[0]) && isascii(buf[1]) && isdigit(buf[1]) && isascii(buf[2]) && isdigit(buf[2]) && buf[3] == ' ') { char fmt[10]; strncpy(fmt, buf, 3); strcpy(&fmt[3], " %s"); usrerr(fmt, buf + 4); } else { usrerr("553 %s", buf); } goto badaddr; } for (mp = Mailer; (m = *mp++) != NULL; ) { if (strcasecmp(m->m_name, *tv) == 0) break; } if (m == NULL) { syserr("554 buildaddr: unknown mailer %s", *tv); goto badaddr; } a->q_mailer = m; /* figure out what host (if any) */ tv++; if ((**tv & 0377) == CANONHOST) { bp = buf; spaceleft = sizeof buf - 1; while (*++tv != NULL && (**tv & 0377) != CANONUSER) { int i = strlen(*tv); if (i > spaceleft) { /* out of space for this address */ if (spaceleft >= 0) syserr("554 buildaddr: host too long (%.40s...)", buf); i = spaceleft; spaceleft = 0; } if (i <= 0) continue; bcopy(*tv, bp, i); bp += i; spaceleft -= i; } *bp = '\0'; a->q_host = newstr(buf); } else { if (!bitnset(M_LOCALMAILER, m->m_flags)) { syserr("554 buildaddr: no host"); goto badaddr; } a->q_host = NULL; } /* figure out the user */ if (*tv == NULL || (**tv & 0377) != CANONUSER) { syserr("554 buildaddr: no user"); goto badaddr; } tv++; /* do special mapping for local mailer */ if (m == LocalMailer && *tv != NULL) { register char *p = *tv; if (*p == '"') p++; if (*p == '|') a->q_mailer = m = ProgMailer; else if (*p == '/') a->q_mailer = m = FileMailer; else if (*p == ':') { /* may be :include: */ cataddr(tv, NULL, buf, sizeof buf, '\0'); stripquotes(buf); if (strncasecmp(buf, ":include:", 9) == 0) { /* if :include:, don't need further rewriting */ a->q_mailer = m = InclMailer; a->q_user = &buf[9]; return (a); } } } if (m == LocalMailer && *tv != NULL && strcmp(*tv, "@") == 0) { tv++; a->q_flags |= QNOTREMOTE; } /* rewrite according recipient mailer rewriting rules */ define('h', a->q_host, e); if (!bitset(RF_SENDERADDR|RF_HEADERADDR, flags)) { /* sender addresses done later */ (void) rewrite(tv, 2, 0, e); if (m->m_re_rwset > 0) (void) rewrite(tv, m->m_re_rwset, 0, e); } (void) rewrite(tv, 4, 0, e); /* save the result for the command line/RCPT argument */ cataddr(tv, NULL, buf, sizeof buf, '\0'); a->q_user = buf; /* ** Do mapping to lower case as requested by mailer */ if (a->q_host != NULL && !bitnset(M_HST_UPPER, m->m_flags)) makelower(a->q_host); if (!bitnset(M_USR_UPPER, m->m_flags)) makelower(a->q_user); return (a);}/*** CATADDR -- concatenate pieces of addresses (putting in <LWSP> subs)**** Parameters:** pvp -- parameter vector to rebuild.** evp -- last parameter to include. Can be NULL to** use entire pvp.** buf -- buffer to build the string into.** sz -- size of buf.** spacesub -- the space separator character; if null,** use SpaceSub.**** Returns:** none.**** Side Effects:** Destroys buf.*/cataddr(pvp, evp, buf, sz, spacesub) char **pvp; char **evp; char *buf; register int sz; char spacesub;{ bool oatomtok = FALSE; bool natomtok = FALSE; register int i; register char *p; if (spacesub == '\0') spacesub = SpaceSub; if (pvp == NULL) { (void) strcpy(buf, ""); return; } p = buf; sz -= 2; while (*pvp != NULL && (i = strlen(*pvp)) < sz) { natomtok = (toktype(**pvp) == ATM); if (oatomtok && natomtok) *p++ = spacesub; (void) strcpy(p, *pvp); oatomtok = natomtok; p += i; sz -= i + 1; if (pvp++ == evp) break; } *p = '\0';}/*** SAMEADDR -- Determine if two addresses are the same**** This is not just a straight comparison -- if the mailer doesn't** care about the host we just ignore it, etc.**** Parameters:** a, b -- pointers to the internal forms to compare.**** Returns:** TRUE -- they represent the same mailbox.** FALSE -- they don't.**** Side Effects:** none.*/boolsameaddr(a, b) register ADDRESS *a; register ADDRESS *b;{ register ADDRESS *ca, *cb; /* if they don't have the same mailer, forget it */ if (a->q_mailer != b->q_mailer) return (FALSE); /* if the user isn't the same, we can drop out */ if (strcmp(a->q_user, b->q_user) != 0) return (FALSE); /* if we have good uids for both but they differ, these are different */ if (a->q_mailer == ProgMailer) { ca = getctladdr(a); cb = getctladdr(b); if (ca != NULL && cb != NULL && bitset(QGOODUID, ca->q_flags & cb->q_flags) && ca->q_uid != cb->q_uid) return (FALSE); } /* otherwise compare hosts (but be careful for NULL ptrs) */ if (a->q_host == b->q_host) { /* probably both null pointers */ return (TRUE); } if (a->q_host == NULL || b->q_host == NULL) { /* only one is a null pointer */ return (FALSE); } if (strcmp(a->q_host, b->q_host) != 0) return (FALSE); return (TRUE);}/*** PRINTADDR -- print address (for debugging)**** Parameters:** a -- the address to print** follow -- follow the q_next chain.**** Returns:** none.**** Side Effects:** none.*/printaddr(a, follow) register ADDRESS *a; bool follow;{ bool first = TRUE; register MAILER *m; MAILER pseudomailer; while (a != NULL) { first = FALSE; printf("%x=", a); (void) fflush(stdout); /* find the mailer -- carefully */ m = a->q_mailer; if (m == NULL) { m = &pseudomailer; m->m_mno = -1; m->m_name = "NULL"; } printf("%s:\n\tmailer %d (%s), host `%s', user `%s', ruser `%s'\n", a->q_paddr, m->m_mno, m->m_name, a->q_host, a->q_user, a->q_ruser ? a->q_ruser : "<null>"); printf("\tnext=%x, flags=%o, alias %x, uid %d, gid %d\n", a->q_next, a->q_flags, a->q_alias, a->q_uid, a->q_gid); printf("\towner=%s, home=\"%s\", fullname=\"%s\"\n", a->q_owner == NULL ? "(none)" : a->q_owner, a->q_home == NULL ? "(none)" : a->q_home, a->q_fullname == NULL ? "(none)" : a->q_fullname); if (!follow) return; a = a->q_next; } if (first) printf("[NULL]\n");}/*** REMOTENAME -- return the name relative to the current mailer**** Parameters:** name -- the name to translate.** m -- the mailer that we want to do rewriting relative** to.** flags -- fine tune operations.** pstat -- pointer to status word.** e -- the current envelope.**** Returns:** the text string representing this address relative to** the receiving mailer.**** Side Effects:** none.**** Warnings:** The text string returned is tucked away locally;** copy it if you intend to save it.*/char *remotename(name, m, flags, pstat, e) char *name; struct mailer *m; int flags; int *pstat; register ENVELOPE *e;{ register char **pvp; char *fancy; char *oldg = macvalue('g', e); int rwset; static char buf[MAXNAME]; char lbuf[MAXNAME]; char pvpbuf[PSBUFSIZE]; extern char *crackaddr(); if (tTd(12, 1)) printf("remotename(%s)\n", name); /* don't do anything if we are tagging it as special */ if (bitset(RF_SENDERADDR, flags)) rwset = bitset(RF_HEADERADDR, flags) ? m->m_sh_rwset : m->m_se_rwset; else rwset = bitset(RF_HEADERADDR, flags) ? m->m_rh_rwset : m->m_re_rwset; if (rwset < 0) return (name); /* ** Do a heuristic crack of this name to extract any comment info. ** This will leave the name as a comment and a $g macro. */ if (bitset(RF_CANONICAL, flags) || bitnset(M_NOCOMMENT, m->m_flags)) fancy = "\201g"; else fancy = crackaddr(name); /* ** Turn the name into canonical form. ** Normally this will be RFC 822 style, i.e., "user@domain". ** If this only resolves to "user", and the "C" flag is ** specified in the sending mailer, then the sender's ** domain will be appended. */ pvp = prescan(name, '\0', pvpbuf, sizeof pvpbuf, NULL); if (pvp == NULL) return (name); if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL) *pstat = EX_TEMPFAIL; if (bitset(RF_ADDDOMAIN, flags) && e->e_fromdomain != NULL) { /* append from domain to this address */ register char **pxp = pvp; /* see if there is an "@domain" in the current name */ while (*pxp != NULL && strcmp(*pxp, "@") != 0) pxp++; if (*pxp == NULL) { /* no.... append the "@domain" from the sender */ register char **qxq = e->e_fromdomain; while ((*pxp++ = *qxq++) != NULL) continue; if (rewrite(pvp, 3, 0, e) == EX_TEMPFAIL) *pstat = EX_TEMPFAIL; } } /* ** Do more specific rewriting. ** Rewrite using ruleset 1 or 2 depending on whether this is ** a sender address or not. ** Then run it through any receiving-mailer-specific rulesets. */ if (bitset(RF_SENDERADDR, flags)) { if (rewrite(pvp, 1, 0, e) == EX_TEMPFAIL) *pstat = EX_TEMPFAIL; } else { if (rewrite(pvp, 2, 0, e) == EX_TEMPFAIL) *pstat = EX_TEMPFAIL; } if (rwset > 0) { if (rewrite(pvp, rwset, 0, e) == EX_TEMPFAIL) *pstat = EX_TEMPFAIL; } /* ** Do any final sanitation the address may require. ** This will normally be used to turn internal forms ** (e.g., user@host.LOCAL) into external form. This ** may be used as a default to the above rules. */ if (rewrite(pvp, 4, 0, e) == EX_TEMPFAIL) *pstat = EX_TEMPFAIL; /* ** Now restore the comment information we had at the beginning. */ cataddr(pvp, NULL, lbuf, sizeof lbuf, '\0'); define('g', lbuf, e); /* need to make sure route-addrs have <angle brackets> */ if (bitset(RF_CANONICAL, flags) && lbuf[0] == '@') expand("<\201g>", buf, &buf[sizeof buf - 1], e); else expand(fancy, buf, &buf[sizeof buf - 1], e); define('g', oldg, e); if (tTd(12, 1)) printf("remotename => `%s'\n", buf); return (buf);}/*** MAPLOCALUSER -- run local username through ruleset 5 for final redirection**** Parameters:** a -- the address to map (but just the user name part).** sendq -- the sendq in which to install any replacement** addresses.**** Returns:** none.*/maplocaluser(a, sendq, e) register ADDRESS *a; ADDRESS **sendq; ENVELOPE *e;{ register char **pvp; register ADDRESS *a1 = NULL; auto char *delimptr; char pvpbuf[PSBUFSIZE]; if (tTd(29, 1)) { printf("maplocaluser: "); printaddr(a, FALSE); } pvp = prescan(a->q_user, '\0', pvpbuf, sizeof pvpbuf, &delimptr); if (pvp == NULL) return; (void) rewrite(pvp, 5, 0, e); if (pvp[0] == NULL || (pvp[0][0] & 0377) != CANONNET) return; /* if non-null, mailer destination specified -- has it changed? */ a1 = buildaddr(pvp, NULL, 0, e); if (a1 == NULL || sameaddr(a, a1)) return; /* mark old address as dead; insert new address */ a->q_flags |= QDONTSEND; if (tTd(29, 5)) { printf("maplocaluser: QDONTSEND "); printaddr(a, FALSE); } a1->q_alias = a; allocaddr(a1, RF_COPYALL, NULL); (void) recipient(a1, sendq, e);}/*** DEQUOTE_INIT -- initialize dequote map**** This is a no-op.**** Parameters:** map -- the internal map structure.** args -- arguments.**** Returns:** TRUE.*/booldequote_init(map, args) MAP *map; char *args;{ register char *p = args; for (;;) { while (isascii(*p) && isspace(*p)) p++; if (*p != '-') break; switch (*++p) { case 'a': map->map_app = ++p; break; } while (*p != '\0' && !(isascii(*p) && isspace(*p))) p++; if (*p != '\0') *p = '\0'; } if (map->map_app != NULL) map->map_app = newstr(map->map_app); return TRUE;}/*** DEQUOTE_MAP -- unquote an address**** Parameters:** map -- the internal map structure (ignored).** name -- the name to dequote.** av -- arguments (ignored).** statp -- pointer to status out-parameter.**** Returns:** NULL -- if there were no quotes, or if the resulting** unquoted buffer would not be acceptable to prescan.** else -- The dequoted buffer.*/char *dequote_map(map, name, av, statp) MAP *map; char *name; char **av; int *statp;{ register char *p; register char *q; register char c; int anglecnt; int cmntcnt; int quotecnt; int spacecnt; bool quotemode; bool bslashmode; anglecnt = 0; cmntcnt = 0; quotecnt = 0; spacecnt = 0; quotemode = FALSE; bslashmode = FALSE; for (p = q = name; (c = *p++) != '\0'; ) { if (bslashmode) { bslashmode = FALSE; *q++ = c; continue; } switch (c) { case '\\': bslashmode = TRUE; break; case '(': cmntcnt++; break; case ')': if (cmntcnt-- <= 0) return NULL; break; case ' ': spacecnt++; break; } if (cmntcnt > 0) { *q++ = c; continue; } switch (c) { case '"': quotemode = !quotemode; quotecnt++; continue; case '<': anglecnt++; break; case '>': if (anglecnt-- <= 0) return NULL; break; } *q++ = c; } if (anglecnt != 0 || cmntcnt != 0 || bslashmode || quotemode || quotecnt <= 0 || spacecnt != 0) return NULL; *q++ = '\0'; return name;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -