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

⟦da4417730⟧ TextFile

    Length: 24807 (0x60e7)
    Types: TextFile
    Names: »RFCtoP2.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/RFCtoP2.c« 

TextFile

/* RFCtoP2.c : 1138 encoding 822 -> P2 for headers */

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

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



#include "head.h"
#include "util.h"
#include "P2-types.h"
#include "rfc-hdr.h"
#include "ap.h"
#include "or.h"
#include "oids.h"

static FILE *fp_P2_out;
static FILE *fp_rfc_in;
static FILE *fp_P2_ext;
static char P2_ext [FILNSIZE];

static struct type_P2_Heading *head;
static char first_hdr = TRUE;
static int comments_started = FALSE;

extern struct rfc_hdr hdr_list[];
extern time_t time();

RFCtoP2 (rfc_in, P2_out, P2_ext_out, ep, x40084)
char *rfc_in;
char *P2_out;
char *P2_ext_out;
char	**ep;
int	x40084;
{
	PE      pe;
	PS      ps;
	int     retval;
	char	buf[BUFSIZ];

	first_hdr = TRUE;
	comments_started = FALSE;
	if (P2_ext_out)
		strcpy (P2_ext, P2_ext_out);
	else
		P2_ext[0] = '\0';

	head = (struct type_P2_Heading *)
		calloc (1, sizeof (struct type_P2_Heading));

	if ( head ==  (struct type_P2_Heading *) NOTOK)

	{
		PP_LOG (LLOG_EXCEPTIONS, ("RFCtoP2 - malloc failed"));
		return NOTOK;
	}                       /* allocate h, so that we can free */
				/* cleanly at the end of all this */

	if (P2_out == NULLCP)
		fp_P2_out = stdout;

	else if ((fp_P2_out = fopen (P2_out, "w")) == NULL )
	{
		PP_SLOG (LLOG_EXCEPTIONS, P2_out,
			 ("Can't open file"));
		(void) sprintf (buf,
				"Unable to open output file '%s'",
				P2_out);
		*ep = strdup(buf);
		return NOTOK;
	}

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



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


			/* set defaults */

	head -> importance = (struct type_P2_ImportanceField *) calloc (1, sizeof(struct type_P2_ImportanceField));
	head -> importance -> parm = int_P2_ImportanceField_normal;

	if (build_hdr (x40084, ep) == NOTOK)
	{
		PP_LOG (LLOG_EXCEPTIONS, ("build_hdr blew it"));
		retval = NOTOK;
		goto cleanup;
	}

	PY_pepy[0] = 0;

	if (encode_P2_Heading (&pe, 0, 0, NULLCP, head) != OK)
	{
		PP_OPER (NULLCP, 
			 ("RFCtoP2() failed to encode header [%s]", PY_pepy));
		(void) sprintf (buf,
				"Unable to encode p2 hdr ['%s']", 
				PY_pepy);
		*ep = strdup(buf);
		retval = NOTOK;
		goto cleanup;
	}

	if (PY_pepy[0] != 0)
		PP_LOG(LLOG_EXCEPTIONS,
		       ("encode_P2_Heading non-fatal failure [%s]",PY_pepy));

	if (pe2ps (ps, pe) == NOTOK)
	{
		PP_LOG (LLOG_EXCEPTIONS, ("RFCtoP2 failed to write heading"));
		*ep = strdup("Failed to write header");
		pe_free (pe);
		retval = NOTOK;
		goto cleanup;
	}

	retval = OK;

cleanup:
	ps_free (ps);
	fclose (fp_P2_out);
	fclose (fp_rfc_in);
	if (fp_P2_ext != NULL)
		fclose (fp_P2_ext);
	free_P2_Heading (head);
	return retval;
}

/* \f

 */

