1*3455Sroot static char *SCCS_ID = "@(#)more.c 4.2 (Berkeley) 3/27/81"; 21500Serics /* 31500Serics ** more.c - General purpose tty output filter and file perusal program 41500Serics ** 51500Serics ** by Eric Shienbrood, UC Berkeley 61500Serics */ 71500Serics 81500Serics #include <whoami.h> 91500Serics #ifdef V6 101500Serics #include <retrofit.h> 111500Serics #endif 121500Serics #include <stdio.h> 131500Serics #include <ctype.h> 141500Serics #include <signal.h> 151500Serics #include <errno.h> 161500Serics #include <sgtty.h> 171500Serics #include <setjmp.h> 181500Serics #include <sys/types.h> 191500Serics #include <sys/dir.h> 201500Serics #include <sys/stat.h> 211500Serics #include <local/uparm.h> 221500Serics 231500Serics /* Help file will eventually go in libpath(more.help) on all systems */ 241500Serics 251500Serics #ifdef INGRES 261500Serics #define VI "/usr/bin/vi" 271500Serics #define HELPFILE "/mntp/doucette/more/more.help" 281500Serics #endif 291500Serics 301500Serics #ifndef INGRES 311500Serics #ifndef HELPFILE 321500Serics #define HELPFILE libpath(more.help) 331500Serics #endif 341500Serics #define VI binpath(vi) 351500Serics #endif 361500Serics 371500Serics #define Fopen(s,m) (Currline = 0,file_pos=0,fopen(s,m)) 381500Serics #define Ftell(f) file_pos 391500Serics #define Fseek(f,off) (file_pos=off,fseek(f,off,0)) 401500Serics #define Getc(f) (++file_pos, getc(f)) 411500Serics #define Ungetc(c,f) (--file_pos, ungetc(c,f)) 421500Serics 431500Serics #ifdef V6 441500Serics #define MBIT RAW 451500Serics #define CBREAK ~RAW 461500Serics #else 471500Serics #define MBIT CBREAK 481500Serics #define stty(fd,argp) ioctl(fd,TIOCSETN,argp) 491500Serics #endif 501500Serics 511500Serics #define TBUFSIZ 1024 521500Serics #define LINSIZ 256 531500Serics #define ctrl(letter) ('letter' & 077) 541500Serics #define RUBOUT '\177' 551500Serics #define ESC '\033' 561500Serics #define QUIT '\034' 571500Serics 581500Serics struct sgttyb otty; 591500Serics long file_pos, file_size; 601500Serics int fnum, no_intty, no_tty, slow_tty; 611500Serics int dum_opt, dlines, onquit(), end_it(); 621500Serics #ifdef SIGTSTP 631500Serics int onsusp(); 641500Serics #endif 651500Serics int nscroll = 11; /* Number of lines scrolled by 'd' */ 661500Serics int fold_opt = 1; /* Fold long lines */ 671500Serics int stop_opt = 1; /* Stop after form feeds */ 681500Serics int promptlen; 691500Serics int Currline; /* Line we are currently at */ 701500Serics int startup = 1; 711500Serics int firstf = 1; 721500Serics int notell = 1; 731500Serics int bad_so; /* True if overwriting does not turn off standout */ 741500Serics int inwait, Pause, errors; 751500Serics int within; /* true if we are within a file, 761500Serics false if we are between files */ 77*3455Sroot int hard, dumb, noscroll, hardtabs,clreol; 781500Serics int catch_susp; /* We should catch the SIGTSTP signal */ 791500Serics char **fnames; /* The list of file names */ 801500Serics int nfiles; /* Number of files left to process */ 811500Serics char *shell; /* The name of the shell to use */ 821500Serics int shellp; /* A previous shell command exists */ 831500Serics char ch; 841500Serics jmp_buf restore; 851500Serics char obuf[BUFSIZ]; /* stdout buffer */ 861500Serics char Line[LINSIZ]; /* Line buffer */ 871500Serics int Lpp = 24; /* lines per page */ 881500Serics char *Clear; /* clear screen */ 891500Serics char *eraseln; /* erase line */ 901500Serics char *Senter, *Sexit;/* enter and exit standout mode */ 91*3455Sroot char *Home; /* go to home */ 92*3455Sroot char *cursorm; /* cursor movement */ 93*3455Sroot char cursorhome[40]; /* contains cursor movement to home */ 94*3455Sroot char *Cleareod; /* clear rest of screen */ 951500Serics char *tgetstr(); 961500Serics int Mcol = 80; /* number of columns */ 971500Serics int Wrap = 1; /* set if automargins */ 981500Serics long fseek(); 99*3455Sroot char *getenv(); 1001500Serics struct { 1011500Serics long chrctr, line; 1021500Serics } context, screen_start; 1031500Serics extern char PC; /* pad character */ 1041500Serics extern short ospeed; 1051500Serics 1061500Serics 1071500Serics main(argc, argv) 1081500Serics int argc; 1091500Serics char *argv[]; 1101500Serics { 1111500Serics register FILE *f; 1121500Serics register char *s; 1131500Serics register char *p; 1141500Serics register char ch; 1151500Serics register int left; 1161500Serics int prnames = 0; 1171500Serics int initopt = 0; 1181500Serics int srchopt = 0; 1191500Serics int clearit = 0; 1201500Serics int initline; 1211500Serics char initbuf[80]; 1221500Serics FILE *checkf(); 1231500Serics 1241500Serics nfiles = argc; 1251500Serics fnames = argv; 1261500Serics initterm (); 127*3455Sroot if(s = getenv("MORE")) argscan(s); 1281500Serics while (--nfiles > 0) { 1291500Serics if ((ch = (*++fnames)[0]) == '-') { 130*3455Sroot argscan(*fnames+1); 1311500Serics } 1321500Serics else if (ch == '+') { 1331500Serics s = *fnames; 1341500Serics if (*++s == '/') { 1351500Serics srchopt++; 1361500Serics for (++s, p = initbuf; p < initbuf + 79 && *s != '\0';) 1371500Serics *p++ = *s++; 1381500Serics *p = '\0'; 1391500Serics } 1401500Serics else { 1411500Serics initopt++; 1421500Serics for (initline = 0; *s != '\0'; s++) 1431500Serics if (isdigit (*s)) 1441500Serics initline = initline*10 + *s -'0'; 1451500Serics --initline; 1461500Serics } 1471500Serics } 1481500Serics else break; 1491500Serics } 150*3455Sroot /* allow clreol only if Home and eraseln and Cleareod strings are 151*3455Sroot * defined, and in that case, make sure we are in noscroll mode 152*3455Sroot */ 153*3455Sroot if(clreol) 154*3455Sroot { 155*3455Sroot if((*Home == '\0') || (*eraseln == '\0') || (*Cleareod == '\0')) 156*3455Sroot clreol = 0; 157*3455Sroot else noscroll = 1; 158*3455Sroot } 159*3455Sroot 1601500Serics if (dlines == 0) 1611500Serics dlines = Lpp - (noscroll ? 1 : 2); 1621500Serics left = dlines; 1631500Serics if (nfiles > 1) 1641500Serics prnames++; 1651500Serics if (!no_intty && nfiles == 0) { 1661500Serics fputs("Usage: ",stderr); 1671500Serics fputs(argv[0],stderr); 1681500Serics fputs(" [-dfln] [+linenum | +/pattern] name1 name2 ...\n",stderr); 1691500Serics exit(1); 1701500Serics } 1711500Serics else 1721500Serics f = stdin; 1731500Serics if (!no_tty) { 1741500Serics signal(SIGQUIT, onquit); 1751500Serics signal(SIGINT, end_it); 1761500Serics #ifdef SIGTSTP 1771500Serics if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) { 1781500Serics signal(SIGTSTP, onsusp); 1791500Serics catch_susp++; 1801500Serics } 1811500Serics #endif 1821500Serics stty (2, &otty); 1831500Serics } 1841500Serics if (no_intty) { 1851500Serics if (no_tty) 1861500Serics copy_file (stdin); 1871500Serics else { 1881500Serics if ((ch = Getc (f)) == '\f') 1891500Serics doclear (); 1901500Serics else { 1911500Serics Ungetc (ch, f); 192*3455Sroot if (noscroll && (ch != EOF)) 193*3455Sroot { if(clreol) home(); 194*3455Sroot else doclear (); 195*3455Sroot } 1961500Serics } 1971500Serics if (srchopt) 198*3455Sroot { 1991500Serics search (initbuf, stdin, 1); 200*3455Sroot if(noscroll) left--; 201*3455Sroot } 2021500Serics else if (initopt) 2031500Serics skiplns (initline, stdin); 2041500Serics screen (stdin, left); 2051500Serics } 2061500Serics no_intty = 0; 2071500Serics prnames++; 2081500Serics firstf = 0; 2091500Serics } 2101500Serics 2111500Serics while (fnum < nfiles) { 2121500Serics if ((f = checkf (fnames[fnum], &clearit)) != NULL) { 2131500Serics context.line = context.chrctr = 0; 2141500Serics Currline = 0; 2151500Serics if (firstf) setjmp (restore); 2161500Serics if (firstf) { 2171500Serics firstf = 0; 2181500Serics if (srchopt) 219*3455Sroot { 2201500Serics search (initbuf, f, 1); 221*3455Sroot if(noscroll) left--; 222*3455Sroot } 2231500Serics else if (initopt) 2241500Serics skiplns (initline, f); 2251500Serics } 2261500Serics else if (fnum < nfiles && !no_tty) { 2271500Serics setjmp (restore); 2281500Serics left = command (fnames[fnum], f); 2291500Serics } 2301500Serics if (left != 0) { 231*3455Sroot if((noscroll || clearit) && (file_size != 0x7fffffffffffffffL)) 232*3455Sroot if(clreol) home(); 233*3455Sroot else doclear (); 2341500Serics if (prnames) { 2351500Serics if (bad_so) 2361500Serics erase (0); 237*3455Sroot if(clreol)cleareol(); 2381500Serics pr("::::::::::::::"); 2391500Serics if (promptlen > 14) 2401500Serics erase (14); 241*3455Sroot printf ("\n"); 242*3455Sroot if(clreol) cleareol(); 243*3455Sroot printf("%s\n", fnames[fnum]); 244*3455Sroot if(clreol) cleareol(); 245*3455Sroot printf("::::::::::::::\n", fnames[fnum]); 2461500Serics if (left > Lpp - 4) 2471500Serics left = Lpp - 4; 2481500Serics } 2491500Serics if (no_tty) 2501500Serics copy_file (f); 2511500Serics else { 2521500Serics within++; 2531500Serics screen(f, left); 2541500Serics within = 0; 2551500Serics } 2561500Serics } 2571500Serics setjmp (restore); 2581500Serics fflush(stdout); 2591500Serics fclose(f); 2601500Serics screen_start.line = screen_start.chrctr = 0L; 2611500Serics context.line = context.chrctr = 0L; 2621500Serics } 2631500Serics fnum++; 2641500Serics firstf = 0; 2651500Serics } 2661500Serics reset_tty (); 2671500Serics exit(0); 2681500Serics } 2691500Serics 270*3455Sroot argscan(s) 271*3455Sroot char *s; 272*3455Sroot { 273*3455Sroot for (dlines = 0; *s != '\0'; s++) 274*3455Sroot if (isdigit(*s)) 275*3455Sroot dlines = dlines*10 + *s - '0'; 276*3455Sroot else if (*s == 'd') 277*3455Sroot dum_opt = 1; 278*3455Sroot else if (*s == 'l') 279*3455Sroot stop_opt = 0; 280*3455Sroot else if (*s == 'f') 281*3455Sroot fold_opt = 0; 282*3455Sroot else if (*s == 'p') 283*3455Sroot noscroll++; 284*3455Sroot else if (*s == 'c') 285*3455Sroot clreol++; 286*3455Sroot } 287*3455Sroot 288*3455Sroot 2891500Serics /* 290*3455Sroot 2911500Serics ** Check whether the file named by fs is an ASCII file which the user may 2921500Serics ** access. If it is, return the opened file. Otherwise return NULL. 2931500Serics */ 2941500Serics 2951500Serics FILE * 2961500Serics checkf (fs, clearfirst) 2971500Serics register char *fs; 2981500Serics int *clearfirst; 2991500Serics { 3001500Serics struct stat stbuf; 3011500Serics register FILE *f; 3021500Serics char c; 3031500Serics 3041500Serics if (stat (fs, &stbuf) == -1) { 3051500Serics fflush(stdout); 306*3455Sroot if(clreol)cleareol(); 3071500Serics perror(fs); 3081500Serics return (NULL); 3091500Serics } 3101500Serics if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 3111500Serics printf("\n*** %s: directory ***\n\n", fs); 3121500Serics return (NULL); 3131500Serics } 3141500Serics if ((f=Fopen(fs, "r")) == NULL) { 3151500Serics fflush(stdout); 3161500Serics perror(fs); 3171500Serics return (NULL); 3181500Serics } 3191500Serics c = Getc(f); 3201500Serics 3211500Serics /* Try to see whether it is an ASCII file */ 3221500Serics 3231500Serics switch ((c | *f->_ptr << 8) & 0177777) { 3241500Serics case 0405: 3251500Serics case 0407: 3261500Serics case 0410: 3271500Serics case 0411: 3281500Serics case 0413: 3291500Serics case 0177545: 3301500Serics printf("\n******** %s: Not a text file ********\n\n", fs); 3311500Serics fclose (f); 3321500Serics return (NULL); 3331500Serics default: 3341500Serics break; 3351500Serics } 3361500Serics if (c == '\f') 3371500Serics *clearfirst = 1; 3381500Serics else { 3391500Serics *clearfirst = 0; 3401500Serics Ungetc (c, f); 3411500Serics } 3421500Serics if ((file_size = stbuf.st_size) == 0) 3431500Serics file_size = 0x7fffffffffffffffL; 3441500Serics return (f); 3451500Serics } 3461500Serics 3471500Serics /* 3481500Serics ** A real function, for the tputs routine in termlib 3491500Serics */ 3501500Serics 3511500Serics putch (ch) 3521500Serics char ch; 3531500Serics { 3541500Serics putchar (ch); 3551500Serics } 3561500Serics 3571500Serics /* 3581500Serics ** Print out the contents of the file f, one screenful at a time. 3591500Serics */ 3601500Serics 3611500Serics #define STOP -10 3621500Serics 3631500Serics screen (f, num_lines) 3641500Serics register FILE *f; 3651500Serics register int num_lines; 3661500Serics { 3671500Serics register int c; 3681500Serics register int nchars; 3691500Serics int length; 3701500Serics 3711500Serics for (;;) { 3721500Serics while (num_lines > 0 && !Pause) { 3731500Serics if ((nchars = getline (f, &length)) == EOF) 374*3455Sroot { 375*3455Sroot if(clreol) cleareod(); 3761500Serics return; 377*3455Sroot } 3781500Serics if (bad_so || (Senter && *Senter == ' ') && promptlen > 0) 3791500Serics erase (0); 380*3455Sroot if (clreol) cleareol(); 3811500Serics prbuf (Line, length); 3821500Serics if (nchars < promptlen) 3831500Serics erase (nchars); /* erase () sets promptlen to 0 */ 3841500Serics else promptlen = 0; 3851500Serics if (nchars < Mcol || !fold_opt) 3861500Serics putchar('\n'); 3871500Serics if (nchars == STOP) 3881500Serics break; 3891500Serics num_lines--; 3901500Serics } 3911500Serics fflush(stdout); 3921500Serics if ((c = Getc(f)) == EOF) 393*3455Sroot { 394*3455Sroot if(clreol) cleareod(); 3951500Serics return; 396*3455Sroot } 397*3455Sroot 398*3455Sroot if(Pause && clreol) cleareod(); 399*3455Sroot 4001500Serics Ungetc (c, f); 4011500Serics setjmp (restore); 4021500Serics Pause = 0; startup = 0; 4031500Serics if ((num_lines = command (NULL, f)) == 0) 4041500Serics return; 4051500Serics if (hard && promptlen > 0) 4061500Serics erase (0); 4071500Serics if (noscroll && num_lines == dlines) 408*3455Sroot { 409*3455Sroot if(clreol) home(); 410*3455Sroot else doclear (); 411*3455Sroot } 4121500Serics screen_start.line = Currline; 4131500Serics screen_start.chrctr = Ftell (f); 4141500Serics } 4151500Serics } 4161500Serics 4171500Serics /* 4181500Serics ** Come here if a quit signal is received 4191500Serics */ 4201500Serics 4211500Serics onquit() 4221500Serics { 4231500Serics signal(SIGQUIT, SIG_IGN); 4241500Serics if (!inwait) { 4251500Serics putchar ('\n'); 4261500Serics if (!startup) { 4271500Serics signal(SIGQUIT, onquit); 4281500Serics longjmp (restore, 1); 4291500Serics } 4301500Serics else 4311500Serics Pause++; 4321500Serics } 4331500Serics else if (!dum_opt && notell) { 4341500Serics write (2, "[Use q or Q to quit]", 20); 4351500Serics promptlen += 20; 4361500Serics notell = 0; 4371500Serics } 4381500Serics signal(SIGQUIT, onquit); 4391500Serics } 4401500Serics 4411500Serics /* 4421500Serics ** Clean up terminal state and exit. Also come here if interrupt signal received 4431500Serics */ 4441500Serics 4451500Serics end_it () 4461500Serics { 4471500Serics 4481500Serics reset_tty (); 449*3455Sroot if(clreol) { putchar('\r'); cleareod(); fflush(stdout); } 450*3455Sroot else if (!clreol && (promptlen > 0)) { 4511500Serics kill_line (); 4521500Serics fflush (stdout); 4531500Serics } 4541500Serics else 4551500Serics write (2, "\n", 1); 4561500Serics _exit(0); 4571500Serics } 4581500Serics 4591500Serics copy_file(f) 4601500Serics register FILE *f; 4611500Serics { 4621500Serics register int c; 4631500Serics 4641500Serics while ((c = getc(f)) != EOF) 4651500Serics putchar(c); 4661500Serics } 4671500Serics 4681500Serics /* Simplified printf function */ 4691500Serics 4701500Serics printf (fmt, args) 4711500Serics register char *fmt; 4721500Serics int args; 4731500Serics { 4741500Serics register int *argp; 4751500Serics register char ch; 4761500Serics register int ccount; 4771500Serics 4781500Serics ccount = 0; 4791500Serics argp = &args; 4801500Serics while (*fmt) { 4811500Serics while ((ch = *fmt++) != '%') { 4821500Serics if (ch == '\0') 4831500Serics return (ccount); 4841500Serics ccount++; 4851500Serics putchar (ch); 4861500Serics } 4871500Serics switch (*fmt++) { 4881500Serics case 'd': 4891500Serics ccount += printd (*argp); 4901500Serics break; 4911500Serics case 's': 4921500Serics ccount += pr ((char *)*argp); 4931500Serics break; 4941500Serics case '%': 4951500Serics ccount++; 4961500Serics argp--; 4971500Serics putchar ('%'); 4981500Serics break; 4991500Serics case '0': 5001500Serics return (ccount); 5011500Serics default: 5021500Serics break; 5031500Serics } 5041500Serics ++argp; 5051500Serics } 5061500Serics return (ccount); 5071500Serics 5081500Serics } 5091500Serics 5101500Serics /* 5111500Serics ** Print an integer as a string of decimal digits, 5121500Serics ** returning the length of the print representation. 5131500Serics */ 5141500Serics 5151500Serics printd (n) 5161500Serics int n; 5171500Serics { 5181500Serics int a, nchars; 5191500Serics 5201500Serics if (a = n/10) 5211500Serics nchars = 1 + printd(a); 5221500Serics else 5231500Serics nchars = 1; 5241500Serics putchar (n % 10 + '0'); 5251500Serics return (nchars); 5261500Serics } 5271500Serics 5281500Serics /* Put the print representation of an integer into a string */ 5291500Serics static char *sptr; 5301500Serics 5311500Serics scanstr (n, str) 5321500Serics int n; 5331500Serics char *str; 5341500Serics { 5351500Serics sptr = str; 5361500Serics sprintf (n); 5371500Serics *sptr = '\0'; 5381500Serics } 5391500Serics 5401500Serics sprintf (n) 5411500Serics { 5421500Serics int a; 5431500Serics 5441500Serics if (a = n/10) 5451500Serics sprintf (a); 5461500Serics *sptr++ = n % 10 + '0'; 5471500Serics } 5481500Serics 5491500Serics static char bell = ctrl(G); 5501500Serics 5511500Serics strlen (s) 5521500Serics char *s; 5531500Serics { 5541500Serics register char *p; 5551500Serics 5561500Serics p = s; 5571500Serics while (*p++) 5581500Serics ; 5591500Serics return (p - s - 1); 5601500Serics } 5611500Serics 5621500Serics /* See whether the last component of the path name "path" is equal to the 5631500Serics ** string "string" 5641500Serics */ 5651500Serics 5661500Serics tailequ (path, string) 5671500Serics char *path; 5681500Serics register char *string; 5691500Serics { 5701500Serics register char *tail; 5711500Serics 5721500Serics tail = path + strlen(path); 5731500Serics while (tail >= path) 5741500Serics if (*(--tail) == '/') 5751500Serics break; 5761500Serics ++tail; 5771500Serics while (*tail++ == *string++) 5781500Serics if (*tail == '\0') 5791500Serics return(1); 5801500Serics return(0); 5811500Serics } 5821500Serics 5831500Serics prompt (filename) 5841500Serics char *filename; 5851500Serics { 586*3455Sroot if(clreol)cleareol(); 587*3455Sroot else if (promptlen > 0) 5881500Serics kill_line (); 5891500Serics if (!hard) { 5901500Serics promptlen = 8; 5911500Serics if (Senter && Sexit) 5921500Serics tputs (Senter, 1, putch); 593*3455Sroot if(clreol)cleareol(); 5941500Serics pr("--More--"); 5951500Serics if (filename != NULL) { 5961500Serics promptlen += printf ("(Next file: %s)", filename); 5971500Serics } 5981500Serics else if (!no_intty) { 5991500Serics promptlen += printf ("(%d%%)", (int)((file_pos * 100) / file_size)); 6001500Serics } 6011500Serics if (dum_opt) { 6021500Serics promptlen += pr("[Hit space to continue, Rubout to abort]"); 6031500Serics } 6041500Serics if (Senter && Sexit) 6051500Serics tputs (Sexit, 1, putch); 6061500Serics fflush(stdout); 6071500Serics } 6081500Serics else 6091500Serics write (2, &bell, 1); 6101500Serics inwait++; 6111500Serics } 6121500Serics 6131500Serics /* 6141500Serics ** Get a logical line 6151500Serics */ 6161500Serics 6171500Serics getline(f, length) 6181500Serics register FILE *f; 6191500Serics int *length; 6201500Serics { 6211500Serics register int c; 6221500Serics register char *p; 6231500Serics register int column; 6241500Serics static int colflg; 6251500Serics 6261500Serics p = Line; 6271500Serics column = 0; 6281500Serics c = Getc (f); 6291500Serics if (colflg && c == '\n') { 6301500Serics Currline++; 6311500Serics c = Getc (f); 6321500Serics } 6331500Serics while (p < &Line[LINSIZ - 1]) { 6341500Serics if (c == EOF) { 6351500Serics if (p > Line) { 6361500Serics *p = '\0'; 6371500Serics *length = p - Line; 6381500Serics return (column); 6391500Serics } 6401500Serics *length = p - Line; 6411500Serics return (EOF); 6421500Serics } 6431500Serics if (c == '\n') { 6441500Serics Currline++; 6451500Serics break; 6461500Serics } 6471500Serics *p++ = c; 6481500Serics if (c == '\t') 6491500Serics if (hardtabs && column < promptlen && !hard) { 6501500Serics if (eraseln && !dumb) { 6511500Serics column = 1 + (column | 7); 6521500Serics tputs (eraseln, 1, putch); 6531500Serics promptlen = 0; 6541500Serics } 6551500Serics else { 6561500Serics for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) { 6571500Serics *p++ = ' '; 6581500Serics } 6591500Serics if (column >= promptlen) promptlen = 0; 6601500Serics } 6611500Serics } 6621500Serics else 6631500Serics column = 1 + (column | 7); 6641500Serics else if (c == '\b') 6651500Serics column--; 6661500Serics else if (c == '\r') 6671500Serics column = 0; 6681500Serics else if (c == '\f' && stop_opt) { 6691500Serics p[-1] = '^'; 6701500Serics *p++ = 'L'; 6711500Serics column += 2; 6721500Serics Pause++; 6731500Serics } 6741500Serics else if (c == EOF) { 6751500Serics *length = p - Line; 6761500Serics return (column); 6771500Serics } 6781500Serics else if (c >= ' ' && c != RUBOUT) 6791500Serics column++; 6801500Serics if (column >= Mcol && fold_opt) break; 6811500Serics c = Getc (f); 6821500Serics } 6831500Serics if (column >= Mcol && Mcol > 0) { 6841500Serics if (!Wrap) { 6851500Serics *p++ = '\n'; 6861500Serics } 6871500Serics } 6881500Serics colflg = column == Mcol && fold_opt; 6891500Serics *length = p - Line; 6901500Serics *p = 0; 6911500Serics return (column); 6921500Serics } 6931500Serics 6941500Serics /* 6951500Serics ** Erase the rest of the prompt, assuming we are starting at column col. 6961500Serics */ 6971500Serics 6981500Serics erase (col) 6991500Serics register int col; 7001500Serics { 7011500Serics 7021500Serics if (promptlen == 0) 7031500Serics return; 7041500Serics if (hard) { 7051500Serics putchar ('\n'); 7061500Serics } 7071500Serics else { 7081500Serics if (col == 0) 7091500Serics putchar ('\r'); 7101500Serics if (!dumb && eraseln) 7111500Serics tputs (eraseln, 1, putch); 7121500Serics else 7131500Serics for (col = promptlen - col; col > 0; col--) 7141500Serics putchar (' '); 7151500Serics } 7161500Serics promptlen = 0; 7171500Serics } 7181500Serics 7191500Serics /* 7201500Serics ** Erase the current line entirely 7211500Serics */ 7221500Serics 7231500Serics kill_line () 7241500Serics { 7251500Serics erase (0); 7261500Serics if (!eraseln || dumb) putchar ('\r'); 7271500Serics } 7281500Serics 7291500Serics /* 730*3455Sroot * force clear to end of line 731*3455Sroot */ 732*3455Sroot cleareol() 733*3455Sroot { 734*3455Sroot tputs(eraseln,1,putch); 735*3455Sroot } 736*3455Sroot 737*3455Sroot cleareod() 738*3455Sroot { 739*3455Sroot tputs(Cleareod,1,putch); 740*3455Sroot } 741*3455Sroot 742*3455Sroot /* 7431500Serics ** Print string and return number of characters 7441500Serics */ 7451500Serics 7461500Serics pr(s1) 7471500Serics char *s1; 7481500Serics { 7491500Serics register char *s; 7501500Serics register char c; 7511500Serics 7521500Serics for (s = s1; c = *s++; ) 7531500Serics putchar(c); 7541500Serics return (s - s1 - 1); 7551500Serics } 7561500Serics 7571500Serics 7581500Serics /* Print a buffer of n characters */ 7591500Serics 7601500Serics prbuf (s, n) 7611500Serics register char *s; 7621500Serics register int n; 7631500Serics { 7641500Serics while (n-- > 0) 7651500Serics putchar (*s++); 7661500Serics } 7671500Serics 7681500Serics /* 7691500Serics ** Clear the screen 7701500Serics */ 7711500Serics 7721500Serics doclear() 7731500Serics { 7741500Serics if (Clear && !hard) { 7751500Serics tputs(Clear, 1, putch); 7761500Serics 7771500Serics /* Put out carriage return so that system doesn't 7781500Serics ** get confused by escape sequences when expanding tabs 7791500Serics */ 7801500Serics putchar ('\r'); 7811500Serics promptlen = 0; 7821500Serics } 7831500Serics } 7841500Serics 785*3455Sroot /* 786*3455Sroot * Go to home position 787*3455Sroot */ 788*3455Sroot home() 789*3455Sroot { 790*3455Sroot tputs(Home,1,putch); 791*3455Sroot } 792*3455Sroot 7931500Serics static int lastcmd, lastarg, lastp; 7941500Serics static int lastcolon; 7951500Serics char shell_line[132]; 7961500Serics 7971500Serics /* 7981500Serics ** Read a command and do it. A command consists of an optional integer 7991500Serics ** argument followed by the command character. Return the number of lines 8001500Serics ** to display in the next screenful. If there is nothing more to display 8011500Serics ** in the current file, zero is returned. 8021500Serics */ 8031500Serics 8041500Serics command (filename, f) 8051500Serics char *filename; 8061500Serics register FILE *f; 8071500Serics { 8081500Serics register int nlines; 8091500Serics register int retval; 8101500Serics register char c; 8111500Serics char colonch; 8121500Serics FILE *helpf; 8131500Serics int done; 8141500Serics char comchar, cmdbuf[80], *p; 8151500Serics 8161500Serics #define ret(val) retval=val;done++;break 8171500Serics 8181500Serics done = 0; 8191500Serics if (!errors) 8201500Serics prompt (filename); 8211500Serics else 8221500Serics errors = 0; 8231500Serics if (MBIT == RAW && slow_tty) { 8241500Serics otty.sg_flags |= MBIT; 8251500Serics stty(2, &otty); 8261500Serics } 8271500Serics for (;;) { 8281500Serics nlines = number (&comchar); 8291500Serics lastp = colonch = 0; 8301500Serics if (comchar == '.') { /* Repeat last command */ 8311500Serics lastp++; 8321500Serics comchar = lastcmd; 8331500Serics nlines = lastarg; 8341500Serics if (lastcmd == ':') 8351500Serics colonch = lastcolon; 8361500Serics } 8371500Serics lastcmd = comchar; 8381500Serics lastarg = nlines; 8391500Serics if (comchar == otty.sg_erase) { 8401500Serics kill_line (); 8411500Serics prompt (filename); 8421500Serics continue; 8431500Serics } 8441500Serics switch (comchar) { 8451500Serics case ':': 8461500Serics retval = colon (filename, colonch, nlines); 8471500Serics if (retval >= 0) 8481500Serics done++; 8491500Serics break; 8501500Serics case ' ': 8511500Serics case 'z': 8521500Serics if (nlines == 0) nlines = dlines; 8531500Serics else if (comchar == 'z') dlines = nlines; 8541500Serics ret (nlines); 8551500Serics case 'd': 8561500Serics case ctrl(D): 8571500Serics if (nlines != 0) nscroll = nlines; 8581500Serics ret (nscroll); 8591500Serics case RUBOUT: 8601500Serics case 'q': 8611500Serics case 'Q': 8621500Serics end_it (); 8631500Serics case 's': 8641500Serics case 'f': 8651500Serics if (nlines == 0) nlines++; 8661500Serics if (comchar == 'f') 8671500Serics nlines *= dlines; 8681500Serics putchar ('\r'); 8691500Serics erase (0); 870*3455Sroot printf("\n"); 871*3455Sroot if(clreol)cleareol(); 872*3455Sroot printf("...skipping %d line", nlines); 8731500Serics if (nlines > 1) 874*3455Sroot { 875*3455Sroot pr("s\n"); 876*3455Sroot if(clreol)cleareol(); 877*3455Sroot pr("\n"); 878*3455Sroot } 8791500Serics else 880*3455Sroot { 881*3455Sroot pr("\n"); 882*3455Sroot if(clreol)cleareol(); 883*3455Sroot pr("\n"); 884*3455Sroot } 8851500Serics while (nlines > 0) { 8861500Serics while ((c = Getc (f)) != '\n') 8871500Serics if (c == EOF) { 8881500Serics retval = 0; 8891500Serics done++; 8901500Serics goto endsw; 8911500Serics } 8921500Serics Currline++; 8931500Serics nlines--; 8941500Serics } 8951500Serics ret (dlines); 8961500Serics case '\n': 8971500Serics if (nlines != 0) 8981500Serics dlines = nlines; 8991500Serics else 9001500Serics nlines = 1; 9011500Serics ret (nlines); 9021500Serics case '\f': 9031500Serics if (!no_intty) { 9041500Serics doclear (); 9051500Serics Fseek (f, screen_start.chrctr); 9061500Serics Currline = screen_start.line; 9071500Serics ret (dlines); 9081500Serics } 9091500Serics else { 9101500Serics write (2, &bell, 1); 9111500Serics break; 9121500Serics } 9131500Serics case '\'': 9141500Serics if (!no_intty) { 9151500Serics kill_line (); 9161500Serics pr ("\n***Back***\n\n"); 9171500Serics Fseek (f, context.chrctr); 9181500Serics Currline = context.line; 9191500Serics ret (dlines); 9201500Serics } 9211500Serics else { 9221500Serics write (2, &bell, 1); 9231500Serics break; 9241500Serics } 9251500Serics case '=': 9261500Serics kill_line (); 9271500Serics promptlen = printd (Currline); 9281500Serics fflush (stdout); 9291500Serics break; 9301500Serics case 'n': 9311500Serics lastp++; 9321500Serics case '/': 9331500Serics if (nlines == 0) nlines++; 9341500Serics kill_line (); 9351500Serics pr ("/"); 9361500Serics promptlen = 1; 9371500Serics fflush (stdout); 9381500Serics if (lastp) { 9391500Serics write (2,"\r", 1); 9401500Serics search (NULL, f, nlines); /* Use previous r.e. */ 9411500Serics } 9421500Serics else { 9431500Serics ttyin (cmdbuf, 78, '/'); 9441500Serics write (2, "\r", 1); 9451500Serics search (cmdbuf, f, nlines); 9461500Serics } 947*3455Sroot ret (dlines-1); 9481500Serics case '!': 9491500Serics do_shell (filename); 9501500Serics break; 9511500Serics case 'h': 9521500Serics if ((helpf = fopen (HELPFILE, "r")) == NULL) 9531500Serics error ("Can't open help file"); 9541500Serics if (noscroll) doclear (); 9551500Serics copy_file (helpf); 9561500Serics close (helpf); 9571500Serics prompt (filename); 9581500Serics break; 9591500Serics case 'v': /* This case should go right before default */ 9601500Serics if (!no_intty) { 9611500Serics kill_line (); 9621500Serics cmdbuf[0] = '+'; 9631500Serics scanstr (Currline, &cmdbuf[1]); 9641500Serics pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]); 9651500Serics execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0); 9661500Serics break; 9671500Serics } 9681500Serics default: 9691500Serics write (2, &bell, 1); 9701500Serics break; 9711500Serics } 9721500Serics if (done) break; 9731500Serics } 9741500Serics putchar ('\r'); 9751500Serics endsw: 9761500Serics inwait = 0; 9771500Serics notell++; 9781500Serics if (MBIT == RAW && slow_tty) { 9791500Serics otty.sg_flags &= ~MBIT; 9801500Serics stty(2, &otty); 9811500Serics } 9821500Serics return (retval); 9831500Serics } 9841500Serics 9851500Serics char ch; 9861500Serics 9871500Serics /* 9881500Serics * Execute a colon-prefixed command. 9891500Serics * Returns <0 if not a command that should cause 9901500Serics * more of the file to be printed. 9911500Serics */ 9921500Serics 9931500Serics colon (filename, cmd, nlines) 9941500Serics char *filename; 9951500Serics int cmd; 9961500Serics int nlines; 9971500Serics { 9981500Serics if (cmd == 0) 9991500Serics ch = readch (); 10001500Serics else 10011500Serics ch = cmd; 10021500Serics lastcolon = ch; 10031500Serics switch (ch) { 10041500Serics case 'f': 10051500Serics kill_line (); 10061500Serics if (!no_intty) 10071500Serics promptlen = printf ("\"%s\" line %d", fnames[fnum], Currline); 10081500Serics else 10091500Serics promptlen = printf ("[Not a file] line %d", Currline); 10101500Serics fflush (stdout); 10111500Serics return (-1); 10121500Serics case 'n': 10131500Serics if (nlines == 0) { 10141500Serics if (fnum >= nfiles - 1) 10151500Serics end_it (); 10161500Serics nlines++; 10171500Serics } 10181500Serics putchar ('\r'); 10191500Serics erase (0); 10201500Serics skipf (nlines); 10211500Serics return (0); 10221500Serics case 'p': 10231500Serics if (no_intty) { 10241500Serics write (2, &bell, 1); 10251500Serics return (-1); 10261500Serics } 10271500Serics putchar ('\r'); 10281500Serics erase (0); 10291500Serics if (nlines == 0) 10301500Serics nlines++; 10311500Serics skipf (-nlines); 10321500Serics return (0); 10331500Serics case '!': 10341500Serics do_shell (filename); 10351500Serics return (-1); 10361500Serics case 'q': 10371500Serics case 'Q': 10381500Serics end_it (); 10391500Serics default: 10401500Serics write (2, &bell, 1); 10411500Serics return (-1); 10421500Serics } 10431500Serics } 10441500Serics 10451500Serics /* 10461500Serics ** Read a decimal number from the terminal. Set cmd to the non-digit which 10471500Serics ** terminates the number. 10481500Serics */ 10491500Serics 10501500Serics number(cmd) 10511500Serics char *cmd; 10521500Serics { 10531500Serics register int i; 10541500Serics 10551500Serics i = 0; ch = otty.sg_kill; 10561500Serics for (;;) { 10571500Serics ch = readch (); 10581500Serics if (ch >= '0' && ch <= '9') 10591500Serics i = i*10 + ch - '0'; 10601500Serics else if (ch == otty.sg_kill) 10611500Serics i = 0; 10621500Serics else { 10631500Serics *cmd = ch; 10641500Serics break; 10651500Serics } 10661500Serics } 10671500Serics return (i); 10681500Serics } 10691500Serics 10701500Serics do_shell (filename) 10711500Serics char *filename; 10721500Serics { 10731500Serics char cmdbuf[80]; 10741500Serics 10751500Serics kill_line (); 10761500Serics pr ("!"); 10771500Serics fflush (stdout); 10781500Serics promptlen = 1; 10791500Serics if (lastp) 10801500Serics pr (shell_line); 10811500Serics else { 10821500Serics ttyin (cmdbuf, 78, '!'); 10831500Serics if (expand (shell_line, cmdbuf)) { 10841500Serics kill_line (); 10851500Serics promptlen = printf ("!%s", shell_line); 10861500Serics } 10871500Serics } 10881500Serics fflush (stdout); 10891500Serics write (2, "\n", 1); 10901500Serics promptlen = 0; 10911500Serics shellp = 1; 10921500Serics execute (filename, shell, shell, "-c", shell_line, 0); 10931500Serics } 10941500Serics 10951500Serics /* 10961500Serics ** Search for nth ocurrence of regular expression contained in buf in the file 10971500Serics */ 10981500Serics 10991500Serics search (buf, file, n) 11001500Serics char buf[]; 11011500Serics FILE *file; 11021500Serics register int n; 11031500Serics { 11041500Serics long startline = Ftell (file); 11051500Serics register long line1 = startline; 11061500Serics register long line2 = startline; 11071500Serics register long line3 = startline; 11081500Serics register int lncount; 11091500Serics int saveln, rv, re_exec(); 11101500Serics char *s, *re_comp(); 11111500Serics 11121500Serics context.line = saveln = Currline; 11131500Serics context.chrctr = startline; 11141500Serics lncount = 0; 11151500Serics if ((s = re_comp (buf)) != 0) 11161500Serics error (s); 11171500Serics while (!feof (file)) { 11181500Serics line3 = line2; 11191500Serics line2 = line1; 11201500Serics line1 = Ftell (file); 11211500Serics rdline (file); 11221500Serics lncount++; 11231500Serics if ((rv = re_exec (Line)) == 1) 11241500Serics if (--n == 0) { 11251500Serics if (lncount > 3 || (lncount > 1 && no_intty)) 1126*3455Sroot { 1127*3455Sroot pr ("\n"); 1128*3455Sroot if(clreol) cleareol(); 1129*3455Sroot pr("...skipping\n"); 1130*3455Sroot } 11311500Serics if (!no_intty) { 11321500Serics Currline -= (lncount >= 3 ? 3 : lncount); 11331500Serics Fseek (file, line3); 1134*3455Sroot if(noscroll) 1135*3455Sroot if(clreol) 1136*3455Sroot { 1137*3455Sroot home(); 1138*3455Sroot cleareol(); 1139*3455Sroot } 1140*3455Sroot else doclear(); 11411500Serics } 11421500Serics else { 11431500Serics kill_line (); 1144*3455Sroot if(noscroll) 1145*3455Sroot if(clreol) 1146*3455Sroot { 1147*3455Sroot home(); 1148*3455Sroot cleareol(); 1149*3455Sroot } 1150*3455Sroot else doclear(); 11511500Serics pr (Line); 11521500Serics putchar ('\n'); 11531500Serics } 11541500Serics break; 11551500Serics } 11561500Serics else if (rv == -1) 11571500Serics error ("Regular expression botch"); 11581500Serics } 11591500Serics if (feof (file)) { 11601500Serics if (!no_intty) { 11611500Serics #ifdef V6 11621500Serics file->_flag &= ~_IOEOF; /* why doesn't fseek do this ??!!??! */ 11631500Serics #endif 11641500Serics Currline = saveln; 11651500Serics Fseek (file, startline); 11661500Serics } 11671500Serics else { 11681500Serics pr ("\nPattern not found\n"); 11691500Serics end_it (); 11701500Serics } 11711500Serics error ("Pattern not found"); 11721500Serics } 11731500Serics } 11741500Serics 11751500Serics execute (filename, cmd, args) 11761500Serics char *filename; 11771500Serics char *cmd, *args; 11781500Serics { 11791500Serics int id; 11801500Serics 11811500Serics fflush (stdout); 11821500Serics reset_tty (); 11831500Serics while ((id = fork ()) < 0) 11841500Serics sleep (5); 11851500Serics if (id == 0) { 11861500Serics execv (cmd, &args); 11871500Serics write (2, "exec failed\n", 12); 11881500Serics exit (1); 11891500Serics } 11901500Serics signal (SIGINT, SIG_IGN); 11911500Serics signal (SIGQUIT, SIG_IGN); 11921500Serics #ifdef SIGTSTP 11931500Serics if (catch_susp) 11941500Serics signal(SIGTSTP, SIG_DFL); 11951500Serics #endif 11961500Serics wait (0); 11971500Serics signal (SIGINT, end_it); 11981500Serics signal (SIGQUIT, onquit); 11991500Serics #ifdef SIGTSTP 12001500Serics if (catch_susp) 12011500Serics signal(SIGTSTP, onsusp); 12021500Serics #endif 12031500Serics set_tty (); 12041500Serics pr ("------------------------\n"); 12051500Serics prompt (filename); 12061500Serics } 12071500Serics /* 12081500Serics ** Skip n lines in the file f 12091500Serics */ 12101500Serics 12111500Serics skiplns (n, f) 12121500Serics register int n; 12131500Serics register FILE *f; 12141500Serics { 12151500Serics register char c; 12161500Serics 12171500Serics while (n > 0) { 12181500Serics while ((c = Getc (f)) != '\n') 12191500Serics if (c == EOF) 12201500Serics return; 12211500Serics n--; 12221500Serics Currline++; 12231500Serics } 12241500Serics } 12251500Serics 12261500Serics /* 12271500Serics ** Skip nskip files in the file list (from the command line). Nskip may be 12281500Serics ** negative. 12291500Serics */ 12301500Serics 12311500Serics skipf (nskip) 12321500Serics register int nskip; 12331500Serics { 12341500Serics if (nskip == 0) return; 12351500Serics if (nskip > 0) { 12361500Serics if (fnum + nskip > nfiles - 1) 12371500Serics nskip = nfiles - fnum - 1; 12381500Serics } 12391500Serics else if (within) 12401500Serics ++fnum; 12411500Serics fnum += nskip; 12421500Serics if (fnum < 0) 12431500Serics fnum = 0; 1244*3455Sroot pr ("\n"); 1245*3455Sroot if (clreol) cleareol(); 1246*3455Sroot pr ("...Skipping "); 12471500Serics pr (nskip > 0 ? "to file " : "back to file "); 12481500Serics pr (fnames[fnum]); 1249*3455Sroot pr ("\n"); 1250*3455Sroot if (clreol) cleareol(); 1251*3455Sroot pr ("\n"); 12521500Serics --fnum; 12531500Serics } 12541500Serics 12551500Serics /*----------------------------- Terminal I/O -------------------------------*/ 12561500Serics 12571500Serics initterm () 12581500Serics { 12591500Serics char buf[TBUFSIZ]; 12601500Serics char clearbuf[100]; 12611500Serics char *clearptr, *padstr; 12621500Serics int ldisc; 12631500Serics 12641500Serics setbuf(stdout, obuf); 12651500Serics if (!(no_tty = gtty(1, &otty))) { 12661500Serics if (tgetent(buf, getenv("TERM")) <= 0) { 12671500Serics dumb++; 12681500Serics } 12691500Serics else { 12701500Serics if (((Lpp = tgetnum("li")) < 0) || tgetflag("hc")) { 12711500Serics hard++; /* Hard copy terminal */ 12721500Serics Lpp = 24; 12731500Serics } 12741500Serics if (tailequ (fnames[0], "page") || !hard && tgetflag("ns")) 12751500Serics noscroll++; 12761500Serics if ((Mcol = tgetnum("co")) < 0) 12771500Serics Mcol = 80; 12781500Serics Wrap = tgetflag("am"); 12791500Serics bad_so = tgetflag ("xs"); 12801500Serics clearptr = clearbuf; 12811500Serics eraseln = tgetstr("ce",&clearptr); 12821500Serics Clear = tgetstr("cl", &clearptr); 12831500Serics Senter = tgetstr("so", &clearptr); 12841500Serics Sexit = tgetstr("se", &clearptr); 12851500Serics if (padstr = tgetstr("pc", &clearptr)) 12861500Serics PC = *padstr; 1287*3455Sroot Home = tgetstr("ho",&clearptr); 1288*3455Sroot if(*Home == '\0') 1289*3455Sroot { 1290*3455Sroot if(*(cursorm = tgetstr("cm",&clearptr))) 1291*3455Sroot { 1292*3455Sroot strcpy(cursorhome,tgoto(cursorm,0,0)); 1293*3455Sroot Home = cursorhome; 1294*3455Sroot } 1295*3455Sroot } 1296*3455Sroot Cleareod = tgetstr("cd",&clearptr); 12971500Serics } 12981500Serics if ((shell = getenv("SHELL")) == NULL) 12991500Serics shell = "/bin/sh"; 13001500Serics } 13011500Serics no_intty = gtty(0, &otty); 13021500Serics gtty(2, &otty); 13031500Serics ospeed = otty.sg_ospeed; 13041500Serics slow_tty = ospeed < B1200; 13051500Serics hardtabs = !(otty.sg_flags & XTABS); 13061500Serics if (!no_tty) { 13071500Serics otty.sg_flags &= ~ECHO; 13081500Serics if (MBIT == CBREAK || !slow_tty) 13091500Serics otty.sg_flags |= MBIT; 13101500Serics } 13111500Serics } 13121500Serics 13131500Serics readch () 13141500Serics { 13151500Serics char ch; 13161500Serics extern int errno; 13171500Serics 13181500Serics if (read (2, &ch, 1) <= 0) 13191500Serics if (errno != EINTR) 13201500Serics exit(0); 13211500Serics else 13221500Serics ch = otty.sg_kill; 13231500Serics return (ch); 13241500Serics } 13251500Serics 13261500Serics static char BS = '\b'; 13271500Serics static char CARAT = '^'; 13281500Serics 13291500Serics ttyin (buf, nmax, pchar) 13301500Serics char buf[]; 13311500Serics register int nmax; 13321500Serics char pchar; 13331500Serics { 13341500Serics register char *sptr; 13351500Serics register char ch; 13361500Serics register int slash = 0; 13371500Serics int maxlen; 13381500Serics char cbuf; 13391500Serics 13401500Serics sptr = buf; 13411500Serics maxlen = 0; 13421500Serics while (sptr - buf < nmax) { 13431500Serics if (promptlen > maxlen) maxlen = promptlen; 13441500Serics ch = readch (); 13451500Serics if (ch == '\\') { 13461500Serics slash++; 13471500Serics } 13481500Serics else if ((ch == otty.sg_erase) && !slash) { 13491500Serics if (sptr > buf) { 13501500Serics --promptlen; 13511500Serics write (2, &BS, 1); 13521500Serics --sptr; 13531500Serics if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) { 13541500Serics --promptlen; 13551500Serics write (2, &BS, 1); 13561500Serics } 13571500Serics continue; 13581500Serics } 13591500Serics else { 13601500Serics if (!eraseln) promptlen = maxlen; 13611500Serics longjmp (restore, 1); 13621500Serics } 13631500Serics } 13641500Serics else if ((ch == otty.sg_kill) && !slash) { 13651500Serics if (hard) { 13661500Serics show (ch); 13671500Serics putchar ('\n'); 13681500Serics putchar (pchar); 13691500Serics } 13701500Serics else { 13711500Serics putchar ('\r'); 13721500Serics putchar (pchar); 13731500Serics if (eraseln) 13741500Serics erase (1); 13751500Serics promptlen = 1; 13761500Serics } 13771500Serics sptr = buf; 13781500Serics fflush (stdout); 13791500Serics continue; 13801500Serics } 13811500Serics if (slash && (ch == otty.sg_kill || ch == otty.sg_erase)) { 13821500Serics write (2, &BS, 1); 13831500Serics --sptr; 13841500Serics } 13851500Serics if (ch != '\\') 13861500Serics slash = 0; 13871500Serics *sptr++ = ch; 13881500Serics if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { 13891500Serics ch += ch == RUBOUT ? -0100 : 0100; 13901500Serics write (2, &CARAT, 1); 13911500Serics promptlen++; 13921500Serics } 13931500Serics cbuf = ch; 13941500Serics if (ch != '\n' && ch != ESC) { 13951500Serics write (2, &cbuf, 1); 13961500Serics promptlen++; 13971500Serics } 13981500Serics else 13991500Serics break; 14001500Serics } 14011500Serics *--sptr = '\0'; 14021500Serics if (!eraseln) promptlen = maxlen; 14031500Serics if (sptr - buf >= nmax - 1) 14041500Serics error ("Line too long"); 14051500Serics } 14061500Serics 14071500Serics expand (outbuf, inbuf) 14081500Serics char *outbuf; 14091500Serics char *inbuf; 14101500Serics { 14111500Serics register char *instr; 14121500Serics register char *outstr; 14131500Serics register char ch; 14141500Serics char temp[200]; 14151500Serics int changed = 0; 14161500Serics 14171500Serics instr = inbuf; 14181500Serics outstr = temp; 14191500Serics while ((ch = *instr++) != '\0') 14201500Serics switch (ch) { 14211500Serics case '%': 14221500Serics if (!no_intty) { 14231500Serics strcpy (outstr, fnames[fnum]); 14241500Serics outstr += strlen (fnames[fnum]); 14251500Serics changed++; 14261500Serics } 14271500Serics else 14281500Serics *outstr++ = ch; 14291500Serics break; 14301500Serics case '!': 14311500Serics if (!shellp) 14321500Serics error ("No previous command to substitute for"); 14331500Serics strcpy (outstr, shell_line); 14341500Serics outstr += strlen (shell_line); 14351500Serics changed++; 14361500Serics break; 14371500Serics case '\\': 14381500Serics if (*instr == '%' || *instr == '!') { 14391500Serics *outstr++ = *instr++; 14401500Serics break; 14411500Serics } 14421500Serics default: 14431500Serics *outstr++ = ch; 14441500Serics } 14451500Serics *outstr++ = '\0'; 14461500Serics strcpy (outbuf, temp); 14471500Serics return (changed); 14481500Serics } 14491500Serics 14501500Serics show (ch) 14511500Serics register char ch; 14521500Serics { 14531500Serics char cbuf; 14541500Serics 14551500Serics if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { 14561500Serics ch += ch == RUBOUT ? -0100 : 0100; 14571500Serics write (2, &CARAT, 1); 14581500Serics promptlen++; 14591500Serics } 14601500Serics cbuf = ch; 14611500Serics write (2, &cbuf, 1); 14621500Serics promptlen++; 14631500Serics } 14641500Serics 14651500Serics error (mess) 14661500Serics char *mess; 14671500Serics { 1468*3455Sroot if(clreol)cleareol(); 1469*3455Sroot else kill_line (); 14701500Serics promptlen += strlen (mess); 14711500Serics if (Senter && Sexit) { 14721500Serics tputs (Senter, 1, putch); 14731500Serics pr(mess); 14741500Serics tputs (Sexit, 1, putch); 14751500Serics } 14761500Serics else 14771500Serics pr (mess); 14781500Serics fflush(stdout); 14791500Serics errors++; 14801500Serics longjmp (restore, 1); 14811500Serics } 14821500Serics 14831500Serics 14841500Serics set_tty () 14851500Serics { 14861500Serics otty.sg_flags |= MBIT; 14871500Serics otty.sg_flags &= ~ECHO; 14881500Serics stty(2, &otty); 14891500Serics } 14901500Serics 14911500Serics reset_tty () 14921500Serics { 14931500Serics otty.sg_flags |= ECHO; 14941500Serics otty.sg_flags &= ~MBIT; 14951500Serics stty(2, &otty); 14961500Serics } 14971500Serics 14981500Serics rdline (f) 14991500Serics register FILE *f; 15001500Serics { 15011500Serics register char c; 15021500Serics register char *p; 15031500Serics 15041500Serics p = Line; 15051500Serics while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1) 15061500Serics *p++ = c; 15071500Serics if (c == '\n') 15081500Serics Currline++; 15091500Serics *p = '\0'; 15101500Serics } 15111500Serics 15121500Serics /* Come here when we get a suspend signal from the terminal */ 15131500Serics 15141500Serics #ifdef SIGTSTP 15151500Serics onsusp () 15161500Serics { 15171500Serics reset_tty (); 15181500Serics fflush (stdout); 15191500Serics /* Send the TSTP signal to suspend our process group */ 15201500Serics kill (0, SIGTSTP); 15211500Serics /* Pause for station break */ 15221500Serics 15231500Serics /* We're back */ 15241500Serics signal (SIGTSTP, onsusp); 15251500Serics set_tty (); 15261500Serics if (inwait) 15271500Serics longjmp (restore); 15281500Serics } 15291500Serics #endif 1530