replaced various machine defs with MACHINE
[unix-history] / usr / src / usr.bin / tn3270 / telnet.c
index c25a61d..7e96905 100644 (file)
@@ -68,7 +68,7 @@ static char sccsid[] = "@(#)telnet.c  3.1  10/29/86";
  *
  *     unix            -       Compiles in unix specific stuff.
  *
  *
  *     unix            -       Compiles in unix specific stuff.
  *
- *     msdos           -       Compiles in msdos specific stuff.
+ *     MSDOS           -       Compiles in MSDOS specific stuff.
  *
  */
 
  *
  */
 
@@ -82,12 +82,16 @@ void        setcommandmode(), command();    /* forward declarations */
 
 #include <sys/types.h>
 #include <sys/socket.h>
 
 #include <sys/types.h>
 #include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <sys/time.h>
 
 #include <netinet/in.h>
 
 
 #include <netinet/in.h>
 
+#if    defined(unix)
+/* By the way, we need to include curses.h before telnet.h since,
+ * among other things, telnet.h #defines 'DO', which is a variable
+ * declared in curses.h.
+ */
 #include <curses.h>
 #include <curses.h>
+#endif /* defined(unix) */
 
 #define        TELOPTS
 #include <arpa/telnet.h>
 
 #define        TELOPTS
 #include <arpa/telnet.h>
@@ -102,10 +106,14 @@ extern char       *inet_ntoa();
 #include <stdio.h>
 #include <ctype.h>
 #include <errno.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <errno.h>
-#include <signal.h>
 #include <setjmp.h>
 #include <netdb.h>
 #include <setjmp.h>
 #include <netdb.h>
+
+#if    defined(unix)
 #include <strings.h>
 #include <strings.h>
+#else  /* defined(unix) */
+#include <string.h>
+#endif /* defined(unix) */
 
 #if    defined(TN3270)
 #include "ctlr/screen.h"
 
 #if    defined(TN3270)
 #include "ctlr/screen.h"
@@ -114,8 +122,8 @@ extern char *inet_ntoa();
 #include "ctlr/options.ext"
 #include "ctlr/outbound.ext"
 #include "keyboard/termin.ext"
 #include "ctlr/options.ext"
 #include "ctlr/outbound.ext"
 #include "keyboard/termin.ext"
-#include "general.h"
 #endif /* defined(TN3270) */
 #endif /* defined(TN3270) */
+#include "general.h"
 
 
 
 
 
 
@@ -223,7 +231,8 @@ static int
        autosynch,              /* send interrupt characters with SYNCH? */
        localchars,             /* we recognize interrupt/quit */
        donelclchars,   /* the user has set "localchars" */
        autosynch,              /* send interrupt characters with SYNCH? */
        localchars,             /* we recognize interrupt/quit */
        donelclchars,   /* the user has set "localchars" */
-       dontlecho;              /* do we suppress local echoing right now? */
+       dontlecho,              /* do we suppress local echoing right now? */
+       globalmode;
 
 /*     The following are some tn3270 specific flags */
 #if    defined(TN3270)
 
 /*     The following are some tn3270 specific flags */
 #if    defined(TN3270)
@@ -231,6 +240,16 @@ static int
 static int
        Sent3270TerminalType;   /* Have we said we are a 3270? */
 
 static int
        Sent3270TerminalType;   /* Have we said we are a 3270? */
 
+/* Some real, live, globals. */
+int
+       tout,                   /* Output file descriptor */
+       tin;                    /* Input file descriptor */
+
+#else  /* defined(TN3270) */
+static int tin, tout;          /* file descriptors */
+#endif /* defined(TN3270) */
+
+
 /*
  * Telnet receiver states for fsm
  */
 /*
  * Telnet receiver states for fsm
  */
@@ -245,29 +264,12 @@ static int
 #define        TS_SE           8               /* looking for sub-option end */
 
 static int     telrcv_state = TS_DATA;
 #define        TS_SE           8               /* looking for sub-option end */
 
 static int     telrcv_state = TS_DATA;
-/* Some real, live, globals. */
-int
-#if    defined(unix)
-       HaveInput,              /* There is input available to scan */
-#endif /* defined(unix) */
-       tout,                   /* Output file descriptor */
-       tin;                    /* Input file descriptor */
-#if    defined(unix)
-char   *transcom = 0;  /* transparent mode command (default: none) */
-#endif /* defined(unix) */
-
-#else  /* defined(TN3270) */
-static int tin, tout;          /* file descriptors */
-#endif /* defined(TN3270) */
 
 static char    line[200];
 
 static char    line[200];
-#if    defined(TN3270) && defined(unix)
-static char    tline[200];
-#endif /* defined(TN3270) && defined(unix) */
 static int     margc;
 static char    *margv[20];
 
 static int     margc;
 static char    *margv[20];
 
-static jmp_buf toplevel = 0;
+static jmp_buf toplevel = { 0 };
 static jmp_buf peerdied;
 
 extern int errno;
 static jmp_buf peerdied;
 
 extern int errno;
@@ -277,29 +279,681 @@ static struct sockaddr_in sin;
 
 static struct  servent *sp = 0;
 
 
 static struct  servent *sp = 0;
 
