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: P T

⟦f231db5b0⟧ TextFile

    Length: 29393 (0x72d1)
    Types: TextFile
    Names: »P2toRFC.c«

Derivation

└─⟦2d1937cfd⟧ Bits:30007241 EUUGD22: P.P 5.0
    └─⟦dc59850a2⟧ »EurOpenD22/pp5.0/pp-5.tar.Z« 
        └─⟦e5a54fb17⟧ 
            └─⟦this⟧ »pp-5.0/Format/rfc1148/P2toRFC.c« 

TextFile

/* P2toRFC.c: p2 msg + optional p1 struct + optional bodypart -> RFC 822 hdr */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Format/rfc1148/RCS/P2toRFC.c,v 5.0 90/09/20 16:01:28 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Format/rfc1148/RCS/P2toRFC.c,v 5.0 90/09/20 16:01:28 pp Exp Locker: pp $
 *
 * $Log:	P2toRFC.c,v $
 * Revision 5.0  90/09/20  16:01:28  pp
 * rcsforce : 5.0 public release
 * 
 */



#include "head.h"
#include "util.h"
#include "P2-types.h"
#include "q.h"
#include <isode/cmd_srch.h>
#include "tb_bpt88.h"
#include "or.h"
#include "ap.h"
#include "oids.h"

static FILE *fp_out;
static int linelen = 0;
static struct type_P2_Heading *head;
static struct type_P2_IPN *ipn;
static char	ipn_body[FILNSIZE];
static char abuf [BUFSIZ];
extern CMD_TABLE bptbl_body_parts88[/* x400 88 body_parts */];
extern char	*cont_p2, *cont_p22;
extern char	*hdr_822_bp, *hdr_p2_bp, *ia5_bp, *hdr_p22_bp;
extern void	msgid2rfc(), encinfo2rfc();
extern int	order_pref;
extern UTC	utclocalise();
int		convertresult;

P2toRFC (p2_in, ext_in, qp, rfc_out, ipn_body_out, ep, x40084)
char		*p2_in;
char		*ext_in;
Q_struct   	*qp;
char		*rfc_out;
char		*ipn_body_out;
char		**ep;
int		x40084;
{
	FILE	*fp_in;
	PE	pe = NULLPE;
	PS	ps = NULLPS;
	int	retval, ishead;
	char	*ix;
	char	buf[BUFSIZ];

	head = NULL;
	ipn = NULL;

	linelen = 0;
	convertresult = OK;

	if ((ix = rindex(p2_in, '/')) == NULL)
		ix = p2_in;
	else
		ix++;

	if (lexequ(ix, (x40084 == TRUE) ? hdr_p2_bp : hdr_p22_bp) == 0)
		ishead = OK;
	else
		ishead = NOTOK;
	
	if (rfc_out == NULLCP)
		fp_out = stdout;
	else if ((fp_out = fopen (rfc_out, "w")) == NULL)
	{
		PP_SLOG (LLOG_EXCEPTIONS, rfc_out,
			 ("Can't open file"));
		(void) sprintf (buf,
				"Failed to open output file '%s'", 
				rfc_out);
		*ep = strdup(buf);
		return (NOTOK);
	}

	if (ipn_body_out)
		strcpy(ipn_body, ipn_body_out);
	else
		ipn_body[0] = '\0';

	if (p2_in == NULLCP)
		fp_in = stdin;
	else if ((fp_in = fopen (p2_in, "r")) == NULL)
	{
		PP_SLOG (LLOG_EXCEPTIONS, p2_in,
			 ("Can't open file"));
		fclose (fp_out);
		(void) sprintf (buf,
				"Failed to open input file '%s'",
				p2_in);
		*ep = strdup(buf);
		return (NOTOK);
	}

	if (((ps = ps_alloc (std_open)) == NULLPS) ||
	    (std_setup (ps, fp_in) == NOTOK))
	{
		PP_LOG (LLOG_EXCEPTIONS, ("RFC822toP2() failed to setup PS"));
		retval = NOTOK;
		*ep = strdup("Failed to set up PS");
		goto cleanup;
	}


	if ((pe = ps2pe (ps)) == NULLPE)
	{
		PP_LOG (LLOG_EXCEPTIONS, ("ps2pe error on file '%s'", p2_in));
		retval = NOTOK;
		goto cleanup;
	}

	PY_pepy[0] = 0;
	if (ishead == OK) {
		if (decode_P2_Heading (pe, 0, NULLIP, NULLVP, &head) != OK)
		{
			PP_OPER(NULLCP,
				("decode_P2_heading() failed : [%s]", PY_pepy));
			retval = NOTOK;
			convertresult = NOTOK;
			(void) sprintf(buf,
				       "unable to decode P2 heading [%s]",
				       PY_pepy);
			*ep = strdup(buf);
			goto cleanup;
		}
       
		if (PY_pepy[0] != 0)
			PP_LOG(LLOG_EXCEPTIONS,
			       ("decode_P2_heading non-fatal failure [%s]", PY_pepy));


		if (do_p1 (qp, ishead, ep) != OK)
		{
			PP_TRACE (("P1 output failure"));
			retval = NOTOK;
			goto cleanup;
		}

		if (do_p2_head (ep) != OK)
		{
			PP_TRACE (( "P2 output failure"));
			retval = NOTOK;
			goto cleanup;
		}

	} else {
		if (decode_P2_IPN (pe, 0, NULLIP, NULLVP, &ipn) != OK)
		{
			PP_OPER(NULLCP,
				("decode_P2_IPN() failed : [%s]", PY_pepy));
			retval = NOTOK;
			convertresult = NOTOK;
			(void) sprintf(buf,
				       "unable to decode P2 IPN [%]",
				       PY_pepy);
			*ep = strdup(buf);
			goto cleanup;
		}
		
		if (PY_pepy[0] != 0)
			PP_LOG(LLOG_EXCEPTIONS,
			       ("decode_P2_IPN non-fatal failure [%s]",
				PY_pepy));

		if (do_p1 (qp, ishead, ep) != OK)
		{
			PP_TRACE (("P1 output failure"));
			retval = NOTOK;
			goto cleanup;
		}
		
		if (do_p2_ipn(qp, ep) != OK)
		{
			PP_TRACE (("P2 output failure"));
			retval = NOTOK;
			goto cleanup;
		}
		
	}
	do_same_line ("\n");	/* Terminate header */

	if (do_extra (ext_in, ep) != OK)
	{
		PP_TRACE (( "Extra bits output failure"));
		retval = NOTOK;
		goto cleanup;
	}
	
	if (ishead != OK
	    && do_p2_ipn_body(ep) != OK)
	{
		PP_TRACE((" IPN body output failure"));
		retval = NOTOK;
		goto cleanup;
	}

	retval = OK;
    cleanup:
	fclose (fp_out);
	fclose (fp_in);
	
	if (pe != NULLPE) pe_free(pe);
	if (ps != NULLPS) ps_free(ps);
	if (head != NULL) free_P2_Heading (head);
	if (ipn != NULL) free_P2_IPN (ipn);
	return (retval);
}

