added code for terminals with underline glitch, changed -d messages, a few minor...
[unix-history] / usr / src / old / more / more.c
index 2b9a2ca..f8bc259 100644 (file)
@@ -1,14 +1,16 @@
-static char *SCCS_ID = "@(#)more.c     4.1 (Berkeley) %G%";
+#ifndef lint
+static char *sccsid = "@(#)more.c      4.19 (Berkeley) 84/07/11";
+#endif
+
 /*
 ** more.c - General purpose tty output filter and file perusal program
 **
 **     by Eric Shienbrood, UC Berkeley
 /*
 ** more.c - General purpose tty output filter and file perusal program
 **
 **     by Eric Shienbrood, UC Berkeley
+**
+**     modified by Geoff Peck, UCB to add underlining, single spacing
+**     modified by John Foderaro, UCB to add -c and MORE environment variable
 */
 
 */
 
-#include <whoami.h>
-#ifdef V6
-#include <retrofit.h>
-#endif
 #include <stdio.h>
 #include <ctype.h>
 #include <signal.h>
 #include <stdio.h>
 #include <ctype.h>
 #include <signal.h>
@@ -16,23 +18,10 @@ static char *SCCS_ID = "@(#)more.c  4.1 (Berkeley) %G%";
 #include <sgtty.h>
 #include <setjmp.h>
 #include <sys/types.h>
 #include <sgtty.h>
 #include <setjmp.h>
 #include <sys/types.h>
-#include <sys/dir.h>
 #include <sys/stat.h>
 #include <sys/stat.h>
-#include <local/uparm.h>
-
-/* Help file will eventually go in libpath(more.help) on all systems */
 
 
-#ifdef INGRES
-#define VI             "/usr/bin/vi"
-#define HELPFILE       "/mntp/doucette/more/more.help"
-#endif
-
-#ifndef INGRES
-#ifndef HELPFILE
-#define HELPFILE       libpath(more.help)
-#endif
-#define VI             binpath(vi)
-#endif
+#define HELPFILE       "/usr/lib/more.help"
+#define VI             "/usr/ucb/vi"
 
 #define Fopen(s,m)     (Currline = 0,file_pos=0,fopen(s,m))
 #define Ftell(f)       file_pos
 
 #define Fopen(s,m)     (Currline = 0,file_pos=0,fopen(s,m))
 #define Ftell(f)       file_pos
@@ -40,13 +29,8 @@ static char *SCCS_ID = "@(#)more.c   4.1 (Berkeley) %G%";
 #define Getc(f)                (++file_pos, getc(f))
 #define Ungetc(c,f)    (--file_pos, ungetc(c,f))
 
 #define Getc(f)                (++file_pos, getc(f))
 #define Ungetc(c,f)    (--file_pos, ungetc(c,f))
 
-#ifdef V6
-#define MBIT   RAW
-#define CBREAK ~RAW
-#else
 #define MBIT   CBREAK
 #define stty(fd,argp)  ioctl(fd,TIOCSETN,argp)
 #define MBIT   CBREAK
 #define stty(fd,argp)  ioctl(fd,TIOCSETN,argp)
-#endif
 
 #define TBUFSIZ        1024
 #define LINSIZ 256
 
 #define TBUFSIZ        1024
 #define LINSIZ 256
@@ -55,16 +39,16 @@ static char *SCCS_ID = "@(#)more.c  4.1 (Berkeley) %G%";
 #define ESC    '\033'
 #define QUIT   '\034'
 
 #define ESC    '\033'
 #define QUIT   '\034'
 
-struct sgttyb  otty;
+struct sgttyb  otty, savetty;
 long           file_pos, file_size;
 int            fnum, no_intty, no_tty, slow_tty;
 int            dum_opt, dlines, onquit(), end_it();
 long           file_pos, file_size;
 int            fnum, no_intty, no_tty, slow_tty;
 int            dum_opt, dlines, onquit(), end_it();
-#ifdef SIGTSTP
 int            onsusp();
 int            onsusp();
