aboutsummaryrefslogtreecommitdiff
path: root/unix/os/net
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
committerJoseph Hunkeler <jhunkeler@gmail.com>2015-07-08 20:46:52 -0400
commitfa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch)
treebdda434976bc09c864f2e4fa6f16ba1952b1e555 /unix/os/net
downloadiraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz
Initial commit
Diffstat (limited to 'unix/os/net')
-rw-r--r--unix/os/net/README90
-rw-r--r--unix/os/net/accept.c26
-rw-r--r--unix/os/net/connect.c27
-rw-r--r--unix/os/net/ctype.h4
-rw-r--r--unix/os/net/eprintf.c15
-rw-r--r--unix/os/net/ghostbynm.c37
-rw-r--r--unix/os/net/ghostent.c137
-rw-r--r--unix/os/net/gsocknm.c23
-rw-r--r--unix/os/net/hostdb.c39
-rw-r--r--unix/os/net/htonl.c22
-rw-r--r--unix/os/net/htons.c16
-rw-r--r--unix/os/net/in.h134
-rw-r--r--unix/os/net/inetaddr.c92
-rw-r--r--unix/os/net/kutil.c342
-rw-r--r--unix/os/net/listen.c22
-rw-r--r--unix/os/net/mkpkg25
-rw-r--r--unix/os/net/netdb.h44
-rw-r--r--unix/os/net/ntohl.c22
-rw-r--r--unix/os/net/ntohs.c16
-rw-r--r--unix/os/net/rexec.c160
-rw-r--r--unix/os/net/socket.c25
-rw-r--r--unix/os/net/socket.h109
-rw-r--r--unix/os/net/tcpclose.c16
-rw-r--r--unix/os/net/tcpread.c26
-rw-r--r--unix/os/net/tcpwrite.c23
-rw-r--r--unix/os/net/types.h39
-rw-r--r--unix/os/net/zfioks.c441
-rw-r--r--unix/os/net/zzdebug.x92
28 files changed, 2064 insertions, 0 deletions
diff --git a/unix/os/net/README b/unix/os/net/README
new file mode 100644
index 00000000..af93d174
--- /dev/null
+++ b/unix/os/net/README
@@ -0,0 +1,90 @@
+NETwork interface. 08Oct85 dct
+------------------------------------
+
+This directory contains the network interface software required to support the
+ZFIOKS FIO driver (for the kernel interface) in a TCP/IP environment. The only
+facilities required are those already provided by the IRAF kernel (i.e., to
+read the host name table, a text file), plus the standard TCP network functions
+provided by any system that supports TCP/IP. The interface is self contained,
+requiring only the host TCP/IP facilities and the file "uhosts" in iraf$dev,
+used to map host names to network addresses (see gethostbyname). The code
+supplied here is coded for Berkeley UNIX and works fine, but a much simpler
+Berkeley UNIX dependent version of ZFIOKS is what is actually used on a
+Berkeley host.
+
+The networking interface is not required to run IRAF and the contents of this
+directory may be ignored if the IRAF system is to be configured without
+networking. On a system configured without networking the entry points of the
+ZFIOKS driver must be present but may be stubbed out. Additional information
+on configuration details is given in the discussion of the kernel interface,
+e.g., in sys$ki.
+
+
+STRUCTURE
+
+ The structure of the network interface software is as follows:
+
+
+ ZFIOKS FIO device driver for the kernel server (in ..)
+ |
+ REXEC remote execution of a shell command
+ |
+ TCP_xxx encapsulation of TCP interface
+ |
+ (host TCP/IP) host networking facilities
+
+
+This software is machine dependent but is designed to be reusable, i.e., the
+machine dependence has been isolated into simple procedures and definitions
+whenever possible. On a Berkeley UNIX system the TCP procedures map directly
+into the system services of 4.2 Berkeley UNIX (and no doubt later versions as
+well). On a VMS system running EUNICE the TCP procedures map easily into
+QIOW type device driver calls; EUNICE implements the TCP facilties in the
+network device driver. Similar mappings should be possible on other systems
+with TCP/IP support.
+
+
+TCP INTERFACE
+
+ The TCP interface package consists of the following procedures. On a
+Berkeley UNIX system these TCP functions map directly into calls to the UNIX
+system services.
+
+
+ tcp_gethostbyname get internet code for a host by name
+ tcp_getsockname get socket name
+
+ tcp_socket create and bind a socket (client or server)
+ tcp_connect connect to a socket (client)
+ tcp_listen listen for connections on a socket (server)
+ tcp_accept accept a connection (server)
+ tcp_read read from a socket (synchronous)
+ tcp_write write to a socket (synchronous)
+ tcp_close close a socket (client or server)
+
+
+The usual sequence of calls used by a client process to connect to and
+communicate with a server process is the following.
+
+
+ gethostbyname;involves scan of hostname table
+
+ make a socket
+ connect to the socket
+ (connect returns when the server has accepted the connection)
+ read & write data packets
+ (etc.)
+ close the socket
+
+
+A server does much the same thing, except that the server will listen() for
+connections by client processes, accept() a connection when one occurs, and
+then begin exchanging packets with the client.
+
+------------------------------------
+NOTE -- This directory contains software which is adapted from the Berkeley UNIX
+networking software, hence a UNIX source license is required to use this
+software. Nonetheless, about 90% of the source herein is new; at some point
+the remainder (only 100-200 lines) should be rewritten from scratch to eliminate
+the proprietary restrictions. This was not done initially since the network
+interface is not expected to be included in the standard distribution.
diff --git a/unix/os/net/accept.c b/unix/os/net/accept.c
new file mode 100644
index 00000000..578c1eba
--- /dev/null
+++ b/unix/os/net/accept.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+
+extern int errno;
+extern int tcperrno;
+
+/* TCP_ACCEPT -- Accept a connection on a socket. Accept extracts the first
+ * connection from the queue of pending connections (set up with LISTEN),
+ * creates a new socket with the same properties as S and allocates a new
+ * file descriptor NS for the socket.
+ */
+u_sock
+tcp_accept (s, addr, addrlen)
+u_sock s; /* the socket */
+struct sockaddr *addr; /* endpoint of communications */
+int *addrlen; /* sizeof (addr) */
+{
+ u_sock ns;
+
+ /* MACHDEP */
+ ns = accept (s, addr, addrlen);
+ tcperrno = errno;
+ return (ns);
+}
diff --git a/unix/os/net/connect.c b/unix/os/net/connect.c
new file mode 100644
index 00000000..aeb2b959
--- /dev/null
+++ b/unix/os/net/connect.c
@@ -0,0 +1,27 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+
+extern int errno;
+int tcperrno;
+
+/* TCP_CONNECT -- Initiate a connection on a socket. Returns when the server
+ * accepts the connection and a full duplex connection has been established.
+ * Zero is returned if the connection succeeds; -1 is returned if the connection
+ * fails. The sockaddr argument is necessary because a socket may be used to
+ * talk to multiple endpoints.
+ */
+tcp_connect (s, name, namelen)
+u_sock s; /* the socket */
+struct sockaddr *name; /* endpoint of communications */
+int namelen; /* sizeof(name) */
+{
+ int status;
+eprintf("connect\n");
+
+ /* MACHDEP */
+ status = connect (s, name, namelen);
+ tcperrno = errno;
+ return (status);
+}
diff --git a/unix/os/net/ctype.h b/unix/os/net/ctype.h
new file mode 100644
index 00000000..3a1569c3
--- /dev/null
+++ b/unix/os/net/ctype.h
@@ -0,0 +1,4 @@
+#define isdigit(c) ((c)>='0'&&(c)<='9')
+#define isxdigit(c) (isdigit(c)||(c)>='a'&&(c)<='f'||(c)>='A'&&(c)<='F')
+#define islower(c) ((c)>='a'&&(c)<='z')
+#define isspace(c) ((c)==' '||(c)=='\t'||(c)=='\n')
diff --git a/unix/os/net/eprintf.c b/unix/os/net/eprintf.c
new file mode 100644
index 00000000..4f6bbf06
--- /dev/null
+++ b/unix/os/net/eprintf.c
@@ -0,0 +1,15 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+
+/* EPRINTF -- Formatted print to the standard error output.
+ */
+/* VARARGS */
+eprintf (format, argp)
+char *format; /* format specification */
+int **argp; /* pointer to arg list */
+{
+ _doprnt (format, &argp, stderr);
+ fflush (stderr);
+}
diff --git a/unix/os/net/ghostbynm.c b/unix/os/net/ghostbynm.c
new file mode 100644
index 00000000..42c9fb4a
--- /dev/null
+++ b/unix/os/net/ghostbynm.c
@@ -0,0 +1,37 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include "netdb.h"
+
+#define import_kernel
+#define import_knames
+#define import_spp
+#include <iraf.h>
+
+
+/* TCP_GETHOSTBYNAME -- Scan the host name table to get the internet address
+ * of the named host.
+ */
+struct hostent *
+tcp_gethostbyname (name)
+register char *name;
+{
+ register struct hostent *p;
+ register char **cp;
+ struct hostent *tcp_ghostent();
+
+eprintf("gethostbyname %s\n", name);
+ tcp_ophnt();
+
+ while (p = tcp_ghostent()) {
+ if (strcmp (p->h_name, name) == 0)
+ break;
+ for (cp = p->h_aliases; *cp != 0; cp++)
+ if (strcmp (*cp, name) == 0)
+ goto found;
+ }
+found:
+ tcp_clhnt();
+ return (p);
+}
diff --git a/unix/os/net/ghostent.c b/unix/os/net/ghostent.c
new file mode 100644
index 00000000..484e2640
--- /dev/null
+++ b/unix/os/net/ghostent.c
@@ -0,0 +1,137 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include "types.h"
+#include "netdb.h"
+#include "socket.h"
+
+#define import_kernel
+#define import_knames
+#define import_spp
+#include <iraf.h>
+
+#define MAXALIASES 35
+#define MAXADDRSIZE 14
+#define LINSIZ 80
+
+static int hostf = NULL;
+static char line[LINSIZ+1];
+static char hostaddr[MAXADDRSIZE];
+static struct hostent host;
+static char *host_aliases[MAXALIASES];
+static char *tcp_locate();
+
+
+/* TCP_GHOSTENT -- Return the next entry (line) in the host name table
+ * decoded into a hostent structure.
+ *
+ * The format of an entry in the host name table (e.g., /etc/hosts on a UNIX
+ * system) is as follows:
+ *
+ * ddd.ddd alias1 alias2 ... aliasN
+ */
+struct hostent *
+tcp_ghostent()
+{
+ register char *cp, **q;
+ u_long tcp_inetaddr();
+ char *p, *tcp_hostdb();
+ char *ku_fgets();
+
+ if (hostf == NULL && (hostf = ku_fopen (tcp_hostdb(), "r" )) == NULL)
+ return (NULL);
+
+again:
+ if ((p = ku_fgets (line, LINSIZ, hostf)) == NULL)
+ return (NULL);
+eprintf("..%s", line);
+
+ if (*p == '#')
+ goto again;
+ cp = tcp_locate (p, "#\n");
+ if (cp == NULL)
+ goto again;
+
+ *cp = '\0';
+ cp = tcp_locate (p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+
+ /* THIS STUFF IS INTERNET SPECIFIC.
+ */
+ host.h_addr = hostaddr;
+ *((u_long *)host.h_addr) = tcp_inetaddr (p);
+ host.h_length = sizeof (u_long);
+ host.h_addrtype = AF_INET;
+
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ host.h_name = cp;
+
+ q = host.h_aliases = host_aliases;
+ cp = tcp_locate (cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &host_aliases[MAXALIASES - 1])
+ *q++ = cp;
+ cp = tcp_locate (cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+
+ *q = NULL;
+
+ return (&host);
+}
+
+
+/* TCP_OPHNT -- Open the host name table, a text file.
+ */
+tcp_ophnt()
+{
+ char *tcp_hostdb();
+
+eprintf ("ophnt %s\n", tcp_hostdb);
+ if (hostf == NULL)
+ hostf = ku_fopen (tcp_hostdb(), "r");
+}
+
+
+/* TCP_CLHNT -- Close the host name table file.
+ */
+tcp_clhnt()
+{
+ if (hostf) {
+ ku_fclose (hostf);
+ hostf = NULL;
+ }
+}
+
+
+/* TCP_LOCATE -- Return a pointer to the first character in the indicated
+ * character class.
+ */
+static char *
+tcp_locate (cp, match)
+register char *cp;
+char *match;
+{
+ register char *mp, c;
+
+ while (c = *cp) {
+ for (mp = match; *mp; mp++)
+ if (*mp == c)
+ return (cp);
+ cp++;
+ }
+
+ return ((char *)0);
+}
diff --git a/unix/os/net/gsocknm.c b/unix/os/net/gsocknm.c
new file mode 100644
index 00000000..453fdb70
--- /dev/null
+++ b/unix/os/net/gsocknm.c
@@ -0,0 +1,23 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+
+extern int errno;
+extern int tcperrno;
+
+/* TCP_GSOCKNAME -- Get socket name. Return the current network name for the
+ * indicated socket.
+ */
+tcp_gsockname (s, name, namelen)
+u_sock s; /* the socket */
+struct sockaddr *name; /* endpoint of communications */
+int namelen; /* maxlen in; actual len out */
+{
+ int status;
+
+ /* MACHDEP */
+ status = getsockname (s, name, namelen);
+ tcperrno = errno;
+ return (status);
+}
diff --git a/unix/os/net/hostdb.c b/unix/os/net/hostdb.c
new file mode 100644
index 00000000..3006c56e
--- /dev/null
+++ b/unix/os/net/hostdb.c
@@ -0,0 +1,39 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+
+#define import_kernel
+#define import_knames
+#define import_spp
+#include <iraf.h>
+
+/* MACHDEP */
+#define HOSTDB "/etc/hosts" /* change to "" if not UNIX */
+
+
+/* TCP_HOSTDB -- Return the machine dependent pathname of the host name table
+ * file. On a Berkeley UNIX host system this is "/etc/hosts", but to avoid
+ * hidden machine pathnames in the code we reference "iraf$dev/uhosts" instead.
+ */
+char *
+tcp_hostdb()
+{
+ static char hostdb[SZ_FNAME+1] = HOSTDB;
+ PKCHAR osfn[SZ_FNAME+1];
+
+ /* If HOSTDB is explicitly defined, use it, else return OSFN of the
+ * the file "dev$uhosts". If the filename generation fails (e.g.,
+ * because IRAF is not defined in the host environment) return
+ * anything. In this case anything is the pathname of the Berkeley
+ * UNIX hosts file, which will cause a file open failure on most
+ * systems.
+ */
+ if (hostdb[0] == '\0') {
+ if (ku_mkfname ("iraf", "dev", "uhosts", osfn, SZ_FNAME) == ERR)
+ strcpy ((char *)osfn, "/etc/hosts");
+ strcpy (hostdb, (char *)osfn);
+ }
+
+ return (hostdb);
+}
diff --git a/unix/os/net/htonl.c b/unix/os/net/htonl.c
new file mode 100644
index 00000000..e9c57280
--- /dev/null
+++ b/unix/os/net/htonl.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+/* HTONL -- [MACHDEP] Convert a long integer in host format to net format.
+ */
+htonl (lword)
+long lword;
+{
+ register char *ip, *op;
+ static long hostw, netw;
+
+ hostw = lword;
+ ip = (char *)&hostw;
+ op = (char *)&netw + 4;
+
+ *--op = *ip++;
+ *--op = *ip++;
+ *--op = *ip++;
+ *--op = *ip++;
+
+ return (netw);
+}
diff --git a/unix/os/net/htons.c b/unix/os/net/htons.c
new file mode 100644
index 00000000..9f390c29
--- /dev/null
+++ b/unix/os/net/htons.c
@@ -0,0 +1,16 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+/* HTONS -- [MACHDEP] Convert a short integer in host format to net format.
+ */
+htons (word)
+short word;
+{
+ register char *wp;
+ static short w;
+
+ w = word;
+ wp = (char *)&w;
+
+ return ((wp[0] << 8) | wp[1]);
+}
diff --git a/unix/os/net/in.h b/unix/os/net/in.h
new file mode 100644
index 00000000..825a9d39
--- /dev/null
+++ b/unix/os/net/in.h
@@ -0,0 +1,134 @@
+/* in.h 6.1 83/07/29 */
+
+/*
+ * Constants and structures defined by the internet system,
+ * Per RFC 790, September 1981.
+ */
+
+/*
+ * Protocols
+ */
+#define IPPROTO_ICMP 1 /* control message protocol */
+#define IPPROTO_GGP 2 /* gateway^2 (deprecated) */
+#define IPPROTO_TCP 6 /* tcp */
+#define IPPROTO_PUP 12 /* pup */
+#define IPPROTO_UDP 17 /* user datagram protocol */
+#define IPPROTO_ND 77 /* UNOFFICIAL net disk proto */
+
+#define IPPROTO_RAW 255 /* raw IP packet */
+#define IPPROTO_MAX 256
+
+/*
+ * Port/socket numbers: network standard functions
+ */
+#define IPPORT_ECHO 7
+#define IPPORT_DISCARD 9
+#define IPPORT_SYSTAT 11
+#define IPPORT_DAYTIME 13
+#define IPPORT_NETSTAT 15
+#define IPPORT_FTP 21
+#define IPPORT_TELNET 23
+#define IPPORT_SMTP 25
+#define IPPORT_TIMESERVER 37
+#define IPPORT_NAMESERVER 42
+#define IPPORT_WHOIS 43
+#define IPPORT_MTP 57
+
+/*
+ * Port/socket numbers: host specific functions
+ */
+#define IPPORT_TFTP 69
+#define IPPORT_RJE 77
+#define IPPORT_FINGER 79
+#define IPPORT_TTYLINK 87
+#define IPPORT_SUPDUP 95
+
+/*
+ * UNIX TCP sockets
+ */
+#define IPPORT_EXECSERVER 512
+#define IPPORT_LOGINSERVER 513
+#define IPPORT_CMDSERVER 514
+#define IPPORT_EFSSERVER 520
+
+/*
+ * UNIX UDP sockets
+ */
+#define IPPORT_BIFFUDP 512
+#define IPPORT_WHOSERVER 513
+#define IPPORT_ROUTESERVER 520 /* 520+1 also used */
+
+/*
+ * Ports < IPPORT_RESERVED are reserved for
+ * privileged processes (e.g. root).
+ */
+#define IPPORT_RESERVED 1024
+
+/*
+ * Link numbers
+ */
+#define IMPLINK_IP 155
+#define IMPLINK_LOWEXPER 156
+#define IMPLINK_HIGHEXPER 158
+
+/*
+ * Internet address (old style... should be updated)
+ */
+struct in_addr {
+ union {
+ struct { u_char s_b1,s_b2,s_b3,s_b4; } S_un_b;
+ struct { u_short s_w1,s_w2; } S_un_w;
+ u_long S_addr;
+ } S_un;
+#define s_addr S_un.S_addr /* can be used for most tcp & ip code */
+#define s_host S_un.S_un_b.s_b2 /* host on imp */
+#define s_net S_un.S_un_b.s_b1 /* network */
+#define s_imp S_un.S_un_w.s_w2 /* imp */
+#define s_impno S_un.S_un_b.s_b4 /* imp # */
+#define s_lh S_un.S_un_b.s_b3 /* logical host */
+};
+
+/*
+ * Definitions of bits in internet address integers.
+ */
+#define IN_CLASSA(i) ((((long)(i))&0x80000000)==0)
+#define IN_CLASSA_NET 0xff000000
+#define IN_CLASSA_NSHIFT 24
+#define IN_CLASSA_HOST 0x00ffffff
+
+#define IN_CLASSB(i) ((((long)(i))&0xc0000000)==0x80000000)
+#define IN_CLASSB_NET 0xffff0000
+#define IN_CLASSB_NSHIFT 16
+#define IN_CLASSB_HOST 0x0000ffff
+
+#define IN_CLASSC(i) ((((long)(i))&0xc0000000)==0xc0000000)
+#define IN_CLASSC_NET 0xffffff00
+#define IN_CLASSC_NSHIFT 8
+#define IN_CLASSC_HOST 0x000000ff
+
+#define INADDR_ANY 0x00000000
+
+/*
+ * Socket address, internet style.
+ */
+struct sockaddr_in {
+ short sin_family;
+ u_short sin_port;
+ struct in_addr sin_addr;
+ char sin_zero[8];
+};
+
+#if !defined(vax)
+/*
+ * Macros for number representation conversion.
+ */
+#define ntohl(x) (x)
+#define ntohs(x) (x)
+#define htonl(x) (x)
+#define htons(x) (x)
+#endif
+
+#ifdef KERNEL
+extern struct domain inetdomain;
+extern struct protosw inetsw[];
+#endif
diff --git a/unix/os/net/inetaddr.c b/unix/os/net/inetaddr.c
new file mode 100644
index 00000000..9d96d252
--- /dev/null
+++ b/unix/os/net/inetaddr.c
@@ -0,0 +1,92 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "ctype.h"
+#include "types.h"
+#include "in.h"
+
+/* TCP_INETADDR -- Internet address interpretation routine. Decode a network
+ * address from the host name table. The value returned is in network order.
+ */
+u_long
+tcp_inetaddr (cp)
+register char *cp;
+{
+ register u_long val, base, n;
+ register char c;
+ u_long parts[4], *pp = parts;
+
+again:
+ /* Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, other=decimal.
+ */
+ val = 0; base = 10;
+ if (*cp == '0')
+ base = 8, cp++;
+ if (*cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+
+ while (c = *cp) {
+ if (isdigit(c)) {
+ val = (val * base) + (c - '0');
+ cp++;
+ continue;
+ }
+ if (base == 16 && isxdigit(c)) {
+ val = (val << 4) + (c + 10 - (islower(c) ? 'a' : 'A'));
+ cp++;
+ continue;
+ }
+ break;
+ }
+
+ if (*cp == '.') {
+ /* Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16-bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 4)
+ return (-1);
+ *pp++ = val, cp++;
+ goto again;
+ }
+
+ /* Check for trailing characters.
+ */
+ if (*cp && !isspace(*cp))
+ return (-1);
+ *pp++ = val;
+
+ /* Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts;
+ switch (n) {
+
+ case 1: /* a -- 32 bits */
+ val = parts[0];
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ val = (parts[0] << 24) | (parts[1] & 0xffffff);
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
+ (parts[2] & 0xffff);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ val = (parts[0] << 24) | ((parts[1] & 0xff) << 16) |
+ ((parts[2] & 0xff) << 8) | (parts[3] & 0xff);
+ break;
+
+ default:
+ return (-1);
+ }
+
+ val = htonl(val);
+ return (val);
+}
diff --git a/unix/os/net/kutil.c b/unix/os/net/kutil.c
new file mode 100644
index 00000000..3e7ddb0d
--- /dev/null
+++ b/unix/os/net/kutil.c
@@ -0,0 +1,342 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+
+#define import_kernel
+#define import_knames
+#define import_spp
+#include <iraf.h>
+
+
+/*
+ * KUTIL -- Miscellaneous utilities required by the network interface.
+ * Most of these are either portable (no i/o) or are built upon the kernel
+ * i/o routines.
+ */
+
+/* KU_FOPEN -- Open a text file.
+ */
+ku_fopen (fname, mode)
+char *fname;
+char *mode;
+{
+ PKCHAR osfn[SZ_PATHNAME+1];
+ XINT fmode, chan;
+
+ strcpy ((char *)osfn, fname);
+
+ if (mode[0] == 'r')
+ fmode = READ_ONLY;
+ else
+ return (ERR);
+
+ ZOPNTX (osfn, &fmode, &chan);
+
+ return (chan);
+}
+
+
+/* KU_FCLOSE -- Close a text file.
+ */
+ku_fclose (fd)
+int fd;
+{
+ XINT chan=fd, status;
+
+ ZCLSTX (&chan, &status);
+ return (status);
+}
+
+
+/* KU_FGETS -- Get a newline delimited line from a text file. The semantics of
+ * this procedure are like the unix FGETS.
+ */
+char *
+ku_fgets (obuf, maxch, fd)
+char *obuf;
+int maxch;
+int fd;
+{
+ register XCHAR *ip;
+ register char *op;
+ register int n;
+ XCHAR lbuf[SZ_LINE+1];
+ XINT maxchars, status, chan;
+
+ maxchars = (maxch > SZ_LINE) ? SZ_LINE : maxch;
+ chan = fd;
+
+ ZGETTX (&chan, lbuf, &maxchars, &status);
+ if (status <= 0)
+ return (NULL);
+
+ for (ip=lbuf, op=obuf, n=status; --n >= 0; )
+ *op++ = *ip++;
+ *op++ = EOS;
+
+ return (obuf);
+}
+
+
+/* KU_GPASSWD -- Read a line from the terminal in raw mode (no echo), e.g.,
+ * when reading a password.
+ */
+ku_gpasswd (prompt, passwd, maxch)
+char *prompt; /* user prompt string */
+char *passwd; /* receives password */
+int maxch;
+{
+ XCHAR text[SZ_LINE+1], ch;
+ XINT mode=READ_WRITE, chan, status, nchars;
+ register char *ip;
+ register XCHAR *op;
+ register int n;
+
+ /* Open terminal. */
+ strcpy ((char *)text, TTYNAME);
+ ZOPNTY (text, &mode, &chan);
+ if (chan < 0) {
+ passwd[0] = EOS;
+ return (ERR);
+ }
+
+ /* Write prompt string. */
+ for (ip=prompt, op=text, nchars=0; (*op++ = *ip++) != EOS; )
+ nchars++;
+ ZPUTTY (&chan, text, &nchars, &status);
+ ZFLSTY (&chan, &status);
+
+ /* Read line in raw mode. */
+ nchars = 1;
+ for (n=0; n < maxch; n++) {
+ ZGETTY (&chan, &text, &nchars, &status);
+ ch = text[0];
+ if (status <= 0 || ch == '\n' || ch == '\r')
+ break;
+ passwd[n] = ch;
+ }
+ passwd[n] = EOS;
+
+ /* Echo the newline. */
+ ch = '\n';
+ ZPUTTY (&chan, &ch, &nchars, &status);
+
+ /* Disable raw mode. */
+ nchars = LEN_RAWCMD;
+ for (ip=RAWOFF, op=text, n=LEN_RAWCMD; --n > 0 && (*op++ = *ip++); )
+ ;
+ ZPUTTY (&chan, text, &nchars, &status);
+ ZCLSTY (&chan, &status);
+
+ return (n);
+}
+
+
+/* KU_MKFNAME -- Make an OSFN, given a logical directory name (either "iraf"
+ * or "home"), a subdirectory name, and a filename.
+ */
+ku_mkfname (ldir, subdir, fname, osfn, maxch)
+char *ldir; /* logical directory name */
+char *subdir; /* subdirectory */
+char *fname; /* filename */
+char *osfn; /* receives pathname */
+int maxch;
+{
+ PKCHAR pkname[SZ_PATHNAME+1];
+ PKCHAR temp[SZ_FNAME+1];
+ XINT maxchars=SZ_PATHNAME, nchars;
+
+ if (ku_mapdir (ldir, (char *)pkname, SZ_PATHNAME) == ERR)
+ return (ERR);
+
+ strcpy ((char *)temp, subdir);
+ ku_strupk (pkname, pkname, &maxchars);
+ ku_strupk (temp, temp, &maxchars);
+ ZFSUBD (pkname, &maxchars, temp, &nchars);
+ ku_strpak (pkname, pkname, &maxchars);
+
+ strcat ((char *)pkname, fname);
+ strncpy (osfn, (char *)pkname, maxch);
+ osfn[maxch-1] = EOS;
+
+ return (OK);
+}
+
+
+/* KU_ITOC -- Encode a simple positive integer in a decimal radix, returning
+ * a pointer to the encoded numeric string.
+ */
+char *
+ku_itoc (num)
+int num;
+{
+ register int dig, n;
+ register char *op;
+ static char buf[15];
+
+ op = &buf[15];
+ *--op = '\0';
+
+ for (n=num; dig = n % 10; n /= 10)
+ *--op = dig + '0';
+
+ return (op);
+}
+
+
+/* KU_BCOPY -- Copy a byte array.
+ */
+ku_bcopy (a, b, nbytes)
+char *a; /* input byte array */
+char *b; /* output byte array */
+int nbytes; /* number of bytes to move */
+{
+ register char *ip, *op;
+ register int n = nbytes;
+
+ /* If the two arrays are the same return immediately. If the move is
+ * to the left then copy left to right, else copy right to left.
+ */
+ if (a == b) {
+ return;
+ } else if (b < a) {
+ for (ip=a, op=b; --n >= 0; )
+ *op++ = *ip++;
+ } else {
+ for (ip = &a[n], op = &b[n]; --n >= 0; )
+ *--op = *--ip;
+ }
+}
+
+
+/* KU_SLEEP -- Suspend process execution.
+ */
+ku_sleep (nseconds)
+int nseconds;
+{
+ int mseconds = nseconds*1000;
+
+ ZWMSEC (&mseconds);
+}
+
+
+/* KU_ERROR -- [MACHDEP] Print an error message somewhere where the user can
+ * see it (but do not abort or interrupt execution).
+ */
+ku_error (message)
+char *message;
+{
+ write (2, message, strlen(message));
+ write (2, "\n", 1);
+}
+
+
+/* KU_MAPDIR -- Return the OSFN of the named logical directory, which can
+ * be either "iraf" or "home". The IRAF root directory is either given in
+ * the host system environment and returned by ZGTENV, or is defined as
+ * IRAF in <iraf.h>. The user's login directory "home" is the host
+ * system login directory, not the IRAF login directory. On a UNIX system
+ * the pathname of this directory is given in the UNIX file /etc/passwd.
+ * On other systems, e.g., VMS, the ZGTENV mechanism can be used to define
+ * the user's home directory.
+ */
+ku_mapdir (ldir, osfn, maxch)
+char *ldir; /* logical directory name */
+char *osfn; /* receives filename */
+int maxch;
+{
+ PKCHAR pkname[SZ_FNAME+1];
+ PKCHAR valstr[SZ_PATHNAME+1];
+ XINT maxchars=SZ_PATHNAME, status;
+
+ /* Look in the host environment first.
+ */
+ strcpy ((char *)pkname, ldir);
+ ZGTENV (pkname, valstr, &maxchars, &status);
+
+ if (status > 0) {
+ strncpy (osfn, (char *)valstr, maxch);
+ osfn[maxch-1] = EOS;
+ return (OK);
+ } else if (strncmp (ldir, "iraf", 4) == 0) {
+ strncpy (osfn, IRAF, maxch);
+ osfn[maxch-1] = EOS;
+ return (OK);
+ } else if (strncmp (ldir, "home", 4) != 0) {
+ osfn[0] = EOS;
+ return (ERR);
+ }
+
+ /* If we get here the ldir is "home" and no definition was found in the
+ * host environment. Determine host login directory by some system
+ * dependent means. [MACHDEP].
+ */
+ strcpy ((char *)pkname, "LOGNAME");
+ ZGTENV (pkname, valstr, &maxchars, &status);
+ if (status <= 0) {
+ osfn[0] = EOS;
+ return (ERR);
+ } else {
+ strcpy (osfn, ":udd:");
+ strcat (osfn, (char *)valstr);
+ strcat (osfn, ":");
+ return (OK);
+ }
+}
+
+
+/* STRPAK -- Pack an SPP character string into a C string, i.e., a sequence
+ * of characters stored one per byte, delimited by EOS='\0'. The operation
+ * may be performed in place. This version assumes that the host character
+ * set is ASCII and hence no lookup table reference to map character sets is
+ * needed. If this is not the case, code must be added to convert to the host
+ * character set.
+ *
+ * N.B.: If sizeof(XCHAR)=1, XEOS=EOS, and the host character set is ASCII,
+ * and the operation is being performed in place, then this procedure should
+ * do nothing.
+ */
+ku_strpak (instr, outstr, maxch)
+XCHAR *instr;
+PKCHAR *outstr;
+XINT *maxch;
+{
+ register XCHAR *ip = instr;
+ register char *op = (char *)outstr;
+ register int n = *maxch;
+
+ while ((*op++ = *ip++) != XEOS && --n >= 0)
+ ;
+ *--op = EOS;
+}
+
+/* STRUPK -- Unpack a kernel (C style) string into an SPP string. The unpacking * operation can be performed in place. A kernel string consists of a sequence
+ * of host characters stored one character per byte, delimited by EOS='\0'.
+ * We assume here that the host character set is ASCII. If this is not the
+ * case code must be added to convert from the host character set to ASCII in
+ * the unpacked string.
+ *
+ * N.B.: If sizeof(XCHAR)=1, XEOS=EOS, and the host character set is ASCII,
+ * and the operation is being performed in place, then this procedure should
+ * do nothing.
+ */
+ku_strupk (instr, outstr, maxch)
+PKCHAR *instr;
+XCHAR *outstr;
+XINT *maxch;
+{
+ register char *ip = (char *)instr;
+ register XCHAR *op = outstr;
+ register int n;
+
+ /* Is is necessary to determine the length of the string in order to
+ * be able to unpack the string in place, i.e., from right to left.
+ */
+ n = strlen (ip);
+ n = (n < *maxch) ? n : *maxch;
+ op[n] = XEOS;
+
+ while (--n >= 0)
+ op[n] = ip[n];
+}
diff --git a/unix/os/net/listen.c b/unix/os/net/listen.c
new file mode 100644
index 00000000..02f75651
--- /dev/null
+++ b/unix/os/net/listen.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+
+extern int errno;
+extern int tcperrno;
+
+/* TCP_LISTEN -- Listen for connections on a socket. Returns immediately,
+ * i.e., listen does not block the calling process.
+ */
+tcp_listen (s, backlog)
+u_sock s; /* the socket */
+int backlog; /* max queued connects */
+{
+ int status;
+
+ /* MACHDEP */
+ status = listen (s, backlog);
+ tcperrno = errno;
+ return (status);
+}
diff --git a/unix/os/net/mkpkg b/unix/os/net/mkpkg
new file mode 100644
index 00000000..a534884b
--- /dev/null
+++ b/unix/os/net/mkpkg
@@ -0,0 +1,25 @@
+# Make the ZFIOKS-REXEC-TCP/IP network interface package.
+
+$set XFLAGS = "-c $(HSI_XF)"
+
+libos.a:
+ accept.c types.h
+ connect.c types.h
+ ghostbynm.c netdb.h
+ ghostent.c types.h netdb.h socket.h
+ gsocknm.c types.h
+ hostdb.c
+ htonl.c
+ htons.c
+ inetaddr.c ctype.h in.h types.h
+ kutil.c
+ listen.c types.h
+ ntohl.c
+ ntohs.c
+ rexec.c in.h netdb.h socket.h types.h
+ socket.c types.h
+ tcpclose.c types.h
+ tcpread.c types.h
+ tcpwrite.c types.h
+ zfioks.c ctype.h types.h in.h
+ ;
diff --git a/unix/os/net/netdb.h b/unix/os/net/netdb.h
new file mode 100644
index 00000000..cddd2305
--- /dev/null
+++ b/unix/os/net/netdb.h
@@ -0,0 +1,44 @@
+/* %M% %I% %E% */
+/*
+ * Structures returned by network
+ * data base library. All addresses
+ * are supplied in host order, and
+ * returned in network order (suitable
+ * for use in system calls).
+ */
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char *h_addr; /* address */
+};
+
+/*
+ * Assumption here is that a network number
+ * fits in 32 bits -- probably a poor one.
+ */
+struct netent {
+ char *n_name; /* official name of net */
+ char **n_aliases; /* alias list */
+ int n_addrtype; /* net address type */
+ int n_net; /* network # */
+};
+
+struct servent {
+ char *s_name; /* official service name */
+ char **s_aliases; /* alias list */
+ int s_port; /* port # */
+ char *s_proto; /* protocol to use */
+};
+
+struct protoent {
+ char *p_name; /* official protocol name */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol # */
+};
+
+struct hostent *gethostbyname(), *gethostbyaddr(), *gethostent();
+struct netent *getnetbyname(), *getnetbyaddr(), *getnetent();
+struct servent *getservbyname(), *getservbyport(), *getservent();
+struct protoent *getprotobyname(), *getprotobynumber(), *getprotoent();
diff --git a/unix/os/net/ntohl.c b/unix/os/net/ntohl.c
new file mode 100644
index 00000000..34d6b07a
--- /dev/null
+++ b/unix/os/net/ntohl.c
@@ -0,0 +1,22 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+/* NTOHL -- [MACHDEP] Convert a long integer in net format to host format.
+ */
+ntohl (lword)
+long lword;
+{
+ register char *ip, *op;
+ static long hostw, netw;
+
+ netw = lword;
+ ip = (char *)&netw;
+ op = (char *)&hostw + 4;
+
+ *--op = *ip++;
+ *--op = *ip++;
+ *--op = *ip++;
+ *--op = *ip++;
+
+ return (hostw);
+}
diff --git a/unix/os/net/ntohs.c b/unix/os/net/ntohs.c
new file mode 100644
index 00000000..02a956a6
--- /dev/null
+++ b/unix/os/net/ntohs.c
@@ -0,0 +1,16 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+/* NTOHS -- [MACHDEP] Convert a short integer in net format to host format.
+ */
+ntohs (word)
+short word;
+{
+ register char *wp;
+ static short w;
+
+ w = word;
+ wp = (char *)&w;
+
+ return ((wp[0] << 8) | wp[1]);
+}
diff --git a/unix/os/net/rexec.c b/unix/os/net/rexec.c
new file mode 100644
index 00000000..4f851fb9
--- /dev/null
+++ b/unix/os/net/rexec.c
@@ -0,0 +1,160 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+#include "socket.h"
+#include "in.h"
+#include "netdb.h"
+
+/* TCP_REXEC -- Execute a command on a remote node via the network. This is
+ * an implementation of the Berkeley UNIX procedure of the same name for a
+ * machine independent TCP network interface. Unlike the UNIX rexec,
+ * however, we require that the user login name and password be given as
+ * input arguments, in addition to the host name and port number and the
+ * command to be executed.
+ *
+ * REXEC assumes that it is talking to an REXECD server on the remote node.
+ * The TCP EXEC port on the remote node spawns the REXECD server which reads and
+ * authenticates the user login and password, sets up the error socket if so
+ * indicated, changes the current directory to the user's home directory, and
+ * then executes the command. The command syntax is determined by the shell
+ * REXECD spawns to execute the command, and is implementation dependent.
+ * Currently the REXECD daemons are either UNIX hosted or UNIX emulated, hence
+ * the command syntax is the UNIX shell (Bourne shell usually). The command
+ * executes with its standard input and output (and error output if fd2p=0)
+ * connected to the socket returned by REXEC.
+ *
+ * Note that the shell spawned by the REXEC daemon may be used to spawn a user
+ * specified server process using a shell command, e.g. "run server.e arg arg".
+ * In this case the daemon is used to login and set the current directory and
+ * pass args to the user server, at the expense of one additional process spawn
+ * for the shell.
+ */
+tcp_rexec (ahost, rport, name, pass, cmd, fd2p)
+char **ahost; /* alias of server node */
+int rport; /* IP port number (for EXEC) */
+char *name, *pass; /* user login and password */
+char *cmd; /* command to be executed */
+int *fd2p; /* error channel */
+{
+ struct hostent *tcp_gethostbyname();
+ struct sockaddr_in sin, sin2, from;
+ struct hostent *hp;
+ int timo = 1;
+ u_sock s, s3;
+ char c;
+ short port;
+eprintf("rexec %s %s %s %s\n", *ahost, name, pass, cmd);
+
+ /* Read host name table for the local network to get the internet
+ * address of the named host.
+ */
+ hp = tcp_gethostbyname (*ahost);
+ if (hp == 0) {
+ ku_error ("unknown network host");
+ return (-1);
+ }
+
+ /* Set up a full duplex TCP socket to the TCP/EXEC server process
+ * on the remote node.
+ */
+retry:
+ s = tcp_socket (AF_INET, SOCK_STREAM, 0);
+ if (s < 0) {
+ ku_error ("rexec: cannot make socket");
+ return (-1);
+ }
+
+ sin.sin_family = hp->h_addrtype;
+ sin.sin_port = rport;
+ ku_bcopy (hp->h_addr, (caddr_t)&sin.sin_addr, hp->h_length);
+
+ if (tcp_connect (s, &sin, sizeof(sin)) < 0) {
+ if (timo <= 16) {
+ tcp_close (s);
+ ku_sleep (timo);
+ timo *= 2;
+ goto retry;
+ }
+ ku_error ("rexec: connect failure");
+ return (-1);
+ }
+
+ /* If no output error channel variable was given instruct the REXECD
+ * server to return error output on the data socket, else open a second
+ * socket to be used for error communications and signals.
+ */
+ if (fd2p == 0) {
+ tcp_write (s, "", 1);
+ port = 0;
+
+ } else {
+ char *num, *ku_itoc();
+ int sin2len, len;
+ u_sock s2;
+
+ s2 = tcp_socket (AF_INET, SOCK_STREAM, 0);
+ if (s2 < 0) {
+ tcp_close (s);
+ return (-1);
+ }
+
+ tcp_listen (s2, 1);
+
+ sin2len = sizeof (sin2);
+ if (tcp_gsockname (s2, (char *)&sin2, &sin2len) < 0 ||
+ sin2len != sizeof (sin2)) {
+
+ ku_error ("rexec: getsockname failed");
+ tcp_close (s2);
+ goto bad;
+ }
+
+ port = htons ((u_short)sin2.sin_port);
+ num = ku_itoc (port);
+ tcp_write (s, num, strlen(num)+1);
+ len = sizeof (from);
+
+ s3 = tcp_accept (s2, &from, &len, 0);
+
+ tcp_close (s2);
+ if (s3 < 0) {
+ ku_error ("rexec: accept failure");
+ port = 0;
+ goto bad;
+ }
+
+ *fd2p = s3;
+ }
+
+ tcp_write (s, name, strlen (name) + 1);
+ tcp_write (s, pass, strlen (pass) + 1);
+ tcp_write (s, cmd, strlen (cmd) + 1);
+
+ if (tcp_read (s, &c, 1) != 1) {
+ ku_error ("rexec: cannot read server");
+ goto bad;
+ }
+
+ /* Read error message from server process.
+ */
+ if (c != 0) {
+ char lbuf[80];
+ char *op;
+
+ for (op=lbuf; (tcp_read (s, op, 1) == 1); op++)
+ if (*op == '\n')
+ break;
+ *op = '\0';
+ ku_error (lbuf);
+ goto bad;
+ }
+
+ return (s);
+bad:
+ if (port)
+ tcp_close (*fd2p);
+ tcp_close (s);
+
+ return (-1);
+}
diff --git a/unix/os/net/socket.c b/unix/os/net/socket.c
new file mode 100644
index 00000000..c5872fee
--- /dev/null
+++ b/unix/os/net/socket.c
@@ -0,0 +1,25 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+
+extern int errno;
+extern int tcperrno;
+
+/* TCP_SOCKET -- Create an endpoint for communications (a socket) and bind the
+ * socket to an i/o descriptor, returning the descriptor as the function value.
+ */
+u_sock
+tcp_socket (af, type, protocol)
+int af; /* address format, e.g, AF_INET */
+int type; /* socket type, e.g., SOCK_STREAM */
+int protocol; /* communications protocol, if used */
+{
+ u_sock s;
+
+ /* MACHDEP */
+eprintf ("socket\n");
+ s = socket (af, type, protocol);
+ tcperrno = errno;
+ return (s);
+}
diff --git a/unix/os/net/socket.h b/unix/os/net/socket.h
new file mode 100644
index 00000000..ed399681
--- /dev/null
+++ b/unix/os/net/socket.h
@@ -0,0 +1,109 @@
+/* socket.h 6.1 83/07/29 */
+
+/*
+ * Definitions related to sockets: types, address families, options.
+ */
+
+/*
+ * Types
+ */
+#define SOCK_STREAM 1 /* stream socket */
+#define SOCK_DGRAM 2 /* datagram socket */
+#define SOCK_RAW 3 /* raw-protocol interface */
+#define SOCK_RDM 4 /* reliably-delivered message */
+#define SOCK_SEQPACKET 5 /* sequenced packet stream */
+
+/*
+ * Option flags per-socket.
+ */
+#define SO_DEBUG 0x01 /* turn on debugging info recording */
+#define SO_ACCEPTCONN 0x02 /* socket has had listen() */
+#define SO_REUSEADDR 0x04 /* allow local address reuse */
+#define SO_KEEPALIVE 0x08 /* keep connections alive */
+#define SO_DONTROUTE 0x10 /* just use interface addresses */
+ /* 0x20 was SO_NEWFDONCONN */
+#define SO_USELOOPBACK 0x40 /* bypass hardware when possible */
+#define SO_LINGER 0x80 /* linger on close if data present */
+#define SO_DONTLINGER (~SO_LINGER) /* ~SO_LINGER */
+
+/*
+ * Address families.
+ */
+#define AF_UNSPEC 0 /* unspecified */
+#define AF_UNIX 1 /* local to host (pipes, portals) */
+#define AF_INET 2 /* internetwork: UDP, TCP, etc. */
+#define AF_IMPLINK 3 /* arpanet imp addresses */
+#define AF_PUP 4 /* pup protocols: e.g. BSP */
+#define AF_CHAOS 5 /* mit CHAOS protocols */
+#define AF_NS 6 /* XEROX NS protocols */
+#define AF_NBS 7 /* nbs protocols */
+#define AF_ECMA 8 /* european computer manufacturers */
+#define AF_DATAKIT 9 /* datakit protocols */
+#define AF_CCITT 10 /* CCITT protocols, X.25 etc */
+#define AF_SNA 11 /* IBM SNA */
+
+#define AF_MAX 12
+
+/*
+ * Structure used by kernel to store most
+ * addresses.
+ */
+struct sockaddr {
+ u_short sa_family; /* address family */
+ char sa_data[14]; /* up to 14 bytes of direct address */
+};
+
+/*
+ * Structure used by kernel to pass protocol
+ * information in raw sockets.
+ */
+struct sockproto {
+ u_short sp_family; /* address family */
+ u_short sp_protocol; /* protocol */
+};
+
+/*
+ * Protocol families, same as address families for now.
+ */
+#define PF_UNSPEC AF_UNSPEC
+#define PF_UNIX AF_UNIX
+#define PF_INET AF_INET
+#define PF_IMPLINK AF_IMPLINK
+#define PF_PUP AF_PUP
+#define PF_CHAOS AF_CHAOS
+#define PF_NS AF_NS
+#define PF_NBS AF_NBS
+#define PF_ECMA AF_ECMA
+#define PF_DATAKIT AF_DATAKIT
+#define PF_CCITT AF_CCITT
+#define PF_SNA AF_SNA
+
+#define PF_MAX 12
+
+/*
+ * Level number for (get/set)sockopt() to apply to socket itself.
+ */
+#define SOL_SOCKET 0xffff /* options for socket level */
+
+/*
+ * Maximum queue length specifiable by listen.
+ */
+#define SOMAXCONN 5
+
+/*
+ * Message header for recvmsg and sendmsg calls.
+ */
+struct msghdr {
+ caddr_t msg_name; /* optional address */
+ int msg_namelen; /* size of address */
+ struct iovec *msg_iov; /* scatter/gather array */
+ int msg_iovlen; /* # elements in msg_iov */
+ caddr_t msg_accrights; /* access rights sent/received */
+ int msg_accrightslen;
+};
+
+#define MSG_OOB 0x1 /* process out-of-band data */
+#define MSG_PEEK 0x2 /* peek at incoming message */
+#define MSG_DONTROUTE 0x4 /* send without using routing tables */
+
+#define MSG_MAXIOVLEN 16
diff --git a/unix/os/net/tcpclose.c b/unix/os/net/tcpclose.c
new file mode 100644
index 00000000..0da1cc73
--- /dev/null
+++ b/unix/os/net/tcpclose.c
@@ -0,0 +1,16 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+
+extern int errno;
+extern int tcperrno;
+
+/* TCP_CLOSE -- Close a socket.
+ */
+tcp_close (s)
+u_sock s; /* the socket */
+{
+ /* MACHDEP */
+ return (close (s));
+}
diff --git a/unix/os/net/tcpread.c b/unix/os/net/tcpread.c
new file mode 100644
index 00000000..3a7162d3
--- /dev/null
+++ b/unix/os/net/tcpread.c
@@ -0,0 +1,26 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+
+extern int errno;
+extern int tcperrno;
+
+/* TCP_READ -- Read from a socket.
+ */
+tcp_read (s, buf, maxbytes)
+u_sock s; /* input socket */
+char *buf; /* output buffer */
+int maxbytes; /* max bytes to read */
+{
+ int nbytes;
+
+ /* MACHDEP */
+eprintf ("read %d bytes\n", maxbytes);
+
+ nbytes = read (s, buf, maxbytes);
+eprintf ("\t%d bytes read\n", nbytes);
+
+ tcperrno = errno;
+ return (nbytes);
+}
diff --git a/unix/os/net/tcpwrite.c b/unix/os/net/tcpwrite.c
new file mode 100644
index 00000000..c0a946d3
--- /dev/null
+++ b/unix/os/net/tcpwrite.c
@@ -0,0 +1,23 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include "types.h"
+
+extern int errno;
+extern int tcperrno;
+
+/* TCP_WRITE -- Write to a socket.
+ */
+tcp_write (s, buf, nbytes)
+u_sock s; /* output socket */
+char *buf; /* input buffer */
+int nbytes; /* num bytes to write */
+{
+ /* MACHDEP */
+eprintf ("write %d bytes\n", nbytes);
+ nbytes = write (s, buf, nbytes);
+eprintf ("%d bytes written\n", nbytes);
+
+ tcperrno = errno;
+ return (nbytes);
+}
diff --git a/unix/os/net/types.h b/unix/os/net/types.h
new file mode 100644
index 00000000..3110398c
--- /dev/null
+++ b/unix/os/net/types.h
@@ -0,0 +1,39 @@
+/* types.h 6.1 83/07/29 */
+
+/*
+ * Basic system types and major/minor device constructing/busting macros.
+ */
+
+/* major part of a device */
+#define major(x) ((int)(((unsigned)(x)>>8)&0377))
+
+/* minor part of a device */
+#define minor(x) ((int)((x)&0377))
+
+/* make a device number */
+#define makedev(x,y) ((dev_t)(((x)<<8) | (y)))
+
+typedef unsigned char u_char;
+typedef unsigned short u_short;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+typedef unsigned short ushort; /* sys III compat */
+typedef unsigned int u_sock; /* TCP/IP */
+
+#ifdef vax
+typedef struct _physadr { int r[1]; } *physadr;
+typedef struct label_t {
+ int val[14];
+} label_t;
+#endif
+typedef struct _quad { long val[2]; } quad;
+typedef long daddr_t;
+typedef char * caddr_t;
+typedef u_long ino_t;
+typedef long swblk_t;
+typedef int size_t;
+typedef int time_t;
+typedef short dev_t;
+typedef int off_t;
+
+typedef struct fd_set { int fds_bits[1]; } fd_set;
diff --git a/unix/os/net/zfioks.c b/unix/os/net/zfioks.c
new file mode 100644
index 00000000..1db9cc1e
--- /dev/null
+++ b/unix/os/net/zfioks.c
@@ -0,0 +1,441 @@
+/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+ */
+
+#include <stdio.h>
+#include <ctype.h>
+#include <signal.h>
+#include <setjmp.h>
+
+#include "types.h"
+#include "in.h"
+
+#define import_kernel
+#define import_knames
+#define import_zfstat
+#define import_spp
+#include <iraf.h>
+
+/* ZFIOKS -- File i/o to a remote kernel server. This driver is the network
+ * interface for the kernel interface package (sys$ki). The KS driver is
+ * normally called directly by the KI routines, but is patterned after the
+ * regular FIO drivers hence may be connected to FIO to provide a network
+ * interface to the high level code.
+ *
+ * zopcks open kernel server on remote node
+ * zclcks close kernel server
+ * zardks read from the remote kernel server
+ * zawrks write to the remote kernel server
+ * zawtks wait for i/o
+ * zsttks get channel/device status
+ *
+ * The network interface used is an emulation of the Berkeley UNIX function
+ * REXEC on top of a standard TCP/IP interface.
+ */
+
+#define SZ_NAME 32 /* max size node, etc. name */
+#define SZ_CMD 128 /* max size rexec sh command */
+#define FNNODE_CHAR '!' /* node name delimiter */
+#define HOSTLOGIN "hostlogin" /* user host login file */
+#define IRAFHOSTS ".irafhosts" /* default host login file (dev$) */
+#define USER "<user>" /* symbol for user's login name */
+
+int ks_ionbytes[MAXOFILES]; /* nbytes read|written on channel */
+static jmp_buf jmpbuf;
+static int recursion = 0;
+
+
+/* ZOPNKS -- Open a connected subprocess on a remote node. Parse the "server"
+ * argument to obtain the node name and the command to be issued to connect the
+ * remote process. Call REXEC to exec the remote process and set up a socket
+ * to be used for CLIN, CLOUT to the remote process. The "server" string is
+ * implementation dependent and normally comes from the file "dev$hosts" on each
+ * node. This file is read by the high level code before we are called.
+ */
+ZOPNKS (server, mode, chan)
+PKCHAR *server; /* node name ! command */
+XINT *mode; /* access mode (not used) */
+XINT *chan; /* receives channel code (socket) */
+{
+ register char *ip;
+ char username[SZ_NAME+1], password[SZ_NAME+1];
+ char *host, *cmd;
+ int ipport;
+
+ /* Extract the host name and remote process spawn command from the
+ * server string, format "host!cmd", e.g., "2!/iraf/lib/irafks.e".
+ * If the server is "host", we are being called from a server process
+ * to set up communications with the host process. The UNIX rexec
+ * connects the host to the process standard input and output, hence
+ * if the server is "host" the channels are already active.
+ */
+ if (strcmp ((char *)server, "host") == 0) {
+ *chan = 0;
+ return;
+ }
+
+ host = (char *)server;
+ cmd = NULL;
+
+ for (ip = (char *)server; *ip != EOS; ip++)
+ if (*ip == FNNODE_CHAR) {
+ *ip = EOS;
+ cmd = ip + 1;
+ break;
+ }
+ if (cmd == NULL) {
+ *chan = ERR;
+ return;
+ }
+
+ /* Get login name and password and connect to the kernel server
+ * process. TCP_REXEC is a portable version of the Berkeley UNIX
+ * REXEC facility (see ./net).
+ */
+ if (ks_getlogin (host, username, password) == ERR)
+ *chan = ERR;
+ else {
+ ipport = htons (IPPORT_EXECSERVER);
+ *chan = tcp_rexec (&host, ipport, username, password, cmd, 0);
+ }
+
+ if (*chan > 0)
+ ks_ionbytes[*chan] = 0;
+}
+
+
+/* KS_GETLOGIN -- Get the user's login name and password, required for
+ * authentication on the remote machine. We could get these from the unix
+ * password file on the local machine, but there is no guarantee that the
+ * login name and password would be the same on a remote node as on the
+ * local machine. Instead we look in the user's unix login directory for
+ * the file ".irafhosts". If this file cannot be opened or if it does not
+ * contain an entry for the named node we use a default public login. The
+ * public login provides sufficient priviledge for most operations but will
+ * not provide write access to the user's files on the remote node.
+ */
+ks_getlogin (node, username, password)
+char *node; /* node we wish a login for */
+char *username; /* receives the login name */
+char *password; /* receives the login password */
+{
+ char fname[SZ_FNAME+1];
+ char uname[SZ_FNAME+1];
+
+ /* Get the user login name on the local node, used as the default
+ * login for remote nodes. [MACHDEP - edit for local system]
+ */
+ strcpy (uname, "USER");
+
+ /* Try to open the .irafhosts file in the user's login directory.
+ */
+ if (ku_mkfname ("home", "", IRAFHOSTS, fname, SZ_FNAME) != ERR)
+ if (ks_scanlogin (fname, node, uname, username, password) == OK)
+ return (OK);
+
+ /* Scan the dev$hostlogin file and return a default public login
+ * on the remote node.
+ */
+ if (ku_mkfname ("iraf", "dev", HOSTLOGIN, fname, SZ_FNAME) != ERR)
+ return (ks_scanlogin (fname, node, uname, username, password));
+
+ return (ERR);
+}
+
+
+/* KS_SCANLOGIN -- Open and scan a host login file, returning the login
+ * name and password to be used on the named node. The format of the table
+ * is a series of lines of the form
+ *
+ * alias1 alias2 ... aliasN : loginname password
+ *
+ * If the same login name and password are used on several nodes, a single
+ * entry may be given for all. If the alias "*" is encountered scanning stops
+ * and the next login name and password are used. The table file should of
+ * course be protected from reading except by the owner. If even this is
+ * considered too dangerous, the password "?" may be given in the table and a
+ * runtime query will result - this will fail if one is no longer logged in.
+ */
+ks_scanlogin (fname, node, uname, username, password)
+char *fname; /* table file */
+char *node; /* node name */
+char *uname; /* user login on local node */
+char *username; /* receives user login name */
+char *password; /* receives user password */
+{
+ char *ip;
+ char lbuf[SZ_LINE+1];
+ char wbuf[SZ_NAME+1];
+ int fp;
+ int foundit;
+ char *ku_fgets();
+
+ foundit = 0;
+ if ((fp = ku_fopen (fname, "r")) == ERR)
+ return (ERR);
+
+ /* Scan file for line containing node name.
+ */
+ while (!foundit && ku_fgets (lbuf, SZ_LINE, fp) != NULL) {
+ /* Skip blank lines and comment lines */
+ for (ip=lbuf; *ip == ' ' || *ip == '\t'; ip++)
+ ;
+ if (*ip == '#' || *ip == EOS)
+ continue;
+
+ /* Scan list of aliases */
+ while (ks_getword (&ip, wbuf) > 0) {
+ if (strcmp (wbuf, ":") == 0) {
+ break;
+ } else if (strcmp(wbuf,"*")==0 || strcmp(wbuf,node)==0) {
+ foundit++;
+ break;
+ }
+ }
+ }
+
+ ku_fclose (fp);
+ if (!foundit)
+ return (ERR);
+
+ /* Skip to end of alias list. */
+ while (ks_getword (&ip, wbuf) > 0) {
+ if (strcmp (wbuf, ":") == 0) {
+ /* Return login name and password.
+ */
+
+ /* If the login name is given as the USER string, use the
+ * login name on the local node. If the login name is given
+ * as "?", query the user for the actual login name.
+ */
+ if (ks_getword (&ip, username) <= 0)
+ return (ERR);
+ if (strcmp (username, USER) == 0)
+ strcpy (username, uname);
+ else if (strcmp (username, "?") == 0) {
+ char prompt[80];
+
+ sprintf (prompt, "Login name (%s@%s): ", username, node);
+ if (ku_gpasswd (prompt, username, SZ_NAME) == ERR)
+ return (ERR);
+ }
+
+ /* If the password is given as "?", query the user for
+ * the actual password.
+ */
+ if (ks_getword (&ip, password) <= 0)
+ return (ERR);
+ if (strcmp (password, "?") == 0) {
+ char prompt[80];
+
+ sprintf (prompt, "Password (%s@%s): ", username, node);
+ if (ku_gpasswd (prompt, password, SZ_NAME) == ERR)
+ return (ERR);
+ }
+
+ return (OK); /* SUCCESS */
+ }
+ }
+
+ return (ERR);
+}
+
+
+/* KS_GETWORD -- Get the next whitespace or : delimited word from the
+ * input string.
+ */
+ks_getword (ip, obuf)
+char **ip; /* pointer into input buffer */
+char *obuf; /* receives name */
+{
+ register char *cp, *op;
+ register int n;
+
+ for (cp = *ip; isspace(*cp); cp++)
+ ;
+
+ op = obuf;
+ n = 0;
+
+ if (*cp == ':' || *cp == '*' || *cp == '?') {
+ *op++ = *cp++;
+ n++;
+ } else {
+ while (*cp && !isspace(*cp) && !(*cp==':' || *cp=='*' || *cp=='?'))
+ if (n++ >= SZ_NAME)
+ return (ERR);
+ else
+ *op++ = *cp++;
+ }
+
+ *op = EOS;
+ *ip = cp;
+
+ return (n);
+}
+
+
+/* ZCLSKS -- Close a kernel server connection.
+ */
+ZCLSKS (chan, status)
+XINT *chan; /* socket to kernel server */
+XINT *status; /* receives close status */
+{
+ *status = tcp_close (*chan);
+}
+
+
+/* ZARDKS -- Read from the kernel server channel. No attempt is made to
+ * impose a record structure upon the channel, as is the case with IPC.
+ * In UNIX the channel is stream oriented and it is up to the caller to
+ * unblock records from the input stream. Data blocks are assumed to be
+ * preceded by headers telling how much data to read, hence we read from
+ * the channel until the specified number of bytes have been read or ERR
+ * or EOF is seen on the stream.
+ */
+ZARDKS (chan, buf, totbytes, loffset)
+XINT *chan; /* kernel server channel (socket) */
+XCHAR *buf; /* output buffer */
+XINT *totbytes; /* total number of bytes to read */
+XLONG *loffset; /* not used */
+{
+ register char *op;
+ register int fd, nbytes;
+ int (*sigint)(), (*sigterm)();
+ int status;
+ extern pr_onsig();
+
+ fd = *chan;
+ op = (char *)buf;
+ ks_ionbytes[fd] = nbytes = *totbytes;
+
+ /* Now read exactly nbytes of data from channel into user buffer.
+ * Return actual byte count if EOF is seen. If ERR is seen return
+ * ERR. If necessary multiple read requests are issued to read the
+ * entire record. Reads are interruptable but the interrupt is caught
+ * and returned as a read error on the server channel.
+ */
+ sigint = signal (SIGINT, pr_onsig);
+ sigterm = signal (SIGTERM, pr_onsig);
+
+ while (nbytes > 0) {
+ if (setjmp (jmpbuf) == 0)
+ status = tcp_read (fd, op, nbytes);
+ else
+ status = ERR;
+
+ switch (status) {
+ case 0:
+ ks_ionbytes[fd] -= nbytes;
+ signal (SIGINT, sigint);
+ signal (SIGTERM, sigterm);
+ return;
+ case ERR:
+ ks_ionbytes[fd] = ERR;
+ signal (SIGINT, sigint);
+ signal (SIGTERM, sigterm);
+ return;
+ default:
+ nbytes -= status;
+ op += status;
+ break;
+ }
+ }
+
+ signal (SIGINT, sigint);
+ signal (SIGTERM, sigterm);
+}
+
+
+/* ZAWRKS -- Write to a kernel server channel.
+ */
+ZAWRKS (chan, buf, totbytes, loffset)
+XINT *chan; /* kernel server channel (socket) */
+XCHAR *buf; /* output buffer */
+XINT *totbytes; /* number of bytes to write */
+XLONG *loffset; /* not used */
+{
+ register int fd, ofd, nbytes;
+ int (*sigint)(), (*sigterm)(), (*sigpipe)();
+ extern pr_onsig();
+
+ /* If chan=0 (the process standard input) then we really want to
+ * write to channel 1, the standard output.
+ */
+ if ((ofd = fd = *chan) == 0)
+ ofd = 1;
+
+ ks_ionbytes[fd] = nbytes = *totbytes;
+
+ /* Write exactly nbytes of data to the channel from user buffer to
+ * the channel. Block interrupt during the write to avoid corrupting
+ * the data stream protocol if the user interrupts the client task.
+ * Trap SIGPIPE and return it as a write error on the channel instead.
+ * Likewise, turn an interrupt into a write error on the channel.
+ */
+ sigint = signal (SIGINT, pr_onsig);
+ sigterm = signal (SIGTERM, pr_onsig);
+ sigpipe = signal (SIGPIPE, pr_onsig);
+ recursion = 0;
+
+ if (setjmp (jmpbuf) == 0)
+ ks_ionbytes[fd] = tcp_write (ofd, (char *)buf, nbytes);
+ else
+ ks_ionbytes[fd] = ERR;
+
+ signal (SIGINT, sigint);
+ signal (SIGTERM, sigterm);
+ signal (SIGPIPE, sigpipe);
+}
+
+
+/* PR_ONSIG -- Catch a signal and make it look like a write error on the
+ * server i/o channel.
+ */
+pr_onsig (sig, code, scp)
+int sig; /* signal which was trapped */
+int code; /* subsignal code (vax) */
+struct sigcontext *scp; /* not used */
+{
+ if (sig == SIGPIPE && recursion++ == 0)
+ ku_error ("kernel server process has died");
+
+ longjmp (jmpbuf, sig);
+}
+
+
+/* ZAWTKS -- Wait for i/o to a KS channel. Since UNIX i/o is not asynchronous
+ * we do not really wait, rather we return the status value (byte count) from
+ * the last read or write to the channel.
+ */
+ZAWTKS (chan, status)
+XINT *chan;
+XINT *status;
+{
+ if ((*status = ks_ionbytes[*chan]) == ERR)
+ *status = XERR;
+}
+
+
+/* ZSTTKS -- Get binary file status for an KS channel. A KS channel is a
+ * streaming binary file.
+ */
+ZSTTKS (chan, param, lvalue)
+XINT *chan; /* not used; all KS channels have same status */
+XINT *param;
+XLONG *lvalue;
+{
+ switch (*param) {
+ case FSTT_BLKSIZE:
+ case FSTT_FILSIZE:
+ *lvalue = 0;
+ break;
+ case FSTT_OPTBUFSIZE:
+ *lvalue = KS_OPTBUFSIZE;
+ break;
+ case FSTT_MAXBUFSIZE:
+ *lvalue = KS_MAXBUFSIZE;
+ break;
+ default:
+ *lvalue = XERR;
+ }
+}
diff --git a/unix/os/net/zzdebug.x b/unix/os/net/zzdebug.x
new file mode 100644
index 00000000..6d22d29d
--- /dev/null
+++ b/unix/os/net/zzdebug.x
@@ -0,0 +1,92 @@
+# Copyright(c) 1986 Association of Universities for Research in Astronomy Inc.
+
+task rexec = t_rexec,
+ rtype = t_rtype,
+ rread = t_rread
+
+define SZ_BUF 4096
+
+
+# REXEC -- Execute a command on a remote node and print the resultant output on
+# the standard output. Used to test the kernel server driver.
+
+procedure t_rexec()
+
+char server[SZ_LINE]
+char buf[SZ_BUF]
+int chan, nbytes, status
+
+begin
+ call clgstr ("server", server, SZ_LINE)
+ call strpak (server, server, SZ_LINE)
+
+ call zopnks (server, READ_WRITE, chan)
+ if (chan == ERR)
+ call error (1, "cannot connect to remote server process")
+
+ repeat {
+ call zardks (chan, buf, SZ_BUF, 0)
+ call zawtks (chan, nbytes)
+
+ if (nbytes > 0) {
+ call chrupk (buf, 1, buf, 1, nbytes)
+ call write (STDOUT, buf, nbytes)
+ call flush (STDOUT)
+ }
+ } until (nbytes <= 0)
+
+ call zclsks (chan, status)
+ if (status == ERR)
+ call error (1, "error disconnecting server process")
+end
+
+
+# RTYPE -- Type a text file possibly resident on a remote node.
+
+procedure t_rtype()
+
+char fname[SZ_FNAME]
+char lbuf[SZ_LINE]
+int fd
+int open(), getline()
+
+begin
+ call clgstr ("file", fname, SZ_FNAME)
+ fd = open (fname, READ_ONLY, TEXT_FILE)
+
+ while (getline (fd, lbuf) != EOF) {
+ call putline (STDOUT, lbuf)
+ call flush (STDOUT)
+ }
+
+ call close (fd)
+end
+
+
+# RREAD -- Read a binary file.
+
+procedure t_rread()
+
+char fname[SZ_FNAME]
+char dbuf[SZ_BUF]
+int fd
+long nchars, totchars
+int open(), read()
+
+begin
+ call clgstr ("file", fname, SZ_FNAME)
+ fd = open (fname, READ_ONLY, BINARY_FILE)
+
+ totchars = 0
+
+ repeat {
+ nchars = read (fd, dbuf, SZ_BUF)
+ if (nchars > 0)
+ totchars = totchars + nchars
+ } until (nchars == EOF)
+
+ call close (fd)
+
+ call printf ("read %d chars\n")
+ call pargi (totchars)
+end