/* \f

 */

/* ARGSUSED */
do_p2_head(ep)
char	**ep;
{
	if (head -> authorizing__users == NULL)
	{
		if (head -> originator != NULL)
		{
			do_key	("From");
			do_ORD (head -> originator);
		}
	}
	else
	{
		do_key ("From");
		do_ORD_seq (head -> authorizing__users);
		if (head -> originator != NULL) 
		{
			do_key ("Sender");
			do_ORD (head -> originator);
		}
	}

	if (head -> this__IPM != NULL)
	{
		do_key ("Message-ID");
		if (do_mid (head -> this__IPM) != OK) {
			*ep = strdup("Invalid message id");
			return NOTOK;
		}
	}

	if (head -> primary__recipients != NULL)
	{
		do_key ("To");
		do_recip_seq (head -> primary__recipients);
	}

	if (head -> copy__recipients != NULL)
	{
		do_key ("Cc");
		do_recip_seq (head -> copy__recipients);
	}
	
	if (head -> blind__copy__recipients != NULL)
	{
		do_key ("Bcc");
		do_recip_seq (head -> blind__copy__recipients);
	}

	if (head -> replied__to__IPM != NULL)
	{
		do_key ("In-Reply-To");
		if (do_mid (head -> replied__to__IPM) != OK) {
			*ep = strdup("Invalid In-Reply-To message id");
			return NOTOK;
		}
	}
	
	if (head -> obsoleted__IPMs != NULL)
	{
		do_key ("Obsoletes");
		if (do_mid_seq (head -> obsoleted__IPMs) != OK) {
			*ep = strdup("Invalid Obsoletes message id");
			return NOTOK;
		}
	}
	
	if (head -> related__IPMs != NULL)
	{
		do_key ("References");
		if (do_mid_seq (head -> related__IPMs) != OK) {
			*ep = strdup("Invalid References message id");
			return NOTOK;
		}
	}

	if (head -> subject != NULL)
	{
		do_key ("Subject");
		do_qbuf (head -> subject);
	}

	if (head -> expiry__time != NULL)
	{
		do_key ("Expiry-Date");
		do_utc (head -> expiry__time);
	}

	if (head -> reply__time != NULL)
	{
		do_key ("Reply-By");
		do_utc (head -> reply__time);
	}

	if (head -> reply__recipients != NULL)
	{
		do_key ("Reply-To");
		do_ORD_seq (head -> reply__recipients);
	}

	if (head -> importance != NULL
	    && head -> importance -> parm != int_P2_ImportanceField_normal)
	{
		do_key ("Importance");
		do_importance (head -> importance -> parm);
	}

	if (head -> sensitivity != NULL)
	{
		do_key ("Sensitivity");
		do_sensitivity (head -> sensitivity -> parm);
	}

	if (head -> auto__forwarded != NULL
	    && head -> auto__forwarded -> parm)
	{
		do_key ("Autoforwarded");
		do_boolean (head -> auto__forwarded -> parm);
	}

	if (head -> extensions != NULL)
		do_extensions (head -> extensions);
	/* incomplete-copy */
	/* language */
	return (OK);
}

