current version from monet
[unix-history] / usr / src / usr.bin / tn3270 / telnet.c
index c2fb6b0..4020ef7 100644 (file)
@@ -1,33 +1,24 @@
 /*
 /*
- *     Copyright (c) 1984, 1985, 1986 by the Regents of the
- *     University of California and by Gregory Glenn Minshall.
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
  *
  *
- *     Permission to use, copy, modify, and distribute these
- *     programs and their documentation for any purpose and
- *     without fee is hereby granted, provided that this
- *     copyright and permission appear on all copies and
- *     supporting documentation, the name of the Regents of
- *     the University of California not be used in advertising
- *     or publicity pertaining to distribution of the programs
- *     without specific prior permission, and notice be given in
- *     supporting documentation that copying and distribution is
- *     by permission of the Regents of the University of California
- *     and by Gregory Glenn Minshall.  Neither the Regents of the
- *     University of California nor Gregory Glenn Minshall make
- *     representations about the suitability of this software
- *     for any purpose.  It is provided "as is" without
- *     express or implied warranty.
+ * Redistribution and use in source and binary forms are permitted
+ * provided that this notice is preserved and that due credit is given
+ * to the University of California at Berkeley. The name of the University
+ * may not be used to endorse or promote products derived from this
+ * software without specific prior written permission. This software
+ * is provided ``as is'' without express or implied warranty.
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-static char copyright[] =
-"@(#) Copyright (c) 1984, 1985, 1986 Regents of the University of California.\n\
+char copyright[] =
+"@(#) Copyright (c) 1988 Regents of the University of California.\n\
  All rights reserved.\n";
  All rights reserved.\n";
-#endif /* not lint */
+#endif /* not lint */
 
 #ifndef lint
 
 #ifndef lint
-static char sccsid[] = "@(#)telnet.c   3.1  10/29/86";
-#endif /* not lint */
+static char sccsid[] = "@(#)telnet.c   1.18.1.1 (Berkeley) %G%";
+#endif /* not lint */
 
 /*
  * User telnet program, modified for use by tn3270.c.
 
 /*
  * User telnet program, modified for use by tn3270.c.
@@ -79,6 +70,11 @@ void setcommandmode(), command();    /* forward declarations */
 #endif /* !defined(TN3270) */
 
 #include <sys/types.h>
 #endif /* !defined(TN3270) */
 
 #include <sys/types.h>
+
+#if     defined(pyr)
+#define fd_set fdset_t
+#endif  /* defined(pyr) */
 #include <sys/socket.h>
 
 #include <netinet/in.h>
 #include <sys/socket.h>
 
 #include <netinet/in.h>
@@ -211,7 +207,8 @@ static int
        ISend,          /* trying to send network data in */
        debug = 0,
        crmod,
        ISend,          /* trying to send network data in */
        debug = 0,
        crmod,
-       netdata,
+       netdata,        /* Print out network data flow */
+       crlf,           /* Should '\r' be mapped to <CR><LF> (or <CR><NUL>)? */
        noasynch = 0,   /* User specified "-noasynch" on command line */
        askedSGA = 0,   /* We have talked about suppress go ahead */
        telnetport = 1;
        noasynch = 0,   /* User specified "-noasynch" on command line */
        askedSGA = 0,   /* We have talked about suppress go ahead */
        telnetport = 1;
@@ -615,6 +612,9 @@ int fd;
 #include <time.h>
 #include <signal.h>
 #include <process.h>
 #include <time.h>
 #include <signal.h>
 #include <process.h>
+#include <fcntl.h>
+#include <io.h>
+#include <dos.h>
 
 #if    !defined(SO_OOBINLINE)
 #define        SO_OOBINLINE
 
 #if    !defined(SO_OOBINLINE)
 #define        SO_OOBINLINE
@@ -630,6 +630,8 @@ static char
     termLiteralNextChar,
     termQuitChar;
 
     termLiteralNextChar,
     termQuitChar;
 
+static char
+    savedInState, savedOutState;
 \f
 /*
  * MSDOS doesn't have anyway of deciding whether a full-edited line
 \f
 /*
  * MSDOS doesn't have anyway of deciding whether a full-edited line
@@ -830,6 +832,9 @@ void
 CtrlCInterrupt()
 {
     if (!MODE_COMMAND_LINE(globalmode)) {
 CtrlCInterrupt()
 {
     if (!MODE_COMMAND_LINE(globalmode)) {
+       char far *Bios_Break = (char far *) (((long)0x40<<16)|0x71);
+
+       *Bios_Break = 0;
        ctrlCCount++;           /* XXX */
        signal(SIGINT, CtrlCInterrupt);
     } else {
        ctrlCCount++;           /* XXX */
        signal(SIGINT, CtrlCInterrupt);
     } else {
@@ -837,6 +842,38 @@ CtrlCInterrupt()
        exit(1);
     }
 }
        exit(1);
     }
 }
