|
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; } }