/* ARGSUSED */
do_p2_ipn(qp, ep)
Q_struct *qp;
char	**ep;
{
	do_key ("From");
	do_p1_addrs (qp -> Oaddress);

	if (ipn -> ipn__originator != NULL) {
		do_key ("To");
		do_ORD (ipn -> ipn__originator);
	}

	do_key ("Subject");
	do_token ("X.400 Inter-Personal Receipt Notification");

	do_key ("Message-Type");
	do_token ("InterPersonal Notification");

	if (ipn -> subject__ipm != NULL)
	{
		do_key ("References");
		if (do_mid (ipn -> subject__ipm) != OK) {
			*ep = strdup("Invalid References message id");
			return NOTOK;
		}
	}
	return OK;
}

do_p2_ipn_body (ep)
char	**ep;
{
	FILE	*fp;
	char	buf[BUFSIZ];

	if (ipn_body[0] != '\0') {
		if ((fp = fopen (ipn_body, "w")) == NULL)
		{
			PP_SLOG (LLOG_EXCEPTIONS, ipn_body,
				 ("Can't open file"));
			(void) sprintf(buf,
				       "Unable to open output file '%s' for IPN body",
				       ipn_body);
			*ep = strdup(buf);
			return (NOTOK);
		}
	} else 
		fp = stdout;

	fputs("Your message to: ", fp);
	if (ipn -> ipm__preferred__recipient != NULL) {
		get_ORD (ipn -> ipm__preferred__recipient, abuf);
		fputs(abuf, fp);
	}
	fputs("\n", fp);
	if (ipn -> choice != NULL) {
		if (ipn -> choice -> offset == choice_P2_0_non__receipt__fields)
			do_p2_ipn_body_non__receipt(ipn -> choice -> un.non__receipt__fields, fp);
		else 
			do_p2_ipn_body_receipt (ipn -> choice -> un.receipt__fields, fp);
	}		
	if (ipn -> conversion__eits != NULL) 
		do_p2_ipn_body_eits (ipn -> conversion__eits, fp);
		
	if (ipn -> choice != NULL &&
	    ipn -> choice -> offset == choice_P2_0_non__receipt__fields &&
	    ipn -> choice -> un.non__receipt__fields -> returned__ipm != NULL)
		fputs("The Original Message follows: \n\n", fp);
	else
		fputs("The Original Message is not available\n", fp);
	fclose (fp);
	return (OK);
}	

do_p2_ipn_body_non__receipt (non_receipt, fp)
struct type_P2_NonReceiptFields	*non_receipt;
FILE				*fp;
{
	if (non_receipt -> non__receipt__reason -> parm == int_P2_NonReceiptReasonField_ipm__discarded)
		do_p2_ipn_discard (non_receipt, fp);
	else
		do_p2_ipn_auto_forward (non_receipt, fp);
}

do_p2_ipn_discard (non_receipt, fp)
struct type_P2_NonReceiptFields	*non_receipt;
FILE				*fp;
{
	fputs("was discarded for the following reason: ", fp);
	switch (non_receipt -> discard__reason -> parm) {
	    case int_P2_DiscardReasonField_ipm__expired:
		fputs ("Expired.\n", fp);
		break;
	    case int_P2_DiscardReasonField_ipm__obsoleted:
		fputs ("Obsoleted.\n", fp);
		break;
	    case int_P2_DiscardReasonField_user__subscription__terminated:
		fputs ("User Subscription Terminated.\n", fp);
		break;
	}
}

do_p2_ipn_auto_forward (non_receipt, fp)
struct type_P2_NonReceiptFields	*non_receipt;
FILE				*fp;
{
	char	*cp;
	fputs ("was automatically forwarded.\n", fp);
	if (non_receipt -> auto__forward__comment != NULL) {
		cp = qb2str(non_receipt -> auto__forward__comment);
		fputs ("The following comment was made: ", fp);
		fputs (cp, fp);
		fputs (".\n", fp);
		free (cp);
	}
}
	
do_p2_ipn_body_receipt (receipt, fp)
struct type_P2_ReceiptFields	*receipt;
FILE				*fp;
{
	do_p2_utc (receipt -> receipt__time, fp);
	if (receipt -> acknowledgment__mode != NULL)
		do_p2_ack_mode (receipt -> acknowledgment__mode, fp);
	if (receipt -> suppl__receipt__info != NULL)
		do_p2_suppl_info (receipt -> suppl__receipt__info, fp);
}

do_p2_ack_mode (mode, fp)
struct type_P2_AcknowledgmentModeField	*mode;
FILE	*fp;
{
	fputs ("This notification was generated ", fp);
	if (mode -> parm == int_P2_AcknowledgmentModeField_manual)
		fputs("Manually.\n", fp);
	else
		fputs ("Automatically.\n", fp);
}