build_hdr(x40084, ep)
int	x40084;
char	**ep;
{
	char	*field, *key;
	struct type_P2_RecipientSequence	*from = NULL;
	struct type_P2_RecipientSequence	*temp;
	struct type_P2_ORDescriptorSequence	*ix, *tail = (struct type_P2_ORDescriptorSequence *) 0;
	char	buf[BUFSIZ];

	while (TRUE) {
		switch (get_hdr (&key, &field)) {
		    case HDR_EOH:
			PP_DBG (("HDR_EOH"));
			break;

		    case HDR_ERROR:
			PP_LOG (LLOG_EXCEPTIONS,
				("Error reading header"));
			*ep = strdup("Error reading header");
			return NOTOK;

		    case HDR_ILLEGAL:
			PP_LOG (LLOG_EXCEPTIONS,
				("Erroneous header '%s' '%s'", key, field));
			(void) sprintf (buf,
				       "Erroneous header '%s' '%s'",
				       key, field);
			*ep = strdup(buf);
			return NOTOK;

		    case HDR_IGNORE:
			PP_DBG (("Ignoring header'%s'", key));
			continue;

		    case HDR_COMMENT:
			if (hdr_comment (key, field, ep) != OK)
				return NOTOK;
			continue;
			
		    case HDR_MID:
			if (hdr_mid (field, &(head -> this__IPM)) != OK)
				PP_DBG (("Bad message id '%s'", field));
			continue;

		    case HDR_FROM:
			if (hdr_recip_set (field, &from) != OK)
				PP_DBG (("Bad From '%s'", field));
			continue;

		    case HDR_SENDER:
			if (hdr_ordesc (field, &head -> originator) != OK)
				PP_DBG (("Bad Sender '%s'", field));
			continue;
			
		    case HDR_REPLY_TO:
			if (hdr_ordesc_seq (field, &(head -> reply__recipients)) != OK)
				PP_DBG (("Bad replied to '%s'", field));
			continue;

		    case HDR_TO:
			if (hdr_recip_set (field, &(head -> primary__recipients)) != OK)
				PP_DBG (("Bad to '%s'", field));
			continue;

		    case HDR_CC:
			if (hdr_recip_set (field, &(head -> copy__recipients)) != OK)
				PP_DBG (("Bad cc '%s'", field));
			continue;

		    case HDR_BCC:
			if (hdr_recip_set (field, &(head -> blind__copy__recipients)) != OK)
				PP_DBG (("Bad bcc '%s'", field));
			continue;

		    case HDR_IN_REPLY_TO:
			if (hdr_reply_to (field, 
					  &(head -> replied__to__IPM),
					  &(head -> related__IPMs)) != OK)
				PP_DBG (("Bad in reply to '%s'", field));
			continue;

		    case HDR_REFERENCES:
			if (hdr_mid_seq (field, &(head -> related__IPMs)) != OK)
				PP_DBG (("Bad references '%s'", field));
			continue;

		    case HDR_EXTENSIONS:
			if (x40084 == TRUE) {
				if (hdr_comment (key, field, ep) != OK)
					return NOTOK;
			} else if (hdr_extension (key, field, &(head -> extensions)) != OK)
				PP_DBG (("Bad extension '%s'", field));
			continue;

		    case HDR_INCOMPLETE_COPY:
			if (x40084 == TRUE) {
				PP_LOG(LLOG_EXCEPTIONS,
				       ("Unable to convert to p2 (84) '%s %s'",
					key, field));
				(void) sprintf (buf,
					       "Unable to convert to p2 (84) '%s %s'",
					       key, field);
				*ep = strdup(buf);
				return NOTOK;
			}
			if (hdr_incomplete_copy (&(head -> extensions)) != OK)
				PP_DBG (("Bad incomplete_copy '%s'", field));
			continue;

		    case HDR_LANGUAGE:
			if (x40084 == TRUE) {
				PP_LOG(LLOG_EXCEPTIONS,
				       ("Unable to convert to p2 (84) '%s %s'",
					key, field));
				(void) sprintf (buf,
					       "Unable to convert to p2 (84) '%s %s'",
					       key, field);
				*ep = strdup(buf);
				return NOTOK;
			}
			if (hdr_language (field, &(head -> extensions)) != OK)
				PP_DBG (("Bad language '%s'", field));
			continue;

		    case HDR_SUBJECT:
			if (hdr_subject (field, &(head -> subject)) != OK)
				PP_DBG (("Bad subject '%s'", field));
			continue;

		    default:
			PP_LOG (LLOG_EXCEPTIONS,
				("Unexpected Header Type"));
			*ep = strdup("Unexpected Header Type");
			return NOTOK;
		}
		break;
	}

	if (head -> originator == (struct type_P2_ORDescriptor *) 0) {
		if (from != (struct type_P2_RecipientSequence *) 0) {
			head -> originator = from -> RecipientSpecifier -> recipient;
			free ((char *) from -> RecipientSpecifier);
			temp = from;
			from = from -> next;
			free ((char *) temp);
		}
	}
	
	/* convert RecipientSequence to ORDescriptorSequence */
	while (from != (struct type_P2_RecipientSequence *) 0) {
		ix = (struct type_P2_ORDescriptorSequence *) calloc (1,
								     sizeof(struct type_P2_ORDescriptorSequence));
		ix -> ORDescriptor = from -> RecipientSpecifier -> recipient;
		free((char *) from -> RecipientSpecifier);
		temp=from;
		from=from->next;
		free((char *) temp);
		if (head -> authorizing__users == (struct type_P2_ORDescriptorSequence *) 0) 
			head -> authorizing__users = tail = ix;
		else {
			tail -> next = ix;
			tail = ix;
		}
	}
	if (head -> this__IPM == NULL)
		gen_mid (&(head -> this__IPM));
	
	return OK;
}

