#include "util.h"
#include "mmdf.h"
#include "ph.h"

/*
 *     MULTI-CHANNEL MEMO DISTRIBUTION FACILITY  (MMDF)
 *     
 *
 *     Copyright (C) 1979,1980,1981  University of Delaware
 *     
 *     Department of Electrical Engineering
 *     University of Delaware
 *     Newark, Delaware  19711
 *
 *     Phone:  (302) 738-1163
 *     
 *     
 *     This program module was developed as part of the University
 *     of Delaware's Multi-Channel Memo Distribution Facility (MMDF).
 *     
 *     Acquisition, use, and distribution of this module and its listings
 *     are subject restricted to the terms of a license agreement.
 *     Documents describing systems using this module must cite its source.
 *
 *     The above statements must be retained with all copies of this
 *     program and may not be removed without the consent of the
 *     University of Delaware.
 *     
 *
 *     version  -1    David H. Crocker    March   1979
 *     version   0    David H. Crocker    April   1980
 *     version  v7    David H. Crocker    May     1981
 *     version   1    David H. Crocker    October 1981
 *
 */
/*  CH_PHONE:  deliver-to-phone transmission                            */
/*                                                                      */

/*  Jun 81  D. Crocker      Add d2p_nadrs mechanism to send no msg text
 *                          when there are not valid addresses
 *  Jul 81  D. Crocker      Change state variable values, for more robust
 *                          state diagrams, to avoid hang with Deliver
 */


#include "ch.h"
#include "chan.h"
#include "phs.h"
#include "ap.h"

extern struct ll_struct  *logptr;
extern Chan *curchan;
extern char *strdup();
extern char *ap_p2s();
extern int  ap_outtype;
extern char *supportaddr;
extern char *mmdflogin;

/*#define RUNALON   */

LOCVAR int numadrs;                    /* number of valid addresses          */
LOCVAR char *sender = (char *)NULL;    /* return address for message         */
LOCVAR char *adr    = (char *)NULL;    /* recipient address                  */
LOCVAR struct rp_construct
			    rp_hend  =
{
    RP_NOOP, 'e', 'n', 'd', ' ', 'o', 'f', ' ', 'h', 'o', 's', 't', ' ',
    'i', 'g', 'n', 'o', 'r', 'e', 'd', '\0'
},
	rp_kild =
{
    RP_DHST, 'n', 'o', ' ', 'v', 'a', 'l', 'i', 'd', ' ', 'a', 'd', 'd',
    'r', 'e', 's', 's', 'e', 's', '\0'
};

char ph_state = SND_RINIT;  /* state of processing current msg    */


qu2ph_send (chname)                 /* overall mngmt for batch of msgs    */
    char chname[];                /* name of channel we are             */
{
    short     result;
    char    info[LINESIZE],
            sendbuf[ADDRSIZE];

    if (rp_isbad (result = qu_pkinit ()))
	return (result);

    if (rp_isbad (result = ph_sbinit ()))
    {
	printx ("remote site refuses to receive mail.\n");
	fflush (stdout);
	return (result);
    }

    ph_state = SND_ABORT;
    for(;;){
	AP_ptr  loctree, domtree, routree, sendtree;
	AP_ptr  ap_s2tree(), ap_normalize();

	result = qu_rinit (info, sendbuf, curchan->ch_apout);
	if(rp_gval(result) == RP_NS){
	    qu_rend();
	    continue;
	}
	if(rp_gval(result) == RP_DONE)
	    break;
 
	if (rp_gval(result) == RP_FIO)		/* Can't open message file */
		continue;
	else if (rp_gval(result) != RP_OK)	/* Some other error */
		break;

	if (sender != (char *)NULL){
		free (sender);
		sender = NULL;
	}

	if ( sendbuf[0] == '\0' ||
	    (sendtree = ap_s2tree( sendbuf )) == (AP_ptr) NOTOK) {
		printx("return address unparseable, using Orphanage\n");
		fflush(stdout);
		if ((sendtree = ap_s2tree( supportaddr )) == (AP_ptr) NOTOK) {
		    printx("Orphanage unparseable, using MMDF\n");
		    fflush(stdout);
		} else
		if ((sendtree = ap_s2tree( mmdflogin )) == (AP_ptr) NOTOK) {
		    result = RP_PARM;
		    qu_rend();
		    goto bugout;
		}
	}
	ap_outtype = curchan -> ch_apout;
	sendtree = ap_normalize (curchan -> ch_lname,
			curchan  -> ch_ldomain, sendtree, curchan);
	if(sendtree == (AP_ptr)MAYBE){
	    result = RP_NS;
	    qu_rend();
	    goto bugout;
	}
	ap_t2parts (sendtree, (AP_ptr *)0, (AP_ptr *)0, &loctree,
			&domtree, &routree);
	sender = ap_p2s ((AP_ptr)0, (AP_ptr)0, loctree, domtree, routree);
	if(sender == (char *)MAYBE){
	    result = RP_NS;
	    qu_rend();
	    goto bugout;
	}
	ap_sqdelete( sendtree, (AP_ptr) 0 );
	ap_free( sendtree );

	ph_state = SND_RDADR;
	if (rp_isbad (result = ph_winit (chname, info, sender)))
	    return (result);      /* ready to process a message         */

	if (rp_isbad (result = q2p_admng ()))
	    return (result);      /* send the address list              */
	
	if (rp_gval (result) != RP_DONE)
	    break;		  /* catch protocol errors              */

	if (rp_isbad (result = q2p_txmng ()))
	    return (result);      /* send the message text              */

	qu_rend();
    }
    qu_rend();

    if (rp_gval (result) != RP_DONE)
    {
	ll_log (logptr, LLOGTMP, "not DONE (%s)", rp_valstr (result));
	return (RP_RPLY);	  /* catch protocol errors              */
    }

bugout:
    ph_state = SND_ABORT;
    qu_pkend ();                  /* done getting messages              */
    if (rp_isbad (result = ph_sbend ())) {
				  /* done sending messages              */
	printx ("bad ending for outgoing submission... ");
	fflush (stdout);
    }
    return (result);
}
/**/