do_p2_suppl_info (info, fp)
struct type_P2_SupplReceiptInfoField	*info;
FILE 	*fp;
{
	char	*cp;
	fputs ("The following extra information was given:\n", fp);
	cp = qb2str (info);
	fputs ("\n", fp);
	free(cp);
}

do_p2_ipn_body_eits (eits, fp)
struct type_P2_ConversionEITsField	*eits;
FILE	*fp;
{
	int	first = OK;

	fputs ("The following information types were converted:", fp);
	
	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_undefined) == 1) {
		if (first == OK) {
			fputs ("Undefined", fp);
			first = NOTOK;
		} else
			fputs (", Undefined", fp);
	}

	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_telex) == 1) {
		if (first == OK) {
			fputs ("Telex", fp);
			first = NOTOK;
		} else
			fputs (", Telex", fp);
	}

	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_ia5__text) == 1) {
		if (first == OK) {
			fputs ("IA5-Text", fp);
			first = NOTOK;
		} else
			fputs (", IA5-Text", fp);
	}

	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_g3__facsimile) == 1) {
		if (first == OK) {
			fputs ("G3-Fax", fp);
			first = NOTOK;
		} else
			fputs (", G3-Fax", fp);
	}

	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_g4__class__1) == 1) {
		if (first == OK) {
			fputs ("TIF0", fp);
			first = NOTOK;
		} else
			fputs (", TIF0", fp);
	}

	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_teletex) == 1) {
		if (first == OK) {
			fputs ("Teletex", fp);
			first = NOTOK;
		} else
			fputs (", Teletex", fp);
	}
	
	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_videotex) == 1) {
		if (first == OK) {
			fputs ("Videotex", fp);
			first = NOTOK;
		} else
			fputs (", Videotex", fp);
	}

	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_voice) == 1) {
		if (first == OK) {
			fputs ("Voice", fp);
			first = NOTOK;
		} else
			fputs (", Voice", fp);
	}

	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_sfd) == 1) {
		if (first == OK) {
			fputs ("SFD", fp);
			first = NOTOK;
		} else
			fputs (", SFD", fp);
	}

	if (bit_test (eits -> built__in__encoded__information__types,
		      bit_P2_BuiltInEncodedInformationTypes_mixed__mode) == 1) {
		if (first == OK) {
			fputs ("TIF1", fp);
			first = NOTOK;
		} else
			fputs (", TIF1", fp);
	}

	if (eits -> external__encoded__information__types != NULL) {
		if (first == OK) {
			fputs (", ", fp);
			first = NOTOK;
		}
		fputs (sprintoid (eits -> external__encoded__information__types), fp);
	}
	fputs(".\n", fp);
}

do_p2_utc (utc_qb, fp)
struct qbuf	*utc_qb;
FILE	*fp;
{
	char 	*cp;
	UTC	ut, lut;
	fputs ("was received at", fp);
	cp = qb2str (utc_qb);
	ut = str2utct (cp, strlen(cp));
	lut = utclocalise(ut);
	UTC2rfc (lut, abuf);
	fputs(abuf, fp);
	fputs(".\n", fp);
	free(cp);
	free ((char *)ut);
	free ((char *)lut);
}

/* \f

 */

static UTC oldestTrace(traces)
     	Trace     *traces;
{
  	Trace     *ix;
	UTC	  ret;
	time_t    tmp,
		  oldest = 0;
		
	ix = traces;
	oldest = utc2time_t(ix->trace_DomSinfo.dsi_time);
	ret = ix->trace_DomSinfo.dsi_time;
	ix = ix->trace_next;
	
	while (ix != NULL) {
	     tmp = utc2time_t(ix->trace_DomSinfo.dsi_time);
	     if (tmp && (tmp < oldest || !oldest)) {
	          oldest = tmp;
		  ret = ix->trace_DomSinfo.dsi_time;
	     }
	     ix = ix->trace_next;
	}
	return ret;
}

static int moreThanHdrAndIa5(eit)
EncodedIT	*eit;
{
	LIST_BPT	*ix = eit->eit_types;
	int		found = 0;

	while (found == 0 && ix != NULL) {
		if (strncmp(hdr_822_bp, ix->li_name, strlen(hdr_822_bp)) == 0
		    || strncmp("delivery.", ix->li_name, strlen("delivery.")) == 0
		    || strncmp(hdr_p2_bp, ix->li_name, strlen(hdr_p2_bp)) == 0
		    || strncmp(ia5_bp, ix->li_name, strlen(ia5_bp)) == 0)
			ix = ix->li_next;
		else
			/* not ia5 or hdr */
			found = 1;
	}
	return found;
}

