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 p

⟦9bde1e144⟧ TextFile

    Length: 21644 (0x548c)
    Types: TextFile
    Names: »ppp.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/ppp.c« 

TextFile

/* ppp.c: ppp interface routines */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Chans/grey/RCS/ppp.c,v 5.0 90/09/20 15:48:32 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Chans/grey/RCS/ppp.c,v 5.0 90/09/20 15:48:32 pp Exp Locker: pp $
 *
 * $Log:	ppp.c,v $
 * Revision 5.0  90/09/20  15:48:32  pp
 * rcsforce : 5.0 public release
 * 
 */



#include "util.h"
#include "ppp.h"
#include "qmgr.h"
#include "prm.h"
#include "q.h"
#include "adr.h"
#include "chan.h"
#include <varargs.h>
#include "retcode.h"
#include "dr.h"
#include "ap.h"

static int ppp_sd = NOTOK;
static CHAN *mychan;
static struct prm_vars prm;
static Q_struct Qs;
static ADDR *ad_sender, *ad_recip, *ad_list;
static enum { jnthdr, initialise, go } state;
static char *this_msg;
static int naddrs = 0;
static char *cur_host;
static char *cur_net;
static char *jnt_host;
static int rox_id;
static int ppp_error_status;
static int data_bytes;
static struct timeval data_timer;
#if PP_DEBUG > PP_DEBUG_NONE
static int ppp_debug = 0;
static int debug_init (), debug_nextmsg ();
static void pdeliverystatus (), pindividualdeliverystatus ();
#endif

static int ppp_initfnx (), ppp_procfnx ();
static void ppp_lose ();
static int ros_indication (), ros_work (), ros_result (),
	error (), ureject ();
static void ros_advise (), acs_advise ();
static void cleanup_everything ();
static char *bigendian ();
static char *mk_jnt ();
static int assemble_jntheader ();
static int fetch_data ();
static int ppp_procfnx_aux ();

static int lastop = NOTOK;
#define INITOP	1
#define PROCOP	2
extern struct RyOperation table_QmgrChannel_Operations[];
extern char *quedfldir;

int ppp_init (argc, argv)
int	argc;
char	**argv;
{
	struct AcSAPstart   acss;
	register struct AcSAPstart *acs = &acss;
	struct AcSAPindication  acis;
	register struct AcSAPindication *aci = &acis;
	register struct AcSAPabort   *aca = &aci -> aci_abort;
        struct RoSAPindication  rois;
        register struct RoSAPindication *roi = &rois;
        register struct RoSAPpreject   *rop = &roi -> roi_preject;
	register struct PSAPstart *ps = &acs -> acs_start;
	int	result;

	chan_init (argv[0]);
	(void) chdir (quedfldir);
#if PP_DEBUG > PP_DEBUG_NONE
	if (argc > 1 && strcmp (argv[1], "-P") == 0 && 
	    argc > 2 && strcmp(argv[2], "debug") == 0)
		return debug_init ();
#endif
	if (RyDispatch (NOTOK, table_QmgrChannel_Operations,
			operation_Qmgr_channelInitialise, ppp_initfnx,
			roi) == NOTOK) {
		ros_advise (rop, "RyDispatch: channelInitialise");
		return NOTOK;
	}
	if (RyDispatch (NOTOK, table_QmgrChannel_Operations,
			operation_Qmgr_processmessage, ppp_procfnx,
			roi) == NOTOK) {
		ros_advise (rop, "RyDispatch: processmessage");
		return NOTOK;
	}

	if (AcInit (argc, argv, acs, aci) == NOTOK) {
		acs_advise (aca, "AcInit");
		return NOTOK;
	}

	PP_DBG (("A-ASSOCIATE.INDICATION: <%d, %s, %s, %s, %d>",
		 acs -> acs_sd, sprintoid (acs -> acs_context),
		 sprintaei (&acs -> acs_callingtitle),
		 sprintaei (&acs -> acs_calledtitle), acs -> acs_ninfo));
	ppp_sd = acs -> acs_sd;

	result = AcAssocResponse (ppp_sd, ACS_ACCEPT, ACS_USER_NULL,
				  NULLOID, NULLAEI, NULLPA, NULLPC,
				  ps -> ps_defctxresult,
				  ps -> ps_prequirements,
				  ps -> ps_srequirements, SERIAL_NONE,
				  ps -> ps_settings, &ps -> ps_connect,
				  NULLPEP, 0, aci);
	ACSFREE (acs);
	if (result == NOTOK) {
		acs_advise (aca, "A-ASSOCIATE.RESPONSE");
		return ppp_sd = NOTOK;
	}
	if (RoSetService (ppp_sd, RoPService, roi) == NOTOK) {
		ros_advise (rop, "set RO/PS fails");
		ppp_lose ();
		return NOTOK;
	}

	/* try and get the init channel op */
	if (ros_work (ppp_sd, INITOP) != OK) {
		ppp_lose ();
		return NOTOK;
	}
	return OK;
}


