ignore & before array
[unix-history] / usr / src / old / more / more.c
index 8e86830..f7b6689 100644 (file)
@@ -1,6 +1,24 @@
+/*
+ * Copyright (c) 1980 Regents of the University of California.
+ * All rights reserved.
+ *
+ * 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 written prior permission. This software
+ * is provided ``as is'' without express or implied warranty.
+ */
+
+#ifndef lint
+char copyright[] =
+"@(#) Copyright (c) 1980 Regents of the University of California.\n\
+ All rights reserved.\n";
+#endif /* not lint */
+
 #ifndef lint
 #ifndef lint
-static char *sccsid = "@(#)more.c      4.19 (Berkeley) 84/07/12";
-#endif
+static char sccsid[] = "@(#)more.c     5.18 (Berkeley) %G%";
+#endif /* not lint */
 
 /*
 ** more.c - General purpose tty output filter and file perusal program
 
 /*
 ** more.c - General purpose tty output filter and file perusal program
@@ -12,13 +30,16 @@ static      char *sccsid = "@(#)more.c      4.19 (Berkeley) 84/07/12";
 */
 
 #include <stdio.h>
 */
 
 #include <stdio.h>
+#include <sys/param.h>
 #include <ctype.h>
 #include <signal.h>
 #include <errno.h>
 #include <sgtty.h>
 #include <setjmp.h>
 #include <ctype.h>
 #include <signal.h>
 #include <errno.h>
 #include <sgtty.h>
 #include <setjmp.h>
-#include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
+#include <sys/file.h>
+#include <a.out.h>
+#include <varargs.h>
 
 #define HELPFILE       "/usr/lib/more.help"
 #define VI             "/usr/ucb/vi"
 
 #define HELPFILE       "/usr/lib/more.help"
 #define VI             "/usr/ucb/vi"
@@ -34,7 +55,7 @@ static        char *sccsid = "@(#)more.c      4.19 (Berkeley) 84/07/12";
 
 #define TBUFSIZ        1024
 #define LINSIZ 256
 
 #define TBUFSIZ        1024
 #define LINSIZ 256
-#define ctrl(letter)   ('letter' & 077)
+#define ctrl(letter)   (letter & 077)
 #define RUBOUT '\177'
 #define ESC    '\033'
 #define QUIT   '\034'
 #define RUBOUT '\177'
 #define ESC    '\033'
 #define QUIT   '\034'
@@ -42,7 +63,7 @@ static        char *sccsid = "@(#)more.c      4.19 (Berkeley) 84/07/12";
 struct sgttyb  otty, savetty;
 long           file_pos, file_size;
 int            fnum, no_intty, no_tty, slow_tty;
 struct sgttyb  otty, savetty;
 long           file_pos, file_size;
 int            fnum, no_intty, no_tty, slow_tty;
-int            dum_opt, dlines, onquit(), end_it();
+int            dum_opt, dlines, onquit(), end_it(), chgwinsz();
 int            onsusp();
 int            nscroll = 11;   /* Number of lines scrolled by 'd' */
 int            fold_opt = 1;   /* Fold long lines */
 int            onsusp();
 int            nscroll = 11;   /* Number of lines scrolled by 'd' */
 int            fold_opt = 1;   /* Fold long lines */
@@ -54,11 +75,13 @@ int         Currline;       /* Line we are currently at */
 int            startup = 1;
 int            firstf = 1;
 int            notell = 1;
 int            startup = 1;
 int            firstf = 1;
 int            notell = 1;
+int            docrterase = 0;
+int            docrtkill = 0;
 int            bad_so; /* True if overwriting does not turn off standout */
 int            inwait, Pause, errors;
 int            within; /* true if we are within a file,
                        false if we are between files */
 int            bad_so; /* True if overwriting does not turn off standout */
 int            inwait, Pause, errors;
 int            within; /* true if we are within a file,
                        false if we are between files */
