BSD 4_3_Reno release
[unix-history] / usr / src / usr.bin / telnet / tn3270.c
index 5f10199..db6c361 100644 (file)
@@ -1,7 +1,76 @@
+/*
+ * Copyright (c) 1988 Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted provided
+ * that: (1) source distributions retain this entire copyright notice and
+ * comment, and (2) distributions including binaries display the following
+ * acknowledgement:  ``This product includes software developed by the
+ * University of California, Berkeley and its contributors'' in the
+ * documentation or other materials provided with the distribution and in
+ * all advertising materials mentioning features or use of this software.
+ * Neither the name of the University nor the names of its contributors may
+ * be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+static char sccsid[] = "@(#)tn3270.c   1.21 (Berkeley) 6/28/90";
+#endif /* not lint */
+
+#include <sys/types.h>
+#include <arpa/telnet.h>
+
+#include "general.h"
+
+#include "defines.h"
+#include "ring.h"
+#include "externs.h"
+#include "fdset.h"
+
+#if    defined(TN3270)
+
+#include "../ctlr/screen.h"
+#include "../general/globals.h"
+
+#include "../telextrn.h"
+#include "../ctlr/externs.h"
+
+#if    defined(unix)
+int
+       HaveInput,              /* There is input available to scan */
+       cursesdata,             /* Do we dump curses data? */
+       sigiocount;             /* Number of times we got a SIGIO */
+
+char   tline[200];
+char   *transcom = 0;  /* transparent mode command (default: none) */
+#endif /* defined(unix) */
+
+char   Ibuf[8*BUFSIZ], *Ifrontp, *Ibackp;
+
+static char    sb_terminal[] = { IAC, SB,
+                       TELOPT_TTYPE, TELQUAL_IS,
+                       'I', 'B', 'M', '-', '3', '2', '7', '8', '-', '2',
+                       IAC, SE };
+#define        SBTERMMODEL     13
+
+static int
+       Sent3270TerminalType;   /* Have we said we are a 3270? */
+
+#endif /* defined(TN3270) */
+
+
 void
 void
-tn3270_init()
+init_3270()
 {
 #if    defined(TN3270)
 {
 #if    defined(TN3270)
+#if    defined(unix)
+    HaveInput = 0;
+    sigiocount = 0;
+#endif /* defined(unix) */
     Sent3270TerminalType = 0;
     Ifrontp = Ibackp = Ibuf;
     init_ctlr();               /* Initialize some things */
     Sent3270TerminalType = 0;
     Ifrontp = Ibackp = Ibuf;
     init_ctlr();               /* Initialize some things */
@@ -11,6 +80,7 @@ tn3270_init()
 #endif /* defined(TN3270) */
 }
 
 #endif /* defined(TN3270) */
 }
 