int ppp_getnextmessage (host, net)
char	**host;
char	**net;
{
	int	result;

	state = jnthdr;
#if PP_DEBUG > PP_DEBUG_NONE
	if (ppp_debug)
		result = debug_nextmsg ();
	else
#endif
	result = ros_work (ppp_sd, PROCOP);
	switch (result) {
	    default:
	    case NOTOK:
		ros_result (ppp_sd, deliverystate, rox_id);
		ppp_lose ();
		return NOTOK;

	    case OK:
		if (ppp_error_status == NOTOK) {
			ros_result (ppp_sd, deliverystate, rox_id);
			return ppp_getnextmessage (host, net);
		}
		if (jnt_host)
			free (jnt_host);
		*host = jnt_host = mk_jnt(cur_host);
		if (jnt_host == NULLCP)
			return NOTOK;
		if (cur_net)
			free (cur_net);
		if (mychan -> ch_info == NULLCP) {
			PP_OPER (NULLCP, ("Channel %s has no info string",
					  mychan -> ch_name));
			return NOTOK;
		}
		*net = cur_net = strdup (mychan -> ch_info);
		return OK;

	    case DONE:
		return DONE;
	}
}

static char	*hdrbuf;

int ppp_getdata (buf, len)
char	**buf;
int	*len;
{
	if (hdrbuf) {
		free (hdrbuf);
		hdrbuf = NULLCP;
	}

	switch (state) {
	    case jnthdr:
		data_bytes = 0;
		timer_start (&data_timer);
		state = initialise;
		return assemble_jntheader (buf, len);

	    case initialise:
	    case go:
		return fetch_data (buf, len);

	    default:
		PP_LOG (LLOG_EXCEPTIONS, ("Bad state in getdata"));
		return NOTOK;
	}
}

static int assemble_jntheader (buf, lengthp)
char **buf;
int *lengthp;
{
	ADDR	*ap;
	char	*str;
	int	len = 0;

	PP_NOTICE (("Originator %s", ad_sender -> ad_r822adr));
	for (ap = ad_list; ap; ap = ap -> ad_next) {
		if ((str = bigendian (ap -> ad_r822adr)) == NULLCP)
			return NOTOK;
		if (hdrbuf == NULL) {
			hdrbuf = smalloc (len = strlen (str) + 2 + 1);
			(void) strcpy (hdrbuf, str);
			(void) strcat (hdrbuf, ap -> ad_next ? ",\n" : "\n\n");
		}
		else {
			hdrbuf = realloc (hdrbuf, len += strlen (str) + 2);
			(void) strcat (hdrbuf, str);
			(void) strcat (hdrbuf, ap -> ad_next ? ",\n" : "\n\n");
		}
	}
	*buf = hdrbuf;
	*lengthp = len - 1;
	data_bytes += len - 1;
	return OK;
}

static char transbuf[BUFSIZ];
static char	*formatdir;