-int            hard, dumb, noscroll, hardtabs, clreol;
+int            hard, dumb, noscroll, hardtabs, clreol, eatnl;
 int            catch_susp;     /* We should catch the SIGTSTP signal */
 char           **fnames;       /* The list of file names */
 int            nfiles;         /* Number of files left to process */
 int            catch_susp;     /* We should catch the SIGTSTP signal */
 char           **fnames;       /* The list of file names */
 int            nfiles;         /* Number of files left to process */
@@ -66,7 +89,6 @@ char          *shell;         /* The name of the shell to use */
 int            shellp;         /* A previous shell command exists */
 char           ch;
 jmp_buf                restore;
 int            shellp;         /* A previous shell command exists */
 char           ch;
 jmp_buf                restore;
-char           obuf[BUFSIZ];   /* stdout buffer */
 char           Line[LINSIZ];   /* Line buffer */
 int            Lpp = 24;       /* lines per page */
 char           *Clear;         /* clear screen */
 char           Line[LINSIZ];   /* Line buffer */
 int            Lpp = 24;       /* lines per page */
 char           *Clear;         /* clear screen */
@@ -145,19 +167,23 @@ char *argv[];
      */
     if(clreol)
     {
      */
     if(clreol)
     {
-       if ((*Home == '\0') || (*eraseln == '\0') || (*EodClr == '\0'))
-           clreol = 0;
+        if((Home == NULL) || (*Home == '\0') ||
+          (eraseln == NULL) || (*eraseln == '\0') ||
+           (EodClr == NULL) || (*EodClr == '\0') )
+             clreol = 0;
        else noscroll = 1;
     }
        else noscroll = 1;
     }
-
     if (dlines == 0)
        dlines = Lpp - (noscroll ? 1 : 2);
     left = dlines;
     if (nfiles > 1)
        prnames++;
     if (!no_intty && nfiles == 0) {
     if (dlines == 0)
        dlines = Lpp - (noscroll ? 1 : 2);
     left = dlines;
     if (nfiles > 1)
        prnames++;
     if (!no_intty && nfiles == 0) {
-       fputs("Usage: ",stderr);
-       fputs(argv[0],stderr);
+       char *rindex();
+
+       p = rindex(argv[0], '/');
+       fputs("usage: ",stderr);
+       fputs(p ? p + 1 : argv[0],stderr);
        fputs(" [-dfln] [+linenum | +/pattern] name1 name2 ...\n",stderr);
        exit(1);
     }
        fputs(" [-dfln] [+linenum | +/pattern] name1 name2 ...\n",stderr);
        exit(1);
     }
@@ -166,6 +192,7 @@ char *argv[];
     if (!no_tty) {
        signal(SIGQUIT, onquit);
        signal(SIGINT, end_it);
     if (!no_tty) {
        signal(SIGQUIT, onquit);
        signal(SIGINT, end_it);
+       signal(SIGWINCH, chgwinsz);
        if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
            signal(SIGTSTP, onsusp);
            catch_susp++;
        if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
            signal(SIGTSTP, onsusp);
            catch_susp++;
@@ -223,7 +250,7 @@ char *argv[];
                left = command (fnames[fnum], f);
            }
            if (left != 0) {
                left = command (fnames[fnum], f);
            }
            if (left != 0) {
-               if ((noscroll || clearit) && (file_size != 0x7fffffffffffffffL))
+               if ((noscroll || clearit) && (file_size != LONG_MAX))
                    if (clreol)
                        home ();
                    else
                    if (clreol)
                        home ();
                    else
@@ -240,7 +267,7 @@ char *argv[];
                    if(clreol) cleareol();
                    printf("%s\n", fnames[fnum]);
                    if(clreol) cleareol();
                    if(clreol) cleareol();
                    printf("%s\n", fnames[fnum]);
                    if(clreol) cleareol();
-                   printf("::::::::::::::\n", fnames[fnum]);
+                   printf("::::::::::::::\n");
                    if (left > Lpp - 4)
                        left = Lpp - 4;
                }
                    if (left > Lpp - 4)
                        left = Lpp - 4;
                }