+static int     flushline;
+
+static char    *hostname;
+static char    hnamebuf[32];
+
+/*
+ * The following are some clocks used to decide how to interpret
+ * the relationship between various variables.
+ */
+
+static struct {
+    int
+       system,                 /* what the current time is */
+       echotoggle,             /* last time user entered echo character */
+       modenegotiated,         /* last time operating mode negotiated */
+       didnetreceive,          /* last time we read data from network */
+       gotDM;                  /* when did we last see a data mark */
+} clocks;
+
+#define        settimer(x)     clocks.x = clocks.system++
+\f
+/*     Various modes */
+#define        MODE_LINE(m)    (modelist[m].modetype & LINE)
+#define        MODE_LOCAL_CHARS(m)     (modelist[m].modetype &  LOCAL_CHARS)
+#define        MODE_LOCAL_ECHO(m)      (modelist[m].modetype & LOCAL_ECHO)
+#define        MODE_COMMAND_LINE(m)    (modelist[m].modetype & COMMAND_LINE)
+
+#define        LOCAL_CHARS     0x01            /* Characters processed locally */
+#define        LINE            0x02            /* Line-by-line mode of operation */
+#define        LOCAL_ECHO      0x04            /* Echoing locally */
+#define        COMMAND_LINE    0x08            /* Command line mode */
+
+static struct {
+    char *modedescriptions;
+    char modetype;
+} modelist[] = {
+       { "telnet command mode", COMMAND_LINE },
+       { "character-at-a-time mode", 0 },
+       { "character-at-a-time mode (local echo)", LOCAL_ECHO|LOCAL_CHARS },
+       { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
+       { "line-by-line mode", LINE | LOCAL_ECHO | LOCAL_CHARS },
+       { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
+       { "3270 mode", 0 },
+};
+
+\f
+/*
+ * The following routines try to encapsulate what is system dependent
+ * (at least between 4.x and dos) which is used in telnet.c.
+ */
+
+#if    defined(unix)
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <signal.h>
+
+int
+       HaveInput;              /* There is input available to scan */
+
+#if    defined(TN3270)
+static char    tline[200];
+char   *transcom = 0;  /* transparent mode command (default: none) */
+#endif /* defined(TN3270) */
+
 static struct  tchars otc = { 0 }, ntc = { 0 };
 static struct  ltchars oltc = { 0 }, nltc = { 0 };
 static struct  sgttyb ottyb = { 0 }, nttyb = { 0 };
 static struct  tchars otc = { 0 }, ntc = { 0 };
 static struct  ltchars oltc = { 0 }, nltc = { 0 };
 static struct  sgttyb ottyb = { 0 }, nttyb = { 0 };
-static int     flushline;
 
 
-static char    *hostname;
-static char    hnamebuf[32];
 
 
-/*
- * The following are some clocks used to decide how to interpret
- * the relationship between various variables.
- */
+#define        TerminalWrite(fd,buf,n) write(fd,buf,n)
+#define        TerminalRead(fd,buf,n)  read(fd,buf,n)
+
+/*
+ *
+ */
+
+static int
+TerminalAutoFlush()                                    /* unix */
+{
+#if    defined(LNOFLSH)
+    ioctl(0, TIOCLGET, (char *)&autoflush);
+    return !(autoflush&LNOFLSH);       /* if LNOFLSH, no autoflush */
+#else  /* LNOFLSH */
+    return 1;
+#endif /* LNOFLSH */
+}
+
+/*
+ * TerminalSpecialChars()
+ *
+ * Look at an input character to see if it is a special character
+ * and decide what to do.
+ *
+ * Output:
+ *
+ *     0       Don't add this character.
+ *     1       Do add this character
+ */
+
+int
+TerminalSpecialChars(c)                        /* unix */
+int    c;
+{
+    void doflush(), intp(), sendbrk();
+
+    if (c == ntc.t_intrc) {
+       intp();
+       return 0;
+    } else if (c == ntc.t_quitc) {
+       sendbrk();
+       return 0;
+    } else if (c == nltc.t_flushc) {
+       NET2ADD(IAC, AO);
+       if (autoflush) {
+           doflush();
+       }
+       return 0;
+    } else if (!MODE_LOCAL_CHARS(globalmode)) {
+       if (c == nttyb.sg_kill) {
+           NET2ADD(IAC, EL);
+           return 0;
+       } else if (c == nttyb.sg_erase) {
+           NET2ADD(IAC, EC);
+           return 0;
+       }
+    }
+    return 1;
+}
+
+
+/*
+ * Flush output to the terminal
+ */
+static void
+TerminalFlushOutput()                          /* unix */
+{
+    (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
+}
+
+static void
+TerminalSaveState()                            /* unix */
+{
+    ioctl(0, TIOCGETP, (char *)&ottyb);
+    ioctl(0, TIOCGETC, (char *)&otc);
+    ioctl(0, TIOCGLTC, (char *)&oltc);
+
+    ntc = otc;
+    nltc = oltc;
+    nttyb = ottyb;
+}
+
+static void
+TerminalRestoreState()                         /* unix */
+{
+}
+
+/*
+ * TerminalNewMode - set up terminal to a specific mode.
+ */
+
+
+static void
+TerminalNewMode(f)                                     /* unix */
+register int f;
+{
+    static int prevmode = 0;
+    struct tchars *tc;
+    struct tchars tc3;
+    struct ltchars *ltc;
+    struct sgttyb sb;
+    int onoff;
+    int old;
+    struct     tchars notc2;
+    struct     ltchars noltc2;
+    static struct      tchars notc =   { -1, -1, -1, -1, -1, -1 };
+    static struct      ltchars noltc = { -1, -1, -1, -1, -1, -1 };
+
+    globalmode = f;
+    if (prevmode == f)
+       return;
+    old = prevmode;
+    prevmode = f;
+    sb = nttyb;
+
+    switch (f) {
+
+    case 0:
+       onoff = 0;
+       tc = &otc;
+       ltc = &oltc;
+       break;
+
+    case 1:            /* remote character processing, remote echo */
+    case 2:            /* remote character processing, local echo */
+    case 6:            /* 3270 mode - like 1, but with xon/xoff local */
+                   /* (might be nice to have "6" in telnet also...) */
+           sb.sg_flags |= CBREAK;
+           if ((f == 1) || (f == 6)) {
+               sb.sg_flags &= ~(ECHO|CRMOD);
+           } else {
+               sb.sg_flags |= ECHO|CRMOD;
+           }
+           sb.sg_erase = sb.sg_kill = -1;
+           if (f == 6) {
+               tc = &tc3;
+               tc3 = notc;
+                   /* get XON, XOFF characters */
+               tc3.t_startc = otc.t_startc;
+               tc3.t_stopc = otc.t_stopc;
+           } else {
+               /*
+                * If user hasn't specified one way or the other,
+                * then default to not trapping signals.
+                */
+               if (!donelclchars) {
+                   localchars = 0;
+               }
+               if (localchars) {
+                   notc2 = notc;
+                   notc2.t_intrc = ntc.t_intrc;
+                   notc2.t_quitc = ntc.t_quitc;
+                   tc = &notc2;
+               } else {
+                   tc = &notc;
+               }
+           }
+           ltc = &noltc;
+           onoff = 1;
+           break;
+    case 3:            /* local character processing, remote echo */
+    case 4:            /* local character processing, local echo */
+    case 5:            /* local character processing, no echo */
+           sb.sg_flags &= ~CBREAK;
+           sb.sg_flags |= CRMOD;
+           if (f == 4)
+               sb.sg_flags |= ECHO;
+           else
+               sb.sg_flags &= ~ECHO;
+           notc2 = ntc;
+           tc = &notc2;
+           noltc2 = oltc;
+           ltc = &noltc2;
+           /*
+            * If user hasn't specified one way or the other,
+            * then default to trapping signals.
+            */
+           if (!donelclchars) {
+               localchars = 1;
+           }
+           if (localchars) {
+               notc2.t_brkc = nltc.t_flushc;
+               noltc2.t_flushc = -1;
+           } else {
+               notc2.t_intrc = notc2.t_quitc = -1;
+           }
+           noltc2.t_suspc = escape;
+           noltc2.t_dsuspc = -1;
+           onoff = 1;
+           break;
+
+    default:
+           return;
+    }
+    ioctl(tin, TIOCSLTC, (char *)ltc);
+    ioctl(tin, TIOCSETC, (char *)tc);
+    ioctl(tin, TIOCSETP, (char *)&sb);
+#if    (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
+    ioctl(tin, FIONBIO, (char *)&onoff);
+    ioctl(tout, FIONBIO, (char *)&onoff);
+#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
+#if    defined(TN3270) && !defined(DEBUG)
+    ioctl(tin, FIOASYNC, (char *)&onoff);
+#endif /* defined(TN3270) && !defined(DEBUG) */
+
+    if (MODE_LINE(f)) {
+       void doescape();
+
+       signal(SIGTSTP, doescape);
+    } else if (MODE_LINE(old)) {
+       signal(SIGTSTP, SIG_DFL);
+       sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
+    }
+}
+
+
+int
+NetClose(net)
+int    net;
+{
+    return close(net);
+}
+
+
+static void
+NetNonblockingIO(fd, onoff)                            /* unix */
+int
+       fd,
+       onoff;
+{
+    ioctl(net, FIONBIO, (char *)&onoff);
+}
+
+static void
+NetSigIO(fd, onoff)                            /* unix */
+int
+       fd,
+       onoff;
+{
+    ioctl(net, FIOASYNC, (char *)&onoff);      /* hear about input */
+}
+
+static void
+NetSetPgrp(fd)                         /* unix */
+int fd;
+{
+    int myPid;
+
+    myPid = getpid();
+#if    defined(NOT43)
+    myPid = -myPid;
+#endif /* defined(NOT43) */
+    ioctl(net, SIOCSPGRP, (char *)&myPid);     /* set my pid */
+}
+
+
+#endif /* defined(unix) */
+\f
+#if    defined(MSDOS)
+#include <time.h>
+#include <signal.h>
+#include <process.h>
+
+#if    !defined(SO_OOBINLINE)
+#define        SO_OOBINLINE
+#endif /* !defined(SO_OOBINLINE) */
+
+
+static char
+    termEofChar,
+    termEraseChar,
+    termFlushChar,
+    termIntChar,
+    termKillChar,
+    termLiteralNextChar,
+    termQuitChar;
+
+\f
+/*
+ * MSDOS doesn't have anyway of deciding whether a full-edited line
+ * is ready to be read in, so we need to do character-by-character
+ * reads, and then do the editing in the program (in the case where
+ * we are supporting line-by-line mode).
+ *
+ * The following routines, which are internal to the MSDOS-specific
+ * code, accomplish this miracle.
+ */
+
+#define Hex(c) HEX[(c)&0xff]
+
+static survivorSetup = 0;              /* Do we have ^C hooks in? */
+
+static int
+       lineend = 0,            /* There is a line terminator */
+       ctrlCCount = 0;
+
+static char    linein[200],            /* Where input line is assembled */
+               *nextin = linein,       /* Next input character */
+               *nextout = linein;      /* Next character to be consumed */
+
+#define consumechar() \
+    if ((++nextout) >= nextin) { \
+       nextout = nextin = linein; \
+       lineend = 0; \
+    }
+
+#define        characteratatime()      (!MODE_LINE(globalmode))        /* one by one */
+
+
+/*
+ * killone()
+ *
+ *  Erase the last character on the line.
+ */
+
+static void
+killone()
+{
+    if (lineend) {
+       return;                 /* ??? XXX */
+    }
+    if (nextin == linein) {
+       return;                 /* Nothing to do */
+    }
+    nextin--;
+    if (!(isspace(*nextin) || isprint(*nextin))) {
+       putchar('\b');
+       putchar(' ');
+       putchar('\b');
+    }
+    putchar('\b');
+    putchar(' ');
+    putchar('\b');
+}
+
+
+/*
+ * setlineend()
+ *
+ *  Decide if it's time to send the current line up to the user
+ * process.
+ */
+
+static void
+setlineend()
+{
+    if (nextin == nextout) {
+       return;
+    }
+    if (characteratatime()) {
+       lineend = 1;
+    } else if (nextin >= (linein+sizeof linein)) {
+       lineend = 1;
+    } else {
+       int c = *(nextin-1);
+       if ((c == termIntChar)
+               || (c == termQuitChar)
+               || (c == termEofChar)) {
+           lineend = 1;
+       } else if (c == termFlushChar) {
+           lineend = 1;
+       } else if ((c == '\n') || (c == '\r')) {
+           lineend = 1;
+       }
+    }
+    /* Otherwise, leave it alone (reset by 'consumechar') */
+}
+
+/*
+ * OK, what we do here is:
+ *
+ *   o  If we are echoing, then
+ *     o  Look for character erase, line kill characters
+ *     o  Echo the character (using '^' if a control character)
+ *   o  Put the character in the input buffer
+ *   o  Set 'lineend' as necessary
+ */
+
+static void
+DoNextChar(c)
+int    c;                      /* Character to process */
+{
+    static char literalnextcharacter = 0;
+
+    if (nextin >= (linein+sizeof linein)) {
+       putchar('\7');          /* Ring bell */
+       setlineend();
+       return;
+    }
+    if (MODE_LOCAL_CHARS(globalmode)) {
+       /* Look for some special character */
+       if (!literalnextcharacter) {
+           if (c == termEraseChar) {
+               killone();
+               setlineend();
+               return;
+           } else if (c == termKillChar) {
+               while (nextin != linein) {
+                   killone();
+               }
+               setlineend();
+               return;
+           } else if (c == termLiteralNextChar) {
+               literalnextcharacter = 1;
+               return;
+           }
+       }
+
+       if (MODE_LOCAL_ECHO(globalmode)) {
+           if ((literalnextcharacter == 0) && ((c == '\r') || (c == '\n'))) {
+               putchar('\r');
+               putchar('\n');
+               c = '\n';
+           } else if (!isprint(c) && !isspace(c)) {
+               putchar('^');
+               putchar(c^0x40);
+           } else {
+               putchar(c);
+           }
+       }
+       literalnextcharacter = 0;
+    }
+    *nextin++ = c;
+    setlineend();
+}
+
+static int
+inputExists()
+{
+    int input;
+    static state = 0;
+
+    while (ctrlCCount) {
+       DoNextChar(0x03);
+       ctrlCCount--;
+    }
+    if (lineend) {
+       return 1;
+    }
+#if    1       /* For BIOS variety of calls */
+    if (kbhit() == 0) {
+       return lineend;
+    }
+    input = getch();                   /* MSC - get console character */
+    if ((input&0xff) == 0) {
+       DoNextChar(0x01);               /* ^A */
+    } else {
+       DoNextChar(input&0xff);
+    }
+#else  /* 0 */
+    if ((input = dirconio()) == -1) {
+       return lineend;
+    }
+    if ((input&0xff) == 0) {
+       if ((input&0xff00) == 0x0300) {         /* Null */
+           DoNextChar(0);
+       } else {
+           DoNextChar(0x01);
+           if (input&0x8000) {
+               DoNextChar(0x01);
+               DoNextChar((input>>8)&0x7f);
+           } else {
+               DoNextChar((input>>8)&0xff);
+           }
+       }
+    } else {
+       DoNextChar(input&0xff);
+    }
+#endif /* 0 */
+    return lineend;
+}
+
+
+void
+CtrlCInterrupt()
+{
+    if (!MODE_COMMAND_LINE(globalmode)) {
+       ctrlCCount++;           /* XXX */
+       signal(SIGINT, CtrlCInterrupt);
+    } else {
+       closeallsockets();
+       exit(1);
+    }
+}
+\f
+/*
+ * The MSDOS routines, called from elsewhere.
+ */
+
+
+static int
+TerminalAutoFlush()                            /* MSDOS */
+{
+    return 1;
+}
+
+static int
+TerminalCanRead()
+{
+    return inputExists();
+}
+
+
+/*
+ * Flush output to the terminal
+ */
+static void
+TerminalFlushOutput()                          /* MSDOS */
+{
+}
+
+
+static void
+TerminalNewMode(f)                             /* MSDOS */
+register int f;
+{
+    globalmode = f;
+    signal(SIGINT, CtrlCInterrupt);
+}
+
+
+int
+TerminalRead(fd, buffer, count)
+int    fd;
+char   *buffer;
+int    count;
+{
+    int done = 0;
+
+    for (;;) {
+       while (inputExists() && (done < count)) {
+           *buffer++ = *nextout;
+           consumechar();
+           done++;
+       }
+       if (done) {
+           return(done);
+       } else {
+           return 0;
+       }
+    }
+}
+
+
+static void
+TerminalSaveState()                            /* MSDOS */
+{
+}
+
+int
+TerminalSpecialChars(c)                        /* MSDOS */
+{
+    return 1;
+}
+
+
+static void
+TerminalRestoreState()                         /* MSDOS */
+{
+}
+
+
+static int
+TerminalWrite(fd, buffer, count)               /* MSDOS */
+int    fd;
+char   *buffer;
+int    count;
+{
+    return fwrite(buffer, sizeof (char), count, stdout);
+}
+
+
+static int
+NetClose(fd)
+{
+    return closesocket(fd);
+}
+
+static void
+NetNonblockingIO(fd, onoff)                            /* MSDOS */
+int
+       fd,
+       onoff;
+{
+    if (SetSockOpt(net, SOL_SOCKET, SO_NONBLOCKING, onoff)) {
+       perror("setsockop (SO_NONBLOCKING) ");
+       ExitString(stderr, "exiting\n", 1);
+    }
+}
+
+static void
+NetSigIO(fd)                           /* MSDOS */
+int fd;
+{
+}
+
+static void
+NetSetPgrp(fd)                         /* MSDOS */
+int fd;
+{
+}
 
 
-static struct {
-    int
-       system,                 /* what the current time is */
-       echotoggle,             /* last time user entered echo character */
-       modenegotiated,         /* last time operating mode negotiated */
-       didnetreceive,          /* last time we read data from network */
-       gotDM;                  /* when did we last see a data mark */
-} clocks;
 
 
-#define        settimer(x)     clocks.x = clocks.system++
+#endif /* defined(MSDOS) */
 \f
 /*
  * Initialize variables.
 \f
 /*
  * Initialize variables.
@@ -308,7 +962,11 @@ static struct {
 static void
 tninit()
 {
 static void
 tninit()
 {
+#if    defined(TN3270)
+    Sent3270TerminalType = 0;
     Ifrontp = Ibackp = Ibuf;
     Ifrontp = Ibackp = Ibuf;
+#endif /* defined(TN3270) */
+
     tfrontp = tbackp = ttyobuf;
     nfrontp = nbackp = netobuf;
     
     tfrontp = tbackp = ttyobuf;
     nfrontp = nbackp = netobuf;
     
@@ -321,13 +979,12 @@ tninit()
 
     connected = net = scc = tcc = In3270 = ISend = 0;
     telnetport = 0;
 
     connected = net = scc = tcc = In3270 = ISend = 0;
     telnetport = 0;
-
-    SYNCHing = 0;
-    Sent3270TerminalType = 0;
-
 #if    defined(unix)
     HaveInput = 0;
 #endif /* defined(unix) */
 #if    defined(unix)
     HaveInput = 0;
 #endif /* defined(unix) */
+
+    SYNCHing = 0;
+
     errno = 0;
 
     flushline = 0;
     errno = 0;
 
     flushline = 0;
@@ -490,6 +1147,33 @@ register char *argument;
        argument++;
     }
 }
        argument++;
     }
 }
