|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T r
Length: 27869 (0x6cdd) Types: TextFile Names: »rfc822norm.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« └─⟦e5a54fb17⟧ └─⟦this⟧ »pp-5.0/Format/rfc822norm/rfc822norm.c«
/* rfc822norm: program to 822norm stdin to stdout */ # ifndef lint static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Format/rfc822norm/RCS/rfc822norm.c,v 5.0 90/09/20 16:02:35 pp Exp Locker: pp $"; # endif /* * $Header: /cs/research/pp/hubris/pp-beta/Format/rfc822norm/RCS/rfc822norm.c,v 5.0 90/09/20 16:02:35 pp Exp Locker: pp $ * * $Log: rfc822norm.c,v $ * Revision 5.0 90/09/20 16:02:35 pp * rcsforce : 5.0 public release * */ #include "util.h" #include <isode/cmd_srch.h> #include "ap.h" #include "alias.h" #include "chan.h" #include "retcode.h" #include "adr.h" #define OPT_822 1 #define OPT_733 2 #define OPT_JNT 3 #define OPT_BIGEND 4 #define OPT_LITTLEEND 5 #define OPT_STRIPROUTES 6 #define OPT_STRIPDOMAIN 7 #define OPT_STRIPTRACE 8 #define OPT_JNTSENDER 9 #define OPT_FOLD 10 #define OPT_MSGID 11 #define OPT_PERCENT 12 #define OPT_HIDELOCAL 13 CMD_TABLE tbl_options [] = { /* rfc822norm commandline options */ "-822", OPT_822, "-733", OPT_733, "-jnt", OPT_JNT, "-bigend", OPT_BIGEND, "-littleend", OPT_LITTLEEND, "-striproutes", OPT_STRIPROUTES, "-stripdomain", OPT_STRIPDOMAIN, "-striptrace", OPT_STRIPTRACE, "-jntsender", OPT_JNTSENDER, "-fold", OPT_FOLD, "-msgid", OPT_MSGID, "-percent", OPT_PERCENT, "-hidelocal", OPT_HIDELOCAL, 0, -1 }; #define FLD_TO 1 #define FLD_CC 2 #define FLD_BCC 3 #define FLD_FROM 4 #define FLD_SENDER 5 #define FLD_REPLY_TO 6 #define FLD_RESENT_FROM 7 #define FLD_RESENT_SENDER 8 #define FLD_RESENT_TO 9 #define FLD_RESENT_CC 10 #define FLD_RESENT_BCC 11 #define FLD_RESENT_BY 12 #define FLD_REMAILED_FROM 13 #define FLD_REMAILED_TO 14 #define FLD_REMAILED_BY 15 #define FLD_REDISTRIBUTED_FROM 16 #define FLD_REDISTRIBUTED_TO 17 #define FLD_REDISTRIBUTED_BY 18 #define FLD_ORIG_SENDER 19 /* RFC 987 extensions */ #define FLD_RFC987 20 /* RFC 987 (88) extensions - proposed */ #define FLD_RFC987_88 21 CMD_TABLE tbl_fields [] = {/* address field names */ /* REAL RFC 822 */ "To", FLD_TO, "CC", FLD_CC, "bcc", FLD_BCC, "From", FLD_FROM, "Sender", FLD_SENDER, "Reply-to", FLD_REPLY_TO, "Resent-From", FLD_RESENT_FROM, "Resent-Sender", FLD_RESENT_SENDER, "Resent-To", FLD_RESENT_TO, "Resent-Cc", FLD_RESENT_CC, "Resent-Bcc", FLD_RESENT_BCC, "Resent-By", FLD_RESENT_BY, /* JNT stuff */ "Original-Sender", FLD_ORIG_SENDER, /* RFC 733 & other misc stuff */ "Remailed-From", FLD_REMAILED_FROM, "Remailed-To", FLD_REMAILED_TO, "Remailed-By", FLD_REMAILED_BY, "Redistributed-From", FLD_REDISTRIBUTED_FROM, "Redistributed-To", FLD_REDISTRIBUTED_TO, "Redistributed-By", FLD_REDISTRIBUTED_BY, /* RFC 987 fields */ "P1-Recipient", FLD_RFC987, /* RFC 987 (88) fields */ "X400-Originator", FLD_RFC987_88, "X400-Recipients", FLD_RFC987_88, "Notification-IPM-Originator", FLD_RFC987_88, "Notification-Preferred-Recipients", FLD_RFC987_88, "MTS-Originator", FLD_RFC987_88, "MTS-Recipient", FLD_RFC987_88, "Originally-Intended-Recipient", FLD_RFC987_88, "Originator-Return-Address", FLD_RFC987_88, "DL-Expansion-History", FLD_RFC987_88, "Report-Reporting-DL-Name", FLD_RFC987_88, "Report-Originator-and-DL-Expansion-History", FLD_RFC987_88, 0, -1 }; #define FOLD_SPACE 0 #define FOLD_COMMA 1 #define FOLD_SEMICOLON 2 #define FOLD_RECIEVED 3 #define FOLD_NONE 4 CMD_TABLE tbl_nonfields [] = {/* feilds dont deal with */ "Received", FOLD_RECIEVED, "X400-Received", FOLD_SEMICOLON, "Via", FOLD_SEMICOLON, "References", FOLD_COMMA, "Keywords", FOLD_COMMA, "X400-MTS-Identifier", FOLD_NONE, "Message-ID", FOLD_NONE, "In-Reply-To", FOLD_NONE, "Obsoletes", FOLD_COMMA, 0, -1 }; CMD_TABLE tbl_tracefields [] = {/* fields viable for strip trace */ "Received", FOLD_RECIEVED, "Via", FOLD_SEMICOLON, "X400-Received", FOLD_SEMICOLON, 0, -1 }; typedef enum {maj_none, rfc822, rfc733, jnt} Major_options; typedef enum {min_none, bigend, littleend} Minor_options; extern void sys_init(), err_abrt(); static void norm_sender(); static int equalWithJntsender(), tidy_up(); static getitm(), out_adr(); static AP_ptr parse_and_norm(); char *myname; int nadrs; int pcol; int nonempty; int fold_width; int order_pref; int striptrace = FALSE, striproutes = FALSE; char **stripdomains = NULL; char **hidedomains = NULL; int num_domains = 0, num_to_hide = 0, message_id = 0, msgid_req = FALSE; char *jntsender = NULL, *jntsendernorm = NULL; AP_ptr jnttree, jntgroup, jntname, jntloc, jntdom, jntroute; static int getach(); static int getbufchar(); static char *next_fold(); static char *fold_recieved(); static AP_ptr recur_stripdomain(); extern AP_ptr ap_pinit(); extern char *compress(); extern char *rcmd_srch(); extern int ap_outtype; extern int ap_perlev; extern char *loc_dom_site, *loc_dom_mta; extern char *calloc(); extern char *realloc(); char *rloc_dom_site, *rloc_dom_mta; static char *reverse(); #ifndef BSD42 #define random rand #define srandom srand #endif #define DEFAULT_FOLD_WIDTH 79 /* ARGSUSED */ main(argc,argv) int argc; char **argv; { /* parse flags */ Major_options maj = maj_none; Minor_options mino = min_none; myname = *argv++; sys_init(myname); /* malloc_debug(2);*/ ap_outtype = AP_PARSE_SAME; fold_width = DEFAULT_FOLD_WIDTH; order_pref = CH_USA_PREF; jntsendernorm = NULL; jntsender = NULL; message_id = 0; msgid_req = FALSE; srandom(getpid()); rloc_dom_site = reverse(loc_dom_site); rloc_dom_mta = reverse(loc_dom_mta); while (*argv != NULL) { switch(cmd_srch(*argv,tbl_options)) { case -1: PP_LOG(LLOG_EXCEPTIONS, ("unknown option '%s'",*argv)); exit(1); case OPT_MSGID: msgid_req = TRUE; break; case OPT_PERCENT: ap_use_percent(); ap_norm_all_domains(); break; case OPT_FOLD: if (*(argv+1) == NULL) PP_LOG(LLOG_EXCEPTIONS, ("no fold width given with %s",*argv)); else { ++argv; fold_width = atoi(*argv); } break; case OPT_822: if ((maj == maj_none) || (maj == rfc822)) { ap_outtype |= AP_PARSE_822; maj = rfc822; } break; case OPT_733: if ((maj == maj_none) || (maj == rfc733)) { ap_outtype |= AP_PARSE_733; maj = rfc733; } break; case OPT_JNT: if ((maj == maj_none || maj == jnt) && (mino == min_none || mino == bigend)) { ap_outtype |= AP_PARSE_733; maj = jnt; ap_outtype |= AP_PARSE_BIG; mino = bigend; order_pref = CH_UK_PREF; break; } PP_LOG(LLOG_EXCEPTIONS, ("multiple major parse options")); exit(1); case OPT_BIGEND: if (mino == min_none || mino == bigend) { ap_outtype |= AP_PARSE_BIG; mino = bigend; order_pref = CH_UK_PREF; } break; case OPT_LITTLEEND: if (mino == min_none || mino == littleend) { mino = littleend; break; } PP_LOG(LLOG_EXCEPTIONS, ("multiple minor parse options")); exit(1); case OPT_STRIPTRACE: striptrace = TRUE; break; case OPT_STRIPROUTES: striproutes = TRUE; break; case OPT_STRIPDOMAIN: if (*(argv+1) == NULL) PP_LOG(LLOG_EXCEPTIONS, ("no domain specified with %s", *argv)); else { ++argv; if (num_domains == 0) stripdomains = (char **) calloc(1, (unsigned int) sizeof(char *)); else stripdomains = (char **) realloc((char *) stripdomains, (unsigned int) ((num_domains + 1) * sizeof(char *))); stripdomains[num_domains++] = *argv; } break; case OPT_JNTSENDER: if (*(argv+1) == NULL) PP_LOG(LLOG_EXCEPTIONS, ("no sender specified with %s", *argv)); else { argv++; jntsender = *argv; } break; case OPT_HIDELOCAL: if (*(argv+1) == NULL) PP_LOG(LLOG_EXCEPTIONS, ("no domain specified with %s", *argv)); else { ++argv; if (num_to_hide == 0) hidedomains = (char **) calloc(1, (unsigned int) sizeof(char *)); else hidedomains = (char **) realloc((char *) hidedomains, (unsigned int) ((num_to_hide + 1) * sizeof(char *))); hidedomains[num_to_hide++] = *argv; } break; default: PP_LOG(LLOG_EXCEPTIONS, ("unknown option '%s'")); exit(1); } argv++; } if (jntsender) norm_sender(); /* ap_outtype set so now process */ if (proc() != OK) err_abrt( RP_LIO, "couldn't reformat it"); free(rloc_dom_site); free(rloc_dom_mta); /* copy out rest of file */ exit(0); } /* \f */ static void norm_sender() { jnttree = ap_s2t(jntsender); jnttree = parse_and_norm (jnttree, &jntgroup, &jntname, &jntloc, &jntdom, &jntroute); jntsendernorm = ap_p2s(jntgroup, jntname, jntloc, jntdom, jntroute); } static int equalWithJntsender(tree) AP_ptr tree; { AP_ptr jix = tree, aix = jntloc; while (jix != NULLAP && aix != NULLAP) { if (jix -> ap_obtype == AP_COMMENT) jix = jix -> ap_next; else if (aix -> ap_obtype == AP_COMMENT) aix = aix -> ap_next; else if (strcmp(aix -> ap_obvalue, jix -> ap_obvalue) != 0) return 0; else { aix = aix -> ap_next; jix = jix -> ap_next; } } while (jix != NULLAP && jix->ap_obvalue == NULLCP) jix = jix -> ap_next; while (aix != NULLAP && aix->ap_obvalue == NULLCP) aix = aix -> ap_next; if (aix == NULLAP && jix == NULLAP) return 1; return 0; } /* \f */ int noFrom, from; /* 822norm stdin to stdout */ proc () { int amp_fail; int res; int done; register char *cp; PP_TRACE(("outtype %o",ap_outtype)); noFrom = 1; from = 0; while ((getitm(&res) == OK) && (res == OK)) { ap_clear(); nadrs = 0; amp_fail = FALSE; nonempty = FALSE; done = FALSE; if (ap_pinit(getbufchar) == BADAP) { PP_LOG(LLOG_EXCEPTIONS, ("problem parsing message")); return NOTOK; } while (done == FALSE) { res = ap_1adr(); /* Parse one adr */ switch(res) { case DONE: /* done */ done = TRUE; break; case NOTOK: /* pass the garbage and generate warning */ amp_fail = TRUE; break; default: /* print it */ ap_ppush (getbufchar); if ((res = out_adr(ap_pstrt)) != OK) return res; ap_ppop(); ap_pstrt = ap_pcur = ap_alloc (); break; } } putchar('\n'); if (ap_perlev) { /* if still nested */ PP_TRACE(("nested level %d",ap_perlev)); amp_fail++; } if (amp_fail == TRUE) printf("PP_warning: Parse error in original version of preceding line\n"); } if (message_id == 0 && msgid_req == TRUE) { /* output message id */ MPDUid msgid; char buf[BUFSIZ]; strcpy(buf, "Message-ID"); cp = &buf[0]; while (*cp != '\0') putchar (*cp++); putchar (':'); putchar (' '); MPDUid_new(&msgid); (void) sprintf(buf, "<\"%s\"@%s>", msgid.mpduid_string, loc_dom_site); cp = buf; while (*cp != '\0') putchar (*cp++); putchar ('\n'); } if (jntsendernorm != NULL && noFrom) { /* output Sender */ cp = rcmd_srch(FLD_SENDER, tbl_fields); while (*cp != '\0') putchar(*cp++); putchar(':'); putchar(' '); cp = jntsendernorm; while (*cp != '\0') putchar(*cp++); putchar('\n'); } if (jntsendernorm != NULL) { ap_sqdelete(jnttree, NULLAP); free((char *)jnttree); } if (res == NOTOK) return NOTOK; tidy_up(); /* putchar('\n'); /* put blank line after header */ return (ferror(stdout) ? NOTOK : OK); } /* \f */ /* input routines */ static char *fieldbuf = NULL, *contbuf = NULL; static int fieldsize = 0, contsize = 0; static int fieldlen = 0, contlen = 0; static char *contix = NULL; #define INC 2 /* returns current pointer = *orig + olength */ static char *resize_buf(orig, olength, size) char **orig; int olength, *size; { *size += INC; if (*orig == NULLCP) *orig = calloc (1, (unsigned int) (*size)); else *orig = realloc (*orig, (unsigned int) (*size)); return ((*orig)+olength); } /* returns OK while still got more input to read */ /* result == NOTOK if failed parsing */ static int getitm(result) int *result; { register int c; register char *cp, *ix; int gotitm = FALSE; fieldlen = 0; cp = fieldbuf; *result = OK; while (gotitm == FALSE) { if ((c = getach()) == EOF) /* end of file */ return NOTOK; switch (c) { case '\n': if (fieldlen != 0) break; case '\0': /* end of input */ return NOTOK; } /* putchar(c);*/ switch (c) { case ':': /* Field name collected */ if ((fieldlen+1) >= fieldsize) cp = resize_buf(&fieldbuf,fieldlen,&fieldsize); *cp = '\0'; PP_TRACE(("field '%s'",fieldbuf)); ix = fieldbuf; if (isspace(*ix) && *ix != '\n') { while (isspace(*ix) && *ix != '\n') ix++; /* rewind back one to first nonspace */ ix--; } /* got field now get contents */ cp = contbuf; contlen = 0; while (((c = getach()) != 0) && (c != EOF)) { if (++contlen >= contsize) cp = resize_buf(&contbuf,(contlen-1),&contsize); *cp++ = c; } /* terminate with a null char */ if ((contlen + 1) >= contsize) cp = resize_buf(&contbuf,contlen,&contsize); *cp ='\0'; compress(fieldbuf, fieldbuf); compress(contbuf, contbuf); contix = contbuf; /* check if need to skip */ if ((striptrace == TRUE) && (cmd_srch(fieldbuf, tbl_tracefields) != -1)) { /* skip it */ cp = fieldbuf; fieldlen = 0; break; } if (cmd_srch(fieldbuf, tbl_fields) == FLD_FROM) from = 1; else from = 0; if (jntsender != NULL && (cmd_srch(fieldbuf, tbl_fields) == FLD_SENDER)) /* convert to Original-Sender */ cp = rcmd_srch(FLD_ORIG_SENDER, tbl_fields); else cp = fieldbuf; pcol = strlen(cp)+2; while (*cp != '\0') putchar(*cp++); putchar(':'); /* put in jpo's space */ putchar(' '); if (cmd_srch(ix,tbl_fields) != -1) { gotitm = TRUE; } else { int fold_num; /* copy rest of line out */ nonempty = FALSE; pcol = strlen(fieldbuf) + 1; cp = contix; if (lexequ(fieldbuf, "Message-ID") == 0) message_id++; if ((fold_num = cmd_srch(fieldbuf,tbl_nonfields)) == -1) { PP_DBG(("unknown non field %s folding on spaces",fieldbuf)); fold_num = FOLD_SPACE; } while (*contix != '\0') { /* go to next fold */ cp = next_fold(contix+1,fold_num); if ((fold_width != -1) && (cp - contix + pcol > fold_width) && nonempty) { /* new line */ pcol = strlen(fieldbuf) + 2; printf("\n%*s", strlen(fieldbuf) + 2, ""); /* strip out white space */ while (isspace(*contix)) contix++; } else nonempty = TRUE; pcol += cp - contix; /* output line */ while (contix != cp) putchar(*contix++); } putchar('\n'); if (c == EOF) /* EOF */ return NOTOK; } cp = fieldbuf; fieldlen = 0; break; default: if (++fieldlen >= fieldsize) cp = resize_buf(&fieldbuf,(fieldlen-1),&fieldsize); *cp++ = c; } } return OK; } static int isblank(ch) char ch; { return (ch == ' ' || ch == '\t'); } /* returns 0 when reach end of an item */ /* returns EOF when reach EOF */ static int getach() { static char buf[FILNSIZE]; static char *bufp = buf; static int noInput = 0; if (noInput == 0) { /* buffer is empty */ noInput = read(0, buf, FILNSIZE); bufp = buf; } if (*bufp == '\n') { if (noInput == 1) { /* last char in buffer */ noInput = read(0, buf, FILNSIZE); bufp = buf; if (isblank(*bufp)) { noInput--; return *bufp++; } else return 0; } else if (isblank(*(bufp+1))) { /* skip newline */ bufp++; noInput--; } } if (*bufp == '\n') { bufp++; noInput--; return 0; } return ((--noInput >= 0) ? *bufp++ : EOF); } static int getbufchar() { char ret = *contix; if (ret != 0) contix++; return (ret == 0) ? EOF : ret; } /* \f */ /* output routine */ static char *next_fold(ix,fold) char *ix; int fold; { char fold_ch; switch (fold) { case FOLD_NONE: fold_ch = '\0'; break; case FOLD_SPACE: fold_ch = ' '; break; case FOLD_COMMA: fold_ch = ','; break; case FOLD_SEMICOLON: fold_ch = ';'; break; case FOLD_RECIEVED: return fold_recieved(ix); break; default: PP_LOG(LLOG_EXCEPTIONS, ("unknown fold number %d",fold)); fold_ch = ' '; } while (*ix != '\0' && *ix != fold_ch) ix++; if (*ix == '\0') return ix; else return ++ix; } static char *fold_recieved(chs) char *chs; { char *ix; while (*chs != '\0' && *chs != ';' && *chs != ' ') chs++; if (*chs == '\0') return chs; if (*chs == ';') return ++chs; /* skip leading spaces */ while (isspace(*chs)) chs++; /* now check if have key words */ ix = chs; while (*ix != '\0' && (ix - chs <= strlen("from")+1)) { if (ix - chs == 3) { if (strncmp(chs,"by ",3) == 0) return chs; else if (strncmp(chs,"id ",3) == 0) return chs; } if (ix - chs == 4) { if (strncmp(chs,"via ",4) == 0) return chs; else if (strncmp(chs,"for ",4) == 0) return chs; } if (ix - chs == 5) { if (strncmp(chs,"from ",5) == 0) return chs; else if (strncmp(chs, "with ", 5) == 0) return chs; } ix++; } if (*ix == '\0') return ix; return fold_recieved(chs); } static int specifiedDomain(ptr) AP_ptr ptr; { int specified = FALSE, i = 0; /* get to next domain */ while ((ptr != NULL) && (ptr->ap_obtype != AP_DOMAIN)) ptr = ptr->ap_next; if (ptr == NULL) return FALSE; while (specified != TRUE && i < num_domains) { if ((ptr->ap_obvalue != NULL) && (strcmp(stripdomains[i], ptr->ap_obvalue) == 0)) specified = TRUE; i++; } return specified; } static int hiddenDomain(ptr) AP_ptr ptr; { int hidden = FALSE, i, nwild, nw; char *bp, *cp; /* get to next domain */ while ((ptr != NULL) && (ptr->ap_obtype != AP_DOMAIN)) ptr = ptr->ap_next; if (ptr == NULL) return 0; if (ptr->ap_obvalue != NULL) for (i = 0; hidden != TRUE && i < num_to_hide; i++) { for (nwild = 0; hidedomains[i][nwild] == '.' || hidedomains[i][nwild] == '*'; nwild ++) ; nw = nwild; nwild /= 2; bp = cp = ptr->ap_obvalue; if ( ! hidedomains[i][nw] ) { PP_LOG (LLOG_EXCEPTIONS, ("Format/rfc822norm/hiddenDomain: Too wild - Reality error")); continue; } while ( (nwild -- > 0) && (bp = index(bp, '.')) != NULL) bp ++; if ( !bp ) continue; while ((bp = index(bp,'.')) != NULL) { if (++bp =='\0') break; cp = index(cp,'.'); cp++; if ((strcmp(&hidedomains[i][nw], bp) == 0)) { hidden = TRUE; strcpy(ptr->ap_obvalue, cp); break; } } } return hidden; } static int recognisedDomain(ptr) AP_ptr ptr; { char official[LINESIZE], *subdom = NULLCP; while ((ptr != NULL) && (ptr->ap_obtype != AP_DOMAIN)) ptr = ptr->ap_next; if ((ptr != NULL) && (tb_getdomain(ptr->ap_obvalue, NULLCP, official, order_pref, &subdom) == OK)) { if (subdom != NULL) free(subdom); return TRUE; }else { if (subdom != NULL) free(subdom); return FALSE; } } static int endOfRoute(ptr, group_ptr, name_ptr, loc_ptr, dom_ptr) AP_ptr ptr, group_ptr, name_ptr, loc_ptr, dom_ptr; { if ((ptr == group_ptr) || (ptr == name_ptr) || (ptr == loc_ptr) || (ptr == dom_ptr)) return TRUE; else return FALSE; } static AP_ptr recur_stripdomain(ptr, group_ptr, name_ptr, loc_ptr, dom_ptr) AP_ptr ptr, group_ptr, name_ptr, loc_ptr, dom_ptr; { if (ptr == NULL) return NULL; if (endOfRoute(ptr->ap_next, group_ptr, name_ptr, loc_ptr, dom_ptr) == TRUE) { if ((specifiedDomain(ptr) == TRUE) && (specifiedDomain(dom_ptr) == TRUE || recognisedDomain(dom_ptr) == TRUE)) return ptr->ap_next; else return ptr; } if ((specifiedDomain(ptr) == TRUE) && (specifiedDomain(ptr->ap_next) == TRUE || recognisedDomain(ptr->ap_next) == TRUE)) return recur_stripdomain(ptr->ap_next, group_ptr, name_ptr, loc_ptr, dom_ptr); else { ptr->ap_next = recur_stripdomain(ptr->ap_next, group_ptr, name_ptr, loc_ptr, dom_ptr); return ptr; } } static char *do_stripdomains(group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr) AP_ptr group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr; { char *retval; AP_ptr ptr; int cont = TRUE; if (route_ptr == NULL) retval = ap_p2s(group_ptr, name_ptr, loc_ptr, dom_ptr, (AP_ptr) NULL); else { /* route ptr is least significant domain */ ptr = route_ptr; while ((endOfRoute(ptr->ap_next, group_ptr, name_ptr, loc_ptr, dom_ptr) == FALSE) && (cont == TRUE)) { cont = FALSE; if ((specifiedDomain(ptr) == TRUE) && (specifiedDomain(ptr->ap_next) == TRUE || recognisedDomain(ptr->ap_next) == TRUE)) { cont = TRUE; ptr = ptr->ap_next; } } if (cont == TRUE) { /* must have reached end of route */ /* check with dom_ptr */ if ((specifiedDomain(ptr) == TRUE) && (specifiedDomain(dom_ptr) == TRUE || recognisedDomain(dom_ptr) == TRUE)) /* strip all routes */ ptr = NULL; } retval = ap_p2s(group_ptr, name_ptr, loc_ptr, dom_ptr, ptr); } return retval; } static char *do_striproutes(group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr) AP_ptr group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr; { char *retval; AP_ptr ix_ptr, strip_start; if ((recognisedDomain(dom_ptr) == TRUE) || (route_ptr == NULL)) retval = ap_p2s(group_ptr, name_ptr, loc_ptr, dom_ptr, (AP_ptr) NULL); else { ix_ptr = route_ptr; while ((ix_ptr->ap_next != NULL) && (recognisedDomain(ix_ptr) != TRUE)) ix_ptr = ix_ptr->ap_next; strip_start = ix_ptr->ap_next; ix_ptr->ap_next = NULL; retval = ap_p2s(group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr); ix_ptr->ap_next = strip_start; } return retval; } static do_hidedomains(dom_ptr, route_ptr) AP_ptr dom_ptr, route_ptr; { int retval = 0; AP_ptr ptr; if ( ptr = route_ptr ) while ( ptr ) { retval += hiddenDomain(ptr); ptr = ptr->ap_next; } return retval += hiddenDomain(dom_ptr); } static int tidy_up() { if (random() % 10000 != 42) return; /* lucky person gets a message */ switch (random() % 3) { case 0: printf ("Checked-by: NSA, MI5, CIA, KGB\n"); break; case 1: printf ("Green-Message: This message is stored on recycled memory\n"); break; default: printf ("Congratulations: You are the recipient of our %d message\n", random() % 1000000); break; } } static AP_ptr parse_and_norm(ap, pgroup, pname, ploc, pdom, proute) AP_ptr ap, *pgroup, *pname, *ploc, *pdom, *proute; { char *str, *oldlocal, *newlocal; AP_ptr group, name, loc, dom, route; AP_ptr newtree, newgroup, newname, newloc, newdom, newroute; ADDR *adr; RP_Buf rp; int oldap_outtype; ap = ap_normalize(ap, order_pref); (void) ap_t2p (ap, &group, &name, &loc, &dom, &route); oldap_outtype = ap_outtype; ap_outtype = AP_PARSE_822; str = ap_p2s_nc (group, name, loc, dom, route); adr = adr_new (str, AD_822_TYPE, 0); adr -> ad_resp = NO; if (!rp_isbad(ad_parse(adr, &rp, order_pref))) { /* may have to munge */ ap_s2p(adr->ad_r822adr, &newtree, &newgroup, &newname, &newloc, &newdom, &newroute); oldlocal = ap_p2s_nc(NULLAP, NULLAP, loc, NULLAP, NULLAP); newlocal = ap_p2s_nc(NULLAP, NULLAP, newloc, NULLAP, NULLAP); if (lexequ(oldlocal, newlocal) != 0) { AP_ptr hdr, ix, tmp; AP_ptr firstdom = NULLAP, firstloc = NULLAP; /* oh oh munge address */ /* add header */ hdr = ap_new(AP_COMMENT, "header"); hdr -> ap_next = ap; hdr -> ap_ptrtype = AP_PTR_MORE; ix = hdr; /* delete everything except comments from old tree */ while (ix -> ap_next != NULLAP) { switch (ix -> ap_next -> ap_obtype) { case AP_DOMAIN: case AP_DOMAIN_LITERAL: if (firstloc != NULLAP && firstdom == NULLAP) firstdom = ix; ap_delete(ix); break; case AP_MAILBOX: case AP_GENERIC_WORD: if (firstloc == NULLAP) firstloc = ix; ap_delete(ix); break; default: case AP_COMMENT: ix = ix -> ap_next; break; } } /* now splice new tree into old tree */ for (ix = newdom; ix -> ap_next != NULLAP; ix = ix -> ap_next); /* put newdom -> ix in after firstdom */ tmp = firstdom -> ap_next; firstdom -> ap_next = newdom; ix -> ap_next = tmp; for (ix = newloc; ix -> ap_next != NULLAP && ix -> ap_next != newdom && ix -> ap_next != newroute; ix = ix -> ap_next); /* put newloc -> ix in after firstloc */ tmp = firstloc -> ap_next; firstloc -> ap_next = newloc; ix -> ap_next = tmp; ap = hdr -> ap_next; ap_free(hdr); /* reset parts */ (void) ap_t2p (ap, &group, &name, &loc, &dom, &route); } else ap_sqdelete (newtree, NULLAP); free (oldlocal); free (newlocal); adr_free(adr); } ap_outtype = oldap_outtype; *pgroup = group, *pname = name; *ploc = loc; *pdom = dom; *proute = route; return ap; } static char *re_parse_ptr; static int get_rp_char() { char ret = *re_parse_ptr; if (ret != 0) re_parse_ptr++; return (ret == 0) ? EOF : ret; } static int out_adr(ap) register AP_ptr ap; { AP_ptr loc_ptr, /* -- in case fake personal name needed -- */ group_ptr, name_ptr, dom_ptr, route_ptr; char *addrp; int len; static rd = 0; if (ap->ap_obtype == AP_NIL) return OK; rd++; ap = parse_and_norm(ap, &group_ptr, &name_ptr, &loc_ptr, &dom_ptr, &route_ptr); if (from && equalWithJntsender(loc_ptr)) noFrom = 0; /* do all stripping then create addrp */ if (rd < 3 && (dom_ptr != NULL) && (num_to_hide != 0) && do_hidedomains(dom_ptr, route_ptr)) { /* This might be local now, so go through the whole expansion * process again. Remember though that we might be exremely * silly, and cause `infinite' recursion. Hence the rd variable. */ re_parse_ptr = addrp = ap_p2s(group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr); ap_sqdelete (ap, NULLAP); ap_free (ap); ap = ap_pstrt = ap_pcur = ap_alloc (); ap_ppush(get_rp_char); ap_clear(); if (ap_1adr() == OK) out_adr(ap); ap_ppop(); free(addrp); rd--; return OK; /* NOTREACHED */ } if ((dom_ptr != NULL) && (striproutes == TRUE)) addrp = do_striproutes(group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr); else if ((dom_ptr != NULL) && (num_domains != 0)) addrp = do_stripdomains(group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr); else addrp = ap_p2s(group_ptr, name_ptr, loc_ptr, dom_ptr, route_ptr); if (addrp == (char *)NOTOK) { PP_LOG (LLOG_EXCEPTIONS, ("Lib/addr/ap_t2s: error from ap_p2s()")); addrp = strdup ("(PP Error!)"); } if (rd == 3) { PP_LOG (LLOG_EXCEPTIONS, ("Format/rfc822norm: Excessive local hiding - cannot resolve address")); free(addrp); addrp = strdup ("(PP Configuration Error!)"); } if (nadrs != 0) { printf(", "); pcol += 2; } PP_TRACE(("output '%s'",addrp)); if ((len = strlen(addrp)) > 0) { /* print */ pcol += len; if (fold_width != -1 && pcol > fold_width && nonempty) { pcol = strlen(fieldbuf) + 2 + len; printf("\n%*s", strlen(fieldbuf) + 2, ""); } else nonempty = TRUE; printf("%s",addrp); nadrs++; } free(addrp); /* ap_sqdelete (ap, NULLAP); ap_free (ap);*/ rd--; return OK; } /* \f */ static char *reverse(str) char *str; { char *ret = malloc((unsigned) strlen(str)+1), *dup = strdup(str), *ix; ret[0] = '\0'; while ((ix = rindex(dup,'.')) != NULL) { if (ret[0] == '\0') sprintf(ret, "%s", ix+1); else sprintf(ret,"%s.%s",ret,ix+1); *ix = '\0'; } if (ret[0] == '\0') sprintf(ret, "%s", dup); else sprintf(ret,"%s.%s",ret,dup); free(dup); return ret; }