diff options
author | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
---|---|---|
committer | Joseph Hunkeler <jhunkeler@gmail.com> | 2015-07-08 20:46:52 -0400 |
commit | fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4 (patch) | |
tree | bdda434976bc09c864f2e4fa6f16ba1952b1e555 /unix/os/net | |
download | iraf-linux-fa080de7afc95aa1c19a6e6fc0e0708ced2eadc4.tar.gz |
Initial commit
Diffstat (limited to 'unix/os/net')
-rw-r--r-- | unix/os/net/README | 90 | ||||
-rw-r--r-- | unix/os/net/accept.c | 26 | ||||
-rw-r--r-- | unix/os/net/connect.c | 27 | ||||
-rw-r--r-- | unix/os/net/ctype.h | 4 | ||||
-rw-r--r-- | unix/os/net/eprintf.c | 15 | ||||
-rw-r--r-- | unix/os/net/ghostbynm.c | 37 | ||||
-rw-r--r-- | unix/os/net/ghostent.c | 137 | ||||
-rw-r--r-- | unix/os/net/gsocknm.c | 23 | ||||
-rw-r--r-- | unix/os/net/hostdb.c | 39 | ||||
-rw-r--r-- | unix/os/net/htonl.c | 22 | ||||
-rw-r--r-- | unix/os/net/htons.c | 16 | ||||
-rw-r--r-- | unix/os/net/in.h | 134 | ||||
-rw-r--r-- | unix/os/net/inetaddr.c | 92 | ||||
-rw-r--r-- | unix/os/net/kutil.c | 342 | ||||
-rw-r--r-- | unix/os/net/listen.c | 22 | ||||
-rw-r--r-- | unix/os/net/mkpkg | 25 | ||||
-rw-r--r-- | unix/os/net/netdb.h | 44 | ||||
-rw-r--r-- | unix/os/net/ntohl.c | 22 | ||||
-rw-r--r-- | unix/os/net/ntohs.c | 16 | ||||
-rw-r--r-- | unix/os/net/rexec.c | 160 | ||||
-rw-r--r-- | unix/os/net/socket.c | 25 | ||||
-rw-r--r-- | unix/os/net/socket.h | 109 | ||||
-rw-r--r-- | unix/os/net/tcpclose.c | 16 | ||||
-rw-r--r-- | unix/os/net/tcpread.c | 26 | ||||
-rw-r--r-- | unix/os/net/tcpwrite.c | 23 | ||||
-rw-r--r-- | unix/os/net/types.h | 39 | ||||
-rw-r--r-- | unix/os/net/zfioks.c | 441 | ||||
-rw-r--r-- | unix/os/net/zzdebug.x | 92 |
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 |