static int fetch_data (buf, lengthp)
char	**buf;
int	*lengthp;
{
	char filename[BUFSIZ];
	static FILE *fp;
	static int first;
	int	n;

	*buf = "";
	*lengthp = 0;

	if (state == initialise) {
		state = go;
		first = 1;

		if (qid2dir (this_msg, ad_list, TRUE, &formatdir) == NOTOK)
			return NOTOK;
		if (msg_rinit (formatdir) != RP_OK)
			return NOTOK;
		if (msg_rfile (filename) != RP_OK) {
			msg_rend ();
			return NOTOK;
		}
		if ((fp = fopen (filename, "r")) == NULL) {
			msg_rend ();
			return NOTOK;
		}
	}

	if (!feof(fp) && (n = fread (transbuf, 1, sizeof transbuf, fp)) > 0) {
		*buf = transbuf;
		*lengthp = n;
		data_bytes += n;
		return OK;
	}
	if (first) {
		first = 0;
		(void) strcpy (transbuf, "\n");
		*buf = transbuf;
		*lengthp = 1;
		data_bytes += 1;
		return OK;
	}
	
	if (ferror (fp)) {
		msg_rend ();
		(void) fclose (fp);
		return NOTOK;
	}
	(void) fclose (fp);
	
		
	if ((n = msg_rfile (filename)) == RP_DONE){
		msg_rend ();
		*lengthp = 0;
		return DONE;
	}

	if (rp_isbad (n)) {
		msg_rend ();
		return NOTOK;
	}

	if ((fp = fopen (filename, "r")) == NULL) {
		msg_rend ();
		return NOTOK;
	}

	return fetch_data (buf, lengthp);
}

int ppp_status (status, reason)
int	status;
char	*reason;
{
	ADDR	*ap;
	char	buf[BUFSIZ];
	int	confrep = int_Qmgr_status_positiveDR;
	int	drrep = int_Qmgr_status_negativeDR;

	if (status == PPP_STATUS_DONE)
		timer_end (&data_timer, data_bytes, "Data Transfered");

	for (ap = ad_list; ap; ap = ap -> ad_next) {
		if (ap -> ad_resp == 0)
			continue;
		switch (status) {
		    case PPP_STATUS_DONE:
			if (ap ->ad_usrreq == AD_USR_CONFIRM ||
			    ap -> ad_mtarreq == AD_MTA_CONFIRM ||
			    ap -> ad_mtarreq == AD_MTA_AUDIT_CONFIRM) {
				(void) sprintf (buf, "Successfully sent to %s for recipient %s",
						cur_host, ap -> ad_r822adr);
				set_1dr (&Qs, ap -> ad_no, DRR_NO_REASON,
					 -1, buf);
				delivery_set (ap -> ad_no, confrep);
				confrep = int_Qmgr_status_successSharedDR;
			}
			else {
				(void) wr_ad_status (ap, AD_STAT_DONE);
				delivery_set (ap -> ad_no,
					      int_Qmgr_status_success);
			}
			PP_NOTICE ((">>> Message %s transfered to %s", 
					this_msg, cur_host));
			break;

		    case PPP_STATUS_CONNECT_FAILED:
			delivery_setstate (ap -> ad_no,
					   int_Qmgr_status_mtaFailure,
					   reason);
			PP_NOTICE (("Connection to %s failed [%s]",
					cur_host, reason ? reason : ""));
			break;

		    case PPP_STATUS_PERMANENT_FAILURE:
			(void) sprintf (buf, "Blue book transfer to %s failed: %s",
					cur_host, reason);
			delivery_set (ap -> ad_no,
				      drrep);
			drrep = int_Qmgr_status_failureSharedDR;
			set_1dr (&Qs, ap -> ad_no, DRR_TRANSFER_FAILURE,
				 DRD_MTA_CONGESTION, buf);
			PP_NOTICE (("Transfer to %s for %s perm failed [%s]",
				    cur_host, this_msg, buf));
			break;

		    case PPP_STATUS_TRANSIENT_FAILURE:
			delivery_setstate (ap -> ad_no,
					   int_Qmgr_status_messageFailure,
					   reason);
			PP_NOTICE (("Temporary failure for %s to %s [%s]",
				    this_msg, cur_host, reason ? reason : ""));
			break;
		}
	}
	wr_q2dr (&Qs, this_msg);
	cleanup_everything ();
	rd_end ();
#if PP_DEBUG > PP_DEBUG_NONE
	if (ppp_debug){
		 pdeliverystatus (deliverystate);
		 return OK;
	 }
	else
#endif
		return ros_result (ppp_sd, deliverystate, rox_id);
}