@@ -268,14 +295,18 @@ char *argv[];
 argscan(s)
 char *s;
 {
 argscan(s)
 char *s;
 {
-       for (dlines = 0; *s != '\0'; s++)
-       {
-               switch (*s)
-               {
+       int seen_num = 0;
+
+       while (*s != '\0') {
+               switch (*s) {
                  case '0': case '1': case '2':
                  case '3': case '4': case '5':
                  case '6': case '7': case '8':
                  case '9':
                  case '0': case '1': case '2':
                  case '3': case '4': case '5':
                  case '6': case '7': case '8':
                  case '9':
+                       if (!seen_num) {
+                               dlines = 0;
+                               seen_num = 1;
+                       }
                        dlines = dlines*10 + *s - '0';
                        break;
                  case 'd':
                        dlines = dlines*10 + *s - '0';
                        break;
                  case 'd':
@@ -300,6 +331,7 @@ char *s;
                        ul_opt = 0;
                        break;
                }
                        ul_opt = 0;
                        break;
                }
+               s++;
        }
 }
 
        }
 }
 
@@ -311,55 +343,65 @@ char *s;
 
 FILE *
 checkf (fs, clearfirst)
 
 FILE *
 checkf (fs, clearfirst)
-register char *fs;
-int *clearfirst;
+       register char *fs;
+       int *clearfirst;
 {
 {
-    struct stat stbuf;
-    register FILE *f;
-    char c;
+       struct stat stbuf;
+       register FILE *f;
+       char c;
 
 
-    if (stat (fs, &stbuf) == -1) {
-       fflush(stdout);
-       if (clreol)
-           cleareol ();
-       perror(fs);
-       return (NULL);
-    }
-    if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
-       printf("\n*** %s: directory ***\n\n", fs);
-       return (NULL);
-    }
-    if ((f=Fopen(fs, "r")) == NULL) {
-       fflush(stdout);
-       perror(fs);
-       return (NULL);
-    }
-    c = Getc(f);
-
-    /* Try to see whether it is an ASCII file */
-
-    switch ((c | *f->_ptr << 8) & 0177777) {
-    case 0405:
-    case 0407:
-    case 0410:
-    case 0411:
-    case 0413:
-    case 0177545:
-       printf("\n******** %s: Not a text file ********\n\n", fs);
-       fclose (f);
-       return (NULL);
-    default:
-       break;
-    }
-    if (c == '\f')
-       *clearfirst = 1;
-    else {
-       *clearfirst = 0;
+       if (stat (fs, &stbuf) == -1) {
+               (void)fflush(stdout);
+               if (clreol)
+                       cleareol ();
+               perror(fs);
+               return((FILE *)NULL);
+       }
+       if ((stbuf.st_mode & S_IFMT) == S_IFDIR) {
+               printf("\n*** %s: directory ***\n\n", fs);
+               return((FILE *)NULL);
+       }
+       if ((f = Fopen(fs, "r")) == NULL) {
+               (void)fflush(stdout);
+               perror(fs);
+               return((FILE *)NULL);
+       }
+       if (magic(f, fs))
+               return((FILE *)NULL);
+       c = Getc(f);
+       *clearfirst = c == '\f';
        Ungetc (c, f);
        Ungetc (c, f);
-    }
-    if ((file_size = stbuf.st_size) == 0)
-       file_size = 0x7fffffffffffffffL;
-    return (f);
+       if ((file_size = stbuf.st_size) == 0)
+               file_size = LONG_MAX;
+       return(f);
+}
+
+/*
+ * magic --
+ *     check for file magic numbers.  This code would best be shared with
+ *     the file(1) program or, perhaps, more should not try and be so smart?
+ */
+static
+magic(f, fs)
+       FILE *f;
+       char *fs;
+{
+       struct exec ex;
+
+       if (fread(&ex, sizeof(ex), 1, f) == 1)
+               switch(ex.a_magic) {
+               case OMAGIC:
+               case NMAGIC:
+               case ZMAGIC:
+               case 0405:
+               case 0411:
+               case 0177545:
+                       printf("\n******** %s: Not a text file ********\n\n", fs);
+                       (void)fclose(f);
+                       return(1);
+               }
+       (void)fseek(f, 0L, L_SET);              /* rewind() not necessary */
+       return(0);
 }
 
 /*
 }
 
 /*
@@ -476,6 +518,29 @@ onquit()
     signal(SIGQUIT, onquit);
 }
 
     signal(SIGQUIT, onquit);
 }
 
+/*
+** Come here if a signal for a window size change is received
+*/
+
+chgwinsz()
+{
+    struct winsize win;
+
+    (void) signal(SIGWINCH, SIG_IGN);
+    if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
+       if (win.ws_row != 0) {
+           Lpp = win.ws_row;
+           nscroll = Lpp/2 - 1;
+           if (nscroll <= 0)
+               nscroll = 1;
+           dlines = Lpp - (noscroll ? 1 : 2);
+       }
+       if (win.ws_col != 0)
+           Mcol = win.ws_col;
+    }
+    (void) signal(SIGWINCH, chgwinsz);
+}
+
 /*
 ** Clean up terminal state and exit. Also come here if interrupt signal received
 */
 /*
 ** Clean up terminal state and exit. Also come here if interrupt signal received
 */