/* ARGSUSED */
do_p1 (qp, ishead, ep)
Q_struct *qp;
int	 ishead;
char	**ep;
{
	if (qp == (Q_struct *) 0)
		return (OK);

	do_p1_trace (qp -> trace);
	
	do_key ("Date");

	do_p1_utc (oldestTrace (qp -> trace));

	if (ishead == OK && head -> originator == NULL)
	{
		if (head -> authorizing__users == NULL)
			do_key("From");
		else
			do_key("Sender");

		do_p1_addrs (qp -> Oaddress);
	}

	do_key ("X400-Originator");
	do_p1_addrs (qp -> Oaddress);

	if (ishead == OK &&
	    head -> primary__recipients == NULL &&
	    head -> copy__recipients == NULL &&
	    head -> blind__copy__recipients == NULL) 
	{
		do_key ("To");
		if (qp -> disclose_recips)
			do_p1_addrs (qp -> Raddress);
		else
			do_token (":;");
	}

	if (qp -> disclose_recips) {
		do_key ("X400-Recipients");
		do_p1_addrs (qp -> Raddress);
	}

	do_key ("X400-MTS-Identifier");
	do_p1_mid (&(qp -> msgid));

	if (qp -> orig_encodedinfo.eit_types != NULL
	    && moreThanHdrAndIa5 (&qp -> orig_encodedinfo)) {
		do_key ("Original-Encoded-Information-Types");
		do_p1_eit (&(qp -> orig_encodedinfo));
	} else if (qp -> encodedinfo.eit_types != NULL
	    && moreThanHdrAndIa5 (&qp -> encodedinfo)) {
		/* not just ia5 bodypart */
		do_key ("Original-Encoded-Information-Types");
		do_p1_eit (&(qp -> encodedinfo));
	}

	if (qp -> cont_type != NULLCP) {
		do_key ("X400-Content-Type");
		if (lexequ (qp -> cont_type, cont_p2) == 0)
			do_token ("P2-1984 (2)");
		else if (lexequ (qp -> cont_type, cont_p22) == 0)
			do_token ("P2-1988 (22)");
		else
			do_token (qp -> cont_type);
	}

	if (qp -> ua_id != NULLCP)
	{
		do_key ("Content-Identifier");
		do_token (qp -> ua_id);
	}

	if (qp -> priority != PRIO_NORMAL)
	{
		do_key ("Priority");
		do_p1_priority (qp -> priority);
	}
	
	if (qp -> originator_return_address != NULL)
	{
		do_key ("Originator-Return-Address");
		do_p1_fullname (qp -> originator_return_address);
	}
	
	if (qp -> dl_expansion_history != NULL)
		do_p1_DLHistory (qp -> dl_expansion_history);

	if (qp -> implicit_conversion == TRUE) 
	{
		do_key("Conversion");
		do_token("Prohibited");
	}
		
	if (qp -> conversion_with_loss_prohibited)
	{
		do_key ("Conversion-With-Loss");
		do_token ("Prohibited");
	}
	
	
       if (qp -> defertime != 0)
       {
	       do_key ("Deferred-Delivery");
	       do_p1_utc (qp -> defertime);
       }
	
	if (qp -> latest_time != 0
	    && qp -> latest_time_crit)
	{
		do_key ("Latest-Delivery-Time");
		do_p1_utc (qp -> latest_time);
	}

	return (OK);
}


/* \f

 */

do_extra (extra, ep)
char *extra;
char	**ep;
{
	char buf [LINESIZE], tmp[BUFSIZ];
	FILE *fp_extra;

	if (extra == NULLCP || extra [0] == '\0')
		return (OK);

	if ((fp_extra = fopen (extra, "r")) == NULL)
	{
		PP_SLOG (LLOG_EXCEPTIONS, extra,
			 ("Can't open file"));
		(void) sprintf (tmp,
				"Unable to open extra input file '%s'", 
				extra); 
		*ep = strdup(tmp);
		return (NOTOK);
	}

	if (fgets (buf, LINESIZE - 1, fp_extra) == NULL)
	{
		PP_DBG (( "Null file '%s'", extra));
		(void) sprintf (tmp,
				"Empty extra file '%s'", 
				extra);
		*ep = strdup(tmp);
		fclose (fp_extra);
		return (NOTOK);
	}

	buf [strlen(buf) - 1] = '\0';  /* remvove \n */
	if (lexnequ (buf, "RFC-822-HEADERS:", 
		     strlen("RFC-822-HEADERS")) != 0)
	{
		PP_DBG (( "Illegal first line '%s' in file '%s'",
				buf, extra));
		(void) sprintf (tmp,
				"Illegal first line '%s' in file '%s'",
				buf, extra);
		fclose (fp_extra);
		*ep = strdup(tmp);
		return (NOTOK);
	}

	while (TRUE)
	{
		if ((fgets (buf, LINESIZE -1, fp_extra) == NULL) 
			&& !feof (fp_extra))
		{
			PP_DBG (( "File read error"));
			fclose (fp_extra);
			return (NOTOK);
		}

		if (!feof (fp_extra))
			fputs (buf, fp_out);
		else
		{
			fclose (fp_extra);
			return (OK);
		}
	}

}

/* \f

 */