-#endif
 int            nscroll = 11;   /* Number of lines scrolled by 'd' */
 int            fold_opt = 1;   /* Fold long lines */
 int            stop_opt = 1;   /* Stop after form feeds */
 int            nscroll = 11;   /* Number of lines scrolled by 'd' */
 int            fold_opt = 1;   /* Fold long lines */
 int            stop_opt = 1;   /* Stop after form feeds */
+int            ssp_opt = 0;    /* Suppress white space */
+int            ul_opt = 1;     /* Underline as best we can */
 int            promptlen;
 int            Currline;       /* Line we are currently at */
 int            startup = 1;
 int            promptlen;
 int            Currline;       /* Line we are currently at */
 int            startup = 1;
@@ -74,7 +58,7 @@ 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            inwait, Pause, errors;
 int            within; /* true if we are within a file,
                        false if we are between files */
-int            hard, dumb, noscroll, hardtabs;
+int            hard, dumb, noscroll, hardtabs, clreol;
 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 */
@@ -88,10 +72,18 @@ int         Lpp = 24;       /* lines per page */
 char           *Clear;         /* clear screen */
 char           *eraseln;       /* erase line */
 char           *Senter, *Sexit;/* enter and exit standout mode */
 char           *Clear;         /* clear screen */
 char           *eraseln;       /* erase line */
 char           *Senter, *Sexit;/* enter and exit standout mode */
+char           *ULenter, *ULexit;      /* enter and exit underline mode */
+char           *chUL;          /* underline character */
+char           *chBS;          /* backspace character */
+char           *Home;          /* go to home */
+char           *cursorm;       /* cursor movement */
+char           cursorhome[40]; /* contains cursor movement to home */
+char           *EodClr;        /* clear rest of screen */
 char           *tgetstr();
 int            Mcol = 80;      /* number of columns */
 int            Wrap = 1;       /* set if automargins */
 long           fseek();
 char           *tgetstr();
 int            Mcol = 80;      /* number of columns */
 int            Wrap = 1;       /* set if automargins */
 long           fseek();
+char           *getenv();
 struct {
     long chrctr, line;
 } context, screen_start;
 struct {
     long chrctr, line;
 } context, screen_start;
@@ -108,7 +100,7 @@ char *argv[];
     register char      *p;
     register char      ch;
     register int       left;
     register char      *p;
     register char      ch;
     register int       left;
-    int                        prnames = 0; 
+    int                        prnames = 0;
     int                        initopt = 0;
     int                        srchopt = 0;
     int                        clearit = 0;
     int                        initopt = 0;
     int                        srchopt = 0;
     int                        clearit = 0;
@@ -119,17 +111,13 @@ char *argv[];
     nfiles = argc;
     fnames = argv;
     initterm ();
     nfiles = argc;
     fnames = argv;
     initterm ();
+    nscroll = Lpp/2 - 1;
+    if (nscroll <= 0)
+       nscroll = 1;
+    if(s = getenv("MORE")) argscan(s);
     while (--nfiles > 0) {
        if ((ch = (*++fnames)[0]) == '-') {
     while (--nfiles > 0) {
        if ((ch = (*++fnames)[0]) == '-') {
-           for (s = fnames[0] + 1, dlines = 0; *s != '\0'; s++)
-               if (isdigit(*s))
-                   dlines = dlines*10 + *s - '0';
-               else if (*s == 'd')
-                   dum_opt = 1;
-               else if (*s == 'l')
-                   stop_opt = 0;
-               else if (*s == 'f')
-                   fold_opt = 0;
+           argscan(*fnames+1);
        }
        else if (ch == '+') {
            s = *fnames;
        }
        else if (ch == '+') {
            s = *fnames;
@@ -149,6 +137,16 @@ char *argv[];
        }
        else break;
     }
        }
        else break;
     }
+    /* allow clreol only if Home and eraseln and EodClr strings are
+     *  defined, and in that case, make sure we are in noscroll mode
+     */
+    if(clreol)
+    {
+       if ((*Home == '\0') || (*eraseln == '\0') || (*EodClr == '\0'))
+           clreol = 0;
+       else noscroll = 1;
+    }
+
     if (dlines == 0)
        dlines = Lpp - (noscroll ? 1 : 2);
     left = dlines;
     if (dlines == 0)
        dlines = Lpp - (noscroll ? 1 : 2);
     left = dlines;