@@ -509,16 +574,16 @@ register FILE *f;
 
 /* Simplified printf function */
 
 
 /* Simplified printf function */
 
-printf (fmt, args)
+printf (fmt, va_alist)
 register char *fmt;
 register char *fmt;
-int args;
+va_dcl
 {
 {
-       register int *argp;
+       va_list ap;
        register char ch;
        register int ccount;
 
        ccount = 0;
        register char ch;
        register int ccount;
 
        ccount = 0;
-       argp = &args;
+       va_start(ap);
        while (*fmt) {
                while ((ch = *fmt++) != '%') {
                        if (ch == '\0')
        while (*fmt) {
                while ((ch = *fmt++) != '%') {
                        if (ch == '\0')
@@ -528,14 +593,13 @@ int args;
                }
                switch (*fmt++) {
                case 'd':
                }
                switch (*fmt++) {
                case 'd':
-                       ccount += printd (*argp);
+                       ccount += printd (va_arg(ap, int));
                        break;
                case 's':
                        break;
                case 's':
-                       ccount += pr ((char *)*argp);
+                       ccount += pr (va_arg(ap, char *));
                        break;
                case '%':
                        ccount++;
                        break;
                case '%':
                        ccount++;
-                       argp--;
                        putchar ('%');
                        break;
                case '0':
                        putchar ('%');
                        break;
                case '0':
@@ -543,8 +607,8 @@ int args;
                default:
                        break;
                }
                default:
                        break;
                }
-               ++argp;
        }
        }
+       va_end(ap);
        return (ccount);
 
 }
        return (ccount);
 
 }
@@ -588,7 +652,7 @@ Sprintf (n)
     *sptr++ = n % 10 + '0';
 }
 
     *sptr++ = n % 10 + '0';
 }
 
-static char bell = ctrl(G);
+static char bell = ctrl('G');
 
 strlen (s)
 char *s;
 
 strlen (s)
 char *s;
@@ -694,15 +758,17 @@ int *length;
        }
        *p++ = c;
        if (c == '\t')
        }
        *p++ = c;
        if (c == '\t')
-           if (hardtabs && column < promptlen && !hard) {
-               if (eraseln && !dumb) {
+           if (!hardtabs || column < promptlen && !hard) {
+               if (hardtabs && eraseln && !dumb) {
                    column = 1 + (column | 7);
                    tputs (eraseln, 1, putch);
                    promptlen = 0;
                }
                else {
                    column = 1 + (column | 7);
                    tputs (eraseln, 1, putch);
                    promptlen = 0;
                }
                else {
-                   for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) {
+                   for (--p; p < &Line[LINSIZ - 1];) {
                        *p++ = ' ';
                        *p++ = ' ';
+                       if ((++column & 7) == 0)
+                           break;
                    }
                    if (column >= promptlen) promptlen = 0;
                }
                    }
                    if (column >= promptlen) promptlen = 0;
                }
@@ -734,6 +800,9 @@ int *length;
        }
     }
     colflg = column == Mcol && fold_opt;
        }
     }
     colflg = column == Mcol && fold_opt;