+
+int
+dosbinary(fd, onoff)
+int    fd;
+int    onoff;
+{
+    union REGS regs;
+    int oldstate;
+
+    /* Get old stuff */
+    regs.h.ah = 0x44;
+    regs.h.al = 0;
+    regs.x.bx = fd;
+    intdos(&regs, &regs);
+    oldstate = regs.h.dl&(1<<5);               /* Save state */
+
+    /* Set correct bits in new mode */
+    regs.h.dh = 0;
+    if (onoff) {
+       regs.h.dl |= 1<<5;
+    } else {
+       regs.h.dl &= ~(1<<5);
+    }
+
+    /* Set in new mode */
+    regs.h.ah = 0x44;
+    regs.h.al = 1;
+    regs.x.bx = fd;
+    intdos(&regs, &regs);
+
+    return oldstate;
+}
 \f
 /*
  * The MSDOS routines, called from elsewhere.
 \f
 /*
  * The MSDOS routines, called from elsewhere.
@@ -870,8 +907,66 @@ static void
 TerminalNewMode(f)                             /* MSDOS */
 register int f;
 {
 TerminalNewMode(f)                             /* MSDOS */
 register int f;
 {
+    union REGS inregs;
+    struct SREGS segregs;
+    static old_1b_offset = 0, old_1b_segment = 0;
+
     globalmode = f;
     globalmode = f;
-    signal(SIGINT, CtrlCInterrupt);
+    if (MODE_COMMAND_LINE(f)) {
+       signal(SIGINT, SIG_DFL);
+       if (old_1b_segment|old_1b_offset) {
+           inregs.h.ah = 0x25;
+           inregs.h.al = 0x1b;
+           inregs.x.dx = old_1b_offset;
+           segregs.ds = old_1b_segment;
+           intdosx(&inregs, &inregs, &segregs);
+           old_1b_segment = old_1b_offset = 0;
+       }
+       if (setmode(fileno(stdout), O_TEXT) == -1) {
+           ExitPerror("setmode (text)", 1);
+       }
+       (void) dosbinary(fileno(stdout), 0);
+       if (setmode(fileno(stdin), O_TEXT) == -1) {
+           ExitPerror("setmode (text)", 1);
+       }
+       (void) dosbinary(fileno(stdin), 0);
+    } else {
+       signal(SIGINT, CtrlCInterrupt);
+       if ((old_1b_segment|old_1b_offset) == 0) {
+           extern void iret_subr();
+           void (far *foo_subr)() = iret_subr;
+
+           inregs.h.ah = 0x35;
+           inregs.h.al = 0x1b;
+           intdosx(&inregs, &inregs, &segregs);
+           old_1b_segment = segregs.es;
+           old_1b_offset = inregs.x.bx;
+           inregs.h.ah = 0x25;
+           inregs.h.al = 0x1b;
+           inregs.x.dx = FP_OFF(foo_subr);
+           segregs.ds = FP_SEG(foo_subr);
+           intdosx(&inregs, &inregs, &segregs);
+       }
+       if (MODE_LOCAL_CHARS(f)) {
+           if (setmode(fileno(stdout), O_TEXT) == -1) {
+               ExitPerror("setmode (text)", 1);
+           }
+           (void) dosbinary(fileno(stdout), 0);
+           if (setmode(fileno(stdin), O_TEXT) == -1) {
+               ExitPerror("setmode (text)", 1);
+           }
+           (void) dosbinary(fileno(stdin), 0);
+       } else {
+           if (setmode(fileno(stdout), O_BINARY) == -1) {
+               ExitPerror("setmode (binary)", 1);
+           }
+           (void) dosbinary(fileno(stdout), 1);
+           if (setmode(fileno(stdin), O_BINARY) == -1) {
+               ExitPerror("setmode (binary)", 1);
+           }
+           (void) dosbinary(fileno(stdin), 1);
+       }
+    }
 }
 
 
 }
 
 
@@ -901,6 +996,8 @@ int count;
 static void
 TerminalSaveState()                            /* MSDOS */
 {
 static void
 TerminalSaveState()                            /* MSDOS */
 {
+    savedInState = dosbinary(fileno(stdin), 0);
+    savedOutState = dosbinary(fileno(stdout), 0);
 }
 
 int
 }
 
 int
@@ -913,6 +1010,8 @@ TerminalSpecialChars(c)                    /* MSDOS */
 static void
 TerminalRestoreState()                         /* MSDOS */
 {
 static void
 TerminalRestoreState()                         /* MSDOS */
 {
+    (void) dosbinary(fileno(stdin), savedInState);
+    (void) dosbinary(fileno(stdout), savedOutState);
 }
 
 
 }
 
 