/* \f

 */

hdr_comment (key, field, ep)
char	*key,
	*field,
	**ep;
{
	char	buf[BUFSIZ];
	PP_DBG (("hdr_comments '%s'", field));
	if (P2_ext == NULLCP || P2_ext[0] == '\0')
		return OK;
	
	if (!comments_started) {
		comments_started = TRUE;
		if ((fp_P2_ext = fopen (P2_ext, "w")) == NULL) {
			PP_SLOG (LLOG_EXCEPTIONS, P2_ext,
				 ("Can't open file"));
			(void) sprintf (buf,
					"Failed to open extension file '%s'",
					P2_ext);
			*ep = strdup(buf);
			return NOTOK;
		}
		fputs("RFC-822-HEADERS:\n", fp_P2_ext);
	}
	field_tidy(key);
	fputs (key, fp_P2_ext);
	fputs (": ", fp_P2_ext);
	field_tidy(field);
	fputs (field, fp_P2_ext);
	fputs ("\n", fp_P2_ext);
	return OK;
}

hdr_mid_seq (field, seq_ptr)
char	*field;
struct type_P2_IPMIdentifierSequence	**seq_ptr;
{
	char	*p, *q;
	struct type_P2_IPMIdentifierSequence	*temp, *ix;
	
	field_tidy (field);
	p = q = field;
	while (q != NULLCP)
	{
		if ((q = index (p, ',')) != NULLCP)
			*q++ = '\0';
		temp = (struct type_P2_IPMIdentifierSequence *)
			calloc (1, sizeof (struct type_P2_IPMIdentifierSequence));
		if (hdr_mid (p, &(temp -> IPMIdentifier)) != OK) {
			free ((char *) temp);
			return NOTOK;
		}
		p = q;
		if (*seq_ptr == NULL)
			*seq_ptr = temp;
		else {
			ix = *seq_ptr;
			while (ix -> next != NULL) ix = ix -> next;
			ix -> next = temp;
		}
	}
	return OK;
}
		
hdr_mid (field, mid_ptr)
char	*field;
struct type_P2_IPMIdentifier	**mid_ptr;
{
	/* see rfc 1138 4.7.3.3 */
	char *midstring, *cp;
	char	ps[BUFSIZ];
	AP_ptr	ap, local, domain;
	PE	pe;

	if ((midstring = index (field, '<')) == NULLCP
	    || (cp = rindex (field, '>')) == NULLCP)
		return NOTOK;
	*cp = '\0';
	midstring++;
	if (ap_s2p (midstring, &ap, (AP_ptr *) 0, (AP_ptr *) 0, &local,
		    &domain, (AP_ptr *) 0) == (char *) NOTOK)
	{
		PP_LOG (LLOG_EXCEPTIONS,
			( "Illegal Message ID '%s'", midstring));
		*mid_ptr = NULL;
		return NOTOK;
	}
	