+    if (colflg && eatnl && Wrap) {
+       *p++ = '\n'; /* simulate normal wrap */
+    }
     *length = p - Line;
     *p = 0;
     return (column);
     *length = p - Line;
     *p = 0;
     return (column);
@@ -925,16 +994,56 @@ register FILE *f;
            if (retval >= 0)
                done++;
            break;
            if (retval >= 0)
                done++;
            break;
+       case 'b':
+       case ctrl('B'):
+           {
+               register int initline;
+
+               if (no_intty) {
+                   write(2, &bell, 1);
+                   return (-1);
+               }
+
+               if (nlines == 0) nlines++;
+
+               putchar ('\r');
+               erase (0);
+               printf ("\n");
+               if (clreol)
+                       cleareol ();
+               printf ("...back %d page", nlines);
+               if (nlines > 1)
+                       pr ("s\n");
+               else
+                       pr ("\n");
+
+               if (clreol)
+                       cleareol ();
+               pr ("\n");
+
+               initline = Currline - dlines * (nlines + 1);
+               if (! noscroll)
+                   --initline;
+               if (initline < 0) initline = 0;
+               Fseek(f, 0L);
+               Currline = 0;   /* skiplns() will make Currline correct */
+               skiplns(initline, f);
+               if (! noscroll) {
+                   ret(dlines + 1);
+               }
+               else {
+                   ret(dlines);
+               }
+           }
        case ' ':
        case 'z':
            if (nlines == 0) nlines = dlines;
            else if (comchar == 'z') dlines = nlines;
            ret (nlines);
        case 'd':
        case ' ':
        case 'z':
            if (nlines == 0) nlines = dlines;
            else if (comchar == 'z') dlines = nlines;
            ret (nlines);
        case 'd':
-       case ctrl(D):
+       case ctrl('D'):
            if (nlines != 0) nscroll = nlines;
            ret (nscroll);
            if (nlines != 0) nscroll = nlines;
            ret (nscroll);
-       case RUBOUT:
        case 'q':
        case 'Q':
            end_it ();
        case 'q':
        case 'Q':
            end_it ();
@@ -1024,19 +1133,21 @@ register FILE *f;
        case '!':
            do_shell (filename);
            break;
        case '!':
            do_shell (filename);
            break;
+       case '?':
        case 'h':
            if ((helpf = fopen (HELPFILE, "r")) == NULL)
                error ("Can't open help file");
            if (noscroll) doclear ();
            copy_file (helpf);
        case 'h':
            if ((helpf = fopen (HELPFILE, "r")) == NULL)
                error ("Can't open help file");
            if (noscroll) doclear ();
            copy_file (helpf);
-           close (helpf);
+           fclose (helpf);
            prompt (filename);
            break;
        case 'v':       /* This case should go right before default */
            if (!no_intty) {
                kill_line ();
                cmdbuf[0] = '+';
            prompt (filename);
            break;
        case 'v':       /* This case should go right before default */
            if (!no_intty) {
                kill_line ();
                cmdbuf[0] = '+';
-               scanstr (Currline, &cmdbuf[1]);
+               scanstr (Currline - dlines < 0 ? 0
+                               : Currline - (dlines + 1) / 2, &cmdbuf[1]);
                pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]);
                execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0);
                break;
                pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]);
                execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0);
                break;
@@ -1259,12 +1370,15 @@ register int n;
     }
 }
 
     }
 }
 
-execute (filename, cmd, args)
+/*VARARGS2*/
+execute (filename, cmd, va_alist)
 char *filename;
 char *filename;