void ppp_terminate ()
{
	if (ppp_sd != NOTOK)
		ppp_lose ();
}

static void ppp_lose ()
{
	struct AcSAPindication  acis;
	struct RoSAPindication  rois;
	register struct RoSAPindication *roi = &rois;

	(void) AcUAbortRequest (ppp_sd, NULLPEP, 0, &acis);
	(void) RyLose (ppp_sd, roi);
	ppp_sd = NOTOK;
}

static int ppp_initfnx (sd, ryo, rox, in, roi)
int	sd;
struct RyOperation *ryo;
struct RoSAPinvoke *rox;
caddr_t in;
struct RoSAPindication *roi;
{
	char	*p;

        if (rox -> rox_nolinked == 0) {
                PP_LOG (LLOG_EXCEPTIONS,
                        ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d",
                        sd, ryo -> ryo_name, rox -> rox_linkid));
                return ureject (sd, ROS_IP_LINKED, rox, roi);
        }
        PP_DBG (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name));

	p = qb2str ((struct type_Qmgr_Channel *) in);

	if ((mychan = ch_nm2struct (p)) == NULLCHAN) {
		PP_LOG (LLOG_EXCEPTIONS, ("Unknown channel %s", p));
		free (p);
		error (sd, error_Qmgr_protocol, (caddr_t) NULL, rox -> rox_id);
		return NOTOK;
	}
	PP_NOTICE (("Starting %s (%s)", mychan -> ch_name, mychan -> ch_show));
	rename_log (mychan -> ch_name);

	free (p);

	if (RyDsResult (sd, rox -> rox_id, (caddr_t) NULL,
			ROS_NOPRIO, roi) == NOTOK) {
		ros_advise (&roi -> roi_preject, "RESULT");
		return NOTOK;
	}
	
	lastop = INITOP;
	return OK;
}

static int ppp_procfnx (sd, ryo, rox, in, roi)
int	sd;
struct RyOperation *ryo;
struct RoSAPinvoke *rox;
caddr_t in;
struct RoSAPindication *roi;
{
	struct type_Qmgr_ProcMsg *arg = (struct type_Qmgr_ProcMsg *)in;

        if (rox -> rox_nolinked == 0) {
                PP_LOG (LLOG_EXCEPTIONS,
                        ("RO-INVOKE.INDICATION/%d: %s, unknown linkage %d",
                        sd, ryo -> ryo_name, rox -> rox_linkid));
                return ureject (sd, ROS_IP_LINKED, rox, roi);
        }
        PP_DBG (("RO-INVOKE.INDICATION/%d: %s", sd, ryo -> ryo_name));

	rox_id = rox -> rox_id;
	lastop = PROCOP;
	return ppp_procfnx_aux (arg);
}

static int ppp_procfnx_aux (arg)
struct type_Qmgr_ProcMsg *arg;
{
	struct type_Qmgr_UserList *up;
	int	retval;
	int	ad_count = 0;
	ADDR	*ap, *alp = NULL;

	delivery_init (arg -> users);

	if (this_msg)
		free (this_msg);
	this_msg = qb2str (arg -> qid);

	ad_sender = NULLADDR;

	if (ad_recip) {
		q_free (&Qs);
		prm_free (&prm);
	}
	ad_recip = NULLADDR;

	retval = rd_msg (this_msg, &prm, &Qs, &ad_sender, &ad_recip, &ad_count);
	if (rp_isbad (retval)) {
		PP_LOG (LLOG_EXCEPTIONS, ("local/rd_msg err: %s", this_msg));
		return NOTOK;
	}