/* P2 structure bits */
do_822_extension (pe)
PE	pe;
{
	char	*hdr_txt, *ix;

	struct type_P2_RFC822Field 	*hdr;
	PY_pepy[0] = 0;
	if (decode_P2_RFC822Field (pe, 0, NULLIP, NULLVP, &hdr) != OK)
		PP_OPER(NULLCP,
			("decode_P2_RFC822Field () Failed : [%s]", PY_pepy));
	else {
		hdr_txt = qb2str(hdr);
		if ((ix = index(hdr_txt, ':')) == NULLCP) {
			PP_LOG(LLOG_EXCEPTIONS,
			       ("Unable to parse extra 822 hdr '%s'", hdr_txt));
			free(hdr_txt);
			return;
		}
		*ix++ = '\0';
		while (isspace(*ix)) ix++;
		do_key(hdr_txt);
		do_token (ix);
		free(hdr_txt);
		free_P2_RFC822Field(hdr);
	}
}
	
do_incomplete_copy()
{
	do_key ("Incomplete-Copy");
	do_token ("");
}

do_languages (pe)
PE	pe;
{
	char	*lang_txt;

	struct type_P2_Languages	*lang, *ix;
	PY_pepy[0] = 0;
	if (decode_P2_Languages (pe, 0, NULLIP, NULLVP, &lang) != OK)
		PP_OPER(NULLCP,
			("decode_P2_Languages () failed : [%s]", PY_pepy));
	else {
		ix = lang;
		while (ix != NULL) {
			lang_txt = qb2str(ix -> Language);
			do_key ("Language");
			do_token (lang_txt);
			free(lang_txt);
			ix = ix -> next;
		}
		free_P2_Languages(lang);
	}
}
	
		
do_extension (extension)
struct type_P2_HeadingExtension	*extension;
{
	if (extension -> type == NULL) {
		PP_LOG(LLOG_EXCEPTIONS,
		       ("NULL oid in header extension"));
		return;
	}
	if (oid_cmp (extension -> type, str2oid(id_rfc_822_field)) == 0)
		do_822_extension (extension -> value);
	else if (oid_cmp (extension -> type, str2oid(id_hex_incomplete_copy)) == 0)
		do_incomplete_copy();
	else if (oid_cmp (extension -> type, str2oid(id_hex_languages)) == 0)
		do_languages (extension -> value);
	else 
		PP_LOG(LLOG_EXCEPTIONS,
		       ("Unrecognised oid '%s' in header extension", 
			sprintoid(extension -> type)));
}

do_extensions (extensions)
struct type_P2_ExtensionsField	*extensions;
{
	while (extensions != NULL) {
		do_extension (extensions -> HeadingExtension);
		extensions = extensions -> next;
	}
}

do_qbuf (qb)
struct qbuf *qb;
{
	char *cp;
	cp = qb2str (qb);
	do_string (cp);
	free (cp);
}


do_recip_seq (recip_seq)
struct type_P2_RecipientSequence *recip_seq;
{
	struct type_P2_RecipientSpecifier *recip;

	recip = recip_seq -> RecipientSpecifier;
	get_ORD (recip -> recipient, abuf);

	if (recip -> notification__requests != NULLPE &&
		bit_test (recip -> notification__requests,
				bit_P2_NotificationRequests_rn) == 1) {
		strcat (abuf, " (Receipt Notification Requested)");
	}

	if (recip -> notification__requests != NULLPE &&
		bit_test (recip -> notification__requests,
				bit_P2_NotificationRequests_nrn) == 1) {
		strcat (abuf, " (Non Receipt Notification Requested)");
	}

	if (recip -> notification__requests != NULLPE &&
		bit_test (recip -> notification__requests,
				bit_P2_NotificationRequests_ipm__return) == 1) {
		strcat (abuf, " (IPM Return Requested)");
	}

	if (recip -> reply__requested)
		strcat (abuf, " (Reply Requested)");

	do_token (abuf);
	if (recip_seq -> next != NULL)
	{
		do_same_line (",");
		do_recip_seq (recip_seq -> next);
	}
}



do_ORD_seq (ord_seq)
struct type_P2_ORDescriptorSequence *ord_seq;
{
	get_ORD (ord_seq -> ORDescriptor, abuf);
	do_token (abuf);
	if (ord_seq -> next != NULL)
	{
		do_same_line (",");
		do_ORD_seq (ord_seq -> next);
	}
}


do_ORD (ord)
struct type_P2_ORDescriptor *ord;
{
	get_ORD (ord, abuf);
	do_token (abuf);
}

OR_ptr pe2or();

