DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T i

⟦d587130a1⟧ TextFile

    Length: 16747 (0x416b)
    Types: TextFile
    Names: »io_grey.c«

Derivation

└─⟦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« 

TextFile

/* 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;
}