	*mid_ptr = (struct type_P2_IPMIdentifier *) calloc (1,
							    sizeof (struct type_P2_IPMIdentifier));

	if (domain != NULLAP && local != NULLAP
	    && lexequ (domain -> ap_obvalue, "MHS") == 0
	    && (cp = index (local -> ap_obvalue, '*')) != NULLCP) {
		/* x.400 generated */
		if (cp != local -> ap_obvalue) {
			*cp++ = '\0';
			(*mid_ptr)-> user__relative__identifier = str2qb (local -> ap_obvalue,
									  strlen (local -> ap_obvalue),
									  1);
		}
		if (*cp == '\0')
			return OK;
		strcpy (local -> ap_obvalue, cp);
		cp = ap_p2s (NULLAP, NULLAP, local, domain, NULLAP);

		if (ORstring2pe (cp, &pe) != OK) {
			free (cp);
			ap_1delete(ap);
			ap_free(ap);
			return NOTOK;
		}
		free (cp);
		ap_1delete(ap);
		ap_free(ap);

		(*mid_ptr) -> user = (struct type_P2_ORAddress *) calloc (1, sizeof (struct type_P2_ORAddress));
		if (pe != NULLPE) {
			(*mid_ptr) -> user -> x1 = pe;
			(*mid_ptr) -> user -> x2 = pe -> pe_next;
		}
		return OK;
	} else {
		/* 822 generated */
		or_asc2ps(midstring, ps);
		(*mid_ptr) -> user__relative__identifier = str2qb (ps,	
								   strlen(ps),
								   1);
		return OK;
	}
}

get_comments (buf, addr)
char *buf;
AP_ptr addr;
{
	AP_ptr ap;

	buf [0] = '\0';
	ap = addr;
	while (TRUE)
	{
		if (ap -> ap_obtype == AP_COMMENT)
		{
			strcat (buf, " (");
			strcat (buf, ap -> ap_obvalue);
			strcat (buf, ")");
		}
		if (ap -> ap_next == NULLAP
			|| ap -> ap_next -> ap_ptrtype == AP_PTR_NXT)
			break;
		ap = ap -> ap_next;
	}
	PP_DBG (("Comment '%s'", buf));
	return OK;
}
PE or2pe();

ORstring2pe (orstring, pe)
char *orstring;
PE *pe;
{
	OR_ptr or;
	*pe = NULLPE;

	if (or_rfc2or (orstring, &or) == NOTOK)
	{
		PP_DBG (("Failed to parse '%s'", orstring));
		return NOTOK;
	}

	or = or_default (or);

	if ((*pe = or2pe (or)) == NULLPE)
	{
		PP_DBG (("Failed to decode OR_Ptr '%s'", orstring));
		return NOTOK;
	}
	or_free (or);
	return OK;
}
	
get_ordesc (cpp, or_desc_ptr, group_ptr)
char	**cpp;
struct type_P2_ORDescriptor	**or_desc_ptr, **group_ptr;
{
	/* see rfc 1138 4.7.1 */
	AP_ptr	ap, group, name, local, domain, route, ix;
	char	comment[BUFSIZ], freeform[BUFSIZ], buf[BUFSIZ];
	char	*addr;
	PE	pe;

	if (*cpp == NULLCP || **cpp == '\0')
		return OK;

	PP_DBG (("get_ordesc ('%s')", *cpp));

	if ((*cpp = ap_s2p (*cpp, &ap,
			    &group, &name, &local,
			    &domain, &route)) == (char *) NOTOK)
		return NOTOK;

	*or_desc_ptr = (struct type_P2_ORDescriptor *) 
		calloc (1, sizeof (struct type_P2_ORDescriptor));

	addr = ap_p2s (NULLAP, NULLAP, local, domain, route);
	
	if (ORstring2pe (addr, &pe) != OK) {
		PP_DBG (("Failed to encode '%s'", addr));
		free (addr);
		return NOTOK;
	}
	free(addr);
	(*or_desc_ptr) -> formal__name = (struct type_P2_ORName *)
		calloc (1, sizeof (struct type_P2_ORName));
	if (pe != NULLPE) {
		(*or_desc_ptr) -> formal__name -> x1 = pe;
		(*or_desc_ptr) -> formal__name -> x2 = pe -> pe_next;
		pe -> pe_next = NULLPE;
	}
	