-char *cmd, *args;
+char *cmd;
+va_dcl
 {
        int id;
        int n;
 {
        int id;
        int n;
+       va_list argp;
 
        fflush (stdout);
        reset_tty ();
 
        fflush (stdout);
        reset_tty ();
@@ -1275,9 +1389,11 @@ char *cmd, *args;
                close(0);
                open("/dev/tty", 0);
            }
                close(0);
                open("/dev/tty", 0);
            }
-           execv (cmd, &args);
+           va_start(argp);
+           execv (cmd, argp);
            write (2, "exec failed\n", 12);
            exit (1);
            write (2, "exec failed\n", 12);
            exit (1);
+           va_end(argp);       /* balance {}'s for some UNIX's */
        }
        if (id > 0) {
            signal (SIGINT, SIG_IGN);
        }
        if (id > 0) {
            signal (SIGINT, SIG_IGN);
@@ -1351,21 +1467,28 @@ register int nskip;
 initterm ()
 {
     char       buf[TBUFSIZ];
 initterm ()
 {
     char       buf[TBUFSIZ];
-    char       clearbuf[100];
+    static char        clearbuf[TBUFSIZ];
     char       *clearptr, *padstr;
     int                ldisc;
     char       *clearptr, *padstr;
     int                ldisc;
+    int                lmode;
     char       *term;
     int                tgrp;
     char       *term;
     int                tgrp;
+    struct winsize win;
 
 
-    setbuf(stdout, obuf);
 retry:
     if (!(no_tty = gtty(fileno(stdout), &otty))) {
 retry:
     if (!(no_tty = gtty(fileno(stdout), &otty))) {
+       if (ioctl(fileno(stdout), TIOCLGET, &lmode) < 0) {
+           perror("TIOCLGET");
+           exit(1);
+       }
+       docrterase = ((lmode & LCRTERA) != 0);
+       docrtkill = ((lmode & LCRTKIL) != 0);
        /*
        /*
-        * Wait until we're in the foreground before we get the
-        * save the terminal modes.
+        * Wait until we're in the foreground before we save the
+        * the terminal modes.
         */
        if (ioctl(fileno(stdout), TIOCGPGRP, &tgrp) < 0) {
         */
        if (ioctl(fileno(stdout), TIOCGPGRP, &tgrp) < 0) {
-           perror("ioctl");
+           perror("TIOCGPGRP");
            exit(1);
        }
        if (tgrp != getpgrp(0)) {
            exit(1);
        }
        if (tgrp != getpgrp(0)) {
@@ -1376,14 +1499,26 @@ retry:
            dumb++; ul_opt = 0;
        }
        else {
            dumb++; ul_opt = 0;
        }
        else {
-           if (((Lpp = tgetnum("li")) < 0) || tgetflag("hc")) {
+           if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
+               Lpp = tgetnum("li");
+               Mcol = tgetnum("co");
+           } else {
+               if ((Lpp = win.ws_row) == 0)
+                   Lpp = tgetnum("li");
+               if ((Mcol = win.ws_col) == 0)
+                   Mcol = tgetnum("co");
+           }
+           if ((Lpp <= 0) || tgetflag("hc")) {
                hard++; /* Hard copy terminal */
                Lpp = 24;
            }
                hard++; /* Hard copy terminal */
                Lpp = 24;
            }
+           if (tgetflag("xn"))
+               eatnl++; /* Eat newline at last column + 1; dec, concept */
+           if (Mcol <= 0)
+               Mcol = 80;
+
            if (tailequ (fnames[0], "page") || !hard && tgetflag("ns"))
                noscroll++;
            if (tailequ (fnames[0], "page") || !hard && tgetflag("ns"))
                noscroll++;
-           if ((Mcol = tgetnum("co")) < 0)
-               Mcol = 80;
            Wrap = tgetflag("am");
            bad_so = tgetflag ("xs");
            clearptr = clearbuf;
            Wrap = tgetflag("am");
            bad_so = tgetflag ("xs");
            clearptr = clearbuf;
@@ -1429,6 +1564,9 @@ retry:
               }
            }
            EodClr = tgetstr("cd", &clearptr);
               }
            }
            EodClr = tgetstr("cd", &clearptr);
+           if ((chBS = tgetstr("bc", &clearptr)) == NULL)
+               chBS = "\b";
+
        }
        if ((shell = getenv("SHELL")) == NULL)
            shell = "/bin/sh";
        }
        if ((shell = getenv("SHELL")) == NULL)
            shell = "/bin/sh";