+
+/*
+ * SetSockOpt()
+ *
+ * Compensate for differences in 4.2 and 4.3 systems.
+ */
+
+static int
+SetSockOpt(fd, level, option, yesno)
+int
+       fd,
+       level,
+       option,
+       yesno;
+{
+#ifndef        NOT43
+    return setsockopt(fd, level, option,
+                               (char *)&yesno, sizeof yesno);
+#else  /* NOT43 */
+    if (yesno == 0) {          /* Can't do that in 4.2! */
+       fprintf(stderr, "Error: attempt to turn off an option 0x%x.\n",
+                               option);
+       return -1;
+    }
+    return setsockopt(fd, level, option, 0, 0);
+#endif /* NOT43 */
+}
 \f
 /*
  * The following are routines used to print out debugging information.
 \f
 /*
  * The following are routines used to print out debugging information.
@@ -577,7 +1261,7 @@ int        length;                 /* length of suboption data */
                    char tmpbuf[sizeof subbuffer];
                    int minlen = min(length, sizeof tmpbuf);
 
                    char tmpbuf[sizeof subbuffer];
                    int minlen = min(length, sizeof tmpbuf);
 
-                   bcopy(pointer+2, tmpbuf, minlen);
+                   memcpy(tmpbuf, pointer+2, minlen);
                    tmpbuf[minlen-1] = 0;
                    fprintf(NetTrace, "is %s.\n", tmpbuf);
                }
                    tmpbuf[minlen-1] = 0;
                    fprintf(NetTrace, "is %s.\n", tmpbuf);
                }