	get_comments (comment, ap);

	freeform [0] = '\0';
	if (name != NULLAP) {
		ix = name;
		while (ix != NULLAP &&
		       (ix -> ap_obtype == AP_COMMENT ||
			ix -> ap_obtype == AP_PERSON_END ||
			ix -> ap_obtype == AP_PERSON_NAME ||
			ix -> ap_obtype == AP_PERSON_START)) {
			if (ix -> ap_obtype != AP_COMMENT &&
			    ix -> ap_obvalue != NULLCP) {
				if (freeform[0] != '\0')
					strcat (freeform, " ");
				strcat (freeform, ix -> ap_obvalue);
			}
			ix = ix -> ap_next;
		}
	}

	strcat (freeform, comment);
	
	if (freeform[0] != '\0') {
		or_asc2ps (freeform, buf);
		
		(*or_desc_ptr) -> free__form__name = str2qb (buf, strlen(buf), 1);
	}

	if (group != NULLAP) {
		freeform[0] = '\0';
		ix = group;
		while (ix != NULLAP &&
		       (ix -> ap_obtype == AP_COMMENT ||
			ix -> ap_obtype == AP_GROUP_END ||
			ix -> ap_obtype == AP_GROUP_NAME ||
			ix -> ap_obtype == AP_GROUP_START)) {
			if (ix -> ap_obtype != AP_COMMENT
			    && ix -> ap_obvalue != NULLCP) {
				if (freeform[0] != '\0')
					strcat (freeform, " ");
				strcat (freeform, ix -> ap_obvalue);
			}
			ix = ix -> ap_next;
		}
		if (freeform[0] != '\0') {
			*group_ptr = (struct type_P2_ORDescriptor *)
				calloc (1, sizeof (struct type_P2_ORDescriptor));
			or_asc2ps (freeform, buf);
			
			(*group_ptr) -> free__form__name = str2qb(buf, strlen(buf), 1);
		}
	} else
		*group_ptr = NULL;
	ap_1delete(ap);
	ap_free (ap);
	return OK;
}

hdr_ordesc (field, or_desc_ptr)
char	*field;
struct type_P2_ORDescriptor	**or_desc_ptr;
{
	struct type_P2_ORDescriptor	*gptr;
	char	*cp;
	
	field_tidy (field);
	cp = field;
	if (cp == NULLCP || *cp == '\0')
		return OK;

	if (get_ordesc (&cp, or_desc_ptr, &gptr) != OK) {
		PP_DBG(("Bad single OR desc '%s'", field));
		return NOTOK;
	}
	return OK;
}

hdr_ordesc_seq (field, or_desc_ptr)
char	*field;
struct type_P2_ORDescriptorSequence	**or_desc_ptr;
{
	char	*cp;
	struct type_P2_ORDescriptorSequence	*temp, *ix;
	struct type_P2_ORDescriptor	*dptr, *gptr;

	field_tidy (field);
	cp = field;
	
	if (cp == NULLCP || *cp == '\0')
		return OK;
	
	while (get_ordesc (&cp, &dptr, &gptr) == OK) {
		if (gptr != (struct type_P2_ORDescriptor *) NULL) {
			temp = (struct type_P2_ORDescriptorSequence *)
				calloc (1, sizeof (struct type_P2_ORDescriptorSequence));
			temp -> ORDescriptor = gptr;
			if (*or_desc_ptr == NULL)
				*or_desc_ptr = temp;
			else {
				ix = *or_desc_ptr;
				while (ix -> next != NULL) ix = ix -> next;
				ix -> next = temp;
			}
		}
		temp = (struct type_P2_ORDescriptorSequence *)
			calloc (1, sizeof (struct type_P2_ORDescriptorSequence));
		temp -> ORDescriptor = dptr;
		if (*or_desc_ptr == NULL)
			*or_desc_ptr = temp;
		else {
			ix = *or_desc_ptr;
			while (ix -> next != NULL) ix = ix -> next;
			ix -> next = temp;
		}
		if (cp == NULLCP || *cp == '\0')
			return OK;
	}
	PP_DBG (("Bad address field '%s'", field));
	return NOTOK;
}