@@ -1060,6 +1159,9 @@ char      **(*next)();    /* routine to return next entry in table */
        register char **c, **found;
        register int nmatches, longest;
 
        register char **c, **found;
        register int nmatches, longest;
 
+       if (name == 0) {
+           return 0;
+       }
        longest = 0;
        nmatches = 0;
        found = 0;
        longest = 0;
        nmatches = 0;
        found = 0;
@@ -1269,10 +1371,10 @@ int     length;                 /* length of suboption data */
            case TELQUAL_IS:
                {
                    char tmpbuf[sizeof subbuffer];
            case TELQUAL_IS:
                {
                    char tmpbuf[sizeof subbuffer];
-                   int minlen = min(length, sizeof tmpbuf);
+                   int minlen = min(length-4, sizeof tmpbuf-1);
 
                    memcpy(tmpbuf, pointer+2, minlen);
 
                    memcpy(tmpbuf, pointer+2, minlen);
-                   tmpbuf[minlen-1] = 0;
+                   tmpbuf[minlen] = 0;
                    fprintf(NetTrace, "is %s.\n", tmpbuf);
                }
                break;
                    fprintf(NetTrace, "is %s.\n", tmpbuf);
                }
                break;
@@ -1746,6 +1848,8 @@ wontoption(option, reply)
 
        default:
                fmt = dont;
 
        default:
                fmt = dont;
+               hisopts[option] = 0;
+               break;
        }
        sprintf(nfrontp, fmt, option);
        nfrontp += sizeof (doopt) - 2;
        }
        sprintf(nfrontp, fmt, option);
        nfrontp += sizeof (doopt) - 2;
@@ -1894,6 +1998,7 @@ SetIn3270()
            Init3270();         /* Initialize 3270 functions */
            /* initialize terminal key mapping */
            InitTerminal();     /* Start terminal going */
            Init3270();         /* Initialize 3270 functions */
            /* initialize terminal key mapping */
            InitTerminal();     /* Start terminal going */
