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

⟦e5d85f0c7⟧ TextFile

    Length: 12780 (0x31ec)
    Types: TextFile
    Names: »io_lib.c«

Derivation

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

TextFile

/* io.c: This file contains the entire io library */

# ifndef lint
static char Rcsid[] = "@(#)$Header: /cs/research/pp/hubris/pp-beta/Lib/io/RCS/io_lib.c,v 5.0 90/09/20 16:06:30 pp Exp Locker: pp $";
# endif

/*
 * $Header: /cs/research/pp/hubris/pp-beta/Lib/io/RCS/io_lib.c,v 5.0 90/09/20 16:06:30 pp Exp Locker: pp $
 *
 * $Log:	io_lib.c,v $
 * Revision 5.0  90/09/20  16:06:30  pp
 * rcsforce : 5.0 public release
 * 
 */



#include "head.h"
#include "q.h"
#include "adr.h"
#include "prm.h"
#include "dr.h"
#include <sys/socket.h>
#include <signal.h>
#include <netdb.h>
#include <netinet/in.h>


extern char     *cmddfldir;

static  int     mm_cid;       /* process id of child mail process */
static FILE     *io_wfp,
		*io_rfp;

char            *submit_host = 0;
int             remote_submit = 0;
short		submit_port = 4001;
extern  int     protocol_mode;
static enum {
	is_init,
	is_parm,
	is_queue,
	is_addrs,
	is_adend,
	is_txtinit,
	is_data,
	is_txtend,
	} is_state = is_init;
#define check_proto(x)	if (is_state != (x)) \
	return io_lose (rp, RP_MECH, "Protocol state mismatch")
static int io_init_remote ();
static int io_init_local ();
static int io_lose ();
static void set_protocol_mode ();
static void unset_protocol_mode ();
static int io_rrply ();
static int io_wrec ();
static int io_rrec ();
static int io_tdata_aux ();
static char *io_data_vis ();

extern void getfpath ();
/* ---------------------  Begin  Routines  -------------------------------- */




/*
Initialise for submission
*/

int io_init (rp)
RP_Buf  *rp;
{
	is_state = is_init;
	if (io_wfp != NULLFILE) {
		(void) fclose (io_wfp);
		io_wfp = NULLFILE;
	}
	if (io_rfp != NULLFILE) {
		(void) fclose (io_rfp);
		io_rfp = NULLFILE;
	}

	if (remote_submit)
		return (io_init_remote (rp));
	else    return (io_init_local (rp));
}




/*
Parameter handling
*/