hdr_recip_set (field, or_recip_ptr)
char	*field;
struct type_P2_RecipientSequence	**or_recip_ptr;
{
	/* see rfc 1138 4.7.1 */
	struct type_P2_RecipientSequence	*temp, *ix;
	char	*cp;
	struct type_P2_ORDescriptor	*dptr, *gptr;

	field_tidy (field);
	cp = field;

	if (cp == NULLCP || *cp == '\0')
		return OK;
	
	while (get_ordesc (&cp, &dptr, &gptr) == OK) {
		if (gptr != (struct type_P2_ORDescriptor *) NULL) {
			temp = (struct type_P2_RecipientSequence *)
				calloc (1, sizeof (struct type_P2_RecipientSequence));
			temp -> RecipientSpecifier = (struct type_P2_RecipientSpecifier *)
				calloc (1, sizeof(struct type_P2_RecipientSpecifier));
			temp -> RecipientSpecifier -> recipient = gptr;
			/* defaults for other fields == 0 */
			if (*or_recip_ptr == NULL)
				*or_recip_ptr = temp;
			else {
				ix = *or_recip_ptr;
				while (ix -> next != NULL) ix = ix -> next;
				ix -> next = temp;
			}
		}
		temp = (struct type_P2_RecipientSequence *)
			calloc (1, sizeof (struct type_P2_RecipientSequence));
		temp -> RecipientSpecifier = (struct type_P2_RecipientSpecifier *)
			calloc (1, sizeof(struct type_P2_RecipientSpecifier));
		temp -> RecipientSpecifier -> recipient = dptr;
		/* defaults for other fields == 0 */
		if (*or_recip_ptr == NULL)
			*or_recip_ptr = temp;
		else {
			ix = *or_recip_ptr;
			while (ix -> next != NULL) ix = ix -> next;
			ix -> next = temp;
		}
		if (cp == NULLCP || *cp == '\0')
			return OK;
	}
	PP_DBG (("Bad Address field '%s'", field));
	return NOTOK;
}

hdr_reply_to (field, replied_ptr, related_ptr)
char	*field;
struct type_P2_IPMIdentifier	**replied_ptr;
struct type_P2_IPMIdentifierSequence	**related_ptr;
{
	char	*start, *end, savech;
	struct type_P2_IPMIdentifierSequence	*temp, *ix;
	struct type_P2_IPMIdentifier	*msgid;
	
	if ((start = index(field, '<')) == NULLCP)
		/* no message id can't do anything */
		return OK;
	
	while (*(start+1) != '\0' && *(start+1) == '<') start++;

	if ((end = index(start, '>')) == NULLCP)
		/* incomplete msgid can't do anything */
		return OK;
	end++;
	savech = *end;
	*end = '\0';
	if (hdr_mid (start, &msgid) != OK) 
		return NOTOK;
	*end = savech;

	if (*end == '\0'
	    || (start = index(end, '<')) == NULLCP) 
		/* only one so put in replied_ptr */
		*replied_ptr = msgid;
	else {
		/* more than one put in related_ptr */
		temp = (struct type_P2_IPMIdentifierSequence *)
			calloc (1, sizeof(struct type_P2_IPMIdentifierSequence));
		temp -> IPMIdentifier = msgid;
		
		if (*related_ptr == NULL)
			*related_ptr = temp;
		else {
			ix = *related_ptr;
			while (ix -> next != NULL) ix = ix -> next;
			ix -> next = temp;
		}

		while (end != NULLCP && *end != '\0') {

			if ((start = index(end, '<')) == NULLCP)
				/* no message id can't do anything */
				return OK;
			while (*(start+1) != '\0' && *(start+1) == '<') start++;
			if ((end = index(start, '>')) == NULLCP)
				/* incomplete msgid can't do anything */
				return OK;
			temp = (struct type_P2_IPMIdentifierSequence *)
				calloc (1, sizeof(struct type_P2_IPMIdentifierSequence));
			end++;
			savech = *end;
			*end = '\0';
			if (hdr_mid (start, &(temp -> IPMIdentifier)) != OK) {
				free(temp);
				return OK;
			}
			*end = savech;
			if (*related_ptr == NULL)
				*related_ptr = temp;
			else {
				ix = *related_ptr;
				while (ix -> next != NULL) ix = ix -> next;
				ix -> next = temp;
			}
			
		}			
	}
	return OK;
}