+           LocalClearScreen(); /* Make sure the screen is clear */
            setconnmode();
        }
     } else {
            setconnmode();
        }
     } else {
@@ -1963,7 +2068,7 @@ telrcv()
                     * \n; since we must turn off CRMOD to get proper
                     * input, the mapping is done here (sigh).
                     */
                     * \n; since we must turn off CRMOD to get proper
                     * input, the mapping is done here (sigh).
                     */
-           if (c == '\r') {
+           if ((c == '\r') && !hisopts[TELOPT_BINARY]) {
                if (scc > 0) {
                    c = *sbp&0xff;
                    if (c == 0) {
                if (scc > 0) {
                    c = *sbp&0xff;
                    if (c == 0) {
@@ -2422,9 +2527,15 @@ int      block;                  /* should we block in the select ? */
     if (TTYBYTES()) {
        FD_SET(tout, &obits);
     }
     if (TTYBYTES()) {
        FD_SET(tout, &obits);
     }
+#if    defined(TN3270)
     if ((tcc == 0) && NETROOM() && (shell_active == 0)) {
        FD_SET(tin, &ibits);
     }
     if ((tcc == 0) && NETROOM() && (shell_active == 0)) {
        FD_SET(tin, &ibits);
     }
+#else  /* defined(TN3270) */
+    if ((tcc == 0) && NETROOM()) {
+       FD_SET(tin, &ibits);
+    }
+#endif /* defined(TN3270) */
 #endif /* !defined(MSDOS) */
 #   if !defined(TN3270)
     if (TTYROOM()) {
 #endif /* !defined(MSDOS) */
 #   if !defined(TN3270)
     if (TTYROOM()) {
@@ -2647,29 +2758,39 @@ int     block;                  /* should we block in the select ? */
                        break;
                    }
                }
                        break;
                    }
                }
-               switch (c) {
-               case '\n':
-                       /*
-                        * If we are in CRMOD mode (\r ==> \n)
-                        * on our local machine, then probably
-                        * a newline (unix) is CRLF (TELNET).
-                        */
-                   if (MODE_LOCAL_CHARS(globalmode)) {
-                       NETADD('\r');
+               if (!myopts[TELOPT_BINARY]) {
+                   switch (c) {
+                   case '\n':
+                           /*
+                            * If we are in CRMOD mode (\r ==> \n)
+                            * on our local machine, then probably
+                            * a newline (unix) is CRLF (TELNET).
+                            */
+                       if (MODE_LOCAL_CHARS(globalmode)) {
+                           NETADD('\r');
+                       }
+                       NETADD('\n');
+                       flushline = 1;
+                       break;
+                   case '\r':
+                       if (!crlf) {
+                           NET2ADD('\r', '\0');
+                       } else {
+                           NET2ADD('\r', '\n');
+                       }
+                       flushline = 1;
+                       break;
+                   case IAC:
+                       NET2ADD(IAC, IAC);
+                       break;
+                   default:
+                       NETADD(c);
+                       break;
                    }
                    }
-                   NETADD('\n');
-                   flushline = 1;
-                   break;
-               case '\r':
-                   NET2ADD('\r', '\0');
-                   flushline = 1;
-                   break;
-               case IAC:
+               } else if (c == IAC) {
                    NET2ADD(IAC, IAC);
                    NET2ADD(IAC, IAC);
-                   break;
-               default:
+               } else {
                    NETADD(c);
                    NETADD(c);
-                   break;
                }
            }
 #   if defined(TN3270)
                }
            }
 #   if defined(TN3270)
@@ -2677,7 +2798,7 @@ int       block;                  /* should we block in the select ? */
     }
 #   endif /* defined(TN3270) */
 
     }
 #   endif /* defined(TN3270) */
 
-    if ((!MODE_LINE(globalmode) || flushline) &&
+    if ((!MODE_LINE(globalmode) || flushline || myopts[TELOPT_BINARY]) &&
        FD_ISSET(net, &obits) && (NETBYTES() > 0)) {
        FD_CLR(net, &obits);
        returnValue = netflush();
        FD_ISSET(net, &obits) && (NETBYTES() > 0)) {
        FD_CLR(net, &obits);
        returnValue = netflush();
@@ -2996,6 +3117,18 @@ togdebug()
 }
 
 
 }
 
 
+static int
+togcrlf()
+{
+    if (crlf) {
+       printf("Will send carriage returns as telnet <CR><LF>.\n");
+    } else {
+       printf("Will send carriage returns as telnet <CR><NUL>.\n");
+    }
+    return 1;
+}
+
+
 static int
 togbinary()
 {
 static int
 togbinary()
 {
@@ -3054,7 +3187,13 @@ static struct togglelist Togglelist[] = {
            togbinary,
                1,
                    0,
            togbinary,
                1,
                    0,
-                       "send and receive network data in binary mode" },
+                       0 },
+    { "crlf",
+       "toggle sending carriage returns as telnet <CR><LF>",
+           togcrlf,
+               1,
+                   &crlf,
+                       0 },
     { "crmod",
        "toggle mapping of received carriage returns",
            0,
     { "crmod",
        "toggle mapping of received carriage returns",
            0,
@@ -3158,8 +3297,10 @@ char     *argv[];
        } else {
            if (c->variable) {
                *c->variable = !*c->variable;           /* invert it */
        } else {
            if (c->variable) {
                *c->variable = !*c->variable;           /* invert it */
-               printf("%s %s.\n", *c->variable? "Will" : "Won't",
+               if (c->actionexplanation) {
+                   printf("%s %s.\n", *c->variable? "Will" : "Won't",
                                                        c->actionexplanation);
                                                        c->actionexplanation);
+               }
            }
            if (c->handler) {
                retval &= (*c->handler)(c);
            }
            if (c->handler) {
                retval &= (*c->handler)(c);
@@ -3585,7 +3726,7 @@ tn(argc, argv)
        argc = margc;
        argv = margv;
     }
        argc = margc;
        argv = margv;
     }
-    if (argc > 3) {
+    if ((argc < 2) || (argc > 3)) {
        printf("usage: %s host-name [port]\n", argv[0]);
        return 0;
     }
        printf("usage: %s host-name [port]\n", argv[0]);
        return 0;
     }
@@ -3832,9 +3973,13 @@ command(top)
            longjmp(toplevel, 1);
            /*NOTREACHED*/
        }
            longjmp(toplevel, 1);
            /*NOTREACHED*/
        }
+#if    defined(TN3270)
        if (shell_active == 0) {
            setconnmode();
        }
        if (shell_active == 0) {
            setconnmode();
        }
+#else  /* defined(TN3270) */
+       setconnmode();
+#endif /* defined(TN3270) */
     }
 }
 \f
     }
 }
 \f
@@ -3903,7 +4048,7 @@ main(argc, argv)
        } else {
 #if    defined(TN3270) && defined(unix)
            if (!strcmp(argv[1], "-t")) {
        } else {
 #if    defined(TN3270) && defined(unix)
            if (!strcmp(argv[1], "-t")) {
-               if ((argc > 1) && (argv[1][0] != '-')) { /* get file name */
+               if ((argc > 1) && (argv[2][0] != '-')) { /* get file name */
                    transcom = tline;
                    (void) strcpy(transcom, argv[1]);
                    argv++;
                    transcom = tline;
                    (void) strcpy(transcom, argv[1]);
                    argv++;