BSD 4_4 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 25 Nov 1992 05:29:29 +0000 (21:29 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Wed, 25 Nov 1992 05:29:29 +0000 (21:29 -0800)
Work on file usr/src/contrib/kermit-5A.188/ckcnet.c
Work on file usr/src/contrib/kermit-5A.188/ckcnet.h

Synthesized-from: CSRG/cd3/4.4

usr/src/contrib/kermit-5A.188/ckcnet.c [new file with mode: 0644]
usr/src/contrib/kermit-5A.188/ckcnet.h [new file with mode: 0644]

diff --git a/usr/src/contrib/kermit-5A.188/ckcnet.c b/usr/src/contrib/kermit-5A.188/ckcnet.c
new file mode 100644 (file)
index 0000000..b6b30d7
--- /dev/null
@@ -0,0 +1,1704 @@
+char *cknetv = "Network support, 5A(015) 23 Nov 92";
+
+/*  C K C N E T  --  Network support  */
+/*
+  Authors:
+
+  Frank da Cruz (fdc@columbia.edu, FDCCU@CUVMA.BITNET),
+    Columbia University Center for Computing Activities.
+  netopen() routine for TCP/IP originally by Ken Yap, Rochester University
+    (ken@cs.rochester.edu) (no longer at that address).
+  Missing pieces for Excelan sockets library from William Bader, Moravian
+    College <bader@moravian.edu>.
+  TELNET protocol by Frank da Cruz.
+  TGV MultiNet code by Frank da Cruz.
+  MultiNet code adapted to WIN/TCP by Ray Hunter of TWG.
+  MultiNet code adapted to DEC TCP/IP by Lee Tibbert of DEC and Frank da Cruz.
+  SunLink X.25 support by Marcello Frutig, Catholic University,
+    Rio de Janeiro, Brazil (frutig@rnp.impa.br) with fixes from
+    Stefaan Eeckels, Eurokom, Luxembourg.
+  Other contributions as indicated below.
+
+  Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New
+  York.  Permission is granted to any individual or institution to use this
+  software as long as it is not sold for profit.  This copyright notice must be
+  retained.  This software may not be included in commercial products without
+  written permission of Columbia University.
+*/
+
+#include "ckcdeb.h"
+#include "ckcker.h"
+#ifdef I386IX                          /* Has to come before ckcnet.h in */
+#include <errno.h>                     /* this version, but after in others */
+#endif /* I386IX */
+#include "ckcnet.h"
+
+#ifdef NETCONN
+/* Don't need these if there is no network support. */
+
+#ifdef WINTCP
+
+#include <errno.h>
+#include <setjmp.h>
+#include <signal.h>
+/*
+ * The WIN/TCP code path is the same as that for Multinet.  Only the routine
+ * names have changed ...
+ */
+#define socket_errno   errno
+#define socket_read    netread
+#define socket_ioctl   ioctl
+#define socket_write   netwrite
+#define socket_perror   win$perror
+#define socket_close   netclose
+
+#else /* Not WINTCP */
+#ifndef I386IX
+#include <errno.h>
+#endif /* I386IX */
+#include <signal.h>
+#ifndef ZILOG
+#include <setjmp.h>
+#else
+#include <setret.h>
+#endif /* ZILOG */
+#endif /* WINTCP */
+
+#ifdef datageneral                     /* Data General AOS/VS */
+#include <:usr:include:vs_tcp_errno.h>
+#include <:usr:include:sys:vs_tcp_types.h>
+#include <:usr:include:sys:socket.h>
+#include <:usr:include:netinet:in.h>
+#include <:usr:include:netdb.h>
+#endif /* datageneral */
+
+extern SIGTYP (*saval)();              /* For saving alarm handler */
+
+_PROTOTYP( VOID bgchk, (void) );
+
+extern int                             /* External variables */
+  duplex, debses, seslog, ttyfd, quiet, msgflg;
+
+#ifdef SVR4
+/*
+  These suggested by Rob Healey, rhealey@kas.helios.mn.org, to avoid
+  bugs in Berkeley compatibility library on Sys V R4 systems, but untested
+  by me (fdc).  Remove this bit if it gives you trouble.
+  (Later corrected by Marc Boucher <mboucher@iro.umontreal.ca> because
+  bzero/bcopy are not argument-compatible with memset/memcpy|memmove.)
+*/
+#define bzero(s,n) memset(s,0,n)
+#define bcopy(h,a,l) memmove(a,h,l)
+#else
+#ifdef PTX                             /* Sequent DYNIX PTX 1.3 */
+#define bzero(s,n) memset(s,0,n)
+#define bcopy(h,a,l) memcpy(a,h,l)
+#endif /* PTX */
+#endif /* SVR4 */
+
+#define NAMECPYL 100                   /* Local copy of hostname */
+static char namecopy[NAMECPYL];
+
+char ipaddr[20] = { '\0' };            /* Global copy of IP address */
+
+/*
+  VMSTCPIP means "DEC_TCPIP or MULTINET or WINTCP" (defined in ckcnet.h).
+*/
+#ifdef VMSTCPIP
+/*
+  General global variables, but so far used only by MultiNet and WIN/TCP.
+  Kept within #ifdef MULTINET..#endif to keep strict compilers (and lint)
+  from complaining about unused variables.
+*/
+static jmp_buf njbuf;                  /* For timeout longjumps */
+#endif /* VMSTCPIP */
+
+#endif /* NETCONN */
+
+int ttnet = NET_NONE;                  /* Network type */
+int ttnproto = NP_NONE;                        /* Network virtual terminal protocol */
+int tn_init = 0;                       /* Telnet protocol initialized flag */
+int tn_duplex = 1;                     /* Initial echo status */
+char *tn_term = NULL;                  /* Terminal type override */
+int tn_nlm = 1;                                /* Telnet CR -> CR LF mode */
+
+#ifndef NETCONN
+/*
+  Network support not defined.
+  Dummy functions here in case #ifdef's forgotten elsewhere.
+*/
+int                                    /* Open network connection */
+netopen(name, lcl, nett) char *name; int *lcl, nett; {
+    return(-1);
+}
+int                                    /* Close network connection */
+netclos() {
+    return(-1);
+}
+int                                    /* Check network input buffer */
+nettchk() {
+    return(-1);
+}
+int                                    /* Flush network input buffer */
+netflui() {
+    return(-1);
+}
+int                                    /* Send network BREAK */
+netbreak() {
+    return(-1);
+}
+int                                    /* Input character from network */
+netinc(timo) int timo; {
+}
+int                                    /* Output character to network */
+#ifdef CK_ANSIC
+nettoc(char c)
+#else
+nettoc(c) char c;
+#endif /* CK_ANSIC */
+/* nettoc */ {
+    return(-1);
+}
+int
+nettol(s,n) char *s; int n; {
+    return(-1);
+}
+
+#else /* NETCONN is defined (rest of this module...) */
+
+#ifdef VMSTCPIP
+
+/* For buffered network reads... */
+/*
+  If the buffering code is written right, it shouldn't matter how long this
+  buffer is -- it could even be shorter than a Kermit packet.
+*/
+#define TTIBUFL 8192                   /* Maybe 8K?... */
+
+CHAR   ttibuf[TTIBUFL+1];
+int    ttibp = 0, ttibn = 0;
+/*
+  Read bytes from network into internal buffer ttibuf[].
+  To be called when input buffer is empty, i.e. when ttibn == 0.
+
+  Other network reading routines, like ttinc, ttinl, ttxin, should check the
+  internal buffer first, and call this routine for a refill if necessary.
+
+  Returns -1 on error, 0 if nothing happens.  When data is read successfully,
+  returns number of bytes read, and sets global ttibn to that number and
+  ttibp (the buffer pointer) to zero.
+*/
+int
+ttbufr() {                             /* TT Buffer Read */
+    int count;
+
+    if (ttnet != NET_TCPB) {           /* First make sure current net is */
+       return(-1);                     /* TCP/IP; if not, do nothing. */
+    } else {
+       if (ttibn > 0)                  /* Out internal buffer is not empty, */
+         return(ttibn);                /* so keep using it. */
+#ifdef WINTCP
+       count = 512;                    /* This works for WIN/TCP */
+#else                                  /* Not WINTCP, i.e it's Multinet */
+#ifdef DEC_TCPIP
+       count = 512;                    /* This works for WIN/TCP */
+#else                                  /* Not WINTCP, i.e it's Multinet */
+       count = nettchk();              /* Check network input buffer, */
+       if (ttibn > 0) return(ttibn);   /* which can put a char there! */
+       if (count < 0)                  /* Read error */
+         return(-1);
+       else if (count > TTIBUFL)       /* Too many to read */
+         count = TTIBUFL;
+       else if (count == 0)            /* None, so force blocking read */
+         count = 1;
+#endif /* DEC_TCPIP */
+#endif /* WINTCP */
+       debug(F101,"ttbufr count 1","",count);
+
+#ifdef COMMENT
+/*
+ This is for nonblocking reads, which we don't do any more.  This code didn't
+ work anyway, in the sense that a broken connection was never sensed.
+*/
+       if ((count = socket_read(ttyfd,ttibuf,count)) < 1) {
+           if (count == -1 && socket_errno == EWOULDBLOCK) {
+               debug(F100,"ttbufr finds nothing","",0);
+               return(0);
+           } else if (count == 0) {
+               debug(F100,"ttbufr socket eof","",0);           
+               return(-1);
+           } else {
+               debug(F101,"ttbufr socket_read error","",socket_errno);
+               return(-1);
+           }
+       }
+#else
+/* This is for blocking reads */
+       if ((count = socket_read(ttyfd,ttibuf,count)) < 1) {
+           debug(F101,"ttbufr socket_read","",count);
+           debug(F101,"ttbufr socket_errno","",socket_errno);
+           return(-1);
+       }
+#endif /* COMMENT */
+       ttibp = 0;                      /* Reset buffer pointer. */
+       ttibn = count;
+#ifdef DEBUG
+       debug(F101,"ttbufr count 2","",count); /* Got some bytes. */
+       if (count > 0) ttibuf[count] = '\0';
+       debug(F111,"ttbufr ttibuf",ttibuf,ttibp);
+#endif /* DEBUG */
+       return(ttibn);                  /* Return buffer count. */
+    }
+}
+#endif /* VMSTCPIP */
+
+/*
+  C-Kermit network open/close functions for BSD-sockets.
+  Much of this code shared by SunLink X.25, which also uses the socket library.
+*/
+
+/*  N E T O P E N  --  Open a network connection.  */
+
+/*  Returns 0 on success, -1 on failure.  */
+
+#define        TELNET_PORT     23         /* Should do lookup, but it won't change */
+
+/* This symbol is not known to, e.g., Ultrix 2.0 */
+#ifndef TELOPT_TTYPE
+#define TELOPT_TTYPE 24
+#endif /* TELOPT_TTYPE */
+
+/*  N E T O P N  --  Open a network connection.  */
+/*
+  Call with:
+    name of host (or host:service),
+    lcl - local-mode flag to be set if this function succeeds,
+    network type - value defined in ckunet.h.
+*/
+
+#ifdef EXCELAN
+/*
+  Most other BSD sockets implementations define these in header files
+  and libraries.
+*/
+struct servent {
+    unsigned short s_port;
+};
+
+struct hostent {
+    short h_addrtype;
+    struct in_addr h_addr;
+    int h_length;
+};
+
+struct servent *
+getservbyname(service, connection) char *service,*connection; {
+    static struct servent servrec;
+    int port;
+
+    port = 0;
+    if (strcmp(service, "telnet") == 0) port = 23;
+    else if (strcmp(service, "smtp") == 0) port = 25;
+    else port = atoi(service);
+
+    debug(F101,"getservbyname return port ","",port);
+
+    if (port > 0) {
+       servrec.s_port = htons(port);
+       return( &servrec );
+    }
+    return( (struct servent *) NULL );
+}
+
+struct hostent *
+gethostbyname(hostname) char *hostname; {
+    return( (struct hostent *) NULL );
+}
+
+unsigned long
+inet_addr(name) char *name; {
+    unsigned long addr;
+
+    addr = rhost(&name);
+    debug(F111,"inet_addr ",name,(int)addr);
+    return(addr);
+}
+
+char *
+inet_ntoa(in) struct in_addr in; {
+    static char name[80];
+    sprintf(name, "%d.%d.%d.%d", in.s_net, in.s_host, in.s_lh, in.s_impno);
+    return(name);
+}
+#endif /* EXCELAN */
+
+/*  N E T O P E N  --  Open a network connection  */
+/*
+  Calling conventions same as ttopen(), except third argument is network
+  type rather than modem type.  Designed to be called from within ttopen.
+*/
+int
+netopen(name, lcl, nett) char *name; int *lcl, nett; {
+    char *p;
+#ifdef SO_OOBINLINE
+    int on = 1;
+#endif /* SO_OOBINLINE */
+    int i, x;
+    struct servent *service, servrec;
+    struct hostent *host;
+    struct sockaddr_in saddr;
+#ifdef EXCELAN
+    struct sockaddr_in send_socket;
+#endif /* EXCELAN */
+
+#ifdef SUNX25                          /* Code for SunLink X.25 support */
+#define X29PID 1                       /* X.29 Protocol ID */
+    VOID x25oobh();
+    CONN_DB x25host;
+    FACILITY_DB x25facil;
+    static int needh = 1;
+    PID_T pid;
+    extern int linkid, lcn, x25ver;
+    extern int revcall, closgr, cudata;
+    extern char udata[MAXCUDATA];
+#endif /* SUNX25 */
+
+    debug(F101,"netopen nett","",nett);
+    *ipaddr = '\0';                    /* Initialize IP address string */
+
+#ifdef SUNX25
+    if (nett == NET_SX25) {            /* If network type is X.25 */
+        netclos();                     /* Close any previous net connection */
+        ttnproto = NP_NONE;            /* No protocol selected yet */
+
+        /* Set up host structure */
+        bzero ((char *)&x25host,sizeof(x25host));
+        if ((x25host.hostlen = pkx121 (name,x25host.host)) < 0) {
+            fprintf (stderr,"Invalid X.121 host address %s\n",name);
+            errno = 0;
+            return (-1);
+        }
+        x25host.datalen = X29PIDLEN;
+        x25host.data[0] = X29PID;
+
+       /* Set call user data if specified */
+        if (cudata) {
+            strncpy(x25host.data+X29PIDLEN,udata,(int)strlen(udata));
+            x25host.datalen += (int)strlen(udata);
+        }
+
+        /* Open SunLink X.25 socket */
+        if ((ttyfd = socket (AF_X25, SOCK_STREAM, 0)) < 0) {
+           debug(F101,"netopen socket error","",errno);
+            perror ("X.25 connect socket error");
+            return (-1);
+        }
+
+        /* Setting X.25 out-of-band data handler */
+        pid = getpid();
+        if (ioctl(ttyfd,SIOCSPGRP,&pid)) {
+            perror("Setting process group id");
+            return(-1);
+        }
+        (VOID) signal(SIGURG,x25oobh);
+
+        /* Set reverse charge call and closed user group if requested */
+        bzero ((char *)&x25facil,sizeof(x25facil));
+        if (revcall) x25facil.reverse_charge = revcall;
+        if (closgr > -1) {
+            x25facil.cug_req = 1;
+            x25facil.cug_index = closgr;
+        }
+        if (ioctl(ttyfd,X25_WR_FACILITY,&x25facil) < 0) {
+            perror ("Setting X.25 facilities");
+            return (-1);
+        }
+
+        /*  Need X.25 header with bits Q and M */
+        if (ioctl (ttyfd,X25_HEADER,&needh) < 0) {
+            perror ("Setting X.25 header");
+            return (-1);
+        }
+
+        /* Connects to remote host via SunLink X.25 */
+        if (connect(ttyfd,&x25host,sizeof(x25host)) < 0) {
+            debug(F101,"netopen connect errno","",errno);
+            i = errno;
+           if (errno) {
+                perror("netopen");
+                x25diag();
+            }
+            (VOID) close (ttyfd);
+            ttyfd = -1;
+            errno = i;
+            return (-1);
+        }
+
+        /* Get X.25 link identification used for the connection */
+        if (ioctl(ttyfd,X25_GET_LINK,&linkid) < 0) {
+            perror ("Getting X.25 link id");
+            return (-1);
+        }
+
+        /* Get X.25 logical channel number used for the connection */
+        if (ioctl(ttyfd,X25_RD_LCGN,&lcn) < 0) {
+            perror ("Getting X.25 lcn");
+            return (-1);
+        }
+
+        /* Get SunLink X.25 version */
+        if (ioctl(ttyfd,X25_VERSION,&x25ver) < 0) {
+            perror ("Getting SunLink X.25 version");
+            return (-1);
+        }
+        ttnet = nett;                   /* Sunlink X.25 network */
+        ttnproto = NP_X3;               /* PAD X.3, X.28, X.29 protocol */
+        if (*lcl < 0) *lcl = 1;         /* Local mode */
+        return(0);
+    } else /* Note that SUNX25 support can coexist with TCP/IP support. */
+#endif /* SUNX25 */
+/*
+  Add support for other networks here.
+*/
+    if (nett != NET_TCPB) return(-1);  /* BSD socket support */
+
+    netclos();                         /* Close any previous connection. */
+    strncpy(namecopy, name, NAMECPYL); /* Copy the hostname. */
+    ttnproto = NP_NONE;                        /* No protocol selected yet. */
+    debug(F110,"netopen namecopy",namecopy,0);
+
+    p = namecopy;                      /* Was a service requested? */
+    while (*p != '\0' && *p != ':') p++; /* Look for colon */
+    if (*p == ':') {                   /* Have a colon */
+       *p++ = '\0';                    /* Get service name or number */
+    } else {                           /* Otherwise use telnet */
+       p = "telnet";
+    }
+    debug(F110,"netopen service requested",p,0);
+    if (isdigit(*p)) {                 /* Use socket number without lookup */
+       service = &servrec;
+       service->s_port = htons((unsigned short)atoi(p));
+    } else {                           /* Otherwise lookup the service name */
+       service = getservbyname(p, "tcp");
+    }
+    if (!service) {
+       fprintf(stderr, "Cannot find port for service %s\n", p);
+#ifdef MULTINET
+       debug(F101,"netopen can't get service","",socket_errno);
+#else
+       debug(F101,"netopen can't get service","",errno);
+#endif /* MULTINET */
+       errno = 0;                      /* rather than mislead */
+       return(-1);
+    }
+    /* Set up socket structure and get host address */
+
+    bzero((char *)&saddr, sizeof(saddr));
+    if ((host = gethostbyname(namecopy)) != NULL) {
+       saddr.sin_family = host->h_addrtype;
+       bcopy(host->h_addr, (caddr_t)&saddr.sin_addr, host->h_length);
+    } else {
+#ifdef INADDRX
+/* inet_addr() is of type struct in_addr */
+       struct in_addr ina;
+       unsigned long uu;
+#ifdef datageneral
+        extern struct in_addr inet_addr();
+#endif /* datageneral */
+       ina = inet_addr(namecopy);
+       uu = *(unsigned long *)&ina;
+#else /* Not INADDRX */
+/* inet_addr() is unsigned long */
+       unsigned long uu;
+       uu = inet_addr(namecopy);
+#endif /* INADDRX */
+       if ((saddr.sin_addr.s_addr = uu) != ((unsigned long)-1))
+         saddr.sin_family = AF_INET;
+       else {
+         fprintf(stderr, "Can't get address for %s\n", namecopy);
+#ifdef MULTINET
+         debug(F101,"netopen can't get address","",socket_errno);
+#else
+         debug(F101,"netopen can't get address","",errno);
+#endif /* MULTINET */
+         errno = 0;                    /* rather than mislead */
+         return(-1);
+      }
+    }
+
+    /* Get a file descriptor for the connection. */
+
+    saddr.sin_port = service->s_port;
+    sprintf(ipaddr,"%s", inet_ntoa(saddr.sin_addr));
+    if (!quiet && *ipaddr) printf(" Trying %s...\n", ipaddr);
+
+#ifdef EXCELAN
+    send_socket.sin_family = AF_INET;
+    send_socket.sin_addr.s_addr = 0;
+    send_socket.sin_port = 0;
+    if ((ttyfd = socket(SOCK_STREAM, (struct sockproto *)0,
+               &send_socket, SO_REUSEADDR)) < 0)
+#else
+    if ((ttyfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+#endif /* EXCELAN */
+      {
+#ifdef EXCELAN
+       experror("TCP socket error");
+#else
+#ifdef MULTINET
+       socket_perror("TCP socket error");
+       debug(F101,"netopen socket error","",socket_errno);
+#else
+       perror("TCP socket error");
+       debug(F101,"netopen socket error","",errno);
+#endif /* MULTINET */
+#endif /* EXCELAN */
+       return (-1);
+    }
+    errno = 0;
+
+    /* Now connect to the socket on the other end. */
+
+#ifdef EXCELAN
+    if (connect(ttyfd, &saddr) < 0)
+#else
+    if (connect(ttyfd, (struct sockaddr *)&saddr, sizeof(saddr)) < 0)
+#endif /* EXCELAN */
+      {
+       i = errno;                      /* save error code */
+       close(ttyfd);
+       ttyfd = -1;
+       errno = i;                      /* and report this error */
+#ifdef EXCELAN
+       if (errno) experror("netopen connect");
+#else
+#ifdef MULTINET
+       debug(F101,"netopen connect error","",socket_errno);
+       if (errno) socket_perror("netopen connect");
+#else
+       debug(F101,"netopen connect errno","",errno);
+#ifdef WINTCP
+       perror("netopen connect");
+#endif /* WINTCP */
+#ifdef DEC_TCPIP
+       perror("netopen connect");
+#endif /* DEC_TCPIP */
+#endif /* MULTINET */
+#endif /* EXCELAN */
+       return(-1);
+    }
+#ifdef SO_OOBINLINE
+/*
+  The symbol SO_OOBINLINE is not known to Ultrix 2.0.
+  It means "leave out of band data inline".  The normal value is 0x0100,
+  but don't try this on systems where the symbol is undefined.
+*/
+#ifdef datageneral
+    setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
+#else
+#ifdef BSD43
+    setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
+#else
+#ifdef OSF1
+    setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
+#else
+#ifdef POSIX
+    setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
+#else
+#ifdef SOLARIS
+/*
+  Maybe this applies to all SVR4 versions, but the other (else) way has been
+  compiling and working fine on all the others, so best not to change it.
+*/
+    setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE,(char *) &on, sizeof on);
+#else
+    setsockopt(ttyfd, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
+#endif /* SOLARIS */
+#endif /* POSIX */
+#endif /* BSD43 */
+#endif /* OSF1 */
+#endif /* datageneral */
+#endif /* SO_OOBINLINE */
+
+    /* See if the service is TELNET. */
+    if ((x = ntohs((unsigned short)service->s_port)) == TELNET_PORT)
+      ttnproto = NP_TELNET;            /* Yes, set global flag. */
+    debug(F101,"netopen service","",x);
+    ttnet = nett;                      /* TCP/IP (sockets) network */
+    tn_init = 0;                       /* Telnet protocol not init'd yet */
+    if (*lcl < 0) *lcl = 1;            /* Local mode. */
+    return(0);                         /* Done. */
+}
+\f
+/*  N E T C L O S  --  Close current network connection.  */
+
+int
+netclos() {
+    int x = 0;
+    if (ttyfd < 0)                     /* Was open? */
+      return(0);                       /* Wasn't. */
+    if (ttyfd > -1)                    /* Was. */
+#ifdef VMSTCPIP
+      x = socket_close(ttyfd);         /* Close it. */
+#else
+      x = close(ttyfd);
+#endif /* VMSTCPIP */
+    ttyfd = -1;                                /* Mark it as closed. */
+    tn_init = 0;                       /* Remember about telnet protocol... */
+    *ipaddr = '\0';                    /* Zero the IP address string */
+    return(x);
+}
+
+/*  N E T T C H K  --  Check if network up, and how many bytes can be read */
+/*
+  Returns number of bytes waiting, or -1 if connection has been dropped.
+*/
+int                                    /* Check how many bytes are ready */
+nettchk() {                            /* for reading from network */
+#ifdef VMSTCPIP
+    unsigned int count;
+    int x, y;
+    char c;
+
+    debug(F101,"nettchk entry ttibn","",ttibn);
+    debug(F101,"nettchk entry ttibp","",ttibp);
+    socket_errno = 0;
+/*
+  Note: this socket_ioctl() call does NOT return an error if the
+  connection has been broken.  (At least not in Multinet.)
+*/
+    if (socket_ioctl(ttyfd,FIONREAD,&count) < 0) {
+       debug(F101,"nettchk socket_ioctl error","",socket_errno);
+       if (ttibn < 1) return(-1);
+       else return(ttibn);
+    }
+    debug(F101,"nettchk count","",count);
+
+#ifndef DEC_TCPIP
+/*
+  Let's see if we can skip this for UCX, since it seems to cause trouble.
+*/
+    if (count == 0) {
+/*
+  Here we need to tell the difference between a 0 count on an active
+  connection, and a 0 count because the remote end of the socket broke the
+  connection.  There is no mechanism in TGV MultiNet (or WIN/TCP?) to query
+  the status of the connection, so we have to do a read.  -1 means there was
+  no data available (socket_errno == EWOULDBLOCK), 0 means the connection is
+  down.  But if, by chance, we actually get a character, we have to put it
+  where it won't be lost.
+*/
+       y = 1;                          /* Turn on nonblocking reads */
+       debug(F101,"nettchk before FIONBIO","",x);
+       x = socket_ioctl(ttyfd,FIONBIO,&y);
+       debug(F101,"nettchk FIONBIO","",x);
+       x = socket_read(ttyfd,&c,1);    /* Returns -1 if no data */
+       debug(F101,"nettchk socket_read","",x);
+       y = 0;                          /* Turn them back off */
+       socket_ioctl(ttyfd,FIONBIO,&y);
+       if (x == 0) return(-1);         /* Connection is broken. */
+       if (x == 1) {                   /* Oops, actually got a byte? */
+           debug(F101,"nettchk socket_read char","",c);
+           debug(F101,"nettchk ttibp","",ttibp);
+           debug(F101,"nettchk ttibn","",ttibn);
+/*
+  So put the byte we got into the buffer at the current position.
+  Increment the buffer count, but DON'T increment the buffer pointer.
+*/
+           ttibuf[ttibp+ttibn] = c;
+           ttibn++;
+#ifdef DEBUG
+           ttibuf[ttibp+ttibn] = '\0';
+           debug(F111,"nettchk ttibn",ttibuf,ttibn);
+#endif /* DEBUG */
+       }
+    }
+#endif /* DEC_TCPIP */
+    debug(F101,"nettchk returns","",count+ttibn);
+    return(count + ttibn);
+
+#else /* Not VMSTCPIP */
+/*
+  UNIX just uses ttchk(), in which the ioctl() calls on the file descriptor
+  seem to work OK.
+*/
+    return(0);
+#endif /* VMSTCPIP */
+/*
+  But what about X.25?
+*/
+}
+
+/*  N E T I N C --  Input character from network */
+
+int                    
+netinc(timo) int timo; {
+#ifdef VMSTCPIP
+    int x; unsigned char c;            /* The locals. */
+
+    if (ttibn > 0) {                   /* Something in internal buffer? */
+       debug(F100,"netinc char in buf","",0); /* Yes. */
+       x = 0;                          /* Success. */
+    } else {                           /* Else must read from network. */
+       x = -1;                         /* Assume failure. */
+#ifdef DEBUG
+       debug(F101,"netinc goes to net, timo","",timo);
+       ttibuf[ttibp+1] = '\0';
+       debug(F111,"netinc ttibuf",ttibuf,ttibp);
+#endif /* DEBUG */
+       if (timo <= 0) {                /* Untimed case. */
+           while (1) {                 /* Wait forever if necessary. */
+               if (ttbufr() < 0)       /* Refill buffer. */
+                 break;                /* Error, fail. */
+               if (ttibn > 0) {        /* Success. */
+                   x = 0;
+                   break;
+               }
+           }
+       } else {                        /* Timed case... */
+           saval = signal(SIGALRM,ttimoff); /* Enable timer interrupt */
+           alarm(timo);                /* for requested interval. */
+           if (setjmp(njbuf)) {        /* Timer went off? */
+               x = -1;                 /* Yes, fail. */
+           } else {
+               while (1) {
+                   if (ttbufr() < 0)   /* Keep trying to refill it. */
+                     break;            /* Till we get an error. */
+                   if (ttibn > 0) {    /* Or we get a character. */
+                       x = 0;
+                       break;
+                   }
+               }
+           }
+           ttimoff();                  /* Timer off. */
+       }
+    }
+    if (x < 0) {                       /* Return -1 if we failed. */
+       debug(F100,"netinc timed out","",0);
+       return(-1);
+    } else {                           /* Otherwise */
+       ttibn--;                        /* Return what we got. */
+       c = ttibuf[ttibp++];
+       debug(F101,"netinc returning","",c);
+       return((c & 0xff));
+    }
+#else /* Not MULTINET or WINTCP */
+    return(-1);
+#endif /* VMSTCPIP */
+}
+
+/*  N E T T O L  --  Output a string of bytes to the network  */
+/*
+  Call with s = pointer to string, n = length.
+  Returns number of bytes actually written on success, or
+  -1 on i/o error, -2 if called improperly.
+*/
+int
+nettol(s,n) char *s; int n; {
+#ifdef VMSTCPIP
+    int count;
+    if (ttnet == NET_TCPB) {
+       if ((count = socket_write(ttyfd,s,n)) < 1) {
+           debug(F101,"nettol socket_write error","",socket_errno);
+           return(-1);
+       }
+       debug(F111,"nettol socket_write",s,count);
+       return(count);
+    } else return(-2);
+#else
+    debug(F100,"nettol VMSTCPIP not defined","",0);
+    return(-2);
+#endif /* VMSTCPIP */
+}
+
+/*  N E T T O C  --   Output character to network */
+/*
+  Call with character to be transmitted.
+  Returns 0 if transmission was successful, or
+  -1 upon i/o error, or -2 if called improperly.
+*/
+int                    
+#ifdef CK_ANSIC
+nettoc(char c)
+#else
+nettoc(c) char c;
+#endif /* CK_ANSIC */
+/* nettoc */ {
+#ifdef VMSTCPIP
+    unsigned char cc;
+    cc = c;
+    if (ttnet == NET_TCPB) {
+       debug(F101,"nettoc cc","",cc);
+       if (socket_write(ttyfd,&cc,1) < 1) {
+           debug(F101,"nettoc socket_write error","",socket_errno);
+           return(-1);
+       }
+       debug(F101,"nettoc socket_write","", cc);
+       return(0);
+    } else return(-2);
+#else
+    return(-2);
+#endif /* MULTINET */
+}
+
+/*  N E T F L U I  --  Flush network input buffer  */
+
+int
+netflui() {
+    int n;
+#ifdef VMSTCPIP
+    ttibuf[ttibp+1] = '\0';
+    debug(F111,"netflui 1",ttibuf,ttibn);
+    ttibn = ttibp = 0;                 /* Flush internal buffer *FIRST* */
+    if ((n = nettchk()) > 0) {         /* Now see what's waiting on the net */
+       if (n > TTIBUFL) n = TTIBUFL;   /* and sponge it up */
+       debug(F101,"netflui 2","",n);   /* ... */
+       n = socket_read(ttyfd,ttibuf,n) ; /* into our buffer */
+       if (n >= 0) ttibuf[n] = '\0';
+       debug(F111,"netflui 3",ttibuf,n);
+       ttibuf[0] = '\0';
+    }
+#else
+/*
+  It seems the UNIX ioctl()s don't do the trick, so we have to read the
+  stuff ourselves.  This should be pretty much portable, if not elegant.
+*/
+    if ((n = ttchk()) > 0) {
+       debug(F101,"netflui","",n);
+       while ((n--) && ttinc(0) > -1) ; /* Don't worry, it's buffered. */
+    }
+#endif /* VMSTCPIP */
+    return(0);
+}
+
+#ifdef TNCODE                          /* Compile in telnet support code */
+
+/* TCP/IP Telnet negotiation support code */
+
+static int sgaflg = 0;                 /* telnet SGA flag */
+static int wttflg = 0;                 /* telnet terminal type flag */
+
+#ifndef TELCMDS
+char *telcmds[] = {
+    "SE", "NOP", "DMARK", "BRK",  "IP",   "AO", "AYT",  "EC",
+    "EL", "GA",  "SB",    "WILL", "WONT", "DO", "DONT", "IAC",
+};
+int ntelcmds = sizeof(telcmds) / sizeof(char *);
+#endif /* TELCMDS */
+
+#ifndef TELOPTS
+char *telopts[] = {
+       "BINARY", "ECHO", "RCP", "SUPPRESS GO AHEAD", "NAME",
+       "STATUS", "TIMING MARK", "RCTE", "NAOL", "NAOP",
+       "NAOCRD", "NAOHTS", "NAOHTD", "NAOFFD", "NAOVTS",
+       "NAOVTD", "NAOLFD", "EXTEND ASCII", "LOGOUT", "BYTE MACRO",
+       "DATA ENTRY TERMINAL", "SUPDUP", "SUPDUP OUTPUT",
+       "SEND LOCATION", "TERMINAL TYPE", "END OF RECORD"
+#ifdef TELOPT_TUID
+       ,"TACACS UID"
+#ifdef TELOPT_OUTMRK
+       ,"OUTPUT MARKING"
+#ifdef TELOPT_TTYLOC
+       ,"TTYLOC"
+#ifdef TELOPT_3270REGIME
+       ,"3270 REGIME"
+#ifdef TELOPT_X3PAD
+       ,"X.3 PAD"
+#ifdef TELOPT_NAWS
+       ,"NAWS"
+#ifdef TELOPT_TSPEED
+       ,"TSPEED"
+#ifdef TELOPT_LFLOW
+       ,"LFLOW"
+#ifdef TELOPT_LINEMODE
+       ,"LINEMODE"
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+#endif
+};
+#endif /* TELOPTS */
+
+int ntelopts = sizeof(telopts) / sizeof(char *);
+#endif /* TNCODE */
+
+
+/* Send network BREAK */
+/*
+  Returns -1 on error, 0 if nothing happens, 1 if BREAK sent successfully.
+*/
+int
+netbreak() {
+    CHAR buf[3];
+    if (ttnet == NET_TCPB) {
+       if (ttnproto == NP_TELNET) {
+#ifdef TNCODE
+           buf[0] = (CHAR) IAC; buf[1] = (CHAR) BREAK;
+           if (ttol(buf,2) < 2) return(-1);
+           debug(F101,"telnet BREAK ok","",BREAK);
+           return(1);
+#else
+           debug(F100,"netbreak no TNCODE","",0);
+           return(0);
+#endif /* TNCODE */
+       }
+       /* Insert other TCP/IP protocols here */
+    }
+    /* Insert other networks here */
+    return(0);
+}
+
+/* Send a telnet option, avoid loops. */
+/* Returns 1 if command was sent, 0 if not, -1 on error */
+
+int
+tn_sopt(cmd,opt) int cmd, opt; {       /* TELNET SEND OPTION */
+    CHAR buf[4];
+    int n;
+    if (ttnet != NET_TCPB) return(0);  /* Must be TCP/IP */
+    if (ttnproto != NP_TELNET) return(0); /* Must be telnet protocol */
+    n = cmd - SE;
+    if (n < 0 || n > ntelcmds) return(0);
+#ifdef TNCODE
+    buf[0] = (CHAR) IAC;
+    buf[1] = (CHAR) cmd & 0xff;
+    buf[2] = (CHAR) opt & 0xff;
+    if (ttol(buf,3) < 3)
+      return(-1);
+    debug(F111,"telnet cmd >",telcmds[n],cmd);
+    debug(F111,"telnet opt >",
+         (opt < ntelopts) ? telopts[opt] : "UNKNOWN", opt );
+    if (debses && cmd != SB)
+      printf("[%s %s]",telcmds[n],
+            (opt < ntelopts) ? telopts[opt] : "UNKNOWN");
+    return(1);
+#else
+    debug(F100,"tn_sopt no TNCODE","",0);
+    return(0);
+#endif /* TNCODE */
+}
+
+/* Initialize a telnet connection. */
+/* Returns -1 on error, 0 if nothing happens, 1 if init msgs sent ok */
+
+int
+tn_ini() {
+#ifndef TNCODE
+    debug(F100,"tn_ini no TNCODE","",0);
+    return(0);
+#else /* TELNET protocol support */
+    debug(F101,"tn_ini ttnproto","",ttnproto);
+    debug(F101,"tn_ini tn_init","",tn_init);
+
+    if (ttnet != NET_TCPB)             /* Make sure connection is TCP/IP. */
+      return(0);
+    if (tn_init)                       /* Have we done this already? */
+      return(0);                       /* Don't do it again. */
+    debug(F101,"tn_ini tn_duplex","",tn_duplex);
+    duplex = tn_duplex;                        /* Assume local echo. */
+    sgaflg = 0;                                /* Assume Go-Ahead suppressed. */
+    wttflg = 0;                                /* Did not send WILL TERM TYPE yet. */
+    if (ttnproto == NP_NONE) {         /* If not talking to a telnet port, */
+       ttnproto = NP_TELNET;           /* pretend it's telnet anyway, */
+       tn_init = 1;                    /* but don't send initial options. */
+       debug(F100,"tn_ini skipping telnet negotiations","",0);
+       return(0);
+    }
+    /* Talking to telnet port, so send WILL TERMINAL TYPE and DO SGA */
+
+    if (tn_sopt(WILL,TELOPT_TTYPE) < 0)        /* Will send terminal type. */
+      return(-1);
+    wttflg = 1;                                /* Remember I said I would. */
+    if (tn_sopt(DO,TELOPT_SGA) < 0)    /* Please suppress go-ahead. */
+      return(-1);
+#ifdef COMMENT
+    if (tn_sopt(DO,TELOPT_ECHO) < 0)   /* Ask the server to echo, since */
+      return(-1);                      /* I'm assuming it will. */
+#endif /* COMMENT */
+    tn_init = 1;                       /* Set telnet-initialized flag. */
+
+    /* Don't send anthing else! */
+
+    debug(F101,"tn_ini duplex","",duplex);
+    return(1);
+#endif /* TNCODE */
+}
+
+/*
+  Process in-band Telnet negotiation characters from the remote host.
+  Call with the telnet IAC character and the current duplex setting
+  (0 = remote echo, 1 = local echo).
+  Returns:
+    3 if server has sent us a quoted IAC
+    2 if local echo must be changed to remote
+    1 if remote echo must be changed to local
+    0 if nothing happens or no action necessary
+   -1 on failure (= internal or i/o error)
+*/
+
+#define TSBUFSIZ 41
+char sb[TSBUFSIZ];                     /* Buffer for subnegotiations */
+
+int
+#ifdef CK_ANSIC                                /* TELNET DO OPTION */
+tn_doop( CHAR z, int echo, int (*fn)(int) )
+#else
+tn_doop(z, echo, fn) CHAR z; int echo; int (*fn)();
+#endif /* CK_ANSIC */
+/* tn_doop */ {
+    int c, x, y, n, m, flag;
+
+#ifndef TNCODE
+    debug(F100,"tn_doop no TNCODE","",0);
+    return(0);
+#else
+    if (z != (CHAR) IAC) {
+       debug(F101,"tn_doop bad call","",z);
+       return(-1);
+    }
+    if (ttnet != NET_TCPB) return(0);
+    if (ttnproto != NP_TELNET) return(0);      /* Check protocol */
+
+/* Have IAC, read command character. */
+
+    c = (*fn)(0) & 0xff;               /* Read command character */
+    m = c - SE;                                /* Check validity */
+    if (m < 0 || m > ntelcmds) {
+       debug(F101,"tn_doop bad cmd","",c);
+       return(0);
+    }
+    if (seslog) {                      /* Copy to session log, if any. */
+       if (zchout(ZSFILE, (char) z) < 0) seslog = 0; /* Log IAC. */
+       else if (zchout(ZSFILE, (char) c) < 0) seslog = 0; /* Log command */
+    }
+    debug(F111,"telnet cmd <",telcmds[m],c); /* Debug log. */
+
+    if (c == (CHAR) IAC) return(3);    /* Quoted IAC */
+    if (c < SB) return(0);             /* Other command with no arguments. */
+
+/* SB, WILL, WONT, DO, or DONT need more bytes... */
+
+    if ((x = (*fn)(0)) < 0) return(-1);        /* Get the option. */
+    x &= 0xff;                         /* Trim to 8 bits. */
+
+    debug(F111,"telnet opt <",
+         (x < ntelopts) ? telopts[x] : "UNKNOWN", x );
+    if (seslog)                                /* Session log */
+      if (zchout(ZSFILE, (char) x) < 0) seslog = 0;
+
+    /* Now handle the command */
+
+    if (debses && c != SB)             /* Debug to screen. */
+      printf("<%s %s>",telcmds[m],
+            (x < ntelopts) ? telopts[x] : "UNKNOWN" );
+    switch (x) {
+      case TELOPT_ECHO:                        /* ECHO negotiation. */
+       switch (c) {                    /* Command */
+         case WILL:                    /* Host says it will echo. */
+           if (echo)                   /* Only reply if change required. */
+             return((tn_sopt(DO,x) < 0) ? -1 : 2); /* Please do. */
+           else return(0);             /* Otherwise no change. */
+         case WONT:                    /* Host says it won't echo. */
+           if (!echo)                  /* If I'm full duplex */
+             return ((tn_sopt(DONT,x) < 0) ? -1 : 1); /* Switch to half */
+           else return(0);             /* Otherwise, no change.  */
+         case DO:                      /* Host wants me to echo */
+           if (tn_sopt(WONT,x) < 0)    /* but the client never echoes */
+             return(-1);               /* back to the server. */
+         default:                      /* Don't reply to anything else */
+           return(0);
+       }
+
+      case TELOPT_SGA:                 /* Suppress Go-Ahead */
+       switch (c) {                    /* Command... */
+         case WONT:                    /* Host says it won't. */
+           if (!sgaflg) {
+               sgaflg = 1;             /* Remember. */
+               if (tn_sopt(DONT,x) < 0) /* acknowledge, */
+                 return(-1);
+           }
+           return(echo ? 0 : 1);       /* Switch to half duplex */
+         case WILL:                    /* Server says it will SGA */
+           if (sgaflg) {               /* ACK only if necessary */
+               if (tn_sopt(DO,x) < 0)
+                 return(-1);
+               sgaflg = 0;             /* Remember new SGA state. */
+           }
+           return(0);                  /* But don't change echo state. */
+       }
+
+#ifdef TELOPT_TTYPE
+      case TELOPT_TTYPE:               /* Terminal Type */
+       switch (c) {
+         case DO:                      /* DO terminal type. */
+           if (wttflg == 0) {          /* If I haven't said so before, */
+               if (tn_sopt((CHAR)WILL,x) < 0) /* say I'll send it if asked. */
+                 return(-1);
+               wttflg++;
+           }
+           return(0);
+         case SB:
+           debug(F100,"TELNET subnegotiation:","",0);
+           n = flag = 0;               /* Flag for when done reading SB */
+           while (n < TSBUFSIZ) {      /* Loop looking for IAC SE */
+               if ((y = (*fn)(0)) < 0) /* Read a byte */
+                 return(-1);
+               y &= 0xff;              /* Make sure it's just 8 bits. */
+               sb[n++] = y;            /* Deposit in buffer. */
+               if (seslog)             /* Take care of session log */
+                 if (zchout(ZSFILE, (char) y) < 0)
+                   seslog = 0;
+               if (y == IAC) {         /* If this is an IAC */
+                   if (flag) {         /* If previous char was IAC */
+                       n--;            /* it's quoted, keep one IAC */
+                       flag = 0;       /* and turn off the flag. */
+                   } else flag = 1;    /* Otherwise set the flag. */
+               } else if (flag) {      /* Something else following IAC */
+                   if (y != SE)        /* If not SE, it's a protocol error */
+                     flag = 0;
+                   break;
+               }
+           }
+           if (!flag) {                /* Make sure we got a valid SB */
+               debug(F100, "TELNET Subnegotian prematurely broken", "",0);
+               return(-1);
+           }
+           if (debses) {               /* Debug to screen. */
+               int i;
+               printf("<SB %s ",telopts[TELOPT_TTYPE]);
+               for (i = 0; i < n-2; i++) printf("%02x",sb[i]);
+               printf(" IAC SE>");
+           }
+           debug(F101,"TELNET suboption<","",sb[0]);
+           if (sb[0] == 1) {           /* SEND terminal type? */
+               if (tn_sttyp() < 0)     /* Yes, so send it. */
+                 return(-1);
+           }
+         default:                      /* Others, ignore */
+           return(0);
+       }
+#endif /* TELOPT_TTYPE */
+
+      default:                         /* All others: refuse */
+       switch(c) {
+         case WILL:                    /* You will? */
+           if (tn_sopt(DONT,x) < 0)    /* Please don't. */
+             return(-1);               /* (Could this cause a loop?) */
+           break;
+         case DO:                      /* You want me to? */
+           if (tn_sopt(WONT,x) < 0)    /* I won't. */
+             return(-1);
+           break;
+         case DONT:                    /* You don't want me to? */
+           if (tn_sopt(WONT,x) < 0)    /* I won't. */
+             return(-1);               /* (Could this cause a loop?) */
+         case WONT:                    /* You won't? */
+           break;                      /* I didn't want you to. */
+       }                               /* Anything else, treat as user data */
+       return(0);
+    }
+#endif /* TNCODE */
+}
+
+/* Telnet send terminal type */
+/* Returns -1 on error, 0 if nothing happens, 1 if type sent successfully */
+
+int
+tn_sttyp() {                           /* Send telnet terminal type. */
+#ifndef TNCODE
+    debug(F100,"tn_sttyp no TNCODE","",0);
+    return(0);
+#else
+    char *ttn; int ttl, i;             /* Name & length of terminal type. */
+
+    if (ttnet != NET_TCPB) return(0);
+    if (ttnproto != NP_TELNET) return(0);
+
+    ttn = NULL;
+
+    if (tn_term) {                     /* Terminal type override? */
+       debug(F110,"tn_sttyp",tn_term,0);
+       if (*tn_term) ttn = tn_term;
+    } else debug(F100,"tn_sttyp no term override","",0);
+#ifndef datageneral
+    if (!ttn)                          /* If no override, */
+      ttn = getenv("TERM");            /* get it from the environment. */
+#endif /* datageneral */
+    if ((ttn == ((char *)0)) || ((ttl = (int)strlen(ttn)) >= TSBUFSIZ)) {
+       ttn = "UNKNOWN";
+       ttl = 7;
+    }
+    sb[0] = IAC;                       /* I Am a Command */
+    sb[1] = SB;                                /* Subnegotiation */
+    sb[2] = TELOPT_TTYPE;              /* Terminal Type */
+    sb[3] = (CHAR) 0;                  /* Is... */
+    for (i = 4; *ttn; ttn++,i++)       /* Copy and uppercase it */
+      sb[i] = (islower(*ttn)) ? toupper(*ttn) : *ttn;
+    ttn = sb;                          /* Point back to beginning */
+    sb[i++] = IAC;                     /* End of Subnegotiation */
+    sb[i++] = SE;                      /* marked by IAC SE */
+    if (ttol((CHAR *)sb,i) < 0)                /* Send it. */
+      return(-1);
+#ifdef DEBUG
+    sb[i-2] = '\0';                    /* For debugging */
+    debug(F111,"telnet SB sent ttype",sb+4,ttl);
+#endif /* DEBUG */
+    if (debses)                                /* Debug to screen. */
+      printf("[SB TERMINAL TYPE 00 %s IAC SE]",sb+4);
+    return(1);
+#endif /* TNCODE */
+}
+
+#ifdef SUNX25
+/*
+  SunLink X.25 support by Marcello Frutig, Catholic University,
+  Rio de Janeiro, Brazil, 1990.
+*/
+
+/* PAD X.3, X.28 and X.29 support */
+
+static CHAR x29err [MAXPADPARMS+3] = { X29_ERROR, INVALID_PAD_PARM, '\0' };
+
+
+/* Initialize PAD */
+
+extern CHAR padparms[MAXPADPARMS+1];
+
+VOID
+initpad() {
+  padparms[PAD_BREAK_CHARACTER]        = 0;  /* Break character */
+  padparms[PAD_ESCAPE]                 = 1;  /* Escape permitted */
+  padparms[PAD_ECHO]                   = 1;  /* Kermit PAD does echo */
+  padparms[PAD_DATA_FORWARD_CHAR]      = 2;  /* forward character CR */
+  padparms[PAD_DATA_FORWARD_TIMEOUT]   = 0;  /* no timeout forward condition */
+  padparms[PAD_FLOW_CONTROL_BY_PAD]    = 0;  /* not used */
+  padparms[PAD_SUPPRESSION_OF_SIGNALS] = 1;  /* allow PAD service signals */
+  padparms[PAD_BREAK_ACTION]           = 21; /* brk action: INT pk + brk ind*/
+  padparms[PAD_SUPPRESSION_OF_DATA]    = 0;  /* no supression of user data */
+  padparms[PAD_PADDING_AFTER_CR]       = 0;  /* no padding after CR */
+  padparms[PAD_LINE_FOLDING]           = 0;  /* no line fold */
+  padparms[PAD_LINE_SPEED]             = 0;  /* line speed - don't care */
+  padparms[PAD_FLOW_CONTROL_BY_USER]   = 0;  /* flow cont of PAD - not used */
+  padparms[PAD_LF_AFTER_CR]            = 0;  /* no LF insertion after CR */
+  padparms[PAD_PADDING_AFTER_LF]       = 0;  /* no padding after LF */
+  padparms[PAD_EDITING]                = 1;  /* can edit */
+  padparms[PAD_CHAR_DELETE_CHAR]       = 8;  /* character delete character */
+  padparms[PAD_BUFFER_DELETE_CHAR]     = 21; /* buffer delete character */
+  padparms[PAD_BUFFER_DISPLAY_CHAR]    = 18; /* buffer display character */
+}
+
+
+/* Set PAD parameters */
+
+VOID
+setpad(s,n) CHAR *s; int n; {
+    int i;
+    CHAR *ps = s;
+
+    for (i = 0; i < n; i++) {
+        if (*ps > MAXPADPARMS)
+         x29err[i+2] = *ps;
+        else
+         padparms[*ps] = *(ps+1);
+        ps += 2;
+    }
+}
+
+/* Read PAD parameters */
+
+VOID
+readpad(s,n,r) CHAR *s; int n; CHAR *r; {
+    int i;
+    CHAR *ps = s;
+    CHAR *pr = r;
+
+    *pr++ = X29_PARAMETER_INDICATION;
+    for (i = 0; i < n; i++, ps++) {
+         if (*ps > MAXPADPARMS) {
+             x29err[i+2] = *ps++;
+         } else {
+             *pr++ = *ps;
+             *pr++ = padparms[*ps++];
+         }
+    }
+}
+
+int
+qbitpkt(s,n) CHAR *s; int n; {
+    CHAR *ps = s;
+    int x29cmd = *ps;
+    CHAR *psa = s+1;
+    CHAR x29resp[(MAXPADPARMS*2)+1];
+
+    switch (x29cmd) {
+
+        case X29_SET_PARMS:
+            setpad (ps+1,n/2);
+            if ((int)strlen(x29err) > 2) {
+                ttol (x29err,(int)strlen(x29err));
+                x29err[2] = '\0';
+            }
+            return (-2);
+        case X29_READ_PARMS:
+            readpad (ps+1,n/2,x29resp);
+            setqbit ();
+            ttol (x29resp,n+1);
+            if ((int)strlen(x29err) > 2) {
+                ttol (x29err,(int)strlen(x29err));
+                x29err[2] = '\0';
+            }
+            resetqbit();
+            break;
+        case X29_SET_AND_READ_PARMS:
+            setpad (ps+1,n/2);
+            readpad (ps+1,n/2,x29resp);
+            setqbit();
+            ttol (x29resp,n+1);
+            if ((int)strlen(x29err) > 2) {
+                ttol (x29err,(int)strlen(x29err));
+                x29err [2] = '\0';
+            }
+            resetqbit();
+            return (-2);
+        case X29_INVITATION_TO_CLEAR:
+            (VOID) x25clear();
+            return (-1) ;
+        case X29_INDICATION_OF_BREAK:
+           break;
+    }
+    return (0);
+}
+
+/* PAD break action processor */
+
+VOID
+breakact() {
+    extern char x25obuf[MAXOX25];
+    extern int obufl;
+    extern int active;
+    extern unsigned char tosend;
+    static CHAR indbrk[3] = {
+       X29_INDICATION_OF_BREAK,
+       PAD_SUPPRESSION_OF_DATA,
+       1
+    };
+    CHAR intudat, cause, diag;
+
+    if (x25stat() < 0) return(0);   /* Ignore if no virtual call established */
+
+    if (padparms[PAD_BREAK_ACTION] != 0) /* Forward condition */
+        if (ttol(x25obuf,obufl) < 0) {
+            perror ("\r\nCan't send characters");
+            active = 0;
+        } else {
+            bzero (x25obuf,sizeof(x25obuf));
+            obufl = 0;
+            tosend = 0;
+        };
+
+    switch (padparms[PAD_BREAK_ACTION]) {
+
+       case 0 : break;                 /* do nothing */
+       case 1 : /* send interrupt packet with interrupt user data field = 1 */
+               intudat = 1;
+                x25intr (intudat);
+                break;
+       case 2 : /* send reset packet with cause and diag = 0 */
+               cause = diag = 0;
+                x25reset (cause,diag);
+                break;
+       case 5 : /* send interrupt packet with interrupt user data field = 0 */
+               intudat = 0;
+                x25intr (intudat) ;
+                setqbit ();
+               /* send indication of break without a parameter field */
+                ttoc(X29_INDICATION_OF_BREAK);
+                resetqbit ();
+                break;
+       case 8 : active = 0;            /* leave data transfer */
+                conol ("\r\n");
+                break;
+       case 21: /* send interrupt packet with interrupt user data field = 0 */
+               intudat = 0;
+                x25intr (intudat);
+                setpad (indbrk+1,2);   /* set pad to discard input */
+                setqbit ();
+               /* send indication of break with parameter field */
+                ttol (indbrk,sizeof(indbrk));
+                resetqbit ();
+                break;
+     }
+}
+
+/* X.25 support functions */
+
+X25_CAUSE_DIAG diag;
+
+/*
+  Convert a null-terminated string representing an X.121 address
+  to a packed BCD form.
+*/
+
+int
+pkx121(str,bcd) char *str; CHAR *bcd; {
+    int i, j;
+    u_char c;
+
+    i = j = 0;
+    while (str[i]) {
+        if ( i >= 15 || str [i] < '0' || str [i] > '9' )
+         return (-1);
+        c = str [i] - '0';
+        if ( i & 1 )
+         bcd [j++] |= c;
+        else
+         bcd [j] = c << 4;
+        i++;
+    }
+    return (i);
+}
+
+/* Reads and prints X.25 diagnostic */
+
+int
+x25diag () {
+    int i;
+
+    bzero ((char *)&diag,sizeof(diag));
+    if (ioctl(ttyfd,X25_RD_CAUSE_DIAG,&diag)) {
+        perror ("Reading X.25 diagnostic");
+        return(-1);
+    }
+    if (diag.datalen > 0) {
+        printf ("X.25 Diagnostic :");
+        for (i = 0; i < diag.datalen; i++) printf (" %02x",diag.data[i]);
+        printf ("\r\n");
+    }
+    return(0);
+}
+
+/* X.25 Out-of-Band Signal Handler */
+
+VOID
+x25oobh() {
+    int oobtype;
+    u_char oobdata;
+
+    (VOID) signal(SIGURG,x25oobh);
+    do {
+        if (ioctl(ttyfd,X25_OOB_TYPE,&oobtype)) {
+            perror ("Getting signal type");
+            return;
+        }
+        switch (oobtype) {
+         case INT_DATA:
+           if (recv(ttyfd,oobdata,1,MSG_OOB) < 0) {
+               perror ("Receiving X.25 interrupt data");
+               return;
+           }
+           printf ("\r\nInterrupt received, data = %d\r\n", oobdata);
+           break;
+         case VC_RESET:
+           printf ("\r\nVirtual circuit reset\r\n");
+           x25diag ();
+           break;
+         case N_RESETS:
+           printf ("\r\nReset timeout\r\n");
+           break;
+         case N_CLEARS:
+           printf ("\r\nClear timeout\r\n");
+           break;
+         case MSG_TOO_LONG:
+           printf ("\r\nMessage discarded, too long\r\n");
+           break;
+         default:
+           if (oobtype) printf("\r\nUnknown oob type %d\r\n",oobtype);
+           break;
+       }
+    } while (oobtype);
+}
+
+/* Send a X.25 interrupt packet */
+
+int
+#ifdef CK_ANSIC
+x25intr(char intr)
+#else
+x25intr(intr) char intr;
+#endif /* CK_ANSIC */
+/* x25intr */ {
+    if (send(ttyfd,&intr,1,MSG_OOB) < 0) return(-1);
+    debug(F100,"X.25 intr","",0);
+    return(0);
+}
+
+/* Reset X.25 virtual circuit */
+int
+#ifdef CK_ANSIC
+x25reset(char cause, char diagn)
+#else
+x25reset(cause, diagn) char cause; char diagn;
+#endif /* CK_ANSIC */
+/* x25reset */ {
+    bzero ((char *)&diag,sizeof(diag));
+    diag.flags   = 0;
+    diag.datalen = 2;
+    diag.data[0] = cause;
+    diag.data[1] = diagn;
+    if (ioctl(ttyfd,X25_WR_CAUSE_DIAG,&diag) < 0)
+      return(-1);
+    debug(F100,"X.25 reset","",0);
+    return(0);
+}
+
+/* Clear X.25 virtual circuit */
+int
+x25clear() {
+    int i;
+    debug(F100,"X.25 clear","",0);
+    bzero ((char *)&diag,sizeof(diag));
+    diag.flags = (1 << DIAG_TYPE);
+    diag.datalen = 2;
+    diag.data[0] = 0;
+    diag.data[1] = 0;
+    ioctl (ttyfd,X25_WR_CAUSE_DIAG,&diag); /* Send Clear Request */
+    return(ttclos(0));                 /* Close socket */
+}
+
+/* X.25 status */
+int
+x25stat() {
+    if (ttyfd < 0) return (-1);
+    return(0);
+}
+
+/* Set Q_BIT on */
+VOID
+setqbit() {
+    static int qbiton = 1 << Q_BIT;
+    ioctl (ttyfd,X25_SEND_TYPE,&qbiton);
+}
+
+/* Set Q_BIT off */
+VOID
+resetqbit() {
+    static int qbitoff = 0;
+    ioctl (ttyfd,X25_SEND_TYPE,&qbitoff);
+}
+
+/* Read n characters from X.25 circuit into buf */
+
+int
+x25xin(n,buf) int n; CHAR *buf; {
+    register int x, c;
+    int qpkt;
+
+    do {
+       x = read(ttyfd,buf,n);
+       if (buf[0] & (1 << Q_BIT)) { /* If Q_BIT packet, process it */
+           /* If return -1 : invitation to clear; -2 : PAD changes */
+           if ((c=qbitpkt(buf+1,x-2)) < 0) return(c);
+           qpkt = 1;
+       } else qpkt = 0;
+    } while (qpkt);
+    if (x > 0) buf[x] = '\0';
+    if (x < 1) x = -1;
+    debug(F101,"x25xin x","",x);
+
+    return(x);
+}
+
+#ifdef COMMENT /* NO LONGER NEEDED! */
+/* X.25 read a line */
+
+int
+#ifdef PARSENSE
+#ifdef CK_ANSIC
+x25inl(CHAR *dest, int max,int timo, CHAR eol, CHAR start)
+#else
+x25inl(dest,max,timo,eol,start) int max,timo; CHAR *dest, eol, start;
+#endif /* CK_ANSIC */
+#else /* not PARSENSE */
+#ifdef CK_ANSIC
+x25inl(CHAR *dest, int max,int timo, CHAR eol)
+#else
+x25inl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
+#endif /* __SDTC__ */
+#endif /* PARSENSE */
+/* x25inl */ {
+    CHAR *pdest;
+    int pktype, goteol, rest, n;
+    int i, flag = 0;
+    extern int ttprty, ttpflg;
+    int ttpmsk;
+
+    ttpmsk = (ttprty) ? 0177 : 0377;   /* Set parity stripping mask */
+
+    debug(F101,"x25inl max","",max);
+    debug(F101,"x25inl eol","",eol);
+    pdest  = dest;
+    rest   = max;
+    goteol = 0;
+    do {
+       n = read(ttyfd,pdest,rest);
+       n--;
+       pktype = *pdest & 0x7f;
+       switch (pktype) {
+         case 1 << Q_BIT:
+           if (qbitpkt(pdest+1,--n) < 0) return(-2);
+           break;
+         default:
+           if (flag == 0) { /* if not in packet, search start */
+               for (i = 1; (i < n) &&
+                    !(flag = ((dest[i] & 0x7f) == start));
+                    i++);
+               if (flag == 0) { /* not found, discard junk */
+                   debug(F101,"x25inl skipping","",n);
+                   continue;
+               } else {                /* found, discard junk before start */
+                   int k;
+                   n = n - i + 1;
+                   for (k = 1; k <= n; k++, i++) dest[k] = dest[i];
+               }
+           }
+           for (i = 0; (i < n) && /* search for eol */
+                !(goteol=(((*pdest = *(pdest+1)&ttpmsk)&0x7f)== eol));
+                i++,pdest++);
+           *pdest = '\0';
+           rest -= n;
+       }
+    } while ( (rest > 0) && (!goteol) );
+
+    if (goteol) {
+       n = max - rest;
+       debug (F111,"x25inl X.25 got",(char *) dest,n);
+       if (timo) ttimoff();
+       if (ttpflg++ == 0 && ttprty == 0) {
+           if ((ttprty = parchk(dest,start,n)) > 0) {
+               int j;
+               debug(F101,"x25inl senses parity","",ttprty);
+               debug(F110,"x25inl packet before",(char *)dest,0);
+               ttpmsk = 0x7f;
+               for (j = 0; j < n; j++)
+                 dest[j] &= 0x7f; /* Strip parity from packet */
+               debug(F110,"x25inl packet after ",dest,0);
+           } else {
+               debug(F101,"parchk","",ttprty);
+               if (ttprty < 0) { ttprty = 0; n = -1; }
+           }
+       }
+       ttimoff();
+       return(n);
+    }
+    ttimoff();
+    return(-1);
+}
+#endif /* COMMENT */
+#endif /* SUNX25 */
+
+#endif /* NETCONN */
diff --git a/usr/src/contrib/kermit-5A.188/ckcnet.h b/usr/src/contrib/kermit-5A.188/ckcnet.h
new file mode 100644 (file)
index 0000000..5d60076
--- /dev/null
@@ -0,0 +1,390 @@
+#ifndef CKCNET_H
+#define CKCNET_H
+
+/* Network types */
+
+#define NET_NONE 0                     /* None */
+#define NET_TCPB 1                     /* TCP/IP Berkeley (socket) */
+#define NET_TCPA 2                     /* TCP/IP AT&T (streams) */
+#define NET_SX25 3                     /* SUNOS SunLink X.25 */
+#define NET_DEC  4                     /* DECnet */
+#define NET_VPSI 5                     /* VAX PSI */
+#define NET_PIPE 6                     /* LAN Manager Named Pipe */
+
+/* Network virtual terminal protocols */
+
+#define NP_NONE 0                      /* None (async) */
+#define NP_TELNET 1                    /* TCP/IP telnet */
+#define NP_VTP 2                       /* ISO Virtual Terminal Protocol */
+#define NP_X3 3                                /* CCITT X.3 */
+#define NP_X28 4                       /* CCITT X.28 */
+#define NP_X29 5                       /* CCITT X.28 */
+#define NP_CTERM 20                    /* DEC CTERM */
+#define NP_LAT 21                      /* DEC LAT */
+/* others here... */
+
+/* Basic network function prototypes, common to all. */
+
+_PROTOTYP( int netopen, (char *, int *, int) );
+_PROTOTYP( int netclos, (void) );
+_PROTOTYP( int netflui, (void) );
+_PROTOTYP( int nettchk, (void) );
+_PROTOTYP( int netbreak, (void) );
+_PROTOTYP( int netinc, (int) );
+_PROTOTYP( int nettol, (char *, int) );
+_PROTOTYP( int nettoc, (char) );
+
+/*
+  SunLink X.25 support by Marcello Frutig, Catholic University,
+  Rio de Janeiro, Brazil, 1990.
+
+  Maybe this can be adapted to VAX PSI and other X.25 products too.
+*/
+#ifndef SUNOS4                         /* Only valid for SUNOS4 */
+#ifdef SUNX25
+#undef SUNX25
+#endif /* SUNX25 */
+#endif /* SUNOS4 */
+
+#ifdef SUNX25
+
+#ifndef NETCONN                                /* SUNX25 implies NETCONN */
+#define NETCONN
+#endif /* NETCONN */
+
+#define MAXPADPARMS                18  /* Number of PAD parameters */
+#define MAXCUDATA                 12   /* Max length of X.25 call user data */
+#define X29PID                     1   /* X.29 protocol ID */
+#define X29PIDLEN                  4   /* X.29 protocol ID length */
+
+#define X29_SET_PARMS               2
+#define X29_READ_PARMS              4
+#define X29_SET_AND_READ_PARMS      6
+#define X29_INVITATION_TO_CLEAR     1
+#define X29_PARAMETER_INDICATION    0
+#define X29_INDICATION_OF_BREAK     3
+#define X29_ERROR                   5
+
+#define INVALID_PAD_PARM            1
+
+#define PAD_BREAK_CHARACTER         0
+
+#define PAD_ESCAPE                  1
+#define PAD_ECHO                    2
+#define PAD_DATA_FORWARD_CHAR       3
+#define PAD_DATA_FORWARD_TIMEOUT    4
+#define PAD_FLOW_CONTROL_BY_PAD     5
+#define PAD_SUPPRESSION_OF_SIGNALS  6
+#define PAD_BREAK_ACTION            7
+#define PAD_SUPPRESSION_OF_DATA     8
+#define PAD_PADDING_AFTER_CR        9
+#define PAD_LINE_FOLDING           10
+#define PAD_LINE_SPEED             11
+#define PAD_FLOW_CONTROL_BY_USER   12
+#define PAD_LF_AFTER_CR            13
+#define PAD_PADDING_AFTER_LF       14
+#define PAD_EDITING                15
+#define PAD_CHAR_DELETE_CHAR       16
+#define PAD_BUFFER_DELETE_CHAR     17
+#define PAD_BUFFER_DISPLAY_CHAR    18
+
+#define MAXIX25 MAX_USER_DATA*7
+#define MAXOX25 MAX_USER_DATA
+
+#include <sys/ioctl.h>                 /* X.25 includes */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/mbuf.h>
+#include <sys/socket.h>
+#include <sys/protosw.h>
+#include <sys/domain.h>
+#include <sys/socketvar.h>
+#include <net/if.h>
+#include <sundev/syncstat.h>
+#include <netx25/x25_pk.h>
+#include <netx25/x25_ctl.h>
+#include <netx25/x25_ioctl.h>
+
+/* C-Kermit X.3 / X.25 / X.29 / X.121 support functions */
+
+_PROTOTYP( VOID shopad, (void) );
+_PROTOTYP( VOID initpad, (void) );
+_PROTOTYP( VOID setpad, (CHAR *, int) );
+_PROTOTYP( VOID readpad, (CHAR *, int, CHAR *) );
+_PROTOTYP( int qbitpkt, (CHAR *, int) );
+_PROTOTYP( VOID setqbit, (void) );
+_PROTOTYP( VOID resetqbit, (void) );
+_PROTOTYP( VOID breakact, (void) );
+_PROTOTYP( int pkx121, (char *, CHAR *) );
+_PROTOTYP( VOID x25oobh, (void) );
+_PROTOTYP( int x25diag, (void) );
+_PROTOTYP( int x25intr, (char) );
+_PROTOTYP( int x25reset, (char, char) );
+_PROTOTYP( int x25clear, (void) );
+_PROTOTYP( int x25stat, (void) );
+_PROTOTYP( int x25in, (int, CHAR *) );
+_PROTOTYP( int x25inl, (CHAR *, int, int, CHAR) );
+
+#endif /* SUNX25 */
+
+/* DEC TCP/IP for (Open)VMS, previously known as UCX */
+
+#ifdef DEC_TCPIP                       /* DEC_TCPIP implies TCPSOCKET */
+#ifndef TCPSOCKET
+#define TCPSOCKET
+#endif /* TCPSOCKET */
+#ifndef VMSTCPIP
+#define VMSTCPIP
+#endif /* VMSTCPIP */
+#endif /* DEC_TCPIP */
+
+/* TGV/SRI MultiNet, TCP/IP for VAX/VMS */
+
+#ifdef MULTINET                                /* MULTINET implies TCPSOCKET */
+#ifndef TCPSOCKET
+#define TCPSOCKET
+#endif /* TCPSOCKET */
+#ifndef VMSTCPIP
+#define VMSTCPIP
+#endif /* VMSTCPIP */
+#ifndef TGVORWIN                       /* MULTINET and WINTCP */
+#define TGVORWIN                       /* share a lot of code... */
+#endif /* TGVORWIN */
+#endif /* MULTINET */
+
+/* Wollongong TCP/IP for VAX/VMS */
+
+#ifdef WINTCP                          /* WINTCP implies TCPSOCKET */
+#ifndef TCPSOCKET
+#define TCPSOCKET
+#endif /* TCPSOCKET */
+#ifndef VMSTCPIP
+#define VMSTCPIP
+#endif /* VMSTCPIP */
+#ifndef TGVORWIN                       /* WINTCP and MULTINET */
+#define TGVORWIN                       /* share a lot of code... */
+#endif /* TGVORWIN */
+#endif /* WINTCP */
+
+/* Wollongong TCP/IP for AT&T Sys V */
+
+#ifdef WOLLONGONG                      /* WOLLONGONG implies TCPSOCKET */
+#ifndef TCPSOCKET                      /* Don't confuse WOLLONGONG */
+#define TCPSOCKET                      /* (which is for UNIX) with */
+#endif /* TCPSOCKET */                 /* WINTCP, which is for VMS! */
+#endif /* WOLLONGONG */
+
+#ifdef EXCELAN                         /* EXCELAN implies TCPSOCKET */
+#ifndef TCPSOCKET
+#define TCPSOCKET
+#endif /* TCPSOCKET */
+#endif /* EXCELAN */
+
+#ifdef INTERLAN                                /* INTERLAN implies TCPSOCKET */
+#ifndef TCPSOCKET
+#define TCPSOCKET
+#endif /* TCPSOCKET */
+#endif /* INTERLAN */
+
+/* Telnet protocol */
+
+#ifdef TCPSOCKET                       /* TCPSOCKET implies TNCODE */
+#ifndef TNCODE                         /* Which means... */
+#define TNCODE                         /* Compile in telnet code */
+#endif /* TNCODE */
+#endif /* TCPSOCKET */
+
+#ifdef SUNX25                          /* SUNX25 implies TCPSOCKET */
+#ifndef TCPSOCKET                      /* But doesn't imply TNCODE */
+#define TCPSOCKET
+#endif /* TCPSOCKET */
+#endif /* SUNX25 */
+
+/* This is the TCPSOCKET section... */
+
+#ifdef TCPSOCKET
+
+#ifndef NETCONN                                /* TCPSOCKET implies NETCONN */
+#define NETCONN
+#endif /* NETCONN */
+
+/* BSD sockets library header files */
+
+#ifdef UNIX                            /* UNIX section */
+
+#ifdef INTERLAN                                /* Racal-Interlan TCP/IP */
+#include <interlan/socket.h>
+#include <interlan/il_types.h>
+#include <interlan/telnet.h>
+#include <interlan/il_errno.h>
+#include <interlan/in.h>
+#include <interlan/telnet.h>
+#else                                  /* Normal BSD TCP/IP library */
+#ifndef HPUX
+#include <arpa/telnet.h>
+#endif /* HPUX */
+#include <sys/socket.h>
+#ifdef WOLLONGONG
+#include <sys/in.h>
+#else
+#include <netinet/in.h>
+#endif /* WOLLONGONG */
+#endif /* INTERLAN */
+
+#ifndef EXCELAN
+#include <netdb.h>
+#ifndef INTERLAN
+#ifdef WOLLONGONG
+#define minor                          /* Do not include <sys/macros.h> */
+#include <sys/inet.h>
+#else
+#ifndef OXOS
+#ifndef HPUX
+#include <arpa/inet.h>
+#endif /* HPUX */
+#else /* OXOS */
+/* In too many releases of X/OS, <arpa/inet.h> declares inet_addr() as
+ * ``struct in_addr''.  This is definitively wrong, and could cause
+ * core dumps.  Instead of including that bad file, inet_addr() is
+ * correctly declared here.  Of course, all the declarations done there
+ * has been copied here.
+ */
+unsigned long inet_addr();
+char   *inet_ntoa();
+struct in_addr inet_makeaddr();
+unsigned long inet_network();
+#endif /* OXOS */
+#endif /* WOLLONGONG */
+#endif /* INTERLAN */
+#endif /* EXCELAN */
+
+#ifdef EXCELAN                         /* Excelan TCP/IP */
+#include <ex_errno.h>
+#endif /* EXCELAN */
+
+#ifdef I386IX                          /* Interactive Sys V R3 network. */
+/* #define TELOPTS */                  /* This might need defining. */
+#define ORG_NLONG ENAMETOOLONG         /* Resolve conflicting symbols */
+#undef ENAMETOOLONG                    /* in <errno.h> and <net/errno.h> */
+#define ORG_NEMPTY ENOTEMPTY
+#undef ENOTEMPTY
+#include <net/errno.h>
+#undef ENAMETOOLONG
+#define ENAMETOOLONG ORG_NLONG
+#undef ENOTEMPTY
+#define ENOTEMPTY ORG_NEMPTY
+#endif /* I386IX */
+/*
+  Data type of the inet_addr() function...
+  We define INADDRX if it is of type struct inaddr.
+  If it is undefined, unsigned long is assumed.
+  Look at <arpa/inet.h> to find out.  The following known cases are
+  handled here.  Other systems that need it can be added here, or else
+  -DINADDRX can be included in the CFLAGS on the cc command line.
+*/
+#ifdef DGUX540                         /* Data General UX 5.40 */
+#define INADDRX
+#endif /* DGUX540 */
+#ifdef DU2                             /* DEC Ultrix 2.0 */
+#define INADDRX
+#endif /* DU2 */
+
+#else /* Not UNIX */
+
+#ifdef VMS                             /* VAX/VMS section */
+
+#ifdef WINTCP                          /* TWG WIN/TCP for VMS */
+#include <errno.h>
+#include "twg$tcp:[netdist.include.sys]types.h"
+#include "twg$tcp:[netdist.include.sys]socket.h"
+#include "twg$tcp:[netdist.include]netdb.h"
+#include "twg$tcp:[netdist.include.sys]domain.h"
+#include "twg$tcp:[netdist.include.sys]protosw.h"
+#include "twg$tcp:[netdist.include.netinet]in.h"
+#include "twg$tcp:[netdist.include.sys]ioctl.h"
+#endif /* WINTCP */
+
+#ifdef MULTINET                                /* TGV MultiNet */
+#include "multinet_root:[multinet.include]errno.h"
+#include "multinet_root:[multinet.include.sys]types.h"
+#include "multinet_root:[multinet.include.sys]socket.h"
+#include "multinet_root:[multinet.include]netdb.h"
+#include "multinet_root:[multinet.include.netinet]in.h"
+#include "multinet_root:[multinet.include.sys]ioctl.h"
+#endif /* MULTINET */
+
+#ifdef DEC_TCPIP
+#include <in.h>
+#include <netdb.h>
+#include <socket.h>
+#include "ckvioc.h"
+#define socket_errno errno
+#define bzero(s,n) memset(s,0,n) 
+#define bcopy(h,a,l) memmove(a,h,l)
+#define socket_read    read
+#define socket_write   write
+#define socket_ioctl   ioctl
+#define socket_close    close
+#endif /* DEC_TCPIP */
+
+#endif /* VMS */
+#endif /* UNIX */
+#endif /* TCPSOCKET */
+
+#ifdef TNCODE                          /* If we're compiling telnet code... */
+/*
+  Make sure telnet symbols are defined; can't rely on library header files
+  for any of them.
+*/
+#ifndef IAC                            /* First the telnet commands */
+#define IAC 255
+#endif /* IAC */
+#ifndef DONT
+#define DONT 254
+#endif /* DONT */
+#ifndef DO
+#define DO 253
+#endif /* DO */
+#ifndef WONT
+#define WONT 252
+#endif /* WONT */
+#ifndef WILL
+#define WILL 251
+#endif /* WILL */
+#ifndef SB
+#define SB 250
+#endif /* SB */
+#ifndef BREAK
+#define BREAK 243
+#endif /* BREAK */
+#ifndef SE
+#define SE 240
+#endif /* SE */
+
+#ifndef TELOPT_ECHO                    /* Then the options */
+#define TELOPT_ECHO 1
+#endif /* TELOPT_ECHO */
+#ifndef TELOPT_SGA
+#define        TELOPT_SGA 3
+#endif /* TELOPT_SGA */
+#ifndef TELOPT_STATUS
+#define        TELOPT_STATUS 5
+#endif /* TELOPT_STATUS */
+#ifndef TELOPT_TTYPE
+#define        TELOPT_TTYPE 24
+#endif /* TELOPT_TTYPE */
+#ifndef NTELOPTS
+#define        NTELOPTS 24
+#endif /* NTELOPTS */
+
+/* Telnet protocol functions defined in C-Kermit */
+
+_PROTOTYP( int tn_ini, (void) );       /* Telnet protocol support */
+_PROTOTYP( int tn_sopt, (int, int) );
+_PROTOTYP( int tn_doop, (CHAR, int, int (*)(int) ) );
+_PROTOTYP( int tn_sttyp, (void) );
+_PROTOTYP( int tnsndbrk, (void) );
+
+#endif /* TNCODE */
+
+#endif /* CKCNET_H */