hdr_extension (key, field, extensionptr)
char	*field, *key;
struct type_P2_ExtensionsField	**extensionptr;
{
	char	buf[BUFSIZ];

	struct type_P2_RFC822Field 	*hdr;
	struct type_P2_ExtensionsField *temp = (struct type_P2_ExtensionsField *)
		calloc (1, sizeof (struct type_P2_ExtensionsField));
	temp -> HeadingExtension = (struct type_P2_HeadingExtension *)
		calloc (1, sizeof (struct type_P2_HeadingExtension));

	if (field[strlen(field)-1] == '\n')
		field[strlen(field)-1] = '\0';
	(void) sprintf (buf, "%s: %s", key, field);
	hdr = str2qb (buf, strlen(buf), 1);
	PY_pepy[0] = 0;
	if (encode_P2_RFC822Field(&(temp -> HeadingExtension -> value),
				  0, 0, NULLCP, hdr) != OK) {
		PP_OPER (NULLCP,
			 ("failed to encode rfc822 header extension [%s]",
			  PY_pepy));
		free((char *) hdr);
		free((char *) temp -> HeadingExtension);
		free((char *) temp);
		return NOTOK;
	}
	temp -> HeadingExtension -> type = oid_cpy(str2oid(id_rfc_822_field));
	temp -> next = *extensionptr;
	*extensionptr = temp;
	return OK;
}

hdr_incomplete_copy (extensionptr)
struct type_P2_ExtensionsField	**extensionptr;
{
	struct type_P2_ExtensionsField *temp = (struct type_P2_ExtensionsField *)
		calloc (1, sizeof (struct type_P2_ExtensionsField));
	temp -> HeadingExtension = (struct type_P2_HeadingExtension *)
		calloc (1, sizeof (struct type_P2_HeadingExtension));

	PY_pepy[0] = 0;

	if (encode_P2_IncompleteCopy (&(temp -> HeadingExtension -> value),
				      0, 0, NULLCP, 
				      (struct type_P2_IncompleteCopy *) NULL) != OK)
	{
		PP_OPER (NULLCP,
			 ("failed to encode incomplete copy value [%s]",
			  PY_pepy));
		free ((char *)temp -> HeadingExtension);
		free ((char *)temp);
		return NOTOK;
	}

	temp -> HeadingExtension -> type = oid_cpy(str2oid(id_hex_incomplete_copy));
	
	temp -> next = *extensionptr;
	*extensionptr = temp;
	return OK;
}
	
hdr_language (field, extensionptr)
char	*field;
struct type_P2_ExtensionsField	**extensionptr;
{
	struct type_P2_Languages	*lang = (struct type_P2_Languages *)
		calloc (1, sizeof (struct type_P2_Languages));

	struct type_P2_ExtensionsField *temp = (struct type_P2_ExtensionsField *)
		calloc (1, sizeof (struct type_P2_ExtensionsField));

	temp -> HeadingExtension = (struct type_P2_HeadingExtension *)
		calloc (1, sizeof (struct type_P2_HeadingExtension));

	while (isspace (*field)) field++;

	lang -> Language = str2qb(field, strlen(field), 1);

	PY_pepy[0] = 0;

	if (encode_P2_Languages (&(temp -> HeadingExtension -> value),
				 0,
				 0,
				 NULLCP,
				 lang) != OK)
	{
		PP_OPER (NULLCP,
			 ("failed to encode language heading extension [%s]",
			  PY_pepy));
		free ((char *)lang);
		free ((char *) temp -> HeadingExtension);
		free ((char *) temp);
		return NOTOK;
	}

	temp -> HeadingExtension -> type = oid_cpy(str2oid(id_hex_languages));

	temp -> next = *extensionptr;
	*extensionptr = temp;

