|
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 i
Length: 16747 (0x416b) Types: TextFile Names: »io_grey.c«
└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0 └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« └─⟦e5a54fb17⟧ └─⟦this⟧ »pp-5.0/Chans/grey/io_grey.c«
/* io_grey.c: These are IO routines for the greybook channel */ # ifndef lint static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/grey/RCS/io_grey.c,v 5.0 90/09/20 15:48:28 pp Exp Locker: pp $"; # endif /* * $Header: /cs/research/pp/hubris/pp-beta/Chans/grey/RCS/io_grey.c,v 5.0 90/09/20 15:48:28 pp Exp Locker: pp $ * * $Log: io_grey.c,v $ * Revision 5.0 90/09/20 15:48:28 pp * rcsforce : 5.0 public release * */ #include "util.h" #include "prm.h" #include "q.h" #include "adr.h" #include "ap.h" #include "retcode.h" #include "tb_q.h" #include "tb_a.h" #include "tb_prm.h" #include <isode/cmd_srch.h> /*--- statics ---*/ static struct prm_vars prm = { NULLCP, 0, PRM_ACCEPTALL }; static Q_struct Qstruct; static int submit_started = 0; #define ST_OPENED 3 #define ST_JNTHDR 0 #define ST_MSGHDR 1 #define ST_BODY 2 static int state = ST_OPENED; static AP_ptr newdomain(); static char *compress(); static void berror (); static int add_via(); static int aprd_done(); static int aprd_init(); static int aprdchr(); static int fixup_sender(); static int hdr_done(); static int hdr_init(); static int hdr_read(); static int process_addrs(); static int pp_error (); static CHAN *mychan = NULLCHAN; static char **errstr = (char **) 0; static char *theheader = NULLCP; static char *hdrptr; static char *apchptr; static char *apcharacters = NULLCP; static int data_bytes; static struct timeval data_timer; /*--- externals */ extern ADDR *adr_new(); extern char *postmaster; extern char *ia5_bp, *hdr_822_bp; #define GB_NOTOK NOTOK #define GB_OK OK #define GB_RECIPFAILED -2 #define GB_SENDERFAILED -3 /* ------------------- Begin Routines ---------------------------------- */ char errbuffer[BUFSIZ]; /*--- tell PP that a call is arriving ---*/ int pp_open (chan, hostname, perrstr) char *chan; char *hostname; char **perrstr; { RP_Buf reply; Q_struct *qp = &Qstruct; LIST_BPT *new; extern char *quedfldir; static int onceonly = 1; errstr = perrstr; if (onceonly) { chan_init (chan); (void) chdir (quedfldir); ap_use_percent (); onceonly = 0; } if (state != ST_OPENED) return pp_error (errstr, GB_RECIPFAILED, "Illegal call to ppp_open - internal botch"); PP_TRACE (("pp_open (%s, %s)", chan, hostname)); if ((mychan = ch_nm2struct (chan)) == NULLCHAN) { (void) sprintf (errbuffer, "Local error: Channel '%s' is not known", chan); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } PP_NOTICE (("Incoming Call from %s to %s", hostname, mychan->ch_name)); if (submit_started == 0 && rp_isbad (io_init (&reply))) { berror (errbuffer, "Can't initialise mail system", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } submit_started = 1; if (rp_isbad (io_wprm (&prm, &reply))) { berror (errbuffer, "Can't set parameters", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } /*--- initialize queue structure ---*/ q_init (qp); qp -> msgtype = MT_UMPDU; qp -> inbound = list_rchan_new (hostname, chan); qp -> encodedinfo.eit_types = NULLIST_BPT; new = list_bpt_new (hdr_822_bp); list_bpt_add (&qp -> encodedinfo.eit_types, new); new = list_bpt_new (ia5_bp); list_bpt_add (&qp -> encodedinfo.eit_types, new); if (rp_isbad (io_wrq (qp, &reply))) { berror (errbuffer, "Can't write Q struct", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } data_bytes = 0; timer_start (&data_timer); state = ST_JNTHDR; return GB_OK; } int pp_write (fd, buff, size) /*--- write some data to PP ---*/ int fd; char buff[]; int size; { static int linefeed = 0; static struct qbuf *qb[2] = {NULL, NULL}, *qp = NULL; char *cp = NULLCP, *ep = NULLCP, *bp = NULLCP, *q; int retval; PP_TRACE (("pp_write (%d bytes)", size)); data_bytes += size; switch (state) { case ST_JNTHDR: case ST_MSGHDR: for (bp = cp = buff, ep = buff + size; cp < ep; cp++) { switch (*cp) { case '\r': continue; case '\n': linefeed ++; if (linefeed < 2) continue; for (q = cp - 1; q > bp && *q == '\r'; q--) continue; if (qb[state] == NULL) qb[state] = str2qb (bp, q - bp, 1); else { qp = str2qb (bp, q - bp, 0); insque (qp, qb[state]->qb_back); } bp = cp + 1; state ++; if (state < ST_BODY) continue; break; default: linefeed = 0; continue; } break; } if (state != ST_BODY && bp + 1 < ep) { if (qb[state] == NULL) qb[state] = str2qb (bp, ep - bp, 1); else { qp = str2qb (bp, ep - bp, 0); insque (qp, qb[state]->qb_back); } } if (qb[0]) { cp = NULLCP; PP_DBG (("pp_write/qb[0]='%.900s'", cp = qb2str(qb[0]))); if (cp) free (cp); } if (qb[1]) { cp = NULLCP; PP_DBG (("pp_write/qb[1]='%.900s'", cp = qb2str (qb[1]))); if (cp) free (cp); } if (state == ST_BODY) { /* GOT IT - lets go!! */ if ((retval = process_addrs (qb[0], qb[1], errstr)) != GB_OK) return retval; qb_free (qb[0]); qb[0] = NULL; qb_free (qb[1]); qb[1] = NULL; if (bp + 1 < ep) if (rp_isbad (io_tdata(bp, size - (bp-buff)))) return pp_error (errstr, GB_RECIPFAILED, "Data Copy failed"); } break; case ST_BODY: if (size <= 0) { PP_LOG (LLOG_EXCEPTIONS, ("Funny size to pp_write: %d", size)); return size; } if (rp_isbad (io_tdata (buff, size))) return pp_error (errstr, GB_RECIPFAILED, "Data Copy Faield"); return size; default: return pp_error (errstr, GB_RECIPFAILED, "Illegal call to pp_write - internal error"); } return size; } int pp_close(fd) /*--- tell PP that all the data has arrived ---*/ int fd; { RP_Buf reply; PP_TRACE (("pp_close()")); if (state == ST_MSGHDR) if (pp_write (0, "\n", 1) != 1) return pp_error (errstr, GB_RECIPFAILED, "pp_write (internal call) failed"); if (state != ST_BODY) return pp_error (errstr, GB_RECIPFAILED, "Illegal call to pp_close - internal error"); timer_end (&data_timer, data_bytes, "Data Received"); if (rp_isbad (io_tdend (&reply))) { berror (errbuffer, "data termination failed", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } if (rp_isbad (io_tend (&reply))) { berror (errbuffer, "data termination (2) failed", &reply); if (rp_gbval (reply.rp_val) == RP_BNO) return pp_error (errstr, GB_NOTOK, errbuffer); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } PP_NOTICE (("Message successfully transfered")); state = ST_OPENED; return GB_OK; } /* ------------------- Static Routines ---------------------------------- */ static AP_ptr newdomain (domn) char *domn; { PP_TRACE (("newdomain (%s)", domn)); return ap_new ((*domn == '[') ? AP_DOMAIN_LITERAL : AP_DOMAIN, domn); } static process_addrs (qbjnt, qbhdr, errstr) struct qbuf *qbjnt; struct qbuf *qbhdr; char **errstr; { RP_Buf reply; char *name, *contents, buffer[BUFSIZ], *p = NULLCP; AP_ptr ap_sender = NULLAP, jntroute = NULLAP, local = NULLAP, domain = NULLAP, route = NULLAP, jntaddr = NULLAP, aptr; ADDR *ap = NULLADDR; int got_sender = 0, ack_flag = AD_USR_BASIC, retval; struct qbuf *qp = NULL; int n; PP_TRACE (("process_addrs()")); hdr_init (qbhdr); while (hdr_read (&name, &contents) != NOTOK) { PP_DBG (("process_addrs (%s %s)", name, contents)); if (lexequ ("sender", name) == 0) { if ((aptr = ap_s2t (contents)) == BADAP || aptr == NULLAP) PP_LOG (LLOG_EXCEPTIONS, ("Bad sender field %s", contents)); else { ap_sender = aptr; got_sender = 1; } } if (lexequ ("from", name) == 0 && !got_sender) { if ((aptr = ap_s2t (contents)) == BADAP || aptr == NULLAP) PP_LOG (LLOG_EXCEPTIONS, ("Bad from field %s", contents)); else ap_sender = aptr; } if (lexequ ("via", name) == 0) { if (add_via (contents, &jntroute, buffer) == NOTOK) { return pp_error (errstr, GB_NOTOK, buffer); } } if (lexequ ("acknowledge-to", name) == 0) ack_flag = AD_USR_CONFIRM; } hdr_done(); if (!ap_sender) return pp_error (errstr, GB_NOTOK, "No sender field present in Header"); fixup_sender (ap_sender, jntroute, buffer); ap = adr_new (buffer, AD_822_TYPE, 0); PP_NOTICE (("Sender '%s'", ap->ad_value)); if (rp_isbad (io_wadr (ap, AD_ORIGINATOR, &reply))) { (void) sprintf (buffer, "Bad sender '%s'", ap -> ad_value); adr_tfree (ap); berror (errbuffer, buffer, &reply); if (reply.rp_val == RP_BHST || rp_gbval(reply.rp_val) == RP_BNO) return pp_error (errstr, GB_NOTOK, errbuffer); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } adr_tfree (ap); aprd_init (qbjnt); n = 0; while ((jntaddr = ap_pinit (aprdchr)) != BADAP) { switch (retval = ap_1adr()) { case NOTOK: ap_free (jntaddr); aprd_done (); return pp_error (errstr, GB_NOTOK, "unparseable JNT address - BAD JNT HEADER"); case DONE: ap_free (jntaddr); break; } if (retval == DONE) break; ap_t2p (jntaddr, (AP_ptr *)0, (AP_ptr *)0, &local, &domain, &route); if (route == NULLAP) { if (domain && domain -> ap_obtype == AP_DOMAIN_LITERAL) { ap_free (domain); domain = NULLAP; } } else { if (route -> ap_obtype == AP_DOMAIN_LITERAL) { aptr = route; route = aptr -> ap_next; if (route -> ap_obtype != AP_DOMAIN_LITERAL || route -> ap_obtype != AP_DOMAIN) route = NULLAP; ap_free (aptr); } } p = ap_p2s_nc (NULLAP, NULLAP, local, domain, route); ap = adr_new (p, AD_822_TYPE, 0); ap -> ad_usrreq = ack_flag; PP_NOTICE (("Recipient Address '%s'", ap->ad_value)); if (rp_isbad (io_wadr (ap, AD_RECIPIENT, &reply))) { berror (errbuffer, "Recipient failed", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } adr_tfree (ap); n ++; } if (n == 0) return pp_error (errstr, GB_NOTOK, "No recipients in JNT Header"); if (rp_isbad (io_adend (&reply))) { berror (errbuffer, "Address termination failed", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } aprd_done(); if (rp_isbad (io_tinit (&reply)) || rp_isbad (io_tpart (hdr_822_bp, FALSE, &reply))) { berror (errbuffer, "Text initialisation", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } for (qp = qbhdr -> qb_forw; qp != qbhdr; qp = qp -> qb_forw) { if (qp -> qb_len <= 0) continue; if (rp_isbad (io_tdata (qp->qb_data, qp->qb_len))) { (void) sprintf (errbuffer, "Data copy Failed"); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } } if (rp_isbad (io_tdend (&reply))) { berror (errbuffer, "Text termination problem", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } if (rp_isbad (io_tpart ("1.ia5", FALSE, &reply))) { berror (errbuffer, "Text body initialiastion probelms", &reply); return pp_error (errstr, GB_RECIPFAILED, errbuffer); } return GB_OK; } static fixup_sender (sender, jntroute, dest) AP_ptr sender; AP_ptr jntroute; char *dest; { extern char *loc_dom_site; AP_ptr ap, route = NULLAP, domain = NULLAP, mbox = NULLAP; int donevia = 0; char *p; PP_TRACE (("fixup_sender()")); ap_t2p (sender, (AP_ptr *)0, (AP_ptr *)0, &mbox, &domain, &route); #define pp_is_burning_up_cpu_time 1 while (pp_is_burning_up_cpu_time) { if (jntroute != NULLAP) { ap = jntroute; jntroute = jntroute -> ap_next; } else if (donevia) break; else { donevia = TRUE; ap = newdomain (loc_dom_site); } if (domain ==NULLAP) domain = ap; else { ap -> ap_next = route; route = ap; } } /*--- normalise the domains ---*/ ap_dmnormalize (domain, CH_UK_PREF); for (ap = route; ap != NULLAP; ap = ap -> ap_next) switch (ap -> ap_obtype) { case AP_DOMAIN: ap_dmnormalize (ap, CH_UK_PREF); break; default: break; } /*--- eliminating redundant entries ---*/ while (route != NULLAP) { for (ap = route; ap -> ap_next != NULLAP;) { if (ap -> ap_next ->ap_obtype == AP_NIL) break; ap = ap -> ap_next; } if (lexequ (domain -> ap_obvalue, ap -> ap_obvalue)) { ap -> ap_obtype = AP_NIL; free (ap -> ap_obvalue); ap -> ap_obvalue = NULLCP; if (ap == route) { ap_free (route); route = NULLAP; break; } } else break; } p = ap_p2s_nc (NULLAP, NULLAP, mbox, domain, route); (void) strcpy (dest, p); free (p); } static add_via (str, route, ebuf) char *str; AP_ptr *route; char *ebuf; { char *p, *q; AP_ptr ap; PP_TRACE (("add_via (%s)", str)); if ((p = rindex (str, ';')) != NULLCP) *p = '\0'; else { (void) sprintf (ebuf, "Illegal Via: field, No ';' \"%s\"", str); PP_LOG (LLOG_EXCEPTIONS, ("%s", ebuf)); return NOTOK; } compress (str, str); while ((p = index (str, '(')) != NULLCP) { if ((q = index (p, ')')) != NULLCP) { q++; while (*q) *p++ = *q++; *p = '\0'; } else break; } compress (str, str); if (str == NULLCP || *str == NULL) { (void) sprintf (ebuf, "empty host component in via field"); PP_LOG (LLOG_EXCEPTIONS, ("%s", ebuf)); return NOTOK; } ap = newdomain (str); ap -> ap_next = *route; *route = ap; return OK; } static hdr_init (qb) struct qbuf *qb; { hdrptr = theheader = qb2str (qb); PP_TRACE (("hdr_init (%.999s)", hdrptr)); } static hdr_read (name, contents) char **name, **contents; { char *cp; PP_DBG (("hdr_read (%.80s)", hdrptr)); if (*hdrptr == '\0') return NOTOK; *name = hdrptr; for (*name = hdrptr; *hdrptr; hdrptr++) { if (*hdrptr == ':') { *hdrptr ++ = '\0'; break; } if (*hdrptr == '\n') { *hdrptr = '\0'; *contents = hdrptr; hdrptr ++; return OK; } } compress (*name, *name); if (*hdrptr == '\0') return OK; while (*hdrptr == ' ' || *hdrptr == '\t') hdrptr ++; for (*contents = hdrptr; *hdrptr; hdrptr++) { if (*hdrptr == '\n') { if (isspace (hdrptr[1])) { *hdrptr = ' '; continue; } *hdrptr ++ = '\0'; break; } } return OK; } static hdr_done() { PP_TRACE (("hdr_done()")); if (theheader) { free (theheader); theheader = NULLCP; } } static aprd_init (qb) struct qbuf *qb; { apchptr= apcharacters = qb2str (qb); PP_TRACE (("aprd_init (%.999s)", apchptr)); } static aprdchr() { return *apchptr == '\0' ? EOF : *apchptr++; } static aprd_done() { PP_TRACE (("aprd_done()")); if (apcharacters) { free (apcharacters); apcharacters = NULLCP; } } static char *compress (fromptr, toptr) register char *fromptr; register char *toptr; { register char chr; char *in_toptr = toptr; PP_DBG (("compress (%s)", fromptr)); /*--- init to skip leading spaces tabs and newlines --- */ chr = ' '; while ((*toptr = *fromptr++) != '\0') { /*--- only save the spaces found in between words ---*/ if (isspace (*toptr)) { if (chr != ' ') *toptr++ = chr = ' '; } else chr = *toptr++; } /*--- remove trailing spaces, tabs and newlines if any ---*/ if ((chr == ' ') && (toptr != in_toptr)) *--toptr = '\0'; return (toptr); } static void berror (buffer, str, rp) char *buffer, *str; RP_Buf *rp; { (void) sprintf (buffer, "%s ([%s] %s)", str, rp_valstr (rp->rp_val), rp -> rp_line[0] ? rp -> rp_line : "No further information"); } static int pp_error (err, code, str) char **err; int code; char *str; { char *kind; switch (code) { case GB_OK: kind = "ok"; break; case GB_RECIPFAILED: kind = "failed - recipient temp"; break; case GB_NOTOK: kind = "failed - permanent"; break; case GB_SENDERFAILED: kind = "failed - sender temporary"; break; default: kind = "UNKNOWN"; break; } if (err) *err = strdup (str); PP_LOG (LLOG_EXCEPTIONS, ("%s %s", str, kind)); submit_started = 0; io_end (NOTOK); state = ST_OPENED; return code; }