* krlogin.c (writer): Improved bandwith efficiency by reading
authorPeter Litwack <plitwack@mit.edu>
Fri, 21 Jul 2000 23:35:12 +0000 (23:35 +0000)
committerPeter Litwack <plitwack@mit.edu>
Fri, 21 Jul 2000 23:35:12 +0000 (23:35 +0000)
and sending more than one character at a time if multiple
characters are available to be read from the terminal.

* krlogin.c (read_wrapper): Added this function as a helper
to writer.  It facilitates checking for escape sequences
(~^Z etc.) when reading mulitple characters at a time.

git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@12581 dc483132-0cff-0310-8789-dd5450dbe970

src/appl/bsd/ChangeLog
src/appl/bsd/krlogin.c

index ed9da43676bb9a5f6b0782a80aa2b7bf5b303da2..4a1fdab64be5a3de6758774df2dd36fce3bdba18 100644 (file)
@@ -1,3 +1,12 @@
+2000-07-21  Peter S Litwack  <plitwack@mit.edu>
+
+       * krlogin.c (writer): Improved bandwith efficiency by reading 
+        and sending more than one character at a time if multiple 
+        characters are available to be read from the terminal.
+        * krlogin.c (read_wrapper): Added this function as a helper
+        to writer.  It facilitates checking for escape sequences 
+        (~^Z etc.) when reading mulitple characters at a time.
+
 2000-07-18  Ezra Peisach  <epeisach@mit.edu>
 
        * krcp.c: Provide format attribute for error() for versions of gcc
index 0039056c31e854b56954dc3196ede0a31583fe0e..d7ec552e917ba648fc80163225fc679687fb2b4b 100644 (file)
@@ -379,7 +379,7 @@ main(argc, argv)
 #endif
     int port, debug_port = 0;
     enum kcmd_proto kcmd_proto = KCMD_PROTOCOL_COMPAT_HACK;
-   
+
     memset(&defaultservent, 0, sizeof(struct servent));
     if (strrchr(argv[0], '/'))
       argv[0] = strrchr(argv[0], '/')+1;