	return OK;
}
	
hdr_subject (field, subject_ptr)
char	*field;
struct type_P2_SubjectField	**subject_ptr;
{
	while (isspace (*field)) field++;
	
	if (*field == '\0') {
		*subject_ptr = NULL;
		return OK;
	}
	if (*(field+strlen(field)-1) == '\n')
		*(field+strlen(field)-1) = '\0';

	*subject_ptr = (struct type_P2_SubjectField *) 
		calloc (1, sizeof(struct type_P2_SubjectField));
	
	*subject_ptr = str2qb (field, strlen(field), 1);
	return OK;
}

/* \f

 */

static char *hdrbuf;
static int hdrbuflen;
static char linebuf [LINESIZE];

get_hdr (key, field)
char **key;
char **field;
{
	char *cp;
	struct rfc_hdr *hp;
	int hval;

PP_DBG (("get_hdr()"));

	if (first_hdr)
	{
		first_hdr = FALSE;
		if (fgets (linebuf, LINESIZE - 1, fp_rfc_in) == NULL)
			return HDR_ERROR;
		hdrbuflen = LINESIZE;
		hdrbuf =  malloc (LINESIZE);
		if (hdrbuf == NULL)
			return HDR_ERROR;
	}

	if (linebuf [0] == '\0')
		return HDR_EOH;

	hdrbuf [0] = '\0';
	strcat (hdrbuf, linebuf);
	linebuf [0] = '\0';

	while (!feof (fp_rfc_in))
	{
		if ((fgets (linebuf, LINESIZE -1, fp_rfc_in) == NULL)
				&& !feof (fp_rfc_in))
			return HDR_ERROR;
		if (!isspace (linebuf[0]))
			break;
					/* continuation */
		if (strlen (linebuf) <= 1)
		{
			PP_DBG (("Header terminated before EOF"));
			linebuf [0] = '\0';
			break;
		}

		if (hdrbuflen < strlen (hdrbuf) + strlen (linebuf))
		{       
			hdrbuflen = hdrbuflen * 2;
					/* linebuf must be shorter */
			hdrbuf = realloc (hdrbuf, (unsigned int) hdrbuflen);
			if (hdrbuf == NULL)
			{
				PP_LOG (LLOG_EXCEPTIONS, ("Malloc failed"));
				return NOTOK;
			}
		}
		strcat (hdrbuf, linebuf);
	}

	if (feof (fp_rfc_in))
		/* set end of file condition ready for next call */
		linebuf[0] = '\0';
	
	if ((cp = index (hdrbuf, ':')) == NULLCP)
	{
		PP_DBG (("Header without key '%s'", hdrbuf));
		*key = hdrbuf;
		*field = hdrbuf;
		return HDR_ERROR;
	}

	*cp++ = '\0';
	*key = hdrbuf;
	*field = cp;
	field_tidy (*key);


	hp = hdr_list;
	hval = HDR_EXTENSIONS;


	while (hp -> key != NULLCP)
	{
		if (lexequ (hp -> key, *key) == 0)
		{
			hval = hp -> value;
			break; 
		}
		hp++;
	}
	PP_DBG (("Header: '%d' '%s' '%s'", hval,
		*key,  *field));
	return hval;
}

field_tidy (field)
char *field;
{       /* strip newlines, leading/trailing space */
	register char *p, *q;

	p = field;
	q = field;


	while (isspace(*p))
		p++;

	while (*p != '\0')
		if (*p != '\n')
			*q++ = *p++;
		else
			p++;
	*q-- = '\0';

	while (isspace(*q))
		*q-- = '\0';
}       

extern char	*loc_dom_site;

gen_mid (mid_ptr)               /* generate  random mailid */
struct type_P2_IPMIdentifier **mid_ptr;
{
        char buf [LINESIZE];
        long now;
        (void) time (&now);
        sprintf (buf, "<\"%ld %s", getpid(), ctime (&now));
        buf [strlen(buf) - 1] = '\0';
        strcat (buf, "\"@");
        strcat (buf, loc_dom_site);
        strcat (buf, ">");
        return (hdr_mid (buf, mid_ptr));
}