get_ORD (ord, buf)
struct type_P2_ORDescriptor *ord;
char *buf;
{
	/* see rfc1138 4.7.2 */
	OR_ptr or;
	char tbuf [BUFSIZ], asc[BUFSIZ];
	char *cp, *str = NULLCP;

	if (ord -> formal__name != NULL && ord -> formal__name -> x1 != NULL)
	{       
		ord -> formal__name -> x1 -> pe_next = 
			ord -> formal__name -> x2;
		if ((or = pe2or (ord -> formal__name -> x1)) == NULLOR)
		{
			PP_DBG (("Failed to decode PE"));
			tbuf[0] = '\0';
		}
		else if (or_or2rfc (or, tbuf) != OK)
		{
			PP_DBG (( "Failed to decode OR Name"));
			tbuf[0] = '\0';
		}
		if (or != NULLOR) or_free(or);
		ord -> formal__name -> x1 -> pe_next = NULLPE;
	}
	else
		tbuf [0] = '\0';


	if (ord -> free__form__name == NULL) 
		if (tbuf[0] == '\0')
			strcpy (buf, "Empty Address :;");
		else
			if (tbuf[0] == '@')
				sprintf (buf, "FOO <%s>", tbuf);
			else
				strcpy (buf, tbuf);
	else
	{
		cp = qb2str (ord -> free__form__name);
		or_ps2asc (cp, asc);
		if (tbuf [0] == '\0')
			sprintf (buf, "\"%s\" :;", asc);
		else
			sprintf (buf, "\"%s\" <%s>", asc, tbuf);
		free (cp);
	}

	if (ord -> telephone__number != NULL)
	{
		cp = qb2str (ord -> telephone__number);
		if (*cp != '\0') {
			strcat (buf, " (Tel ");
			strcat (buf, cp);
			strcat (buf, ")");
			free(cp);
		}
	}
	ap_s2s (buf, &str, order_pref);
	if (str != NULLCP) {
		(void) strcpy(buf, str);
		free(str);
	}
}

do_mid_seq (mid_seq)
struct type_P2_IPMIdentifierSequence *mid_seq;
{
	if (do_mid (mid_seq -> IPMIdentifier) != OK)
		return NOTOK;
	if (mid_seq -> next != NULL)
	{
		do_same_line (",");
		return do_mid_seq (mid_seq -> next);
	}
	return OK;
}

extern char *loc_dom_site;

do_mid (mid)
struct type_P2_IPMIdentifier *mid;
{
	char *midstring;
	OR_ptr or;
	char tbuf [LINESIZE], buf[BUFSIZ];
	char *cp, *str = NULLCP;
	AP_ptr ap;
	AP_ptr local;
	AP_ptr domain;
	/* see rfc 1138 4.7.3.4 */

	if (mid -> user__relative__identifier != NULL) {
		midstring = qb2str (mid -> user__relative__identifier);
		or_ps2asc (midstring, abuf);
		free(midstring);
		if (mid -> user == NULL) {
			(void) sprintf (buf, "<%s>", abuf);
			if ((index(buf, '@') != NULLCP)
			    && (ap_s2p (buf, &ap, (AP_ptr *) 0, (AP_ptr *) 0, 
				       &local, &domain, 
				       (AP_ptr *) 0) != (char *) NOTOK)) {
				/* buf parses as 822.msg-id */
				do_token (buf);
				ap_free(ap);
				return OK;
			}
		}
	} else
		abuf[0] = '\0';

	/* try as x400 generated */
	if (mid -> user != NULL && mid -> user -> x1 != NULL)
	{
		mid -> user -> x1 -> pe_next = 
			mid -> user -> x2;
	
		if ((or = pe2or (mid -> user -> x1)) != NULLOR &&
		    or_or2rfc (or, tbuf) == OK) {
			if (abuf[0] != '\0')
				sprintf (buf, "%s*%s", abuf, tbuf);
			else
				sprintf (buf, "*%s", tbuf);

			local = ap_new (AP_MAILBOX, buf);
			domain = ap_new (AP_DOMAIN, "MHS");
			cp = ap_p2s_nc (NULLAP, NULLAP, local, domain, NULLAP);
			sprintf (abuf, "<%s>", cp);
			free (cp);
			ap_free (local);
			ap_free (domain); 
			do_token (abuf);
			return OK;
		}
	}
	
	if (abuf[0] != '\0') {
		(void) sprintf(buf, "%s*",abuf);
		local = ap_new(AP_MAILBOX, buf);
		domain = ap_new(AP_DOMAIN, "MHS");
		cp = ap_p2s_nc (NULLAP, NULLAP, local, domain, NULLAP);
		sprintf (abuf, "<%s>", cp);
		free (cp);
		ap_free (local);
		ap_free (domain); 
		do_token (abuf);
		return OK;
	}

	PP_DBG (( "Highly dubious ID"));
	(void) sprintf (abuf, "<FOO@%s>", loc_dom_site);
	do_token(abuf);
	/* gen mid */
	return NOTOK;
}

do_utc (utc_qb)
struct qbuf *utc_qb;
{
	char *cp;
	UTC	ut;

	cp = qb2str (utc_qb);
	ut = str2utct (cp, strlen(cp));
	do_p1_utc (ut);
	free (cp);
	free ((char *)ut);
}

do_importance (importance)
int importance;
{
	switch (importance)
	{
		case int_P2_ImportanceField_low:
			do_token ("Low");
			break;
		case int_P2_ImportanceField_normal:
			do_token ("Normal");
			break;
		case int_P2_ImportanceField_high:
			do_token ("High");
			break;
		    default:
			sprintf(abuf, "Undefined (value=%d)", importance);
			do_token (abuf);
			break;
	}
}