@@ -645,7 +1329,7 @@ netflush()
 
     if ((n = nfrontp - nbackp) > 0) {
        if (!neturg) {
 
     if ((n = nfrontp - nbackp) > 0) {
        if (!neturg) {
-           n = write(net, nbackp, n);  /* normal write */
+           n = send(net, nbackp, n, 0);        /* normal write */
        } else {
            n = neturg - nbackp;
            /*
        } else {
            n = neturg - nbackp;
            /*
@@ -667,7 +1351,7 @@ netflush()
        if (errno != ENOBUFS && errno != EWOULDBLOCK) {
            setcommandmode();
            perror(hostname);
        if (errno != ENOBUFS && errno != EWOULDBLOCK) {
            setcommandmode();
            perror(hostname);
-           close(net);
+           NetClose(net);
            neturg = 0;
            longjmp(peerdied, -1);
            /*NOTREACHED*/
            neturg = 0;
            longjmp(peerdied, -1);
            /*NOTREACHED*/
@@ -771,7 +1455,7 @@ netclear()
                next = nextitem(next);
            } while (wewant(next) && (nfrontp > next));
            length = next-thisitem;
                next = nextitem(next);
            } while (wewant(next) && (nfrontp > next));
            length = next-thisitem;
-           bcopy(thisitem, good, length);
+           memcpy(good, thisitem, length);
            good += length;
            thisitem = next;
        } else {
            good += length;
            thisitem = next;
        } else {
@@ -855,9 +1539,9 @@ ttyflush()
 
     if ((n = tfrontp - tbackp) > 0) {
        if (!(SYNCHing||flushout)) {
 
     if ((n = tfrontp - tbackp) > 0) {
        if (!(SYNCHing||flushout)) {
-           n = write(tout, tbackp, n);
+           n = TerminalWrite(tout, tbackp, n);
        } else {
        } else {
-           ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
+           TerminalFlushOutput();
            /* we leave 'n' alone! */
        }
     }
            /* we leave 'n' alone! */
        }
     }
@@ -933,162 +1617,6 @@ doescape()
 }
 #endif /* defined(unix) */
 \f
 }
 #endif /* defined(unix) */
 \f