@@ -1054,13 +1054,15 @@ int signo;
  */
 writer()
 {
-    unsigned char c;
-    register n;
-    register bol = 1;               /* beginning of line */
-    register local = 0;
-    
+    int n_read;
+    char buf[1024];
+    int got_esc; /* set to true by read_wrapper if an escape char
+                   was encountered */
+    char c;
+
 #ifdef ultrix             
     fd_set waitread;
+    register n;
     
     /* we need to wait until the reader() has set up the terminal, else
        the read() below may block and not unblock when the terminal
@@ -1081,90 +1083,173 @@ writer()
          }
     }
 #endif /* ultrix */
+
+    /* This loop works as follows.  Call read_wrapper to get data until
+       we would block or until we read a cmdchar at the beginning of a line.
+       If got_esc is false, we just send everything we got back.  If got_esc 
+       is true, we send everything except the cmdchar at the end and look at 
+       the next char.  If its a "." we break out of the loop and terminate.
+       If its ^Z or ^Y we call stop with the value of the char and continue.
+       If its none of those, we send the cmdchar and then send the char we 
+       just read, unless that char is also the cmdchar (in which case we are
+       only supposed to send one of them).  When this loop ends, so does the
+       program.
+    */
+
     for (;;) {
-       n = read(0, &c, 1);
-       if (n <= 0) {
-           if (n < 0 && errno == EINTR)
-             continue;
+
+      /* read until we would block or we get a cmdchar */
+      n_read = read_wrapper(0,buf,sizeof(buf),&got_esc);
+  
+      /* if read returns an error or 0 bytes, just quit */
+      if (n_read <= 0) {
+       break;
+      }
+      
+      if (!got_esc) {
+       if (rcmd_stream_write(rem, buf, n_read, 0) == 0) {
+         prf("line gone");
+         break;
+       }
+       continue;
+      }
+      else {
+       /* This next test is necessary to avoid sending 0 bytes of data
+          in the event that we got just a cmdchar */
+       if (n_read > 1) {
+         if (rcmd_stream_write(rem, buf, n_read-1, 0) == 0) {
+           prf("line gone");
            break;
+         }
        }
-       /*
-        * If we're at the beginning of the line
-        * and recognize a command character, then
-        * we echo locally.  Otherwise, characters
-        * are echo'd remotely.  If the command
-        * character is doubled, this acts as a 
-        * force and local echo is suppressed.
-        */
-       if (bol) {
-           bol = 0;
-           if (c == cmdchar) {
-               bol = 0;
-               local = 1;
-               continue;
-           }
-       } else if (local) {
-           local = 0;
+       if (read_wrapper(0,&c,1,&got_esc) <= 0) {
+         break;
+       }
+
 #ifdef POSIX_TERMIOS
-           if (c == '.' || c == deftty.c_cc[VEOF]) {
+       if (c == '.' || c == deftty.c_cc[VEOF]) 
 #else
-           if (c == '.' || c == deftc.t_eofc) {
+         if (c == '.' || c == deftc.t_eofc) 
 #endif
-               if (confirm_death()) {
-                   echo(c);
-                   break;
-               }
-           }
-#ifdef TIOCGLTC
-           if ((c == defltc.t_suspc || c == defltc.t_dsuspc)
-               && !no_local_escape) {
-               bol = 1;
+           {
+             if (confirm_death()) {
                echo(c);
-               stop(c);
-               continue;
+               break; 
+             }
            }
+
+#ifdef TIOCGLTC
+       if ((c == defltc.t_suspc || c == defltc.t_dsuspc)
+           && !no_local_escape) {
+         echo(c);
+         stop(c);
+         continue;
+       }
 #else
 #ifdef POSIX_TERMIOS
-           if ( (
-                 (c == deftty.c_cc[VSUSP]) 
+       if ( (
+             (c == deftty.c_cc[VSUSP]) 
 #ifdef VDSUSP
-                 || (c == deftty.c_cc[VDSUSP]) 
+             || (c == deftty.c_cc[VDSUSP]) 
 #endif
-                 )
-               && !no_local_escape) {
-             bol = 1;
-             echo(c);
-             stop(c);
-             continue;
-           }
+             )
+            && !no_local_escape) {
+         echo(c);
+         stop(c);
+         continue;
+       }
 #endif
 #endif
-
-           if (c != cmdchar)
-             (void) rcmd_stream_write(rem, &cmdchar, 1, 0);
+      
+       if (c != cmdchar) {
+         rcmd_stream_write(rem, &cmdchar, 1, 0);
        }
-       if (rcmd_stream_write(rem, &c, 1, 0) == 0) {
-           prf("line gone");
-           break;
+
+       if (rcmd_stream_write(rem,&c,1,0) == 0) {
+         prf("line gone");
+         break;
        }
+      }
+    }
+}
+
+/* This function reads up to size bytes from file desciptor fd into buf.
+   It will copy as much data as it can without blocking, but will never
+   copy more than size bytes.  In addition, if it encounters a cmdchar
+   at the beginning of a line, it will copy everything up to and including
+   the cmdchar, but nothing after that.  In this instance *esc_char is set
+   to true and any remaining data is buffered and copied on a subsequent 
+   call.  Otherwise, *esc_char will be set to false and the minimum of size,
+   1024, and the number of bytes that can be read without blocking will
+   be copied.  In all cases, a non-negative return value indicates the number 
+   of bytes actually copied and a return value of -1 indicates that there
+   was a read error (other than EINTR) and errno is set appropriately. 
+*/
+
+int read_wrapper(fd,buf,size,got_esc) 
+     int fd;
+     char *buf;
+     int size;
+     int *got_esc;
+{
+  static char tbuf[1024];
+  static char *data_start = tbuf;
+  static char *data_end = tbuf;
+  static int bol = 1;
+  int return_length = 0;
+  char c;
+
+  /* if we have no data buffered, get more */
+  if (data_start == data_end) {
+    int n_read;
+    while ((n_read = read(fd, tbuf, sizeof(tbuf))) <= 0) {
+      if (n_read < 0 && errno == EINTR)
+       continue;
+      return n_read;
+    }
+    data_start = tbuf;
+    data_end = tbuf+n_read;
+  }
+
+  *got_esc = 0;
+
+  /* We stop when we've fully checked the buffer or have checked size
+     bytes.  We break out and set *got_esc if we encounter a cmdchar
+     at the beginning of a line.
+  */
+
+  while (data_start+return_length < data_end && return_length < size) {
+    
+    c = *(data_start+return_length);
+    return_length++;
+
+    if (bol == 1 && c == cmdchar) {
+      bol = 0;
+      *got_esc = 1;
+      break;
+    }
+
 #ifdef POSIX_TERMIOS
-       bol = (c == deftty.c_cc[VKILL] ||
-              c == deftty.c_cc[VINTR] ||
-              c == '\r' || c == '\n');
+    bol = (c == deftty.c_cc[VKILL] ||
+          c == deftty.c_cc[VINTR] ||
+          c == '\r' || c == '\n');
 #ifdef TIOCGLTC
-       if (!bol)
-         bol = (c == defltc.t_suspc);
+    if (!bol)
+      bol = (c == defltc.t_suspc);
 #endif
-#else /* !POSIX_TERMIOS */
-       bol = c == defkill || c == deftc.t_eofc ||
-         c == deftc.t_intrc || c == defltc.t_suspc ||
-           c == '\r' || c == '\n';
+       
+#else / * !POSIX_TERMIOS * /
+    bol = c == defkill || c == deftc.t_eofc ||
+      c == deftc.t_intrc || c == defltc.t_suspc ||
+      c == '\r' || c == '\n';
 #endif
-    }
+  }
+   
+  memcpy(buf,tbuf, return_length);
+  data_start = data_start + return_length;
+  return return_length;
 }
 
-
-
 echo(c)
      register char c;
 {