do_sensitivity (sensitivity)
int sensitivity;
{
	switch (sensitivity)
	{
		case int_P2_SensitivityField_personal:
			do_token ("Personal");
			break;
		case int_P2_SensitivityField_private:
			do_token ("Private");
			break;
		case int_P2_SensitivityField_company__confidential:
			do_token ("Company-Confidential");
			break;
		    default:
			sprintf(abuf, "Undefined (value=%d)", sensitivity);
			do_token (abuf);
			break;
	}
}

do_boolean (bool)
char bool;
{
	if (bool)
		do_token ("TRUE");
	else
		do_token ("FALSE");
}

/* \f

 */
/* Stuff for P1 */

do_p1_utc (ut)
UTC	ut;
{
	UTC	lut;
	lut = utclocalise(ut);
	if (UTC2rfc (ut, abuf) == NOTOK)
		strcpy(abuf, ">>INVALID UTC TIME<<");
	do_token (abuf);
	free((char *) lut);
}

do_p1_addrs (addr)
ADDR *addr;
{
	if (adr2rfc (addr, abuf, order_pref) == OK)
		do_token (abuf);
	if (addr -> ad_next != NULL)
	{
		do_same_line (",");
		do_p1_addrs (addr -> ad_next);
	}
}

do_p1_mid (mid)
MPDUid *mid;
{
	msgid2rfc (mid, abuf); 
	do_token (abuf);
}

do_p1_eit (eit)
EncodedIT *eit;
{
	encinfo2rfc (eit, abuf); 
	do_token (abuf);
}

do_p1_priority (priority)
int priority;
{
	switch (priority)
	{
		case PRIO_NORMAL:
			do_token ("Normal");
			break;
		case PRIO_URGENT:
			do_token ("Urgent");
			break;
		case PRIO_NONURGENT:
			do_token ("Non-Urgent");
			break;
	}
}

do_p1_trace (trace)
Trace *trace;
{

	if (trace->trace_next != NULL)
		do_p1_trace(trace->trace_next);
	do_key ("X400-Received");
	x400trace2rfc (trace,abuf);
	do_token (abuf);
}

do_p1_fullname (fullname)
FullName	*fullname;
{
	do_token (fullname->fn_addr);
}

do_p1_DLHistory (history)
DLHistory	*history;
{
	char	temp[BUFSIZ];
	UTC	lut;
	if (history -> dlh_next != NULL)
		do_p1_DLHistory(history -> dlh_next);
	do_key ("DL-Expansion-History");
	(void) sprintf (abuf,
			"%s",
			history -> dlh_addr);
	if (history -> dlh_time != 0) {
		lut = utclocalise(history -> dlh_time);
		UTC2rfc (lut, temp);
		free ((char *) lut);
		(void) sprintf (abuf,
				"%s (%s)",
				abuf, temp);
	}
	do_token (abuf);
}
			

/* \f

 */
/* General purpose header output */

#define FOLD_POINT 78

do_key (key)
char *key;
{
	if (linelen > 0)
		fputs ("\n", fp_out);
	fputs (key, fp_out);
	fputs (": ", fp_out);
	linelen = strlen (key) + 2;
}

do_string (string)              /* fold string on spaces for unstructured */
char *string;
{
	register char *p, *q;
	int gap;

	p = string;
	fputs (" ", fp_out);
	linelen++;
	while (TRUE)
	{
		gap = FOLD_POINT - linelen;
		if (strlen (p) <= gap)
		{
			fputs (p, fp_out);
			linelen += strlen (p);
			return;
		}

		q = p + gap;
		while (q-- > p)
		{
			if (isspace (*q))
			{
				*q++ = '\0';
				fputs (p, fp_out);
				if (*q == '\0')
				{
					linelen += strlen (p);
					return;
				}
				fputs ("\n ", fp_out);
				linelen = 1;
				p = q;
				goto endloop;
			}
		}
					/* Won't fit....  */
		if (linelen > 1)
		{                       /* try next line */
			fputs ("\n ", fp_out);
			linelen = 1;
			goto endloop;
		}

		q = p + gap;
		while (*q++ != '\0')
		{
			if (isspace(*q))
			{
				*q++ = '\0';
				fputs (p, fp_out);
				if (*q == '\0')
				{
					linelen += strlen (p);
					return;
				}
				fputs ("\n ", fp_out);
				linelen = 1;
				p = q;
				goto endloop;
			}
		}
				/* No spaces */
		fputs (p, fp_out);
		linelen += strlen (p);
		return;

endloop:;

	}

}

do_same_line (token)
char *token;
{
	linelen += strlen (token);
	fputs (token, fp_out);
}

do_token (token)
char *token;
{
	linelen += strlen (token) + 1;
	if (linelen < FOLD_POINT)
		fputs (" ", fp_out);
	else
	{
		fputs ("\n ", fp_out);
		linelen = strlen (token) + 1;
	}
	fputs (token, fp_out);
}