/* * Copyright 1990 by Rayan S. Zachariassen, all rights reserved. * This will be free software, but only when it is finished. */ #include "hostenv.h" #include "mailer.h" #include #include "libc.h" #include "libz.h" char *progname = "rfc822test"; int D_alloc = 0; extern union misc parse822(); extern token822 *readlines(); extern time_t time(); extern int fprintToken(); int main(argc, argv) int argc; char *argv[]; { register token822 *t; u_long len; time_t now; const u_char *cp, *ocp; int c; HeaderSemantics entry_pt; token822 *tlist, **prev_tp, *scan_t, *nt; struct address *a; struct addr *p; struct tm localtm; union misc val; FILE *tracefp; entry_pt = AddressList; tracefp = NULL; while ((c = zgetopt(argc, argv, "e:T")) != EOF) { switch (c) { case 'e': entry_pt = (HeaderSemantics)atoi(zoptarg); break; case 'T': tracefp = stdout; (void) setvbuf(stdout, (char *)NULL, _IOLBF, 0); break; } } again: tlist = NULL; prev_tp = &tlist; for (t = readlines(); t != NULL; t = t->t_next) { if (t->t_type != Line) /* sanity check */ continue; /* * Scan the entire line at a time, instead of having the * parser call the scanner when a token is needed. This avoids * nontrivial function-call overhead, but does decrease * flexibility slightly. */ cp = t->t_pname; len = TOKENLEN(t); while (len > 0) { ocp = cp; nt = t; if (entry_pt == DateTime || entry_pt == Received) scan_t = scan822(&cp, len, '-', '/', 0, &nt); else scan_t = scan822(&cp, len, '!', '%', 0, &nt); if (nt != t) { /* compound token across line */ while (t != nt) t = t->t_next; /* len should be 0 */ len = t->t_pname - cp + TOKENLEN(t); } else len -= cp - ocp; /* Append the scanner tokens to the list of tokens */ *prev_tp = scan_t; while (scan_t != NULL) { /* * Doing it in a loop allows the scanner to * return a token list instead of one token. */ prev_tp = &(scan_t->t_next); scan_t = scan_t->t_next; } } } *prev_tp = NULL; time(&now); localtm = *(localtime(&now)); val = parse822(entry_pt, &tlist, &localtm, tracefp); switch (entry_pt) { case Received: printf("Received:\n"); printf("\tFrom:"); if (val.r->r_from != NULL) errprint(stdout, val.r->r_from->a_tokens); else printf("\tnull\n"); printf("\tBy:"); if (val.r->r_by != NULL) errprint(stdout, val.r->r_by->a_tokens); else printf("\tnull\n"); printf("\tVia:\t%s\n", val.r->r_via ? formatToken(val.r->r_via) : "null"); t = val.r->r_with; printf("\tWith:\t%s", t ? formatToken(t) : "null"); if (t != NULL) t = t->t_next; while (t != NULL) printf(", %s", formatToken(t)); printf("\n"); printf("\tId:"); if (val.r->r_id != NULL) errprint(stdout, val.r->r_id->a_tokens); else printf("\tnull\n"); printf("\tFor:"); if (val.r->r_for != NULL) errprint(stdout, val.r->r_for->a_tokens); else printf("\tnull\n"); if (val.r->r_time != 0L) printf("\tDate: %s", rfc822date(&(val.r->r_time))); else printf("\tDate: null\n"); break; case DateTime: if (val.d != 0) printf("DateTime: %s\n", rfc822date(&val.d)); else printf("DateTime: null\n"); break; default: for (a = val.a; a != NULL && a->a_tokens != NULL;a = a->a_next){ for (p = a->a_tokens; p != NULL; p=p->p_next) { printf("\t%s:\n", formatAddr(p->p_type)); for (t = p->p_tokens; t != NULL; t = t->t_next) printf("\t\t%s\n", formatToken(t)); } errprint(stdout, a->a_tokens); printf("--- end of address ---\n"); } break; } exit(0); } token822 * readlines() { token822 *t, **pt; char buf[BUFSIZ]; pt = &t; /*while*/ if (gets(buf) != NULL) { *pt = makeToken(buf, strlen(buf)); (*pt)->t_type = Line; pt = &((*pt)->t_next); } else exit(1); *pt = NULL; return t; } #if 0 char * tmalloc(n) int n; { return malloc(n); } char * strnsave(s, n) char *s; int n; { char *cp = tmalloc(n+1); memcpy(cp, s, n); *(cp+n) = '\0'; return cp; } #endif #define OFFSET 1 errprint(fp, pp) FILE *fp; register struct addr *pp; { int inAddress, n, i, j, len; token822 *t; struct addr *lastp, *tpp; struct { int pos; token822 *tokens; } errmsg[200]; inAddress = 0; for (lastp = NULL, tpp = pp; tpp != NULL; tpp = tpp->p_next) if (tpp->p_type == anAddress) lastp = tpp; (void) putc('\t', fp); len = OFFSET; n = 0; for (; pp != NULL; pp = pp->p_next) { if (pp->p_type == aComment) putc('(', fp), ++len; else if (pp->p_type == anAddress) inAddress = 1; else if (pp->p_type == anError) { errmsg[n].pos = len - OFFSET; errmsg[n++].tokens = pp->p_tokens; continue; } for (t = pp->p_tokens; t != NULL; t = t->t_next) { switch (pp->p_type) { case aPhrase: case aComment: case aGroup: case aWord: if (t != pp->p_tokens) putc(' ', fp), ++len; /* fall through */ case anAddress: case aDomain: case reSync: len = fprintToken(fp, t, len); (void) fprintToken(fp, t, 0); if (pp->p_type == reSync && t->t_next != NULL && (t->t_next->t_type == t->t_type)) putc(' ', fp), ++len; break; case aSpecial: if (t != pp->p_tokens && *(t->t_pname) == '<') putc(' ', fp), ++len; putc((*t->t_pname), fp), ++len; case anError: break; } } if (pp->p_type == aComment) { putc(')', fp), ++len; } else if (lastp == pp) inAddress = 0; if (!inAddress && pp->p_next != NULL && pp->p_next->p_type != anError && !(pp->p_next->p_type == anAddress && pp->p_type == aSpecial && *pp->p_tokens->t_pname == '<') && !(pp->p_next->p_type == aSpecial && pp->p_type == anAddress && *pp->p_next->p_tokens->t_pname == '>') && !(pp->p_next->p_type == aSpecial && *pp->p_next->p_tokens->t_pname == ':')) { putc(' ', fp), ++len; } } (void) putc('\n', fp); if (n == 0) return; (void) putc('\t', fp); for (i = 0, len = 0; i < n;) { for (; (len+1)/8 < errmsg[i].pos/8; len = ((len/8)+1)*8) (void) putc('\t', fp); for (; len < errmsg[i].pos; ++len) (void) putc(' ', fp); while (i < n && len == errmsg[i].pos) (void) putc('^', fp), ++i; ++len; } --n; fprintf(fp, "-%s", errmsg[n].tokens->t_pname); for (t = errmsg[n].tokens->t_next; t != NULL; t = t->t_next) fprintf(fp, ", %s", t->t_pname); (void) putc('\n', fp); for (j = 0; j < n; ++j) { (void) putc('\t', fp); for (i = 0, len = 0; i < n-j;) { for (; (len+1)/8 < errmsg[i].pos/8; len = ((len/8)+1)*8) (void) putc('\t', fp); for (; len < errmsg[i].pos; ++len) (void) putc(' ', fp); while (i < n-j && len == errmsg[i].pos) { if (i == n-j-1) { if (j == 0) (void) putc(' ', fp), ++i; (void) putc('\\', fp), ++i; } else (void) putc('|', fp), ++i; } ++len; } fprintf(fp, "-%s", errmsg[n-j-1].tokens->t_pname); for (t = errmsg[n-j-1].tokens->t_next; t != NULL; t = t->t_next) fprintf(fp, ", %s", t->t_pname); (void) putc('\n', fp); } }