int io_wprm (prm, rp)
struct prm_vars         *prm;
RP_Buf                  *rp;
{
	int             retval;

	PP_DBG (("io_wprm (prm, rp)"));

	check_proto (is_init);

	if (io_wfp == NULLFILE)
		return (io_lose (rp, RP_MECH, "Not connected to sumbit"));

	set_protocol_mode();
	retval = wr_prm (prm, io_wfp);
	unset_protocol_mode();

	if (rp_isbad (retval))
		return (io_lose (rp, retval, "Can't write parameters"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Bad handshake"));

	is_state = is_parm;
	return (rp -> rp_val);
}




/*
Q structure handling
*/

int io_wrq (qp, rp)
Q_struct        *qp;
RP_Buf          *rp;
{
	int     retval;

	PP_DBG (("io_wq (q, rp)"));

	if (io_wfp == NULLFILE)
		return (io_lose (rp, RP_MECH, "Not connected to submit"));
	check_proto (is_parm);

	set_protocol_mode();
	retval = wr_q (qp, io_wfp);
	unset_protocol_mode();

	if (rp_isbad (retval))
		return (io_lose (rp, retval, "Can't write Q structure"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Bad handshake"));

	is_state = is_addrs;
	return (rp -> rp_val);
}




/*
DR structure handling
*/

int io_wdr (dp, rp)
DRmpdu          *dp;
RP_Buf          *rp;
{
	int     retval;

	PP_DBG (("io_wdr (dp, rp)"));

	if (io_wfp == NULLFILE)
		return (io_lose (rp, RP_MECH, "Not connected to submit"));
	check_proto (is_adend);

	set_protocol_mode();
	retval = wr_dr (dp, io_wfp);
	unset_protocol_mode();

	if (rp_isbad (retval))
		return (io_lose (rp, retval, "Can't write DR structure"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Bad Handshake"));

	is_state = is_init;
	return (rp -> rp_val);
}




/*
Address handling
*/

int io_wadr (ap, type, rp)
ADDR            *ap;
int             type;
RP_Buf          *rp;
{
	int     retval;

	PP_DBG (("io_wadr (adr, %d, rp)", type));

	if (io_wfp == NULLFILE)
		return (io_lose (rp, RP_MECH, "Not connected to submit"));
	check_proto (is_addrs);

	set_protocol_mode();
	retval = wr_adr (ap, io_wfp, type);
	unset_protocol_mode();

	if (rp_isbad (retval))
		return (io_lose (rp, retval, "Can't write address"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Bad handshake"));
	if (rp -> rp_val != RP_AOK)
		return RP_BAD;
	return (rp -> rp_val);
}


/*
Address phase termination
*/

int io_adend (rp)
RP_Buf          *rp;
{
	int     retval;

	PP_DBG (("io_adend (rp)"));

	if (io_wfp == NULLFILE)
		return (io_lose (rp, RP_MECH, "Not connected to sumbit"));
	check_proto (is_addrs);

	if (rp_isbad (retval = io_wrec ("", 0)))
		return (io_lose (rp, retval, "Problem ending addreses"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Bad Handshake"));

	is_state = is_adend;
	return (rp -> rp_val);
}




/*
Text phase - initialisation
*/

int io_tinit (rp)
RP_Buf          *rp;
{
	int     retval;

	PP_DBG (("io_tinit()"));

	if (io_wfp == NULLFILE)
		return (io_lose (rp, RP_MECH, "Not connected to submit"));
	check_proto (is_adend);

	if ( rp_isbad (retval = io_wrec ("", 0)))
		return (io_lose (rp, retval, "Problem in text init"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Bad handshake"));

	PP_DBG (("Returned %s\n", rp->rp_line));
	is_state = is_txtinit;
	return (rp -> rp_val);
}




/*
Initialise to pass a single body part to submit
*/

int io_tpart (section, links, rp)
char            *section;
int             links;
RP_Buf          *rp;
{
	int     retval;

	PP_DBG (("io_tpart (%s, %d)", section, links));

	check_proto (is_txtinit);
	if (rp_isbad (retval = io_wrec (section, strlen (section))))
		return (io_lose (rp, retval, "Error writing to submit"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Handshake failure"));

	is_state = is_data;
	return (rp -> rp_val);
}




/*
Write data to submit.
*/

int io_tdata (buf, len)
char            *buf;
int             len;
{
	if (is_state != is_data)
		return NOTOK;
	PP_LOG (LLOG_PDUS, ("Lib/io_tdata(%d): %s", len,
			    io_data_vis (buf, len)));
	return (io_tdata_aux (buf, len, TRUE));
}




/*
End a section sent to submit
*/

int io_tdend (rp)
RP_Buf          *rp;
{
	int     retval;

	PP_DBG (("io_tdend (ret)"));

	check_proto (is_data);
	if (rp_isbad (retval = io_tdata_aux ("", 0, FALSE)))
		return (io_lose (rp, retval, "I/O error"));

	(void) fflush (io_wfp);
	if (ferror (io_wfp))
		return (io_lose (rp, RP_FIO, "Write error"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Bad Handshake"));

	is_state = is_txtinit;
	return (rp -> rp_val);
}




/*
Finally finish the data section
*/

int io_tend (rp)
RP_Buf          *rp;
{
	int     retval;

	PP_DBG (("io_tend (ret)"));

	check_proto (is_txtinit);
	if (rp_isbad (retval = io_wrec ("", 0)))
		return (io_lose (rp, retval, "I/O error"));

	if (rp_isbad (retval = io_rrply (rp)))
		return (io_lose (rp, retval, "Bad Handshake"));

	if (rp_isbad (rp -> rp_val))
		return rp -> rp_val;

	if (rp_isbad (retval = io_rrply (rp)))
		return io_lose (rp, retval, "Bad Handshake");

	is_state = is_init;
	return (rp -> rp_val);
}




int io_end (type)
int     type;
{
	register int   status = OK;

	PP_DBG (("io_end (%d)", type));

	(void) fclose (io_wfp);
	(void) fclose (io_rfp);
	io_rfp = NULLFILE;
	io_wfp = NULLFILE;

	if (type != OK && !remote_submit && mm_cid != 0) {
		PP_DBG (("killing child %d\n", mm_cid));
		(void) kill (mm_cid, SIGKILL);
	}

	if (!remote_submit)
		status = pgmwait (mm_cid);

	mm_cid = 0;
	is_state = is_init;
	return (status);
}




/* ---------------------  Static  Routines  ------------------------------- */




/*
Helper routine if local connection is required
*/

static int io_init_local (rp)
RP_Buf  *rp;
{
	char            temppath[LINESIZE];
	int             sv[2],
			osv[2],
			child,
			i;

	PP_DBG (("<pipe> io_init()"));

	if (pipe (sv) < 0 || pipe (osv) < 0)
		return (io_lose (rp, RP_LIO,
				"Can't create connection to child"));

	if ((child = tryfork()) < 0) {
		(void) close (sv[0]);
		(void) close (sv[1]);
		(void) close (osv[0]);
		(void) close (osv[1]);
		return (io_lose (rp, RP_LIO, "Try again (fork)"));
	}


	if (child == 0) {
		/*
		I am the child (I will use sv[1])
		*/

		getfpath (cmddfldir, "submit", temppath);

		if (osv[0] != 0) {
			(void) dup2 (osv[0], 0);
			(void) close (osv[0]);
		}
		if (sv[1] != 1) {
			(void) dup2 (sv[1], 1);
			(void) close (sv[1]);
		}
		(void) close (osv[1]);
		(void) close (sv[0]);
		for (i = getdtablesize() ; i >= 2 ; i--)
			(void) close (i);

		execl (temppath, "submit", 0);

		PP_OPER (temppath,  ("Cannot exec"));

		_exit (1);
	}

	/*
	I am the parent - I will use sv[0]
	*/
	mm_cid = child;
	(void) close (sv[1]);
	io_rfp = fdopen (sv[0], "r");
	(void) close (osv[0]);
	io_wfp = fdopen (osv[1], "w");
	return (RP_OK);
}




/*
Helper routine for remote connect (submit server)
*/

static int  io_init_remote (rp)
RP_Buf  *rp;
{
	struct servent          *sp;
	u_short                 port;
	struct hostent          *host;
	struct sockaddr_in      sin;
	int                     sd;

	PP_DBG (("<socket> io_init()"));

	if ((sp = getservbyname ("submit", "tcp")) != NULL)
	    port = sp -> s_port;
	else
	    port = htons ((u_short)submit_port);

	sd = socket (AF_INET, SOCK_STREAM, 0);
	if (sd < 0)
		return (io_lose (rp, RP_LIO, "Can't get a socket"));

	bzero ((char *)&sin, sizeof (sin));
	sin.sin_family = AF_INET;
	sin.sin_port = port;

	if ((host = gethostbyname (submit_host)) == NULL) {
		(void) close (sd);
		PP_LOG (LLOG_EXCEPTIONS,
			("Remote server %s not found", submit_host));
		return (io_lose (rp, RP_MECH, "Can't locate host"));
	}

	bcopy ((char *)host -> h_addr, (char *)&sin.sin_addr,
		host -> h_length);

	if (connect (sd, (struct sockaddr *)&sin, sizeof sin) < 0) {
		(void) close (sd);
		return (io_lose (rp, RP_LIO, "Can't connect to submit"));
	}

	io_rfp = fdopen (sd, "r");
	io_wfp = fdopen (sd, "w");

	if (io_wfp == NULLFILE || io_rfp == NULLFILE)
		return (io_lose (rp, RP_FIO, "File pointers not set"));
	return (RP_OK);
}




/*
Helper routine to ensure correct protocol
*/

static int io_tdata_aux (buf, len, flag)
char            *buf;
int             len;
int             flag;
{
	long    datalen = htonl ((u_long)len);

	if (flag && len == 0)
		return (RP_MECH);

	(void) fwrite ((char *)&datalen, sizeof (datalen), 1, io_wfp);
	(void) fwrite (buf, sizeof (char), len, io_wfp);

	return ((ferror (io_wfp) ? RP_FIO : RP_OK));
}




/*
Get a reply from remote process
*/

static int io_rrply (rp)
RP_Buf          *rp;
{
	int     retval;
	int     len;
	char    *rplystr;

	PP_DBG (("io_rrply (rp)"));

	if ((retval = io_rrec ((char *) rp, &len)) != RP_OK)
		return (retval);

	rplystr = rp_valstr ((int)rp -> rp_val);

	if (*rplystr == '*') {
		/*
		Replyer did a no-no
		*/
		PP_LOG (LLOG_EXCEPTIONS, ("ILLEGAL REPLY: (%s)", rplystr));
		rp -> rp_val = RP_RPLY;
	}

	return (RP_OK);
}




/*
Read a record
*/

static int io_rrec (linebuf, len)   /* read one "record" */
char   *linebuf;                /* where to stuff the text */
int    *len;                    /* where to stuff the length count */
{
	register int    c;
	register char   *p;
	register int    i;

	PP_DBG (("io_rrec (linebuf, len)"));

	for (i = 0, p = linebuf ; i < LINESIZE -1 &&
	    (c = getc (io_rfp)) != EOF && c != '\n'; i++)
		*p++ = c;

	if (i >= LINESIZE-1)
		return (RP_LIO);
	if (c == EOF)
		return (RP_EOF);
	*p = '\0';
	*len = i;
	return (RP_OK);
}




/*
Write a record
*/

static int io_wrec (linebuf, len)   /* write a record/packet */
register char   *linebuf;       /* chars to write */
register int    len;            /* number of chars to write */
{
	static char *io_data_vis ();
	PP_LOG (LLOG_PDUS, ("io_wrec ('%s', %d)",
			    io_data_vis (linebuf, len), len));


	(void) fwrite (linebuf, sizeof (char), len, io_wfp);
	(void) putc ('\n', io_wfp);
	(void) fflush (io_wfp);   /* force it out */

	return (ferror (io_wfp) ? RP_LIO : RP_OK);
}




static int io_lose (rp, state, str)
RP_Buf          *rp;
int             state;
char            *str;
{
	rp -> rp_val = rp_gval (state);

	(void) strcpy (rp -> rp_line, str);

	PP_LOG (LLOG_NOTICE,
		("io_lose -> %s [%s]", rp_valstr (state), str));

	is_state = is_init;
	return (state);
}

static  char *io_data_vis (str, n)
char    *str;
int     n;
{
	static char    buffer[128];
	char *cp, *ep;

	for(cp = buffer, ep = buffer + sizeof(buffer) -1;
	    cp < ep && n-- > 0; str ++) {
		if (isprint (*str))
			*cp++ = *str;
		else if (cp >= ep - 3)
			break;
		else {
			*cp ++ = '\\';
			*cp ++ = '0' + ((*str >> 6) & 03);
			*cp ++ = '0' + ((*str >> 3) & 07);
			*cp ++ = '0' + ((*str) & 07);
		}
	}
	*cp = 0;
	return buffer;
}

static void set_protocol_mode ()
{
	unset_protocol_mode();
	protocol_mode = 1;
	return;
}


static void unset_protocol_mode ()
{
	static int      save = -1;

	if (save == -1)
		save = protocol_mode;
	else {
		protocol_mode = save;
		save = -1;
	}
}