-static int     globalmode = 0;
-/*     Various modes */
-#define        MODE_LINE(m)    (modelist[m].modetype & LINE)
-#define        MODE_LOCAL_CHARS(m)     (modelist[m].modetype &  LOCAL_CHARS)
-
-#define        LOCAL_CHARS     0x01            /* Characters processed locally */
-#define        LINE            0x02            /* Line-by-line mode of operation */
-
-static struct {
-    char *modedescriptions;
-    char modetype;
-} modelist[] = {
-       { "telnet command mode", 0 },
-       { "character-at-a-time mode", 0 },
-       { "character-at-a-time mode (local echo)", LOCAL_CHARS },
-       { "line-by-line mode (remote echo)", LINE | LOCAL_CHARS },
-       { "line-by-line mode", LINE | LOCAL_CHARS },
-       { "line-by-line mode (local echoing suppressed)", LINE | LOCAL_CHARS },
-       { "3270 mode", 0 },
-};
-/*
- * Mode - set up terminal to a specific mode.
- */
-
-
-static void
-mode(f)
-       register int f;
-{
-    static int prevmode = 0;
-    struct tchars *tc;
-    struct tchars tc3;
-    struct ltchars *ltc;
-    struct sgttyb sb;
-    int onoff;
-#if    defined(unix)
-    int old;
-#endif /* defined(unix) */
-    struct     tchars notc2;
-    struct     ltchars noltc2;
-    static struct      tchars notc =   { -1, -1, -1, -1, -1, -1 };
-    static struct      ltchars noltc = { -1, -1, -1, -1, -1, -1 };
-
-    globalmode = f;
-    if (prevmode == f)
-       return;
-#if    defined(unix)
-    old = prevmode;
-#endif /* defined(unix) */
-    prevmode = f;
-    sb = nttyb;
-
-    switch (f) {
-
-    case 0:
-       onoff = 0;
-       tc = &otc;
-       ltc = &oltc;
-       break;
-
-    case 1:            /* remote character processing, remote echo */
-    case 2:            /* remote character processing, local echo */
-    case 6:            /* 3270 mode - like 1, but with xon/xoff local */
-                   /* (might be nice to have "6" in telnet also...) */
-           sb.sg_flags |= CBREAK;
-           if ((f == 1) || (f == 6)) {
-               sb.sg_flags &= ~(ECHO|CRMOD);
-           } else {
-               sb.sg_flags |= ECHO|CRMOD;
-           }
-           sb.sg_erase = sb.sg_kill = -1;
-           if (f == 6) {
-               tc = &tc3;
-               tc3 = notc;
-                   /* get XON, XOFF characters */
-               tc3.t_startc = otc.t_startc;
-               tc3.t_stopc = otc.t_stopc;
-           } else {
-               /*
-                * If user hasn't specified one way or the other,
-                * then default to not trapping signals.
-                */
-               if (!donelclchars) {
-                   localchars = 0;
-               }
-               if (localchars) {
-                   notc2 = notc;
-                   notc2.t_intrc = ntc.t_intrc;
-                   notc2.t_quitc = ntc.t_quitc;
-                   tc = &notc2;
-               } else {
-                   tc = &notc;
-               }
-           }
-           ltc = &noltc;
-           onoff = 1;
-           break;
-    case 3:            /* local character processing, remote echo */
-    case 4:            /* local character processing, local echo */
-    case 5:            /* local character processing, no echo */
-           sb.sg_flags &= ~CBREAK;
-           sb.sg_flags |= CRMOD;
-           if (f == 4)
-               sb.sg_flags |= ECHO;
-           else
-               sb.sg_flags &= ~ECHO;
-           notc2 = ntc;
-           tc = &notc2;
-           noltc2 = oltc;
-           ltc = &noltc2;
-#if defined(unix)
-           /*
-            * If user hasn't specified one way or the other,
-            * then default to trapping signals.
-            */
-           if (!donelclchars) {
-               localchars = 1;
-           }
-           if (localchars) {
-               notc2.t_brkc = nltc.t_flushc;
-               noltc2.t_flushc = -1;
-           } else {
-               notc2.t_intrc = notc2.t_quitc = -1;
-           }
-#else  /* defined(unix) */
-           notc2.t_intrc = -1;
-#endif /* defined(unix) */
-           noltc2.t_suspc = escape;
-           noltc2.t_dsuspc = -1;
-           onoff = 1;
-           break;
-
-    default:
-           return;
-    }
-    ioctl(tin, TIOCSLTC, (char *)ltc);
-    ioctl(tin, TIOCSETC, (char *)tc);
-    ioctl(tin, TIOCSETP, (char *)&sb);
-#if    (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR))
-    ioctl(tin, FIONBIO, (char *)&onoff);
-    ioctl(tout, FIONBIO, (char *)&onoff);
-#endif /* (!defined(TN3270)) || ((!defined(NOT43)) || defined(PUTCHAR)) */
-#if    defined(TN3270) && !defined(DEBUG)
-    ioctl(tin, FIOASYNC, (char *)&onoff);
-#endif /* defined(TN3270) && !defined(DEBUG) */
-
-#if    defined(unix)
-    if (MODE_LINE(f)) {
-       signal(SIGTSTP, doescape);
-    } else if (MODE_LINE(old)) {
-       signal(SIGTSTP, SIG_DFL);
-       sigsetmask(sigblock(0) & ~(1<<(SIGTSTP-1)));
-    }
-#endif /* defined(unix) */
-}
-\f
 /*
  * These routines decides on what the mode should be (based on the values
  * of various global variables).
 /*
  * These routines decides on what the mode should be (based on the values
  * of various global variables).
@@ -1120,14 +1648,14 @@ getconnmode()
 void
 setconnmode()
 {
 void
 setconnmode()
 {
-    mode(getconnmode());
+    TerminalNewMode(getconnmode());
 }
 
 
 void
 setcommandmode()
 {
 }
 
 
 void
 setcommandmode()
 {
-    mode(0);
+    TerminalNewMode(0);
 }
 \f
 static void
 }
 \f
 static void
@@ -1280,18 +1808,25 @@ suboption()
             * on the format of our screen, and (in the future) color
             * capaiblities.
             */
             * on the format of our screen, and (in the future) color
             * capaiblities.
             */
-           if ((initscr() != ERR) &&   /* Initialize curses to get line size */
-               (LINES >= 24) && (COLS >= 80)) {
+#if    defined(unix)
+           if (initscr() != ERR) {     /* Initialize curses to get line size */
+               MaxNumberLines = LINES;
+               MaxNumberColumns = COLS;
+           }
+#else  /* defined(unix) */
+           InitTerminal();
+#endif /* defined(unix) */
+           if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
                Sent3270TerminalType = 1;
                Sent3270TerminalType = 1;
-               if ((LINES >= 27) && (COLS >= 132)) {
+               if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
                    MaxNumberLines = 27;
                    MaxNumberColumns = 132;
                    sb_terminal[SBTERMMODEL] = '5';
                    MaxNumberLines = 27;
                    MaxNumberColumns = 132;
                    sb_terminal[SBTERMMODEL] = '5';
-               } else if (LINES >= 43) {
+               } else if (MaxNumberLines >= 43) {
                    MaxNumberLines = 43;
                    MaxNumberColumns = 80;
                    sb_terminal[SBTERMMODEL] = '4';
                    MaxNumberLines = 43;
                    MaxNumberColumns = 80;
                    sb_terminal[SBTERMMODEL] = '4';
-               } else if (LINES >= 32) {
+               } else if (MaxNumberLines >= 32) {
                    MaxNumberLines = 32;
                    MaxNumberColumns = 80;
                    sb_terminal[SBTERMMODEL] = '3';
                    MaxNumberLines = 32;
                    MaxNumberColumns = 80;
                    sb_terminal[SBTERMMODEL] = '3';
@@ -1308,7 +1843,7 @@ suboption()
                        "Programming error:  MAXSCREENSIZE too small.\n", 1);
                    /*NOTREACHED*/
                }
                        "Programming error:  MAXSCREENSIZE too small.\n", 1);
                    /*NOTREACHED*/
                }
-               bcopy(sb_terminal, nfrontp, sizeof sb_terminal);
+               memcpy(nfrontp, sb_terminal, sizeof sb_terminal);
                printsub(">", nfrontp+2, sizeof sb_terminal-2);
                nfrontp += sizeof sb_terminal;
                return;
                printsub(">", nfrontp+2, sizeof sb_terminal-2);
                nfrontp += sizeof sb_terminal;
                return;