	naddrs = 0;
	ad_list = NULLADDR;
	ppp_error_status = OK;
	for (ap = ad_recip; ap; ap = ap -> ad_next) {
                for (up = arg ->users; up; up = up -> next) {
                        if (up -> RecipientId -> parm != ap -> ad_no)
                                continue;

                        switch (chan_acheck (ap, mychan, ad_list == NULLADDR, 
						&cur_host)) {
				case OK:
					break;

				default:
					continue;
			}
			break;
                }
                if (up == NULL)
                        continue;

                if (ad_list == NULLADDR)
                        ad_list = alp = (ADDR *) calloc (1, sizeof *alp);
                else {
                        alp -> ad_next = (ADDR *) calloc (1, sizeof *alp);
                        alp = alp -> ad_next;
                }
                *alp = *ap;
                alp -> ad_next = NULLADDR;
		naddrs ++;
        }

	if (ad_list == NULLADDR) {
		PP_LOG (LLOG_EXCEPTIONS, ("No recipients in user list"));
		rd_end ();
		ppp_error_status = NOTOK;
		return OK;
	}
	PP_NOTICE (("Processing msg %s to %s", this_msg, cur_host));
	return OK;
}


static int  ros_work (fd, what)
int     fd;
int	what;
{
	int     result;
	caddr_t out;
	struct RoSAPindication  rois;
	register struct RoSAPindication *roi = &rois;
	register struct RoSAPpreject   *rop = &roi -> roi_preject;
	fd_set rfds;

	for (;;) {
		PP_TRACE (("ros_work loop (%d, %d)", fd, what));
		FD_ZERO (&rfds);
		FD_SET (fd, &rfds);
		xselect (fd + 1, &rfds, NULLFD, NULLFD, NOTOK);
		switch (result = RyWait (fd, NULLIP, &out, OK, roi)) {
		    case NOTOK: 
			if (rop -> rop_reason == ROS_TIMER)
				break;
		    case OK: 
		    case DONE: 
			if ((result = ros_indication (fd, roi)) != OK)
				return result;
			break;

		    default: 
			PP_LOG (LLOG_EXCEPTIONS,
				("unknown return from RoWaitRequest=%d",
				 result));
			return NOTOK;
		}
		break;
	}
	if (lastop == what)
		return OK;
	return NOTOK;
}

/* \f

 */

static int ros_indication (sd, roi)
int     sd;
register struct RoSAPindication *roi;
{
	int     reply,
		result;

	switch (roi -> roi_type) {
	    case ROI_INVOKE: 
	    case ROI_RESULT: 
	    case ROI_ERROR: 
		PP_LOG (LLOG_EXCEPTIONS,
			("unexpected indication type=%d", roi -> roi_type));
		return NOTOK;

	    case ROI_UREJECT: 
		{
			register struct RoSAPureject   *rou =
				&roi -> roi_ureject;

			if (rou -> rou_noid)
				PP_LOG (LLOG_EXCEPTIONS,
					("RO-REJECT-U.INDICATION/%d: %s",
					 sd, RoErrString (rou -> rou_reason)));
			else
				PP_LOG (LLOG_EXCEPTIONS, 
					("RO-REJECT-U.INDICATION/%d: %s (id=%d)",
					 sd, RoErrString (rou -> rou_reason),
					 rou -> rou_id));
			return NOTOK;
		}

	    case ROI_PREJECT: 
		{
			register struct RoSAPpreject   *rop =
				&roi -> roi_preject;

			ros_advise (rop, "RO-REJECT-P.INDICATION");
			return NOTOK;
		}

	    case ROI_FINISH: 
		{
			register struct AcSAPfinish *acf = &roi -> roi_finish;
			struct AcSAPindication  acis;
			register struct AcSAPabort *aca = &acis.aci_abort;

			PP_TRACE (("A-RELEASE.INDICATION/%d: %d",
				   sd, acf -> acf_reason));

			result = AcRelResponse (sd, reply = ACS_ACCEPT,
						ACR_NORMAL, NULLPEP, 0, &acis);

			ACFFREE (acf);

			if (result == NOTOK)
				acs_advise (aca, "A-RELEASE.RESPONSE");
			else
				if (reply != ACS_ACCEPT)
					break;

			return DONE;
		}
		/* NOTREACHED */

	    default: 
		PP_LOG (LLOG_EXCEPTIONS,
			("unknown indication type=%d", roi -> roi_type));
		return NOTOK;
	}
	return OK;
}