+\f
 #if    defined(TN3270)
 
 /*
 #if    defined(TN3270)
 
 /*
@@ -28,36 +98,50 @@ register char       *buffer;        /* where the data is */
 register int   count;          /* how much to send */
 int            done;           /* is this the last of a logical block */
 {
 register int   count;          /* how much to send */
 int            done;           /* is this the last of a logical block */
 {
-    register int c;
+    register int loop, c;
     int origCount;
     int origCount;
-    fd_set o;
 
     origCount = count;
 
     origCount = count;
-    FD_ZERO(&o);
 
     while (count) {
 
     while (count) {
-       if ((netobuf+sizeof netobuf - nfrontp) < 6) {
+       /* If not enough room for EORs, IACs, etc., wait */
+       if (NETROOM() < 6) {
+           fd_set o;
+
+           FD_ZERO(&o);
            netflush();
            netflush();
-           while ((netobuf+sizeof netobuf - nfrontp) < 6) {
+           while (NETROOM() < 6) {
                FD_SET(net, &o);
                (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
                                                (struct timeval *) 0);
                netflush();
            }
        }
                FD_SET(net, &o);
                (void) select(net+1, (fd_set *) 0, &o, (fd_set *) 0,
                                                (struct timeval *) 0);
                netflush();
            }
        }
-       c = *buffer++;
-       count--;
-       if (c == IAC) {
-           *nfrontp++ = IAC;
-           *nfrontp++ = IAC;
-       } else {
-           *nfrontp++ = c;
+       c = ring_empty_count(&netoring);
+       if (c > count) {
+           c = count;
+       }
+       loop = c;
+       while (loop) {
+           if (((unsigned char)*buffer) == IAC) {
+               break;
+           }
+           buffer++;
+           loop--;
+       }
+       if ((c = c-loop)) {
+           ring_supply_data(&netoring, buffer-c, c);
+           count -= c;
+       }
+       if (loop) {
+           NET2ADD(IAC, IAC);
+           count--;
+           buffer++;
        }
     }
 
        }
     }
 
-    if (done && !count) {
-       *nfrontp++ = IAC;
-       *nfrontp++ = EOR;
+    if (done) {
+       NET2ADD(IAC, EOR);
        netflush();             /* try to move along as quickly as ... */
     }
     return(origCount - count);
        netflush();             /* try to move along as quickly as ... */
     }
     return(origCount - count);
@@ -65,17 +149,18 @@ int                done;           /* is this the last of a logical block */
 
 
 #if    defined(unix)
 
 
 #if    defined(unix)
-static void
+void
 inputAvailable()
 {
     HaveInput = 1;
 inputAvailable()
 {
     HaveInput = 1;
+    sigiocount++;
 }
 #endif /* defined(unix) */
 
 void
 outputPurge()
 {
 }
 #endif /* defined(unix) */
 
 void
 outputPurge()
 {
-    ttyflush(1);
+    (void) ttyflush(1);
 }
 
 
 }
 
 
@@ -84,75 +169,49 @@ outputPurge()
  * routines make calls into telnet.c.
  */
 
  * routines make calls into telnet.c.
  */
 
-/* TtyChars() - returns the number of characters in the TTY buffer */
-TtyChars()
-{
-    return(tfrontp-tbackp);
-}
-
-/* DataToTerminal - queue up some data to go to terminal. */
+/*
+ * DataToTerminal - queue up some data to go to terminal.
+ *
+ * Note: there are people who call us and depend on our processing
+ * *all* the data at one time (thus the select).
+ */
 
 int
 DataToTerminal(buffer, count)
 register char  *buffer;                /* where the data is */
 register int   count;                  /* how much to send */
 {
 
 int
 DataToTerminal(buffer, count)
 register char  *buffer;                /* where the data is */
 register int   count;                  /* how much to send */
 {
+    register int c;
     int origCount;
     int origCount;
-#if    defined(unix)
-    fd_set     o;
 
 
-    FD_ZERO(&o);
-#endif /* defined(unix) */
     origCount = count;
 
     while (count) {
     origCount = count;
 
     while (count) {
-       if (tfrontp >= ttyobuf+sizeof ttyobuf) {
-           ttyflush(0);
-           while (tfrontp >= ttyobuf+sizeof ttyobuf) {
+       if (TTYROOM() == 0) {
+#if    defined(unix)
+           fd_set o;
+
+           FD_ZERO(&o);
+#endif /* defined(unix) */
+           (void) ttyflush(0);
+           while (TTYROOM() == 0) {
 #if    defined(unix)
                FD_SET(tout, &o);
                (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
                                                (struct timeval *) 0);
 #endif /* defined(unix) */
 #if    defined(unix)
                FD_SET(tout, &o);
                (void) select(tout+1, (fd_set *) 0, &o, (fd_set *) 0,
                                                (struct timeval *) 0);
 #endif /* defined(unix) */
-               ttyflush(0);
+               (void) ttyflush(0);
            }
        }
            }
        }
-       *tfrontp++ = *buffer++;
-       count--;
-    }
-    return(origCount - count);
-}
-
-/* EmptyTerminal - called to make sure that the terminal buffer is empty.
- *                     Note that we consider the buffer to run all the
- *                     way to the kernel (thus the select).
- */
-
-void
-EmptyTerminal()
-{
-#if    defined(unix)
-    fd_set     o;
-
-    FD_ZERO(&o);
-#endif /* defined(unix) */
-
-    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 */
-#endif /* defined(unix) */
-    } else {
-       while (tfrontp != tbackp) {
-           ttyflush(0);
-#if    defined(unix)
-           FD_SET(tout, &o);
-           (void) select(tout+1, (int *) 0, &o, (int *) 0,
-                               (struct timeval *) 0);  /* wait for TTLOWAT */
-#endif /* defined(unix) */
+       c = TTYROOM();
+       if (c > count) {
+           c = count;
        }
        }
+       ring_supply_data(&ttyoring, buffer, c);
+       count -= c;
+       buffer += c;
     }
     }
+    return(origCount);
 }
 \f
 
 }
 \f
 
@@ -160,24 +219,24 @@ EmptyTerminal()
  * Push3270 - Try to send data along the 3270 output (to screen) direction.
  */
 
  * Push3270 - Try to send data along the 3270 output (to screen) direction.
  */
 
-static int
+int
 Push3270()
 {
 Push3270()
 {
-    int save = scc;
+    int save = ring_full_count(&netiring);
 
 
-    if (scc) {
-       if (Ifrontp+scc > Ibuf+sizeof Ibuf) {
+    if (save) {
+       if (Ifrontp+save > Ibuf+sizeof Ibuf) {
            if (Ibackp != Ibuf) {
                memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
                Ifrontp -= (Ibackp-Ibuf);
                Ibackp = Ibuf;
            }
        }
            if (Ibackp != Ibuf) {
                memcpy(Ibuf, Ibackp, Ifrontp-Ibackp);
                Ifrontp -= (Ibackp-Ibuf);
                Ibackp = Ibuf;
            }
        }
-       if (Ifrontp+scc < Ibuf+sizeof Ibuf) {
-           telrcv();
+       if (Ifrontp+save < Ibuf+sizeof Ibuf) {
+           (void)telrcv();
        }
     }
        }
     }
-    return save != scc;
+    return save != ring_full_count(&netiring);
 }
 
 
 }
 
 
@@ -186,7 +245,7 @@ Push3270()
  *             before quitting.
  */
 
  *             before quitting.
  */
 
-static void
+void
 Finish3270()
 {
     while (Push3270() || !DoTerminalOutput()) {
 Finish3270()
 {
     while (Push3270() || !DoTerminalOutput()) {
@@ -222,12 +281,114 @@ void
 _putchar(c)
 char c;
 {
 _putchar(c)
 char c;
 {
-    if (tfrontp >= ttyobuf+sizeof ttyobuf) {
+#if    defined(sun)            /* SunOS 4.0 bug */
+    c &= 0x7f;
+#endif /* defined(sun) */
+    if (cursesdata) {
+       Dump('>', &c, 1);
+    }
+    if (!TTYROOM()) {
        (void) DataToTerminal(&c, 1);
     } else {
        (void) DataToTerminal(&c, 1);
     } else {
-       *tfrontp++ = c;         /* optimize if possible. */
+       TTYADD(c);
     }
 }
 #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */
 
     }
 }
 #endif /* ((!defined(NOT43)) || defined(PUTCHAR)) */
 
+void
+SetIn3270()
+{
+    if (Sent3270TerminalType && my_want_state_is_will(TELOPT_BINARY)
+               && my_want_state_is_do(TELOPT_BINARY) && !donebinarytoggle) {
+       if (!In3270) {
+           In3270 = 1;
+           Init3270();         /* Initialize 3270 functions */
+           /* initialize terminal key mapping */
+           InitTerminal();     /* Start terminal going */
+           setconnmode(0);
+       }
+    } else {
+       if (In3270) {
+           StopScreen(1);
+           In3270 = 0;
+           Stop3270();         /* Tell 3270 we aren't here anymore */
+           setconnmode(0);
+       }
+    }
+}
+
+/*
+ * tn3270_ttype()
+ *
+ *     Send a response to a terminal type negotiation.
+ *
+ *     Return '0' if no more responses to send; '1' if a response sent.
+ */
+
+int
+tn3270_ttype()
+{
+    /*
+     * Try to send a 3270 type terminal name.  Decide which one based
+     * on the format of our screen, and (in the future) color
+     * capaiblities.
+     */
+    InitTerminal();            /* Sets MaxNumberColumns, MaxNumberLines */
+    if ((MaxNumberLines >= 24) && (MaxNumberColumns >= 80)) {
+       Sent3270TerminalType = 1;
+       if ((MaxNumberLines >= 27) && (MaxNumberColumns >= 132)) {
+           MaxNumberLines = 27;
+           MaxNumberColumns = 132;
+           sb_terminal[SBTERMMODEL] = '5';
+       } else if (MaxNumberLines >= 43) {
+           MaxNumberLines = 43;
+           MaxNumberColumns = 80;
+           sb_terminal[SBTERMMODEL] = '4';
+       } else if (MaxNumberLines >= 32) {
+           MaxNumberLines = 32;
+           MaxNumberColumns = 80;
+           sb_terminal[SBTERMMODEL] = '3';
+       } else {
+           MaxNumberLines = 24;
+           MaxNumberColumns = 80;
+           sb_terminal[SBTERMMODEL] = '2';
+       }
+       NumberLines = 24;               /* before we start out... */
+       NumberColumns = 80;
+       ScreenSize = NumberLines*NumberColumns;
+       if ((MaxNumberLines*MaxNumberColumns) > MAXSCREENSIZE) {
+           ExitString("Programming error:  MAXSCREENSIZE too small.\n",
+                                                               1);
+           /*NOTREACHED*/
+       }
+       printsub('>', sb_terminal+2, sizeof sb_terminal-2);
+       ring_supply_data(&netoring, sb_terminal, sizeof sb_terminal);
+       return 1;
+    } else {
+       return 0;
+    }
+}
+
+#if    defined(unix)
+settranscom(argc, argv)
+       int argc;
+       char *argv[];
+{
+       int i;
+
+       if (argc == 1 && transcom) {
+          transcom = 0;
+       }
+       if (argc == 1) {
+          return;
+       }
+       transcom = tline;
+       (void) strcpy(transcom, argv[1]);
+       for (i = 2; i < argc; ++i) {
+           (void) strcat(transcom, " ");
+           (void) strcat(transcom, argv[i]);
+       }
+}
+#endif /* defined(unix) */
+
 #endif /* defined(TN3270) */
 #endif /* defined(TN3270) */