@@ -1438,7 +1576,7 @@ retry:
     savetty = otty;
     ospeed = otty.sg_ospeed;
     slow_tty = ospeed < B1200;
     savetty = otty;
     ospeed = otty.sg_ospeed;
     slow_tty = ospeed < B1200;
-    hardtabs =  !(otty.sg_flags & XTABS);
+    hardtabs = (otty.sg_flags & TBDELAY) != XTABS;
     if (!no_tty) {
        otty.sg_flags &= ~ECHO;
        if (MBIT == CBREAK || !slow_tty)
     if (!no_tty) {
        otty.sg_flags &= ~ECHO;
        if (MBIT == CBREAK || !slow_tty)
@@ -1451,16 +1589,23 @@ readch ()
        char ch;
        extern int errno;
 
        char ch;
        extern int errno;
 
+       errno = 0;
        if (read (2, &ch, 1) <= 0)
                if (errno != EINTR)
        if (read (2, &ch, 1) <= 0)
                if (errno != EINTR)
-                       exit(0);
+                       end_it();
                else
                        ch = otty.sg_kill;
        return (ch);
 }
 
 static char BS = '\b';
                else
                        ch = otty.sg_kill;
        return (ch);
 }
 
 static char BS = '\b';
+static char *BSB = "\b \b";
 static char CARAT = '^';
 static char CARAT = '^';
+#define ERASEONECHAR \
+    if (docrterase) \
+       write (2, BSB, sizeof(BSB)); \
+    else \
+       write (2, &BS, sizeof(BS));
 
 ttyin (buf, nmax, pchar)
 char buf[];
 
 ttyin (buf, nmax, pchar)
 char buf[];
@@ -1484,11 +1629,11 @@ char pchar;
        else if ((ch == otty.sg_erase) && !slash) {
            if (sptr > buf) {
                --promptlen;
        else if ((ch == otty.sg_erase) && !slash) {
            if (sptr > buf) {
                --promptlen;
-               write (2, &BS, 1);
+               ERASEONECHAR
                --sptr;
                if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) {
                    --promptlen;
                --sptr;
                if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) {
                    --promptlen;
-                   write (2, &BS, 1);
+                   ERASEONECHAR
                }
                continue;
            }
                }
                continue;
            }
@@ -1508,6 +1653,9 @@ char pchar;
                putchar (pchar);
                if (eraseln)
                    erase (1);
                putchar (pchar);
                if (eraseln)
                    erase (1);
+               else if (docrtkill)
+                   while (promptlen-- > 1)
+                       write (2, BSB, sizeof(BSB));
                promptlen = 1;
            }
            sptr = buf;
                promptlen = 1;
            }
            sptr = buf;
@@ -1515,7 +1663,7 @@ char pchar;
            continue;
        }
        if (slash && (ch == otty.sg_kill || ch == otty.sg_erase)) {
            continue;
        }
        if (slash && (ch == otty.sg_kill || ch == otty.sg_erase)) {
-           write (2, &BS, 1);
+           ERASEONECHAR
            --sptr;
        }
        if (ch != '\\')
            --sptr;
        }
        if (ch != '\\')
@@ -1628,6 +1776,8 @@ set_tty ()
 
 reset_tty ()
 {
 
 reset_tty ()
 {
+    if (no_tty)
+       return;
     if (pstate) {
        tputs(ULexit, 1, putch);
        fflush(stdout);
     if (pstate) {
        tputs(ULexit, 1, putch);
        fflush(stdout);