static int ros_result (sd, val, id)
int     sd;
struct type_Qmgr_DeliveryStatus *val;
int	id;
{
	struct RoSAPindication rois;
	struct RoSAPindication *roi = &rois;

	if (val == NULL)
		return error (sd, error_Qmgr_congested, (caddr_t) NULL,
			      id);

	if (RyDsResult (sd, id, (caddr_t) val, ROS_NOPRIO, roi)
			== NOTOK) {
		ros_advise (&roi -> roi_preject, "RESULT");
		return NOTOK;
	}
	return OK;
}

/* \f

   ERRORS */

static void    ros_advise (rop, event)
register struct RoSAPpreject *rop;
char   *event;
{
    char    buffer[BUFSIZ];

    if (rop -> rop_cc > 0)
	(void) sprintf (buffer, "[%s] %*.*s", RoErrString (rop -> rop_reason),
		rop -> rop_cc, rop -> rop_cc, rop -> rop_data);
    else
	(void) sprintf (buffer, "[%s]", RoErrString (rop -> rop_reason));

    PP_LOG (LLOG_EXCEPTIONS, ("%s: %s", event, buffer));
    if (ROS_FATAL (rop -> rop_reason))
	    exit (1);
}

/* \f

 */

static void    acs_advise (aca, event)
register struct AcSAPabort *aca;
char   *event;
{
    char    buffer[BUFSIZ];

    if (aca -> aca_cc > 0)
	(void) sprintf (buffer, "[%s] %*.*s",
		AcErrString (aca -> aca_reason),
		aca -> aca_cc, aca -> aca_cc, aca -> aca_data);
    else
	(void) sprintf (buffer, "[%s]", AcErrString (aca -> aca_reason));

    PP_LOG (LLOG_EXCEPTIONS, ("%s: %s (source %d)", event, buffer,
		aca -> aca_source));
}

/* \f

   ERROR */

static int  error (sd, err, param, id)
int     sd,
	err;
caddr_t param;
int	id;
{
	struct RoSAPindication rois;
	struct RoSAPindication *roi = &rois;

	if (RyDsError (sd, id, err, param, ROS_NOPRIO, roi) == NOTOK) {
		ros_advise (&roi -> roi_preject, "ERROR");
		return NOTOK;
	}

	return OK;
}

static int  ureject (sd, reason, rox, roi)
int     sd,
	reason;
struct RoSAPinvoke *rox;
struct RoSAPindication *roi;
{
	if (RyDsUReject (sd, rox -> rox_id, reason, ROS_NOPRIO, roi) == NOTOK) {
		ros_advise (&roi -> roi_preject, "U-REJECT");
		return NOTOK;
	}

	return OK;
}

static char *bigendian (addr)
char    *addr;
{
	extern int ap_outtype;
	static char     *newaddr = NULLCP;
	AP_ptr          tree = NULLAP,
			group = NULLAP,
			name = NULLAP,
			local = NULLAP,
			domain = NULLAP,
			route = NULLAP;

	PP_NOTICE (("Recipient Address '%s'",  addr));

	if (newaddr) {
		free (newaddr);
		newaddr = NULLCP;
	}


	ap_outtype = AP_PARSE_733 | AP_PARSE_BIG;


	if (ap_s2p  (addr, &tree, &group, &name, &local, &domain, &route)
	    == (char *)NOTOK) {
		PP_LOG (LLOG_EXCEPTIONS,
			("Unable to parse (s2p) Recipient addr %s", addr));
		return NULLCP;
	}


	if ((newaddr = ap_p2s (group, name, local, domain, route))
	    == (char *)NOTOK) {
		PP_LOG (LLOG_EXCEPTIONS,
			("Unable to parse (p2s) Recipient addr %s", addr));
		newaddr = NULLCP;
	}

	ap_free (tree);

	return newaddr;
}