@@ -1662,18 +2197,22 @@ register char   *buffer;                /* where the data is */
 register int   count;                  /* how much to send */
 {
     int origCount;
 register int   count;                  /* how much to send */
 {
     int origCount;
+#if    defined(unix)
     fd_set     o;
 
     fd_set     o;
 
-    origCount = count;
     FD_ZERO(&o);
     FD_ZERO(&o);
+#endif /* defined(unix) */
+    origCount = count;
 
     while (count) {
        if (tfrontp >= ttyobuf+sizeof ttyobuf) {
            ttyflush();
            while (tfrontp >= ttyobuf+sizeof ttyobuf) {
 
     while (count) {
        if (tfrontp >= ttyobuf+sizeof ttyobuf) {
            ttyflush();
            while (tfrontp >= ttyobuf+sizeof ttyobuf) {
+#if    defined(unix)
                FD_SET(tout, &o);
                (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
                                                (struct timeval *) 0);
                FD_SET(tout, &o);
                (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
                                                (struct timeval *) 0);
+#endif /* defined(unix) */
                ttyflush();
            }
        }
                ttyflush();
            }
        }
@@ -1691,20 +2230,26 @@ register int    count;                  /* how much to send */
 void
 EmptyTerminal()
 {
 void
 EmptyTerminal()
 {
+#if    defined(unix)
     fd_set     o;
 
     FD_ZERO(&o);
     fd_set     o;
 
     FD_ZERO(&o);
+#endif /* defined(unix) */
 
     if (tfrontp == tbackp) {
 
     if (tfrontp == tbackp) {
+#if    defined(unix)
        FD_SET(tout, &o);
        (void) select(tout+1, (int *) 0, &o, (int *) 0,
                        (struct timeval *) 0);  /* wait for TTLOWAT */
        FD_SET(tout, &o);
        (void) select(tout+1, (int *) 0, &o, (int *) 0,
                        (struct timeval *) 0);  /* wait for TTLOWAT */
+#endif /* defined(unix) */
     } else {
        while (tfrontp != tbackp) {
            ttyflush();
     } else {
        while (tfrontp != tbackp) {
            ttyflush();
+#if    defined(unix)
            FD_SET(tout, &o);
            (void) select(tout+1, (int *) 0, &o, (int *) 0,
                                (struct timeval *) 0);  /* wait for TTLOWAT */
            FD_SET(tout, &o);
            (void) select(tout+1, (int *) 0, &o, (int *) 0,
                                (struct timeval *) 0);  /* wait for TTLOWAT */
+#endif /* defined(unix) */
        }
     }
 }
        }
     }
 }
@@ -1721,7 +2266,7 @@ Push3270()
     if (scc) {
        if (Ifrontp+scc > Ibuf+sizeof Ibuf) {
            if (Ibackp != Ibuf) {
     if (scc) {
        if (Ifrontp+scc > Ibuf+sizeof Ibuf) {
            if (Ibackp != Ibuf) {
-               bcopy(Ibackp, Ibuf, Ifrontp-Ibackp);
+               memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
                Ifrontp -= (Ibackp-Ibuf);
                Ibackp = Ibuf;
            }
                Ifrontp -= (Ibackp-Ibuf);
                Ibackp = Ibuf;
            }
@@ -1849,12 +2394,14 @@ int     block;                  /* should we block in the select ? */
     if ((!MODE_LINE(globalmode) || flushline) && NETBYTES()) {
        FD_SET(net, &obits);
     } 
     if ((!MODE_LINE(globalmode) || flushline) && NETBYTES()) {
        FD_SET(net, &obits);
     } 
+#if    !defined(MSDOS)
     if (TTYBYTES()) {
        FD_SET(tout, &obits);
     }
     if ((tcc == 0) && NETROOM()) {
        FD_SET(tin, &ibits);
     }
     if (TTYBYTES()) {
        FD_SET(tout, &obits);
     }
     if ((tcc == 0) && NETROOM()) {
        FD_SET(tin, &ibits);
     }
+#endif /* !defined(MSDOS) */
 #   if !defined(TN3270)
     if (TTYROOM()) {
        FD_SET(net, &ibits);
 #   if !defined(TN3270)
     if (TTYROOM()) {
        FD_SET(net, &ibits);
@@ -1874,7 +2421,7 @@ int       block;                  /* should we block in the select ? */
     }
 #endif /* defined(TN3270) && defined(unix) */
     if ((c = select(16, &ibits, &obits, &xbits,
     }
 #endif /* defined(TN3270) && defined(unix) */
     if ((c = select(16, &ibits, &obits, &xbits,
-                       block? (struct timeval *)0 : &TimeValue)) < 1) {
+                       block? (struct timeval *)0 : &TimeValue)) < 0) {
        if (c == -1) {
                    /*
                     * we can get EINTR if we are in line mode,
        if (c == -1) {
                    /*
                     * we can get EINTR if we are in line mode,
@@ -1972,20 +2519,20 @@ int     block;                  /* should we block in the select ? */
            if (atmark) {
                c = recv(net, sbp+scc, canread, MSG_OOB);
                if ((c == -1) && (errno == EINVAL)) {
            if (atmark) {
                c = recv(net, sbp+scc, canread, MSG_OOB);
                if ((c == -1) && (errno == EINVAL)) {
-                   c = read(net, sbp+scc, canread);
+                   c = recv(net, sbp+scc, canread, 0);
                    if (clocks.didnetreceive < clocks.gotDM) {
                        SYNCHing = stilloob(net);
                    }
                }
            } else {
                    if (clocks.didnetreceive < clocks.gotDM) {
                        SYNCHing = stilloob(net);
                    }
                }
            } else {
-               c = read(net, sbp+scc, canread);
+               c = recv(net, sbp+scc, canread, 0);
            }
        } else {
            }
        } else {
-           c = read(net, sbp+scc, canread);
+           c = recv(net, sbp+scc, canread, 0);
        }
        settimer(didnetreceive);
 #else  /* !defined(SO_OOBINLINE) */
        }
        settimer(didnetreceive);
 #else  /* !defined(SO_OOBINLINE) */
-       c = read(net, sbp+scc, canread);
+       c = recv(net, sbp+scc, canread, 0);
 #endif /* !defined(SO_OOBINLINE) */
        if (c < 0 && errno == EWOULDBLOCK) {
            c = 0;
 #endif /* !defined(SO_OOBINLINE) */
        if (c < 0 && errno == EWOULDBLOCK) {
            c = 0;
@@ -2002,21 +2549,28 @@ int     block;                  /* should we block in the select ? */
     /*
      * Something to read from the tty...
      */
     /*
      * Something to read from the tty...
      */
-    if (FD_ISSET(tin, &ibits)) {
+#if    defined(MSDOS)
+    if ((tcc == 0) && NETROOM() && TerminalCanRead())
+#else  /* defined(MSDOS) */
+    if (FD_ISSET(tin, &ibits))
+#endif /* defined(MSDOS) */
+                                   {
        FD_CLR(tin, &ibits);
        if (tcc == 0) {
            tbp = tibuf;        /* nothing left, reset */
        }
        FD_CLR(tin, &ibits);
        if (tcc == 0) {
            tbp = tibuf;        /* nothing left, reset */
        }
-       c = read(tin, tbp, tibuf+sizeof tibuf - tbp);
+       c = TerminalRead(tin, tbp, tibuf+sizeof tibuf - tbp);
        if (c < 0 && errno == EWOULDBLOCK) {
            c = 0;
        } else {
        if (c < 0 && errno == EWOULDBLOCK) {
            c = 0;
        } else {
+#if    defined(unix)
            /* EOF detection for line mode!!!! */
            if (c == 0 && MODE_LOCAL_CHARS(globalmode)) {
                        /* must be an EOF... */
                *tbp = ntc.t_eofc;
                c = 1;
            }
            /* EOF detection for line mode!!!! */
            if (c == 0 && MODE_LOCAL_CHARS(globalmode)) {
                        /* must be an EOF... */
                *tbp = ntc.t_eofc;
                c = 1;
            }
+#endif /* defined(unix) */
            if (c <= 0) {
                tcc = c;
                return -1;
            if (c <= 0) {
                tcc = c;
                return -1;
@@ -2065,25 +2619,7 @@ int      block;                  /* should we block in the select ? */
                    }
                }
                if (localchars) {
                    }
                }
                if (localchars) {
-                   if (sc == ntc.t_intrc) {
-                       intp();
-                       break;
-                   } else if (sc == ntc.t_quitc) {
-                       sendbrk();
-                       break;
-                   } else if (sc == nltc.t_flushc) {
-                       NET2ADD(IAC, AO);
-                       if (autoflush) {
-                           doflush();
-                       }
-                       break;
-                   } else if (MODE_LOCAL_CHARS(globalmode)) {
-                       ;
-                   } else if (sc == nttyb.sg_kill) {
-                       NET2ADD(IAC, EL);
-                       break;
-                   } else if (sc == nttyb.sg_erase) {
-                       NET2ADD(IAC, EC);
+                   if (TerminalSpecialChars(sc) == 0) {
                        break;
                    }
                }
                        break;
                    }
                }
@@ -2130,7 +2666,12 @@ int      block;                  /* should we block in the select ? */
        returnValue = Push3270();
 #      endif /* !defined(TN3270) */
     }
        returnValue = Push3270();
 #      endif /* !defined(TN3270) */
     }
-    if (FD_ISSET(tout, &obits) && (TTYBYTES() > 0)) {
+#if    defined(MSDOS)
+    if (TTYBYTES())
+#else  /* defined(MSDOS) */
+    if (FD_ISSET(tout, &obits) && (TTYBYTES() > 0))
+#endif /* defined(MSDOS) */
+                                                   {
        FD_CLR(tout, &obits);
        returnValue = ttyflush();
     }
        FD_CLR(tout, &obits);
        returnValue = ttyflush();
     }
@@ -2143,7 +2684,12 @@ int      block;                  /* should we block in the select ? */
 static void
 telnet()
 {
 static void
 telnet()
 {
-    int on = 1;
+#if    defined(MSDOS)
+#define        SCHED_BLOCK     0               /* Don't block in MSDOS */
+#else  /* defined(MSDOS) */
+#define        SCHED_BLOCK     1
+#endif /* defined(MSDOS) */
+
 #if    defined(TN3270) && defined(unix)
     int myPid;
 #endif /* defined(TN3270) */
 #if    defined(TN3270) && defined(unix)
     int myPid;
 #endif /* defined(TN3270) */
@@ -2157,26 +2703,20 @@ telnet()
     FD_ZERO(&obits);
     FD_ZERO(&xbits);
 
     FD_ZERO(&obits);
     FD_ZERO(&xbits);
 
-    ioctl(net, FIONBIO, (char *)&on);
+    NetNonblockingIO(net, 1);
 
 #if    defined(TN3270)
 #if    !defined(DEBUG)         /* DBX can't handle! */
 
 #if    defined(TN3270)
 #if    !defined(DEBUG)         /* DBX can't handle! */
-    ioctl(net, FIOASYNC, (char *)&on); /* hear about input */
+    NetSigIO(net, 1);
 #endif /* !defined(DEBUG) */
 
 #endif /* !defined(DEBUG) */
 
-#if    defined(unix)
-    myPid = getpid();
-#if    defined(NOT43)
-    myPid = -myPid;
-#endif /* defined(NOT43) */
-    ioctl(net, SIOCSPGRP, (char *)&myPid);     /* set my pid */
-#endif /* defined(unix) */
-
+    NetSetPgrp(net);
 #endif /* defined(TN3270) */
 
 #endif /* defined(TN3270) */
 
-#if    defined(SO_OOBINLINE)
-    setsockopt(net, SOL_SOCKET, SO_OOBINLINE, &on, sizeof on);
-#endif /* defined(SO_OOBINLINE) */
+
+#if    defined(SO_OOBINLINE) && !defined(MSDOS)
+    SetSockOpt(net, SOL_SOCKET, SO_OOBINLINE, 1);
+#endif /* defined(SO_OOBINLINE) && !defined(MSDOS) */
 
 #   if !defined(TN3270)
     if (telnetport) {
 
 #   if !defined(TN3270)
     if (telnetport) {
@@ -2191,7 +2731,7 @@ telnet()
 
 #   if !defined(TN3270)
     for (;;) {
 
 #   if !defined(TN3270)
     for (;;) {
-       if (Scheduler(1) == -1) {
+       if (Scheduler(SCHED_BLOCK) == -1) {
            setcommandmode();
            return;
        }
            setcommandmode();
            return;
        }
@@ -2201,7 +2741,7 @@ telnet()
        int schedValue;
 
        while (!In3270) {
        int schedValue;
 
        while (!In3270) {
-           if (Scheduler(1) == -1) {
+           if (Scheduler(SCHED_BLOCK) == -1) {
                setcommandmode();
                return;
            }
                setcommandmode();
                return;
            }
@@ -2222,7 +2762,7 @@ telnet()
            schedValue = DoTerminalOutput();
        }
        if (schedValue) {
            schedValue = DoTerminalOutput();
        }
        if (schedValue) {
-           if (Scheduler(1) == -1) {
+           if (Scheduler(SCHED_BLOCK) == -1) {
                setcommandmode();
                return;
            }
                setcommandmode();
                return;
            }
@@ -2413,13 +2953,12 @@ togdebug()
 {
 #ifndef        NOT43
     if (net > 0 &&
 {
 #ifndef        NOT43
     if (net > 0 &&
-       setsockopt(net, SOL_SOCKET, SO_DEBUG, (char *)&debug, sizeof(debug))
-                                                                       < 0) {
+       (SetSockOpt(net, SOL_SOCKET, SO_DEBUG, debug)) < 0) {
            perror("setsockopt (SO_DEBUG)");
     }
 #else  /* NOT43 */
     if (debug) {
            perror("setsockopt (SO_DEBUG)");
     }
 #else  /* NOT43 */
     if (debug) {
-       if (net > 0 && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
+       if (net > 0 && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
            perror("setsockopt (SO_DEBUG)");
     } else
        printf("Cannot turn off socket debugging\n");
            perror("setsockopt (SO_DEBUG)");
     } else
        printf("Cannot turn off socket debugging\n");
@@ -2582,12 +3121,22 @@ static struct setlist Setlist[] = {
     { "escape",        "character to escape back to telnet command mode", &escape },
     { " ", "" },
     { " ", "The following need 'localchars' to be toggled true", 0 },
     { "escape",        "character to escape back to telnet command mode", &escape },
     { " ", "" },
     { " ", "The following need 'localchars' to be toggled true", 0 },
+#if    defined(unix)
     { "erase", "character to cause an Erase Character", &nttyb.sg_erase },
     { "flushoutput", "character to cause an Abort Oubput", &nltc.t_flushc },
     { "interrupt", "character to cause an Interrupt Process", &ntc.t_intrc },
     { "kill",  "character to cause an Erase Line", &nttyb.sg_kill },
     { "quit",  "character to cause a Break", &ntc.t_quitc },
     { "eof",   "character to cause an EOF ", &ntc.t_eofc },
     { "erase", "character to cause an Erase Character", &nttyb.sg_erase },
     { "flushoutput", "character to cause an Abort Oubput", &nltc.t_flushc },
     { "interrupt", "character to cause an Interrupt Process", &ntc.t_intrc },
     { "kill",  "character to cause an Erase Line", &nttyb.sg_kill },
     { "quit",  "character to cause a Break", &ntc.t_quitc },
     { "eof",   "character to cause an EOF ", &ntc.t_eofc },
+#endif /* defined(unix) */
+#if    defined(MSDOS)
+    { "erase", "character to cause an Erase Character", &termEraseChar },
+    { "flushoutput", "character to cause an Abort Oubput", &termFlushChar },
+    { "interrupt", "character to cause an Interrupt Process", &termIntChar },
+    { "kill",  "character to cause an Erase Line", &termKillChar },
+    { "quit",  "character to cause a Break", &termQuitChar },
+    { "eof",   "character to cause an EOF ", &termEofChar },
+#endif /* defined(MSDOS) */
     { 0 }
 };
 
     { 0 }
 };
 
@@ -2842,11 +3391,9 @@ suspend()
        setcommandmode();
 #if    defined(unix)
        kill(0, SIGTSTP);
        setcommandmode();
 #if    defined(unix)
        kill(0, SIGTSTP);
-#endif /* defined(unix) */
        /* reget parameters in case they were changed */
        /* reget parameters in case they were changed */
-       ioctl(0, TIOCGETP, (char *)&ottyb);
-       ioctl(0, TIOCGETC, (char *)&otc);
-       ioctl(0, TIOCGLTC, (char *)&oltc);
+       TerminalSaveState();
+#endif /* defined(unix) */
        return 1;
 }
 
        return 1;
 }
 
@@ -2859,7 +3406,7 @@ char      *argv[];        /* arguments */
     if (connected) {
        shutdown(net, 2);
        printf("Connection closed.\n");
     if (connected) {
        shutdown(net, 2);
        printf("Connection closed.\n");
-       close(net);
+       NetClose(net);
        connected = 0;
        /* reset options */
        tninit();
        connected = 0;
        /* reset options */
        tninit();
@@ -2951,15 +3498,16 @@ settranscom(argc, argv)
 #endif /* defined(TN3270) && defined(unix) */
 
 
 #endif /* defined(TN3270) && defined(unix) */
 
 
+
 static
 tn(argc, argv)
        int argc;
        char *argv[];
 {
     register struct hostent *host = 0;
 static
 tn(argc, argv)
        int argc;
        char *argv[];
 {
     register struct hostent *host = 0;
-#if defined(msdos)
+#if defined(MSDOS)
     char *cp;
     char *cp;
-#endif /* defined(msdos) */
+#endif /* defined(MSDOS) */
 
     if (connected) {
        printf("?Already connected to %s\n", hostname);
 
     if (connected) {
        printf("?Already connected to %s\n", hostname);
@@ -2977,13 +3525,13 @@ tn(argc, argv)
        printf("usage: %s host-name [port]\n", argv[0]);
        return 0;
     }
        printf("usage: %s host-name [port]\n", argv[0]);
        return 0;
     }
-#if    defined(msdos)
+#if    defined(MSDOS)
     for (cp = argv[1]; *cp; cp++) {
        if (isupper(*cp)) {
            *cp = tolower(*cp);
        }
     }
     for (cp = argv[1]; *cp; cp++) {
        if (isupper(*cp)) {
            *cp = tolower(*cp);
        }
     }
-#endif /* defined(msdos) */
+#endif /* defined(MSDOS) */
     sin.sin_addr.s_addr = inet_addr(argv[1]);
     if (sin.sin_addr.s_addr != -1) {
        sin.sin_family = AF_INET;
     sin.sin_addr.s_addr = inet_addr(argv[1]);
     if (sin.sin_addr.s_addr != -1) {
        sin.sin_family = AF_INET;
@@ -2994,9 +3542,10 @@ tn(argc, argv)
        if (host) {
            sin.sin_family = host->h_addrtype;
 #if    defined(h_addr)         /* In 4.3, this is a #define */
        if (host) {
            sin.sin_family = host->h_addrtype;
 #if    defined(h_addr)         /* In 4.3, this is a #define */
-           bcopy(host->h_addr_list[0], (caddr_t)&sin.sin_addr, host->h_length);
+           memcpy((caddr_t)&sin.sin_addr,
+                               host->h_addr_list[0], host->h_length);
 #else  /* defined(h_addr) */
 #else  /* defined(h_addr) */
-           bcopy(host->h_addr, (caddr_t)&sin.sin_addr, host->h_length);
+           memcpy((caddr_t)&sin.sin_addr, host->h_addr, host->h_length);
 #endif /* defined(h_addr) */
            hostname = host->h_name;
        } else {
 #endif /* defined(h_addr) */
            hostname = host->h_name;
        } else {
@@ -3035,13 +3584,9 @@ tn(argc, argv)
            perror("telnet: socket");
            return 0;
        }
            perror("telnet: socket");
            return 0;
        }
-#ifndef        NOT43
-       if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG,
-                               (char *)&debug, sizeof(debug)) < 0)
-#else  /* NOT43 */
-       if (debug && setsockopt(net, SOL_SOCKET, SO_DEBUG, 0, 0) < 0)
-#endif /* NOT43 */
+       if (debug && SetSockOpt(net, SOL_SOCKET, SO_DEBUG, 1) < 0) {
                perror("setsockopt (SO_DEBUG)");
                perror("setsockopt (SO_DEBUG)");
+       }
 
        if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
 #if    defined(h_addr)         /* In 4.3, this is a #define */
 
        if (connect(net, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
 #if    defined(h_addr)         /* In 4.3, this is a #define */
@@ -3053,11 +3598,11 @@ tn(argc, argv)
                errno = oerrno;
                perror((char *)0);
                host->h_addr_list++;
                errno = oerrno;
                perror((char *)0);
                host->h_addr_list++;
-               bcopy(host->h_addr_list[0],
-                   (caddr_t)&sin.sin_addr, host->h_length);
+               memcpy((caddr_t)&sin.sin_addr, 
+                       host->h_addr_list[0], host->h_length);
                fprintf(stderr, "Trying %s...\n",
                        inet_ntoa(sin.sin_addr));
                fprintf(stderr, "Trying %s...\n",
                        inet_ntoa(sin.sin_addr));
-               (void) close(net);
+               (void) NetClose(net);
                continue;
            }
 #endif /* defined(h_addr) */
                continue;
            }
 #endif /* defined(h_addr) */
@@ -3073,6 +3618,7 @@ tn(argc, argv)
     call(status, "status", "notmuch", 0);
     if (setjmp(peerdied) == 0)
        telnet();
     call(status, "status", "notmuch", 0);
     if (setjmp(peerdied) == 0)
        telnet();
+    NetClose(net);
     ExitString(stderr, "Connection closed by foreign host.\n",1);
     /*NOTREACHED*/
 }
     ExitString(stderr, "Connection closed by foreign host.\n",1);
     /*NOTREACHED*/
 }
@@ -3084,7 +3630,6 @@ static char
        openhelp[] =    "connect to a site",
        closehelp[] =   "close current connection",
        quithelp[] =    "exit telnet",
        openhelp[] =    "connect to a site",
        closehelp[] =   "close current connection",
        quithelp[] =    "exit telnet",
-       zhelp[] =       "suspend telnet",
        statushelp[] =  "print status information",
        helphelp[] =    "print help information",
        sendhelp[] =    "transmit special characters ('send ?' for more)",
        statushelp[] =  "print status information",
        helphelp[] =    "print help information",
        sendhelp[] =    "transmit special characters ('send ?' for more)",
@@ -3094,9 +3639,15 @@ static char
 #if    defined(TN3270) && defined(unix)
        transcomhelp[] = "specify Unix command for transparent mode pipe",
 #endif /* defined(TN3270) && defined(unix) */
 #if    defined(TN3270) && defined(unix)
        transcomhelp[] = "specify Unix command for transparent mode pipe",
 #endif /* defined(TN3270) && defined(unix) */
+#if    defined(unix)
+       zhelp[] =       "suspend telnet",
+#endif /* defined(unix */
+#if    defined(MSDOS)
+       shellhelp[] =   "invoke a subshell",
+#endif /* defined(MSDOS) */
        modehelp[] = "try to enter line-by-line or character-at-a-time mode";
 
        modehelp[] = "try to enter line-by-line or character-at-a-time mode";
 
-extern int     help();
+extern int     help(), shell();
 
 static struct cmd cmdtab[] = {
        { "close",      closehelp,      bye,            1, 1 },
 
 static struct cmd cmdtab[] = {
        { "close",      closehelp,      bye,            1, 1 },
@@ -3111,7 +3662,12 @@ static struct cmd cmdtab[] = {
 #if    defined(TN3270) && defined(unix)
        { "transcom",   transcomhelp,   settranscom,    1, 0 },
 #endif /* defined(TN3270) && defined(unix) */
 #if    defined(TN3270) && defined(unix)
        { "transcom",   transcomhelp,   settranscom,    1, 0 },
 #endif /* defined(TN3270) && defined(unix) */
+#if    defined(unix)
        { "z",          zhelp,          suspend,        1, 0 },
        { "z",          zhelp,          suspend,        1, 0 },
+#endif /* defined(unix) */
+#if    defined(MSDOS)
+       { "!",          shellhelp,      shell,          1, 0 },
+#endif /* defined(MSDOS) */
        { "?",          helphelp,       help,           1, 0 },
        0
 };
        { "?",          helphelp,       help,           1, 0 },
        0
 };
@@ -3262,20 +3818,9 @@ main(argc, argv)
     tninit();          /* Clear out things */
 
     NetTrace = stdout;
     tninit();          /* Clear out things */
 
     NetTrace = stdout;
-    ioctl(0, TIOCGETP, (char *)&ottyb);
-    ioctl(0, TIOCGETC, (char *)&otc);
-    ioctl(0, TIOCGLTC, (char *)&oltc);
-#if    defined(LNOFLSH)
-    ioctl(0, TIOCLGET, (char *)&autoflush);
-    autoflush = !(autoflush&LNOFLSH);  /* if LNOFLSH, no autoflush */
-#else  /* LNOFLSH */
-    autoflush = 1;
-#endif /* LNOFLSH */
-    ntc = otc;
-    nltc = oltc;
-    nttyb = ottyb;
-    setbuf(stdin, (char *)0);
-    setbuf(stdout, (char *)0);
+    TerminalSaveState();
+    autoflush = TerminalAutoFlush();
+
     prompt = argv[0];
     if (argc > 1 && !strcmp(argv[1], "-d")) {
        debug = 1;
     prompt = argv[0];
     if (argc > 1 && !strcmp(argv[1], "-d")) {
        debug = 1;