@@ -165,27 +163,33 @@ char *argv[];
     if (!no_tty) {
        signal(SIGQUIT, onquit);
        signal(SIGINT, end_it);
     if (!no_tty) {
        signal(SIGQUIT, onquit);
        signal(SIGINT, end_it);
-#ifdef SIGTSTP
        if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
            signal(SIGTSTP, onsusp);
            catch_susp++;
        }
        if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) {
            signal(SIGTSTP, onsusp);
            catch_susp++;
        }
-#endif
-       stty (2, &otty);
+       stty (fileno(stderr), &otty);
     }
     if (no_intty) {
        if (no_tty)
            copy_file (stdin);
        else {
            if ((ch = Getc (f)) == '\f')
     }
     if (no_intty) {
        if (no_tty)
            copy_file (stdin);
        else {
            if ((ch = Getc (f)) == '\f')
-               doclear ();
+               doclear();
            else {
                Ungetc (ch, f);
            else {
                Ungetc (ch, f);
-               if (noscroll)
-                   doclear ();
+               if (noscroll && (ch != EOF)) {
+                   if (clreol)
+                       home ();
+                   else
+                       doclear ();
+               }
            }
            if (srchopt)
            }
            if (srchopt)
+           {
                search (initbuf, stdin, 1);
                search (initbuf, stdin, 1);
+               if (noscroll)
+                   left--;
+           }
            else if (initopt)
                skiplns (initline, stdin);
            screen (stdin, left);
            else if (initopt)
                skiplns (initline, stdin);
            screen (stdin, left);
@@ -203,7 +207,11 @@ char *argv[];
            if (firstf) {
                firstf = 0;
                if (srchopt)
            if (firstf) {
                firstf = 0;
                if (srchopt)
+               {
                    search (initbuf, f, 1);
                    search (initbuf, f, 1);
+                   if (noscroll)
+                       left--;
+               }
                else if (initopt)
                    skiplns (initline, f);
            }
                else if (initopt)
                    skiplns (initline, f);
            }
@@ -212,15 +220,24 @@ char *argv[];
                left = command (fnames[fnum], f);
            }
            if (left != 0) {
                left = command (fnames[fnum], f);
            }
            if (left != 0) {
-               if (noscroll || clearit)
-                   doclear ();
+               if ((noscroll || clearit) && (file_size != 0x7fffffffffffffffL))
+                   if (clreol)
+                       home ();
+                   else
+                       doclear ();
                if (prnames) {
                    if (bad_so)
                        erase (0);
                if (prnames) {
                    if (bad_so)
                        erase (0);
+                   if (clreol)
+                       cleareol ();
                    pr("::::::::::::::");
                    if (promptlen > 14)
                        erase (14);
                    pr("::::::::::::::");
                    if (promptlen > 14)
                        erase (14);
-                   printf ("\n%s\n::::::::::::::\n", fnames[fnum]);
+                   printf ("\n");
+                   if(clreol) cleareol();
+                   printf("%s\n", fnames[fnum]);
+                   if(clreol) cleareol();
+                   printf("::::::::::::::\n", fnames[fnum]);
                    if (left > Lpp - 4)
                        left = Lpp - 4;
                }
                    if (left > Lpp - 4)
                        left = Lpp - 4;
                }
@@ -245,6 +262,45 @@ char *argv[];
     exit(0);
 }
 
     exit(0);
 }
 
+argscan(s)
+char *s;
+{
+       for (dlines = 0; *s != '\0'; s++)
+       {
+               switch (*s)
+               {
+                 case '0': case '1': case '2':
+                 case '3': case '4': case '5':
+                 case '6': case '7': case '8':
+                 case '9':
+                       dlines = dlines*10 + *s - '0';
+                       break;
+                 case 'd':
+                       dum_opt = 1;
+                       break;
+                 case 'l':
+                       stop_opt = 0;
+                       break;
+                 case 'f':
+                       fold_opt = 0;
+                       break;
+                 case 'p':
+                       noscroll++;
+                       break;
+                 case 'c':
+                       clreol++;
+                       break;
+                 case 's':
+                       ssp_opt = 1;
+                       break;
+                 case 'u':
+                       ul_opt = 0;
+                       break;
+               }
+       }
+}
+
+
 /*
 ** Check whether the file named by fs is an ASCII file which the user may
 ** access.  If it is, return the opened file. Otherwise return NULL.
 /*
 ** Check whether the file named by fs is an ASCII file which the user may
 ** access.  If it is, return the opened file. Otherwise return NULL.
@@ -261,6 +317,8 @@ int *clearfirst;
 
     if (stat (fs, &stbuf) == -1) {
        fflush(stdout);
 
     if (stat (fs, &stbuf) == -1) {
        fflush(stdout);
+       if (clreol)
+           cleareol ();
        perror(fs);
        return (NULL);
     }
        perror(fs);
        return (NULL);
     }
@@ -323,18 +381,35 @@ register int num_lines;
 {
     register int c;
     register int nchars;
 {
     register int c;
     register int nchars;
-    int length;
+    int length;                        /* length of current line */
+    static int prev_len = 1;   /* length of previous line */
 
     for (;;) {
        while (num_lines > 0 && !Pause) {
            if ((nchars = getline (f, &length)) == EOF)
 
     for (;;) {
        while (num_lines > 0 && !Pause) {
            if ((nchars = getline (f, &length)) == EOF)
+           {
+               if (clreol)
+                   clreos();
                return;
                return;
+           }
+           if (ssp_opt && length == 0 && prev_len == 0)
+               continue;
+           prev_len = length;
            if (bad_so || (Senter && *Senter == ' ') && promptlen > 0)
                erase (0);
            if (bad_so || (Senter && *Senter == ' ') && promptlen > 0)
                erase (0);
+           /* must clear before drawing line since tabs on some terminals
+            * do not erase what they tab over.
+            */
+           if (clreol)
+               cleareol ();
            prbuf (Line, length);
            if (nchars < promptlen)
                erase (nchars); /* erase () sets promptlen to 0 */
            else promptlen = 0;
            prbuf (Line, length);
            if (nchars < promptlen)
                erase (nchars); /* erase () sets promptlen to 0 */
            else promptlen = 0;
+           /* is this needed?
+            * if (clreol)
+            *  cleareol();     /* must clear again in case we wrapped *
+            */
            if (nchars < Mcol || !fold_opt)
                putchar('\n');
            if (nchars == STOP)
            if (nchars < Mcol || !fold_opt)
                putchar('\n');
            if (nchars == STOP)
@@ -343,7 +418,14 @@ register int num_lines;
        }
        fflush(stdout);
        if ((c = Getc(f)) == EOF)
        }
        fflush(stdout);
        if ((c = Getc(f)) == EOF)
+       {
+           if (clreol)
+               clreos ();
            return;
            return;
+       }
+
+       if (Pause && clreol)
+           clreos ();
        Ungetc (c, f);
        setjmp (restore);
        Pause = 0; startup = 0;
        Ungetc (c, f);
        setjmp (restore);
        Pause = 0; startup = 0;
@@ -351,8 +433,13 @@ register int num_lines;
            return;
        if (hard && promptlen > 0)
                erase (0);
            return;
        if (hard && promptlen > 0)
                erase (0);
-       if (noscroll && num_lines == dlines)
+       if (noscroll && num_lines >= dlines)
+       {
+           if (clreol)
+               home();
+           else
                doclear ();
                doclear ();
+       }
        screen_start.line = Currline;
        screen_start.chrctr = Ftell (f);
     }
        screen_start.line = Currline;
        screen_start.chrctr = Ftell (f);
     }
@@ -390,7 +477,12 @@ end_it ()
 {
 
     reset_tty ();
 {
 
     reset_tty ();
-    if (promptlen > 0) {
+    if (clreol) {
+       putchar ('\r');
+       clreos ();
+       fflush (stdout);
+    }
+    else if (!clreol && (promptlen > 0)) {
        kill_line ();
        fflush (stdout);
     }
        kill_line ();
        fflush (stdout);
     }
@@ -476,16 +568,16 @@ int n;
 char *str;
 {
     sptr = str;
 char *str;
 {
     sptr = str;
-    sprintf (n);
+    Sprintf (n);
     *sptr = '\0';
 }
 
     *sptr = '\0';
 }
 
-sprintf (n)
+Sprintf (n)
 {
     int a;
 
     if (a = n/10)
 {
     int a;
 
     if (a = n/10)
-       sprintf (a);
+       Sprintf (a);
     *sptr++ = n % 10 + '0';
 }
 
     *sptr++ = n % 10 + '0';
 }
 
@@ -526,12 +618,16 @@ register char *string;
 prompt (filename)
 char *filename;
 {
 prompt (filename)
 char *filename;
 {
-    if (promptlen > 0)
+    if (clreol)
+       cleareol ();
+    else if (promptlen > 0)
        kill_line ();
     if (!hard) {
        promptlen = 8;
        if (Senter && Sexit)
            tputs (Senter, 1, putch);
        kill_line ();
     if (!hard) {
        promptlen = 8;
        if (Senter && Sexit)
            tputs (Senter, 1, putch);
+       if (clreol)
+           cleareol ();
        pr("--More--");
        if (filename != NULL) {
            promptlen += printf ("(Next file: %s)", filename);
        pr("--More--");
        if (filename != NULL) {
            promptlen += printf ("(Next file: %s)", filename);
@@ -544,6 +640,8 @@ char *filename;
        }
        if (Senter && Sexit)
            tputs (Sexit, 1, putch);
        }
        if (Senter && Sexit)
            tputs (Sexit, 1, putch);
+       if (clreol)
+           clreos ();
        fflush(stdout);
     }
     else
        fflush(stdout);
     }
     else
@@ -602,7 +700,7 @@ int *length;
            }
            else
                column = 1 + (column | 7);
            }
            else
                column = 1 + (column | 7);
-       else if (c == '\b')
+       else if (c == '\b' && column > 0)
            column--;
        else if (c == '\r')
            column = 0;
            column--;
        else if (c == '\r')
            column = 0;
@@ -667,6 +765,19 @@ kill_line ()
     if (!eraseln || dumb) putchar ('\r');
 }
 
     if (!eraseln || dumb) putchar ('\r');
 }
 
+/*
+ * force clear to end of line
+ */
+cleareol()
+{
+    tputs(eraseln, 1, putch);
+}
+
+clreos()
+{
+    tputs(EodClr, 1, putch);
+}
+
 /*
 **  Print string and return number of characters
 */
 /*
 **  Print string and return number of characters
 */
@@ -689,8 +800,37 @@ prbuf (s, n)
 register char *s;
 register int n;
 {
 register char *s;
 register int n;
 {
-    while (n-- > 0)
-       putchar (*s++);
+    char c;                            /* next ouput character */
+    register int state;                        /* next output char's UL state */
+    static int pstate = 0;             /* current terminal UL state (off) */
+
+    while (--n >= 0)
+       if (!ul_opt)
+           putchar (*s++);
+       else {
+           if (n >= 2 && s[0] == '_' && s[1] == '\b') {
+               n -= 2;
+               s += 2;
+               c = *s++;
+               state = 1;
+           } else if (n >= 2 && s[1] == '\b' && s[2] == '_') {
+               n -= 2;
+               c = *s++;
+               s += 2;
+               state = 1;
+           } else {
+               c = *s++;
+               state = 0;
+           }
+           if (state != pstate)
+               tputs(state ? ULenter : ULexit, 1, putch);
+           pstate = state;
+           putchar(c);
+           if (state && *chUL) {
+               pr(chBS);
+               tputs(chUL, 1, putch);
+           }
+       }
 }
 
 /*
 }
 
 /*
@@ -710,6 +850,14 @@ doclear()
     }
 }
 
     }
 }
 
+/*
+ * Go to home position
+ */
+home()
+{
+    tputs(Home,1,putch);
+}
+
 static int lastcmd, lastarg, lastp;
 static int lastcolon;
 char shell_line[132];
 static int lastcmd, lastarg, lastp;
 static int lastcolon;
 char shell_line[132];
@@ -742,7 +890,7 @@ register FILE *f;
        errors = 0;
     if (MBIT == RAW && slow_tty) {
        otty.sg_flags |= MBIT;
        errors = 0;
     if (MBIT == RAW && slow_tty) {
        otty.sg_flags |= MBIT;
-       stty(2, &otty);
+       stty(fileno(stderr), &otty);
     }
     for (;;) {
        nlines = number (&comchar);
     }
     for (;;) {
        nlines = number (&comchar);
@@ -787,11 +935,19 @@ register FILE *f;
                nlines *= dlines;
            putchar ('\r');
            erase (0);
                nlines *= dlines;
            putchar ('\r');
            erase (0);
-           printf("\n...skipping %d line", nlines);
+           printf ("\n");
+           if (clreol)
+               cleareol ();
+           printf ("...skipping %d line", nlines);
            if (nlines > 1)
            if (nlines > 1)
-               pr("s\n\n");
+               pr ("s\n");
            else
            else
-               pr("\n\n");
+               pr ("\n");
+
+           if (clreol)
+               cleareol ();
+           pr ("\n");
+
            while (nlines > 0) {
                while ((c = Getc (f)) != '\n')
                    if (c == EOF) {
            while (nlines > 0) {
                while ((c = Getc (f)) != '\n')
                    if (c == EOF) {
@@ -854,7 +1010,7 @@ register FILE *f;
                write (2, "\r", 1);
                search (cmdbuf, f, nlines);
            }
                write (2, "\r", 1);
                search (cmdbuf, f, nlines);
            }
-           ret (dlines);
+           ret (dlines-1);
        case '!':
            do_shell (filename);
            break;
        case '!':
            do_shell (filename);
            break;
@@ -887,7 +1043,7 @@ endsw:
     notell++;
     if (MBIT == RAW && slow_tty) {
        otty.sg_flags &= ~MBIT;
     notell++;
     if (MBIT == RAW && slow_tty) {
        otty.sg_flags &= ~MBIT;
-       stty(2, &otty);
+       stty(fileno(stderr), &otty);
     }
     return (retval);
 }
     }
     return (retval);
 }
@@ -1033,13 +1189,32 @@ register int n;
        if ((rv = re_exec (Line)) == 1)
                if (--n == 0) {
                    if (lncount > 3 || (lncount > 1 && no_intty))
        if ((rv = re_exec (Line)) == 1)
                if (--n == 0) {
                    if (lncount > 3 || (lncount > 1 && no_intty))
-                       pr ("\n...skipping\n");
+                   {
+                       pr ("\n");
+                       if (clreol)
+                           cleareol ();
+                       pr("...skipping\n");
+                   }
                    if (!no_intty) {
                        Currline -= (lncount >= 3 ? 3 : lncount);
                        Fseek (file, line3);
                    if (!no_intty) {
                        Currline -= (lncount >= 3 ? 3 : lncount);
                        Fseek (file, line3);
+                       if (noscroll)
+                           if (clreol) {
+                               home ();
+                               cleareol ();
+                           }
+                           else
+                               doclear ();
                    }
                    else {
                        kill_line ();
                    }
                    else {
                        kill_line ();
+                       if (noscroll)
+                           if (clreol) {
+                               home ();
+                               cleareol ();
+                           }
+                           else
+                               doclear ();
                        pr (Line);
                        putchar ('\n');
                    }
                        pr (Line);
                        putchar ('\n');
                    }
@@ -1050,9 +1225,7 @@ register int n;
     }
     if (feof (file)) {
        if (!no_intty) {
     }
     if (feof (file)) {
        if (!no_intty) {
-#ifdef V6
            file->_flag &= ~_IOEOF; /* why doesn't fseek do this ??!!??! */
            file->_flag &= ~_IOEOF; /* why doesn't fseek do this ??!!??! */
-#endif
            Currline = saveln;
            Fseek (file, startline);
        }
            Currline = saveln;
            Fseek (file, startline);
        }
@@ -1081,17 +1254,13 @@ char *cmd, *args;
        }
        signal (SIGINT, SIG_IGN);
        signal (SIGQUIT, SIG_IGN);
        }
        signal (SIGINT, SIG_IGN);
        signal (SIGQUIT, SIG_IGN);
-#ifdef SIGTSTP
        if (catch_susp)
            signal(SIGTSTP, SIG_DFL);
        if (catch_susp)
            signal(SIGTSTP, SIG_DFL);
-#endif
        wait (0);
        signal (SIGINT, end_it);
        signal (SIGQUIT, onquit);
        wait (0);
        signal (SIGINT, end_it);
        signal (SIGQUIT, onquit);
-#ifdef SIGTSTP
        if (catch_susp)
            signal(SIGTSTP, onsusp);
        if (catch_susp)
            signal(SIGTSTP, onsusp);
-#endif
        set_tty ();
        pr ("------------------------\n");
        prompt (filename);
        set_tty ();
        pr ("------------------------\n");
        prompt (filename);
@@ -1134,9 +1303,16 @@ register int nskip;
     if (fnum < 0)
        fnum = 0;
     pr ("\n...Skipping ");
     if (fnum < 0)
        fnum = 0;
     pr ("\n...Skipping ");
+    pr ("\n");
+    if (clreol)
+       cleareol ();
+    pr ("...Skipping ");
     pr (nskip > 0 ? "to file " : "back to file ");
     pr (fnames[fnum]);
     pr (nskip > 0 ? "to file " : "back to file ");
     pr (fnames[fnum]);
-    pr ("\n\n");
+    pr ("\n");
+    if (clreol)
+       cleareol ();
+    pr ("\n");
     --fnum;
 }
 
     --fnum;
 }
 
@@ -1147,13 +1323,27 @@ initterm ()
     char       buf[TBUFSIZ];
     char       clearbuf[100];
     char       *clearptr, *padstr;
     char       buf[TBUFSIZ];
     char       clearbuf[100];
     char       *clearptr, *padstr;
-    char       *getenv();
     int                ldisc;
     int                ldisc;
+    char       *term;
+    int                tgrp;
 
     setbuf(stdout, obuf);
 
     setbuf(stdout, obuf);
-    if (!(no_tty = gtty(1, &otty))) {
-       if (tgetent(buf, getenv("TERM")) <= 0) {
-           dumb++;
+retry:
+    if (!(no_tty = gtty(fileno(stdout), &otty))) {
+       /*
+        * Wait until we're in the foreground before we get the
+        * save the terminal modes.
+        */
+       if (ioctl(fileno(stdout), TIOCGPGRP, &tgrp) < 0) {
+           perror("ioctl");
+           exit(1);
+       }
+       if (tgrp != getpgrp(0)) {
+           kill(0, SIGTTOU);
+           goto retry;
+       }
+       if ((term = getenv("TERM")) == 0 || tgetent(buf, term) <= 0) {
+           dumb++; ul_opt = 0;
        }
        else {
            if (((Lpp = tgetnum("li")) < 0) || tgetflag("hc")) {
        }
        else {
            if (((Lpp = tgetnum("li")) < 0) || tgetflag("hc")) {
@@ -1171,14 +1361,44 @@ initterm ()
            Clear = tgetstr("cl", &clearptr);
            Senter = tgetstr("so", &clearptr);
            Sexit = tgetstr("se", &clearptr);
            Clear = tgetstr("cl", &clearptr);
            Senter = tgetstr("so", &clearptr);
            Sexit = tgetstr("se", &clearptr);
+
+           /*
+            *  Set up for underlining:  some terminals don't need it;
+            *  others have start/stop sequences, still others have an
+            *  underline char sequence which is assumed to move the
+            *  cursor forward one character.  If underline sequence
+            *  isn't available, settle for standout sequence.
+            */
+
+           if (tgetflag("ul") || tgetflag("os"))
+               ul_opt = 0;
+           if ((chUL = tgetstr("uc", &clearptr)) == NULL )
+               chUL = "";
+           if ((ULenter = tgetstr("us", &clearptr)) == NULL &&
+               (!*chUL) && (ULenter = tgetstr("so", &clearptr)) == NULL)
+               ULenter = "";
+           if ((ULexit = tgetstr("ue", &clearptr)) == NULL &&
+               (!*chUL) && (ULexit = tgetstr("se", &clearptr)) == NULL)
+               ULexit = "";
+
            if (padstr = tgetstr("pc", &clearptr))
                PC = *padstr;
            if (padstr = tgetstr("pc", &clearptr))
                PC = *padstr;
+           Home = tgetstr("ho",&clearptr);
+           if (Home == 0 || *Home == '\0')
+           {
+               if ((cursorm = tgetstr("cm", &clearptr)) != NULL) {
+                   strcpy(cursorhome, tgoto(cursorm, 0, 0));
+                   Home = cursorhome;
+              }
+           }
+           EodClr = tgetstr("cd", &clearptr);
        }
        if ((shell = getenv("SHELL")) == NULL)
            shell = "/bin/sh";
     }
        }
        if ((shell = getenv("SHELL")) == NULL)
            shell = "/bin/sh";
     }
-    no_intty = gtty(0, &otty);
-    gtty(2, &otty);
+    no_intty = gtty(fileno(stdin), &otty);
+    gtty(fileno(stderr), &otty);
+    savetty = otty;
     ospeed = otty.sg_ospeed;
     slow_tty = ospeed < B1200;
     hardtabs =  !(otty.sg_flags & XTABS);
     ospeed = otty.sg_ospeed;
     slow_tty = ospeed < B1200;
     hardtabs =  !(otty.sg_flags & XTABS);
@@ -1344,7 +1564,10 @@ register char ch;
 error (mess)
 char *mess;
 {
 error (mess)
 char *mess;
 {
-    kill_line ();
+    if (clreol)
+       cleareol ();
+    else
+       kill_line ();
     promptlen += strlen (mess);
     if (Senter && Sexit) {
        tputs (Senter, 1, putch);
     promptlen += strlen (mess);
     if (Senter && Sexit) {
        tputs (Senter, 1, putch);
@@ -1363,14 +1586,14 @@ set_tty ()
 {
        otty.sg_flags |= MBIT;
        otty.sg_flags &= ~ECHO;
 {
        otty.sg_flags |= MBIT;
        otty.sg_flags &= ~ECHO;
-       stty(2, &otty);
+       stty(fileno(stderr), &otty);
 }
 
 reset_tty ()
 {
     otty.sg_flags |= ECHO;
     otty.sg_flags &= ~MBIT;
 }
 
 reset_tty ()
 {
     otty.sg_flags |= ECHO;
     otty.sg_flags &= ~MBIT;
-    stty(2, &otty);
+    stty(fileno(stderr), &savetty);
 }
 
 rdline (f)
 }
 
 rdline (f)
@@ -1389,12 +1612,16 @@ register FILE *f;
 
 /* Come here when we get a suspend signal from the terminal */
 
 
 /* Come here when we get a suspend signal from the terminal */
 
-#ifdef SIGTSTP
 onsusp ()
 {
 onsusp ()
 {
+    /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */
+    signal(SIGTTOU, SIG_IGN);
     reset_tty ();
     fflush (stdout);
     reset_tty ();
     fflush (stdout);
+    signal(SIGTTOU, SIG_DFL);
     /* Send the TSTP signal to suspend our process group */
     /* Send the TSTP signal to suspend our process group */
+    signal(SIGTSTP, SIG_DFL);
+    sigsetmask(0);
     kill (0, SIGTSTP);
     /* Pause for station break */
 
     kill (0, SIGTSTP);
     /* Pause for station break */
 
@@ -1404,4 +1631,3 @@ onsusp ()
     if (inwait)
            longjmp (restore);
 }
     if (inwait)
            longjmp (restore);
 }
-#endif