LOCFUN
	q2p_admng ()              /* send address list                  */
{
    struct rp_bufstruct thereply;
    short     result;
    char    host[ADDRSIZE];
    char    adrbuf[ADDRSIZE];

    AP_ptr  loctree, domtree, routree, adrtree;
    AP_ptr  ap_s2tree(), ap_normalize();

    for (numadrs = 0; ; )         /* reset for each new messages        */
    {                             /* we already have and adr            */
	ph_state = SND_ABORT;
	result = qu_radr (host, adrbuf);
	if (rp_isbad (result))
	    return (result);      /* get address from Deliver           */

	if (rp_gval (result) == RP_HOK)
	{                         /* no-op the sub-list indication      */
	    qu_wrply ((struct rp_bufstruct *) &rp_hend, rp_conlen (rp_hend));
	    continue;
	}

	if (rp_gval (result) == RP_DONE)
	    break;		  /* end of address list                */
        
	if (adr != (char *)NULL)
		free (adr);

	if ( (adrtree = ap_s2tree(adrbuf)) == (AP_ptr) NOTOK)  {
	    adr = strdup( adrbuf );
	} else {
	    ap_outtype = curchan -> ch_apout;
	    adrtree = ap_normalize (curchan -> ch_lname,
				curchan  -> ch_ldomain, adrtree, curchan);
	    if(adrtree == (AP_ptr)MAYBE){
		result = RP_NS;
		goto bugout;
	    }
	    ap_t2parts (adrtree, (AP_ptr *)0, (AP_ptr *)0, &loctree,
			&domtree, &routree);
	    adr = ap_p2s ((AP_ptr)0, (AP_ptr)0, loctree, domtree, routree);
	    if(adr == (char *)MAYBE){
		result = RP_NS;
		goto bugout;
	    }
	    ap_sqdelete( adrtree, (AP_ptr) 0 );
	    ap_free( adrtree );
	}
        
	ph_state = SND_ARPLY;
	if (rp_isbad (result = ph_wadr (host, adr, &thereply)))
	    return (result);      /* give to remote site & get reply    */

bugout:
	switch (rp_gval (thereply.rp_val))
	{			  /* was address acceptable?            */
	    case RP_AOK: 	  /* address ok, text not yet sent      */
		numadrs++;
		ph_state = SND_ABORT;
		qu_wrply (&thereply, rp_structlen(thereply));
		break;

	    case RP_NO: 	  /* remaining acceptible responses     */
		thereply.rp_val = RP_NDEL;
	    case RP_NS:
	    case RP_USER: 
	    case RP_NDEL: 
	    case RP_AGN: 
	    case RP_NOOP: 
		ph_state = SND_ABORT;
		qu_wrply (&thereply, rp_structlen(thereply));
		break;

	    default: 		  /* responses which force abort        */
		if (rp_isbad (thereply.rp_val))
		    return (thereply.rp_val);
		return (RP_RPLY);
	}
    }
    ph_state = SND_TRPLY;
    return (ph_waend ());        /* tell remote of address list end    */
}
/**/

LOCFUN
	q2p_txmng ()              /* send message text                  */
{
    struct rp_bufstruct thereply;
    int     len;
    short   result;
    char    buffer[BUFSIZ];

/*  if no addressees have been accepted, don't bother sending the text */
    if (numadrs == 0)    
    {
	qu_wrply ((struct rp_bufstruct *) &rp_kild, rp_conlen (rp_kild));
	return (RP_DONE);
    }

    if (rp_isbad( ph_wtinit() ))
        return (RP_RPLY);
    printx ("sending...:");
    fflush (stdout);

    len = sizeof(buffer);
    for (qu_rtinit (0L);
	    (rp_gval (result = qu_rtxt (buffer, &len))) == RP_OK; )
    {
        printx (".");         /* to show watcher we're working      */
        fflush (stdout);
        if (rp_isbad (result = ph_wtxt (buffer, len)))
	    return (result);                         
        if (rp_gval (result) != RP_OK)
	    return (RP_RPLY);
	len = sizeof(buffer);
    }
    printx (" ");             /* keep it pretty                     */
    fflush (stdout);

    if (rp_isbad (result))
        return (result);
    if (rp_gval (result) != RP_DONE)
        return (RP_RPLY);         /* didn't get it all across?          */

    if (rp_isbad (result = ph_wtend (&thereply)))
        return (result);          /* flag end of message                */
    
    switch (rp_gval (thereply.rp_val))
    {			          /* was text acceptable?               */
        case RP_OK: 
            thereply.rp_val = RP_MOK;
        case RP_MOK: 	          /* text was accepted                  */
            qu_wrply (&thereply, rp_structlen(thereply));
            break;
    
        case RP_NO: 	          /* remaining acceptible responses     */
            thereply.rp_val = RP_NDEL;
        case RP_NDEL: 
        case RP_AGN: 
        case RP_NOOP: 
            qu_wrply (&thereply, rp_structlen(thereply));
            thereply.rp_val = RP_OK;
            break;                /* don't abort process                */
    
        default: 	          /* responses which force abort        */
            if (rp_isbad (thereply.rp_val))
    	        return (thereply.rp_val);
            return (RP_RPLY);
    }
    return (thereply.rp_val);     /* just quote remote                  */
}