#if PP_DEBUG > PP_DEBUG_NONE
static int debug_init ()
{
	char	buf[BUFSIZ], *p;

	fprintf (stderr, "Running in debug mode\nInput channel name: ");
	ppp_debug = 1;
	(void) fflush (stderr);

	if (fgets (buf, sizeof buf, stdin) == NULL)
		return NOTOK;
	if (p = index (buf, '\n'))
		*p = '\0';
	if ((mychan = ch_nm2struct (buf)) == NULLCHAN) {
		PP_LOG (LLOG_EXCEPTIONS, ("Unknown channel %s", p));
		return NOTOK;
	}
	return OK;
}	

static int debug_nextmsg ()
{
	char 	buf[BUFSIZ], *p;
	int	num;
	struct type_Qmgr_ProcMsg *arg;
	struct type_Qmgr_UserList *temp, *tail = NULL;

	fprintf (stderr, "Input message name: ");
	(void) fflush (stderr);

	if (fgets (buf, sizeof buf, stdin) == NULL)
		return NOTOK;
	if (p = index (buf, '\n'))
		*p = '\0';
	arg = (struct type_Qmgr_ProcMsg *) calloc (1, sizeof *arg);
	arg -> qid = str2qb (buf, strlen (buf), 1);
	arg -> channel = str2qb (mychan -> ch_name, 
				strlen (mychan -> ch_name), 1);
	fprintf (stderr, "Input recipients terminated by -1: ");
	fflush (stderr);

	do {
		scanf ("%d", &num);
		if (num != -1) {
			temp = (struct type_Qmgr_UserList *)
				calloc (1, sizeof *temp);
			temp -> RecipientId = (struct type_Qmgr_RecipientId *)
				calloc (1, sizeof *temp->RecipientId);
			temp -> RecipientId -> parm = num;
			if (arg -> users) {
				tail -> next = temp;
				tail = temp;
			}
			else
				arg -> users = tail = temp;
		}
	} while (num != -1);
	while ((num = getchar()) != EOF && num != '\n')
		continue;
	return ppp_procfnx_aux (arg);
}

static void pdeliverystatus (status)
struct type_Qmgr_DeliveryStatus *status;
{
        fprintf (stderr, "Delivery status\n");
        if (status == NULL)
                fprintf (stderr, "Complete failure\n");
        else {
                struct type_Qmgr_DeliveryStatus *ix = status;
                while (ix != NULL)
                {
                        pindividualdeliverystatus(ix->IndividualDeliveryStatus);
                        ix = ix->next;
                }
        }
}

static void pindividualdeliverystatus(status)
struct type_Qmgr_IndividualDeliveryStatus *status;
{
        fprintf (stderr, "Recipient %d: ", status->recipient->parm);

        switch (status->status) {
            case int_Qmgr_status_success:
                fprintf (stderr, "success");
                break;
            case int_Qmgr_status_successSharedDR:
                fprintf (stderr, "successSharedDR");
                break;
            case int_Qmgr_status_failureSharedDR:
                fprintf (stderr, "failureSharedDR");
                break;
            case int_Qmgr_status_negativeDR:
                fprintf (stderr, "negativeDR");
                break;
            case int_Qmgr_status_positiveDR:
                fprintf (stderr, "positiveDR");
                break;
            case int_Qmgr_status_messageFailure:
                fprintf (stderr, "message failure");
                break;
            case int_Qmgr_status_mtaFailure:
                fprintf (stderr, "mta failure");
                break;
            case int_Qmgr_status_mtaAndMessageFailure:
                fprintf (stderr, "mta and message failure");
                break;
            default:
                fprintf (stderr, "unknown");
                break;
        }
        putc ('\n', stderr);
}

#endif

static void cleanup_everything ()
{
	if (hdrbuf != NULL) {
		free (hdrbuf);
		hdrbuf = NULL;
	}
	lastop = NOTOK;
}

static char	*mk_jnt (str)
char	*str;
{
	char	buf1[BUFSIZ], buf2[BUFSIZ];
	char	*argv[30];
	int	argc;

	strcpy (buf1, str);
	argc = sstr2arg (buf1, 30, argv, ".");
	
	if (argc < 1)
		return NULLCP;
	strcpy (buf2, argv[--argc]);
	while (--argc >= 0) {
		strcat (buf2, ".");
		strcat (buf2, argv[argc]);
	}
	return strdup (buf2);
}