|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 12780 (0x31ec)
Types: TextFile
Names: »io_lib.c«
└─⟦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«
/* 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;
}
}