1*1500Serics static char *SCCS_ID = "@(#)more.c 4.1 (Berkeley) 10/17/80"; 2*1500Serics /* 3*1500Serics ** more.c - General purpose tty output filter and file perusal program 4*1500Serics ** 5*1500Serics ** by Eric Shienbrood, UC Berkeley 6*1500Serics */ 7*1500Serics 8*1500Serics #include <whoami.h> 9*1500Serics #ifdef V6 10*1500Serics #include <retrofit.h> 11*1500Serics #endif 12*1500Serics #include <stdio.h> 13*1500Serics #include <ctype.h> 14*1500Serics #include <signal.h> 15*1500Serics #include <errno.h> 16*1500Serics #include <sgtty.h> 17*1500Serics #include <setjmp.h> 18*1500Serics #include <sys/types.h> 19*1500Serics #include <sys/dir.h> 20*1500Serics #include <sys/stat.h> 21*1500Serics #include <local/uparm.h> 22*1500Serics 23*1500Serics /* Help file will eventually go in libpath(more.help) on all systems */ 24*1500Serics 25*1500Serics #ifdef INGRES 26*1500Serics #define VI "/usr/bin/vi" 27*1500Serics #define HELPFILE "/mntp/doucette/more/more.help" 28*1500Serics #endif 29*1500Serics 30*1500Serics #ifndef INGRES 31*1500Serics #ifndef HELPFILE 32*1500Serics #define HELPFILE libpath(more.help) 33*1500Serics #endif 34*1500Serics #define VI binpath(vi) 35*1500Serics #endif 36*1500Serics 37*1500Serics #define Fopen(s,m) (Currline = 0,file_pos=0,fopen(s,m)) 38*1500Serics #define Ftell(f) file_pos 39*1500Serics #define Fseek(f,off) (file_pos=off,fseek(f,off,0)) 40*1500Serics #define Getc(f) (++file_pos, getc(f)) 41*1500Serics #define Ungetc(c,f) (--file_pos, ungetc(c,f)) 42*1500Serics 43*1500Serics #ifdef V6 44*1500Serics #define MBIT RAW 45*1500Serics #define CBREAK ~RAW 46*1500Serics #else 47*1500Serics #define MBIT CBREAK 48*1500Serics #define stty(fd,argp) ioctl(fd,TIOCSETN,argp) 49*1500Serics #endif 50*1500Serics 51*1500Serics #define TBUFSIZ 1024 52*1500Serics #define LINSIZ 256 53*1500Serics #define ctrl(letter) ('letter' & 077) 54*1500Serics #define RUBOUT '\177' 55*1500Serics #define ESC '\033' 56*1500Serics #define QUIT '\034' 57*1500Serics 58*1500Serics struct sgttyb otty; 59*1500Serics long file_pos, file_size; 60*1500Serics int fnum, no_intty, no_tty, slow_tty; 61*1500Serics int dum_opt, dlines, onquit(), end_it(); 62*1500Serics #ifdef SIGTSTP 63*1500Serics int onsusp(); 64*1500Serics #endif 65*1500Serics int nscroll = 11; /* Number of lines scrolled by 'd' */ 66*1500Serics int fold_opt = 1; /* Fold long lines */ 67*1500Serics int stop_opt = 1; /* Stop after form feeds */ 68*1500Serics int promptlen; 69*1500Serics int Currline; /* Line we are currently at */ 70*1500Serics int startup = 1; 71*1500Serics int firstf = 1; 72*1500Serics int notell = 1; 73*1500Serics int bad_so; /* True if overwriting does not turn off standout */ 74*1500Serics int inwait, Pause, errors; 75*1500Serics int within; /* true if we are within a file, 76*1500Serics false if we are between files */ 77*1500Serics int hard, dumb, noscroll, hardtabs; 78*1500Serics int catch_susp; /* We should catch the SIGTSTP signal */ 79*1500Serics char **fnames; /* The list of file names */ 80*1500Serics int nfiles; /* Number of files left to process */ 81*1500Serics char *shell; /* The name of the shell to use */ 82*1500Serics int shellp; /* A previous shell command exists */ 83*1500Serics char ch; 84*1500Serics jmp_buf restore; 85*1500Serics char obuf[BUFSIZ]; /* stdout buffer */ 86*1500Serics char Line[LINSIZ]; /* Line buffer */ 87*1500Serics int Lpp = 24; /* lines per page */ 88*1500Serics char *Clear; /* clear screen */ 89*1500Serics char *eraseln; /* erase line */ 90*1500Serics char *Senter, *Sexit;/* enter and exit standout mode */ 91*1500Serics char *tgetstr(); 92*1500Serics int Mcol = 80; /* number of columns */ 93*1500Serics int Wrap = 1; /* set if automargins */ 94*1500Serics long fseek(); 95*1500Serics struct { 96*1500Serics long chrctr, line; 97*1500Serics } context, screen_start; 98*1500Serics extern char PC; /* pad character */ 99*1500Serics extern short ospeed; 100*1500Serics 101*1500Serics 102*1500Serics main(argc, argv) 103*1500Serics int argc; 104*1500Serics char *argv[]; 105*1500Serics { 106*1500Serics register FILE *f; 107*1500Serics register char *s; 108*1500Serics register char *p; 109*1500Serics register char ch; 110*1500Serics register int left; 111*1500Serics int prnames = 0; 112*1500Serics int initopt = 0; 113*1500Serics int srchopt = 0; 114*1500Serics int clearit = 0; 115*1500Serics int initline; 116*1500Serics char initbuf[80]; 117*1500Serics FILE *checkf(); 118*1500Serics 119*1500Serics nfiles = argc; 120*1500Serics fnames = argv; 121*1500Serics initterm (); 122*1500Serics while (--nfiles > 0) { 123*1500Serics if ((ch = (*++fnames)[0]) == '-') { 124*1500Serics for (s = fnames[0] + 1, dlines = 0; *s != '\0'; s++) 125*1500Serics if (isdigit(*s)) 126*1500Serics dlines = dlines*10 + *s - '0'; 127*1500Serics else if (*s == 'd') 128*1500Serics dum_opt = 1; 129*1500Serics else if (*s == 'l') 130*1500Serics stop_opt = 0; 131*1500Serics else if (*s == 'f') 132*1500Serics fold_opt = 0; 133*1500Serics } 134*1500Serics else if (ch == '+') { 135*1500Serics s = *fnames; 136*1500Serics if (*++s == '/') { 137*1500Serics srchopt++; 138*1500Serics for (++s, p = initbuf; p < initbuf + 79 && *s != '\0';) 139*1500Serics *p++ = *s++; 140*1500Serics *p = '\0'; 141*1500Serics } 142*1500Serics else { 143*1500Serics initopt++; 144*1500Serics for (initline = 0; *s != '\0'; s++) 145*1500Serics if (isdigit (*s)) 146*1500Serics initline = initline*10 + *s -'0'; 147*1500Serics --initline; 148*1500Serics } 149*1500Serics } 150*1500Serics else break; 151*1500Serics } 152*1500Serics if (dlines == 0) 153*1500Serics dlines = Lpp - (noscroll ? 1 : 2); 154*1500Serics left = dlines; 155*1500Serics if (nfiles > 1) 156*1500Serics prnames++; 157*1500Serics if (!no_intty && nfiles == 0) { 158*1500Serics fputs("Usage: ",stderr); 159*1500Serics fputs(argv[0],stderr); 160*1500Serics fputs(" [-dfln] [+linenum | +/pattern] name1 name2 ...\n",stderr); 161*1500Serics exit(1); 162*1500Serics } 163*1500Serics else 164*1500Serics f = stdin; 165*1500Serics if (!no_tty) { 166*1500Serics signal(SIGQUIT, onquit); 167*1500Serics signal(SIGINT, end_it); 168*1500Serics #ifdef SIGTSTP 169*1500Serics if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) { 170*1500Serics signal(SIGTSTP, onsusp); 171*1500Serics catch_susp++; 172*1500Serics } 173*1500Serics #endif 174*1500Serics stty (2, &otty); 175*1500Serics } 176*1500Serics if (no_intty) { 177*1500Serics if (no_tty) 178*1500Serics copy_file (stdin); 179*1500Serics else { 180*1500Serics if ((ch = Getc (f)) == '\f') 181*1500Serics doclear (); 182*1500Serics else { 183*1500Serics Ungetc (ch, f); 184*1500Serics if (noscroll) 185*1500Serics doclear (); 186*1500Serics } 187*1500Serics if (srchopt) 188*1500Serics search (initbuf, stdin, 1); 189*1500Serics else if (initopt) 190*1500Serics skiplns (initline, stdin); 191*1500Serics screen (stdin, left); 192*1500Serics } 193*1500Serics no_intty = 0; 194*1500Serics prnames++; 195*1500Serics firstf = 0; 196*1500Serics } 197*1500Serics 198*1500Serics while (fnum < nfiles) { 199*1500Serics if ((f = checkf (fnames[fnum], &clearit)) != NULL) { 200*1500Serics context.line = context.chrctr = 0; 201*1500Serics Currline = 0; 202*1500Serics if (firstf) setjmp (restore); 203*1500Serics if (firstf) { 204*1500Serics firstf = 0; 205*1500Serics if (srchopt) 206*1500Serics search (initbuf, f, 1); 207*1500Serics else if (initopt) 208*1500Serics skiplns (initline, f); 209*1500Serics } 210*1500Serics else if (fnum < nfiles && !no_tty) { 211*1500Serics setjmp (restore); 212*1500Serics left = command (fnames[fnum], f); 213*1500Serics } 214*1500Serics if (left != 0) { 215*1500Serics if (noscroll || clearit) 216*1500Serics doclear (); 217*1500Serics if (prnames) { 218*1500Serics if (bad_so) 219*1500Serics erase (0); 220*1500Serics pr("::::::::::::::"); 221*1500Serics if (promptlen > 14) 222*1500Serics erase (14); 223*1500Serics printf ("\n%s\n::::::::::::::\n", fnames[fnum]); 224*1500Serics if (left > Lpp - 4) 225*1500Serics left = Lpp - 4; 226*1500Serics } 227*1500Serics if (no_tty) 228*1500Serics copy_file (f); 229*1500Serics else { 230*1500Serics within++; 231*1500Serics screen(f, left); 232*1500Serics within = 0; 233*1500Serics } 234*1500Serics } 235*1500Serics setjmp (restore); 236*1500Serics fflush(stdout); 237*1500Serics fclose(f); 238*1500Serics screen_start.line = screen_start.chrctr = 0L; 239*1500Serics context.line = context.chrctr = 0L; 240*1500Serics } 241*1500Serics fnum++; 242*1500Serics firstf = 0; 243*1500Serics } 244*1500Serics reset_tty (); 245*1500Serics exit(0); 246*1500Serics } 247*1500Serics 248*1500Serics /* 249*1500Serics ** Check whether the file named by fs is an ASCII file which the user may 250*1500Serics ** access. If it is, return the opened file. Otherwise return NULL. 251*1500Serics */ 252*1500Serics 253*1500Serics FILE * 254*1500Serics checkf (fs, clearfirst) 255*1500Serics register char *fs; 256*1500Serics int *clearfirst; 257*1500Serics { 258*1500Serics struct stat stbuf; 259*1500Serics register FILE *f; 260*1500Serics char c; 261*1500Serics 262*1500Serics if (stat (fs, &stbuf) == -1) { 263*1500Serics fflush(stdout); 264*1500Serics perror(fs); 265*1500Serics return (NULL); 266*1500Serics } 267*1500Serics if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { 268*1500Serics printf("\n*** %s: directory ***\n\n", fs); 269*1500Serics return (NULL); 270*1500Serics } 271*1500Serics if ((f=Fopen(fs, "r")) == NULL) { 272*1500Serics fflush(stdout); 273*1500Serics perror(fs); 274*1500Serics return (NULL); 275*1500Serics } 276*1500Serics c = Getc(f); 277*1500Serics 278*1500Serics /* Try to see whether it is an ASCII file */ 279*1500Serics 280*1500Serics switch ((c | *f->_ptr << 8) & 0177777) { 281*1500Serics case 0405: 282*1500Serics case 0407: 283*1500Serics case 0410: 284*1500Serics case 0411: 285*1500Serics case 0413: 286*1500Serics case 0177545: 287*1500Serics printf("\n******** %s: Not a text file ********\n\n", fs); 288*1500Serics fclose (f); 289*1500Serics return (NULL); 290*1500Serics default: 291*1500Serics break; 292*1500Serics } 293*1500Serics if (c == '\f') 294*1500Serics *clearfirst = 1; 295*1500Serics else { 296*1500Serics *clearfirst = 0; 297*1500Serics Ungetc (c, f); 298*1500Serics } 299*1500Serics if ((file_size = stbuf.st_size) == 0) 300*1500Serics file_size = 0x7fffffffffffffffL; 301*1500Serics return (f); 302*1500Serics } 303*1500Serics 304*1500Serics /* 305*1500Serics ** A real function, for the tputs routine in termlib 306*1500Serics */ 307*1500Serics 308*1500Serics putch (ch) 309*1500Serics char ch; 310*1500Serics { 311*1500Serics putchar (ch); 312*1500Serics } 313*1500Serics 314*1500Serics /* 315*1500Serics ** Print out the contents of the file f, one screenful at a time. 316*1500Serics */ 317*1500Serics 318*1500Serics #define STOP -10 319*1500Serics 320*1500Serics screen (f, num_lines) 321*1500Serics register FILE *f; 322*1500Serics register int num_lines; 323*1500Serics { 324*1500Serics register int c; 325*1500Serics register int nchars; 326*1500Serics int length; 327*1500Serics 328*1500Serics for (;;) { 329*1500Serics while (num_lines > 0 && !Pause) { 330*1500Serics if ((nchars = getline (f, &length)) == EOF) 331*1500Serics return; 332*1500Serics if (bad_so || (Senter && *Senter == ' ') && promptlen > 0) 333*1500Serics erase (0); 334*1500Serics prbuf (Line, length); 335*1500Serics if (nchars < promptlen) 336*1500Serics erase (nchars); /* erase () sets promptlen to 0 */ 337*1500Serics else promptlen = 0; 338*1500Serics if (nchars < Mcol || !fold_opt) 339*1500Serics putchar('\n'); 340*1500Serics if (nchars == STOP) 341*1500Serics break; 342*1500Serics num_lines--; 343*1500Serics } 344*1500Serics fflush(stdout); 345*1500Serics if ((c = Getc(f)) == EOF) 346*1500Serics return; 347*1500Serics Ungetc (c, f); 348*1500Serics setjmp (restore); 349*1500Serics Pause = 0; startup = 0; 350*1500Serics if ((num_lines = command (NULL, f)) == 0) 351*1500Serics return; 352*1500Serics if (hard && promptlen > 0) 353*1500Serics erase (0); 354*1500Serics if (noscroll && num_lines == dlines) 355*1500Serics doclear (); 356*1500Serics screen_start.line = Currline; 357*1500Serics screen_start.chrctr = Ftell (f); 358*1500Serics } 359*1500Serics } 360*1500Serics 361*1500Serics /* 362*1500Serics ** Come here if a quit signal is received 363*1500Serics */ 364*1500Serics 365*1500Serics onquit() 366*1500Serics { 367*1500Serics signal(SIGQUIT, SIG_IGN); 368*1500Serics if (!inwait) { 369*1500Serics putchar ('\n'); 370*1500Serics if (!startup) { 371*1500Serics signal(SIGQUIT, onquit); 372*1500Serics longjmp (restore, 1); 373*1500Serics } 374*1500Serics else 375*1500Serics Pause++; 376*1500Serics } 377*1500Serics else if (!dum_opt && notell) { 378*1500Serics write (2, "[Use q or Q to quit]", 20); 379*1500Serics promptlen += 20; 380*1500Serics notell = 0; 381*1500Serics } 382*1500Serics signal(SIGQUIT, onquit); 383*1500Serics } 384*1500Serics 385*1500Serics /* 386*1500Serics ** Clean up terminal state and exit. Also come here if interrupt signal received 387*1500Serics */ 388*1500Serics 389*1500Serics end_it () 390*1500Serics { 391*1500Serics 392*1500Serics reset_tty (); 393*1500Serics if (promptlen > 0) { 394*1500Serics kill_line (); 395*1500Serics fflush (stdout); 396*1500Serics } 397*1500Serics else 398*1500Serics write (2, "\n", 1); 399*1500Serics _exit(0); 400*1500Serics } 401*1500Serics 402*1500Serics copy_file(f) 403*1500Serics register FILE *f; 404*1500Serics { 405*1500Serics register int c; 406*1500Serics 407*1500Serics while ((c = getc(f)) != EOF) 408*1500Serics putchar(c); 409*1500Serics } 410*1500Serics 411*1500Serics /* Simplified printf function */ 412*1500Serics 413*1500Serics printf (fmt, args) 414*1500Serics register char *fmt; 415*1500Serics int args; 416*1500Serics { 417*1500Serics register int *argp; 418*1500Serics register char ch; 419*1500Serics register int ccount; 420*1500Serics 421*1500Serics ccount = 0; 422*1500Serics argp = &args; 423*1500Serics while (*fmt) { 424*1500Serics while ((ch = *fmt++) != '%') { 425*1500Serics if (ch == '\0') 426*1500Serics return (ccount); 427*1500Serics ccount++; 428*1500Serics putchar (ch); 429*1500Serics } 430*1500Serics switch (*fmt++) { 431*1500Serics case 'd': 432*1500Serics ccount += printd (*argp); 433*1500Serics break; 434*1500Serics case 's': 435*1500Serics ccount += pr ((char *)*argp); 436*1500Serics break; 437*1500Serics case '%': 438*1500Serics ccount++; 439*1500Serics argp--; 440*1500Serics putchar ('%'); 441*1500Serics break; 442*1500Serics case '0': 443*1500Serics return (ccount); 444*1500Serics default: 445*1500Serics break; 446*1500Serics } 447*1500Serics ++argp; 448*1500Serics } 449*1500Serics return (ccount); 450*1500Serics 451*1500Serics } 452*1500Serics 453*1500Serics /* 454*1500Serics ** Print an integer as a string of decimal digits, 455*1500Serics ** returning the length of the print representation. 456*1500Serics */ 457*1500Serics 458*1500Serics printd (n) 459*1500Serics int n; 460*1500Serics { 461*1500Serics int a, nchars; 462*1500Serics 463*1500Serics if (a = n/10) 464*1500Serics nchars = 1 + printd(a); 465*1500Serics else 466*1500Serics nchars = 1; 467*1500Serics putchar (n % 10 + '0'); 468*1500Serics return (nchars); 469*1500Serics } 470*1500Serics 471*1500Serics /* Put the print representation of an integer into a string */ 472*1500Serics static char *sptr; 473*1500Serics 474*1500Serics scanstr (n, str) 475*1500Serics int n; 476*1500Serics char *str; 477*1500Serics { 478*1500Serics sptr = str; 479*1500Serics sprintf (n); 480*1500Serics *sptr = '\0'; 481*1500Serics } 482*1500Serics 483*1500Serics sprintf (n) 484*1500Serics { 485*1500Serics int a; 486*1500Serics 487*1500Serics if (a = n/10) 488*1500Serics sprintf (a); 489*1500Serics *sptr++ = n % 10 + '0'; 490*1500Serics } 491*1500Serics 492*1500Serics static char bell = ctrl(G); 493*1500Serics 494*1500Serics strlen (s) 495*1500Serics char *s; 496*1500Serics { 497*1500Serics register char *p; 498*1500Serics 499*1500Serics p = s; 500*1500Serics while (*p++) 501*1500Serics ; 502*1500Serics return (p - s - 1); 503*1500Serics } 504*1500Serics 505*1500Serics /* See whether the last component of the path name "path" is equal to the 506*1500Serics ** string "string" 507*1500Serics */ 508*1500Serics 509*1500Serics tailequ (path, string) 510*1500Serics char *path; 511*1500Serics register char *string; 512*1500Serics { 513*1500Serics register char *tail; 514*1500Serics 515*1500Serics tail = path + strlen(path); 516*1500Serics while (tail >= path) 517*1500Serics if (*(--tail) == '/') 518*1500Serics break; 519*1500Serics ++tail; 520*1500Serics while (*tail++ == *string++) 521*1500Serics if (*tail == '\0') 522*1500Serics return(1); 523*1500Serics return(0); 524*1500Serics } 525*1500Serics 526*1500Serics prompt (filename) 527*1500Serics char *filename; 528*1500Serics { 529*1500Serics if (promptlen > 0) 530*1500Serics kill_line (); 531*1500Serics if (!hard) { 532*1500Serics promptlen = 8; 533*1500Serics if (Senter && Sexit) 534*1500Serics tputs (Senter, 1, putch); 535*1500Serics pr("--More--"); 536*1500Serics if (filename != NULL) { 537*1500Serics promptlen += printf ("(Next file: %s)", filename); 538*1500Serics } 539*1500Serics else if (!no_intty) { 540*1500Serics promptlen += printf ("(%d%%)", (int)((file_pos * 100) / file_size)); 541*1500Serics } 542*1500Serics if (dum_opt) { 543*1500Serics promptlen += pr("[Hit space to continue, Rubout to abort]"); 544*1500Serics } 545*1500Serics if (Senter && Sexit) 546*1500Serics tputs (Sexit, 1, putch); 547*1500Serics fflush(stdout); 548*1500Serics } 549*1500Serics else 550*1500Serics write (2, &bell, 1); 551*1500Serics inwait++; 552*1500Serics } 553*1500Serics 554*1500Serics /* 555*1500Serics ** Get a logical line 556*1500Serics */ 557*1500Serics 558*1500Serics getline(f, length) 559*1500Serics register FILE *f; 560*1500Serics int *length; 561*1500Serics { 562*1500Serics register int c; 563*1500Serics register char *p; 564*1500Serics register int column; 565*1500Serics static int colflg; 566*1500Serics 567*1500Serics p = Line; 568*1500Serics column = 0; 569*1500Serics c = Getc (f); 570*1500Serics if (colflg && c == '\n') { 571*1500Serics Currline++; 572*1500Serics c = Getc (f); 573*1500Serics } 574*1500Serics while (p < &Line[LINSIZ - 1]) { 575*1500Serics if (c == EOF) { 576*1500Serics if (p > Line) { 577*1500Serics *p = '\0'; 578*1500Serics *length = p - Line; 579*1500Serics return (column); 580*1500Serics } 581*1500Serics *length = p - Line; 582*1500Serics return (EOF); 583*1500Serics } 584*1500Serics if (c == '\n') { 585*1500Serics Currline++; 586*1500Serics break; 587*1500Serics } 588*1500Serics *p++ = c; 589*1500Serics if (c == '\t') 590*1500Serics if (hardtabs && column < promptlen && !hard) { 591*1500Serics if (eraseln && !dumb) { 592*1500Serics column = 1 + (column | 7); 593*1500Serics tputs (eraseln, 1, putch); 594*1500Serics promptlen = 0; 595*1500Serics } 596*1500Serics else { 597*1500Serics for (--p; column & 7 && p < &Line[LINSIZ - 1]; column++) { 598*1500Serics *p++ = ' '; 599*1500Serics } 600*1500Serics if (column >= promptlen) promptlen = 0; 601*1500Serics } 602*1500Serics } 603*1500Serics else 604*1500Serics column = 1 + (column | 7); 605*1500Serics else if (c == '\b') 606*1500Serics column--; 607*1500Serics else if (c == '\r') 608*1500Serics column = 0; 609*1500Serics else if (c == '\f' && stop_opt) { 610*1500Serics p[-1] = '^'; 611*1500Serics *p++ = 'L'; 612*1500Serics column += 2; 613*1500Serics Pause++; 614*1500Serics } 615*1500Serics else if (c == EOF) { 616*1500Serics *length = p - Line; 617*1500Serics return (column); 618*1500Serics } 619*1500Serics else if (c >= ' ' && c != RUBOUT) 620*1500Serics column++; 621*1500Serics if (column >= Mcol && fold_opt) break; 622*1500Serics c = Getc (f); 623*1500Serics } 624*1500Serics if (column >= Mcol && Mcol > 0) { 625*1500Serics if (!Wrap) { 626*1500Serics *p++ = '\n'; 627*1500Serics } 628*1500Serics } 629*1500Serics colflg = column == Mcol && fold_opt; 630*1500Serics *length = p - Line; 631*1500Serics *p = 0; 632*1500Serics return (column); 633*1500Serics } 634*1500Serics 635*1500Serics /* 636*1500Serics ** Erase the rest of the prompt, assuming we are starting at column col. 637*1500Serics */ 638*1500Serics 639*1500Serics erase (col) 640*1500Serics register int col; 641*1500Serics { 642*1500Serics 643*1500Serics if (promptlen == 0) 644*1500Serics return; 645*1500Serics if (hard) { 646*1500Serics putchar ('\n'); 647*1500Serics } 648*1500Serics else { 649*1500Serics if (col == 0) 650*1500Serics putchar ('\r'); 651*1500Serics if (!dumb && eraseln) 652*1500Serics tputs (eraseln, 1, putch); 653*1500Serics else 654*1500Serics for (col = promptlen - col; col > 0; col--) 655*1500Serics putchar (' '); 656*1500Serics } 657*1500Serics promptlen = 0; 658*1500Serics } 659*1500Serics 660*1500Serics /* 661*1500Serics ** Erase the current line entirely 662*1500Serics */ 663*1500Serics 664*1500Serics kill_line () 665*1500Serics { 666*1500Serics erase (0); 667*1500Serics if (!eraseln || dumb) putchar ('\r'); 668*1500Serics } 669*1500Serics 670*1500Serics /* 671*1500Serics ** Print string and return number of characters 672*1500Serics */ 673*1500Serics 674*1500Serics pr(s1) 675*1500Serics char *s1; 676*1500Serics { 677*1500Serics register char *s; 678*1500Serics register char c; 679*1500Serics 680*1500Serics for (s = s1; c = *s++; ) 681*1500Serics putchar(c); 682*1500Serics return (s - s1 - 1); 683*1500Serics } 684*1500Serics 685*1500Serics 686*1500Serics /* Print a buffer of n characters */ 687*1500Serics 688*1500Serics prbuf (s, n) 689*1500Serics register char *s; 690*1500Serics register int n; 691*1500Serics { 692*1500Serics while (n-- > 0) 693*1500Serics putchar (*s++); 694*1500Serics } 695*1500Serics 696*1500Serics /* 697*1500Serics ** Clear the screen 698*1500Serics */ 699*1500Serics 700*1500Serics doclear() 701*1500Serics { 702*1500Serics if (Clear && !hard) { 703*1500Serics tputs(Clear, 1, putch); 704*1500Serics 705*1500Serics /* Put out carriage return so that system doesn't 706*1500Serics ** get confused by escape sequences when expanding tabs 707*1500Serics */ 708*1500Serics putchar ('\r'); 709*1500Serics promptlen = 0; 710*1500Serics } 711*1500Serics } 712*1500Serics 713*1500Serics static int lastcmd, lastarg, lastp; 714*1500Serics static int lastcolon; 715*1500Serics char shell_line[132]; 716*1500Serics 717*1500Serics /* 718*1500Serics ** Read a command and do it. A command consists of an optional integer 719*1500Serics ** argument followed by the command character. Return the number of lines 720*1500Serics ** to display in the next screenful. If there is nothing more to display 721*1500Serics ** in the current file, zero is returned. 722*1500Serics */ 723*1500Serics 724*1500Serics command (filename, f) 725*1500Serics char *filename; 726*1500Serics register FILE *f; 727*1500Serics { 728*1500Serics register int nlines; 729*1500Serics register int retval; 730*1500Serics register char c; 731*1500Serics char colonch; 732*1500Serics FILE *helpf; 733*1500Serics int done; 734*1500Serics char comchar, cmdbuf[80], *p; 735*1500Serics 736*1500Serics #define ret(val) retval=val;done++;break 737*1500Serics 738*1500Serics done = 0; 739*1500Serics if (!errors) 740*1500Serics prompt (filename); 741*1500Serics else 742*1500Serics errors = 0; 743*1500Serics if (MBIT == RAW && slow_tty) { 744*1500Serics otty.sg_flags |= MBIT; 745*1500Serics stty(2, &otty); 746*1500Serics } 747*1500Serics for (;;) { 748*1500Serics nlines = number (&comchar); 749*1500Serics lastp = colonch = 0; 750*1500Serics if (comchar == '.') { /* Repeat last command */ 751*1500Serics lastp++; 752*1500Serics comchar = lastcmd; 753*1500Serics nlines = lastarg; 754*1500Serics if (lastcmd == ':') 755*1500Serics colonch = lastcolon; 756*1500Serics } 757*1500Serics lastcmd = comchar; 758*1500Serics lastarg = nlines; 759*1500Serics if (comchar == otty.sg_erase) { 760*1500Serics kill_line (); 761*1500Serics prompt (filename); 762*1500Serics continue; 763*1500Serics } 764*1500Serics switch (comchar) { 765*1500Serics case ':': 766*1500Serics retval = colon (filename, colonch, nlines); 767*1500Serics if (retval >= 0) 768*1500Serics done++; 769*1500Serics break; 770*1500Serics case ' ': 771*1500Serics case 'z': 772*1500Serics if (nlines == 0) nlines = dlines; 773*1500Serics else if (comchar == 'z') dlines = nlines; 774*1500Serics ret (nlines); 775*1500Serics case 'd': 776*1500Serics case ctrl(D): 777*1500Serics if (nlines != 0) nscroll = nlines; 778*1500Serics ret (nscroll); 779*1500Serics case RUBOUT: 780*1500Serics case 'q': 781*1500Serics case 'Q': 782*1500Serics end_it (); 783*1500Serics case 's': 784*1500Serics case 'f': 785*1500Serics if (nlines == 0) nlines++; 786*1500Serics if (comchar == 'f') 787*1500Serics nlines *= dlines; 788*1500Serics putchar ('\r'); 789*1500Serics erase (0); 790*1500Serics printf("\n...skipping %d line", nlines); 791*1500Serics if (nlines > 1) 792*1500Serics pr("s\n\n"); 793*1500Serics else 794*1500Serics pr("\n\n"); 795*1500Serics while (nlines > 0) { 796*1500Serics while ((c = Getc (f)) != '\n') 797*1500Serics if (c == EOF) { 798*1500Serics retval = 0; 799*1500Serics done++; 800*1500Serics goto endsw; 801*1500Serics } 802*1500Serics Currline++; 803*1500Serics nlines--; 804*1500Serics } 805*1500Serics ret (dlines); 806*1500Serics case '\n': 807*1500Serics if (nlines != 0) 808*1500Serics dlines = nlines; 809*1500Serics else 810*1500Serics nlines = 1; 811*1500Serics ret (nlines); 812*1500Serics case '\f': 813*1500Serics if (!no_intty) { 814*1500Serics doclear (); 815*1500Serics Fseek (f, screen_start.chrctr); 816*1500Serics Currline = screen_start.line; 817*1500Serics ret (dlines); 818*1500Serics } 819*1500Serics else { 820*1500Serics write (2, &bell, 1); 821*1500Serics break; 822*1500Serics } 823*1500Serics case '\'': 824*1500Serics if (!no_intty) { 825*1500Serics kill_line (); 826*1500Serics pr ("\n***Back***\n\n"); 827*1500Serics Fseek (f, context.chrctr); 828*1500Serics Currline = context.line; 829*1500Serics ret (dlines); 830*1500Serics } 831*1500Serics else { 832*1500Serics write (2, &bell, 1); 833*1500Serics break; 834*1500Serics } 835*1500Serics case '=': 836*1500Serics kill_line (); 837*1500Serics promptlen = printd (Currline); 838*1500Serics fflush (stdout); 839*1500Serics break; 840*1500Serics case 'n': 841*1500Serics lastp++; 842*1500Serics case '/': 843*1500Serics if (nlines == 0) nlines++; 844*1500Serics kill_line (); 845*1500Serics pr ("/"); 846*1500Serics promptlen = 1; 847*1500Serics fflush (stdout); 848*1500Serics if (lastp) { 849*1500Serics write (2,"\r", 1); 850*1500Serics search (NULL, f, nlines); /* Use previous r.e. */ 851*1500Serics } 852*1500Serics else { 853*1500Serics ttyin (cmdbuf, 78, '/'); 854*1500Serics write (2, "\r", 1); 855*1500Serics search (cmdbuf, f, nlines); 856*1500Serics } 857*1500Serics ret (dlines); 858*1500Serics case '!': 859*1500Serics do_shell (filename); 860*1500Serics break; 861*1500Serics case 'h': 862*1500Serics if ((helpf = fopen (HELPFILE, "r")) == NULL) 863*1500Serics error ("Can't open help file"); 864*1500Serics if (noscroll) doclear (); 865*1500Serics copy_file (helpf); 866*1500Serics close (helpf); 867*1500Serics prompt (filename); 868*1500Serics break; 869*1500Serics case 'v': /* This case should go right before default */ 870*1500Serics if (!no_intty) { 871*1500Serics kill_line (); 872*1500Serics cmdbuf[0] = '+'; 873*1500Serics scanstr (Currline, &cmdbuf[1]); 874*1500Serics pr ("vi "); pr (cmdbuf); putchar (' '); pr (fnames[fnum]); 875*1500Serics execute (filename, VI, "vi", cmdbuf, fnames[fnum], 0); 876*1500Serics break; 877*1500Serics } 878*1500Serics default: 879*1500Serics write (2, &bell, 1); 880*1500Serics break; 881*1500Serics } 882*1500Serics if (done) break; 883*1500Serics } 884*1500Serics putchar ('\r'); 885*1500Serics endsw: 886*1500Serics inwait = 0; 887*1500Serics notell++; 888*1500Serics if (MBIT == RAW && slow_tty) { 889*1500Serics otty.sg_flags &= ~MBIT; 890*1500Serics stty(2, &otty); 891*1500Serics } 892*1500Serics return (retval); 893*1500Serics } 894*1500Serics 895*1500Serics char ch; 896*1500Serics 897*1500Serics /* 898*1500Serics * Execute a colon-prefixed command. 899*1500Serics * Returns <0 if not a command that should cause 900*1500Serics * more of the file to be printed. 901*1500Serics */ 902*1500Serics 903*1500Serics colon (filename, cmd, nlines) 904*1500Serics char *filename; 905*1500Serics int cmd; 906*1500Serics int nlines; 907*1500Serics { 908*1500Serics if (cmd == 0) 909*1500Serics ch = readch (); 910*1500Serics else 911*1500Serics ch = cmd; 912*1500Serics lastcolon = ch; 913*1500Serics switch (ch) { 914*1500Serics case 'f': 915*1500Serics kill_line (); 916*1500Serics if (!no_intty) 917*1500Serics promptlen = printf ("\"%s\" line %d", fnames[fnum], Currline); 918*1500Serics else 919*1500Serics promptlen = printf ("[Not a file] line %d", Currline); 920*1500Serics fflush (stdout); 921*1500Serics return (-1); 922*1500Serics case 'n': 923*1500Serics if (nlines == 0) { 924*1500Serics if (fnum >= nfiles - 1) 925*1500Serics end_it (); 926*1500Serics nlines++; 927*1500Serics } 928*1500Serics putchar ('\r'); 929*1500Serics erase (0); 930*1500Serics skipf (nlines); 931*1500Serics return (0); 932*1500Serics case 'p': 933*1500Serics if (no_intty) { 934*1500Serics write (2, &bell, 1); 935*1500Serics return (-1); 936*1500Serics } 937*1500Serics putchar ('\r'); 938*1500Serics erase (0); 939*1500Serics if (nlines == 0) 940*1500Serics nlines++; 941*1500Serics skipf (-nlines); 942*1500Serics return (0); 943*1500Serics case '!': 944*1500Serics do_shell (filename); 945*1500Serics return (-1); 946*1500Serics case 'q': 947*1500Serics case 'Q': 948*1500Serics end_it (); 949*1500Serics default: 950*1500Serics write (2, &bell, 1); 951*1500Serics return (-1); 952*1500Serics } 953*1500Serics } 954*1500Serics 955*1500Serics /* 956*1500Serics ** Read a decimal number from the terminal. Set cmd to the non-digit which 957*1500Serics ** terminates the number. 958*1500Serics */ 959*1500Serics 960*1500Serics number(cmd) 961*1500Serics char *cmd; 962*1500Serics { 963*1500Serics register int i; 964*1500Serics 965*1500Serics i = 0; ch = otty.sg_kill; 966*1500Serics for (;;) { 967*1500Serics ch = readch (); 968*1500Serics if (ch >= '0' && ch <= '9') 969*1500Serics i = i*10 + ch - '0'; 970*1500Serics else if (ch == otty.sg_kill) 971*1500Serics i = 0; 972*1500Serics else { 973*1500Serics *cmd = ch; 974*1500Serics break; 975*1500Serics } 976*1500Serics } 977*1500Serics return (i); 978*1500Serics } 979*1500Serics 980*1500Serics do_shell (filename) 981*1500Serics char *filename; 982*1500Serics { 983*1500Serics char cmdbuf[80]; 984*1500Serics 985*1500Serics kill_line (); 986*1500Serics pr ("!"); 987*1500Serics fflush (stdout); 988*1500Serics promptlen = 1; 989*1500Serics if (lastp) 990*1500Serics pr (shell_line); 991*1500Serics else { 992*1500Serics ttyin (cmdbuf, 78, '!'); 993*1500Serics if (expand (shell_line, cmdbuf)) { 994*1500Serics kill_line (); 995*1500Serics promptlen = printf ("!%s", shell_line); 996*1500Serics } 997*1500Serics } 998*1500Serics fflush (stdout); 999*1500Serics write (2, "\n", 1); 1000*1500Serics promptlen = 0; 1001*1500Serics shellp = 1; 1002*1500Serics execute (filename, shell, shell, "-c", shell_line, 0); 1003*1500Serics } 1004*1500Serics 1005*1500Serics /* 1006*1500Serics ** Search for nth ocurrence of regular expression contained in buf in the file 1007*1500Serics */ 1008*1500Serics 1009*1500Serics search (buf, file, n) 1010*1500Serics char buf[]; 1011*1500Serics FILE *file; 1012*1500Serics register int n; 1013*1500Serics { 1014*1500Serics long startline = Ftell (file); 1015*1500Serics register long line1 = startline; 1016*1500Serics register long line2 = startline; 1017*1500Serics register long line3 = startline; 1018*1500Serics register int lncount; 1019*1500Serics int saveln, rv, re_exec(); 1020*1500Serics char *s, *re_comp(); 1021*1500Serics 1022*1500Serics context.line = saveln = Currline; 1023*1500Serics context.chrctr = startline; 1024*1500Serics lncount = 0; 1025*1500Serics if ((s = re_comp (buf)) != 0) 1026*1500Serics error (s); 1027*1500Serics while (!feof (file)) { 1028*1500Serics line3 = line2; 1029*1500Serics line2 = line1; 1030*1500Serics line1 = Ftell (file); 1031*1500Serics rdline (file); 1032*1500Serics lncount++; 1033*1500Serics if ((rv = re_exec (Line)) == 1) 1034*1500Serics if (--n == 0) { 1035*1500Serics if (lncount > 3 || (lncount > 1 && no_intty)) 1036*1500Serics pr ("\n...skipping\n"); 1037*1500Serics if (!no_intty) { 1038*1500Serics Currline -= (lncount >= 3 ? 3 : lncount); 1039*1500Serics Fseek (file, line3); 1040*1500Serics } 1041*1500Serics else { 1042*1500Serics kill_line (); 1043*1500Serics pr (Line); 1044*1500Serics putchar ('\n'); 1045*1500Serics } 1046*1500Serics break; 1047*1500Serics } 1048*1500Serics else if (rv == -1) 1049*1500Serics error ("Regular expression botch"); 1050*1500Serics } 1051*1500Serics if (feof (file)) { 1052*1500Serics if (!no_intty) { 1053*1500Serics #ifdef V6 1054*1500Serics file->_flag &= ~_IOEOF; /* why doesn't fseek do this ??!!??! */ 1055*1500Serics #endif 1056*1500Serics Currline = saveln; 1057*1500Serics Fseek (file, startline); 1058*1500Serics } 1059*1500Serics else { 1060*1500Serics pr ("\nPattern not found\n"); 1061*1500Serics end_it (); 1062*1500Serics } 1063*1500Serics error ("Pattern not found"); 1064*1500Serics } 1065*1500Serics } 1066*1500Serics 1067*1500Serics execute (filename, cmd, args) 1068*1500Serics char *filename; 1069*1500Serics char *cmd, *args; 1070*1500Serics { 1071*1500Serics int id; 1072*1500Serics 1073*1500Serics fflush (stdout); 1074*1500Serics reset_tty (); 1075*1500Serics while ((id = fork ()) < 0) 1076*1500Serics sleep (5); 1077*1500Serics if (id == 0) { 1078*1500Serics execv (cmd, &args); 1079*1500Serics write (2, "exec failed\n", 12); 1080*1500Serics exit (1); 1081*1500Serics } 1082*1500Serics signal (SIGINT, SIG_IGN); 1083*1500Serics signal (SIGQUIT, SIG_IGN); 1084*1500Serics #ifdef SIGTSTP 1085*1500Serics if (catch_susp) 1086*1500Serics signal(SIGTSTP, SIG_DFL); 1087*1500Serics #endif 1088*1500Serics wait (0); 1089*1500Serics signal (SIGINT, end_it); 1090*1500Serics signal (SIGQUIT, onquit); 1091*1500Serics #ifdef SIGTSTP 1092*1500Serics if (catch_susp) 1093*1500Serics signal(SIGTSTP, onsusp); 1094*1500Serics #endif 1095*1500Serics set_tty (); 1096*1500Serics pr ("------------------------\n"); 1097*1500Serics prompt (filename); 1098*1500Serics } 1099*1500Serics /* 1100*1500Serics ** Skip n lines in the file f 1101*1500Serics */ 1102*1500Serics 1103*1500Serics skiplns (n, f) 1104*1500Serics register int n; 1105*1500Serics register FILE *f; 1106*1500Serics { 1107*1500Serics register char c; 1108*1500Serics 1109*1500Serics while (n > 0) { 1110*1500Serics while ((c = Getc (f)) != '\n') 1111*1500Serics if (c == EOF) 1112*1500Serics return; 1113*1500Serics n--; 1114*1500Serics Currline++; 1115*1500Serics } 1116*1500Serics } 1117*1500Serics 1118*1500Serics /* 1119*1500Serics ** Skip nskip files in the file list (from the command line). Nskip may be 1120*1500Serics ** negative. 1121*1500Serics */ 1122*1500Serics 1123*1500Serics skipf (nskip) 1124*1500Serics register int nskip; 1125*1500Serics { 1126*1500Serics if (nskip == 0) return; 1127*1500Serics if (nskip > 0) { 1128*1500Serics if (fnum + nskip > nfiles - 1) 1129*1500Serics nskip = nfiles - fnum - 1; 1130*1500Serics } 1131*1500Serics else if (within) 1132*1500Serics ++fnum; 1133*1500Serics fnum += nskip; 1134*1500Serics if (fnum < 0) 1135*1500Serics fnum = 0; 1136*1500Serics pr ("\n...Skipping "); 1137*1500Serics pr (nskip > 0 ? "to file " : "back to file "); 1138*1500Serics pr (fnames[fnum]); 1139*1500Serics pr ("\n\n"); 1140*1500Serics --fnum; 1141*1500Serics } 1142*1500Serics 1143*1500Serics /*----------------------------- Terminal I/O -------------------------------*/ 1144*1500Serics 1145*1500Serics initterm () 1146*1500Serics { 1147*1500Serics char buf[TBUFSIZ]; 1148*1500Serics char clearbuf[100]; 1149*1500Serics char *clearptr, *padstr; 1150*1500Serics char *getenv(); 1151*1500Serics int ldisc; 1152*1500Serics 1153*1500Serics setbuf(stdout, obuf); 1154*1500Serics if (!(no_tty = gtty(1, &otty))) { 1155*1500Serics if (tgetent(buf, getenv("TERM")) <= 0) { 1156*1500Serics dumb++; 1157*1500Serics } 1158*1500Serics else { 1159*1500Serics if (((Lpp = tgetnum("li")) < 0) || tgetflag("hc")) { 1160*1500Serics hard++; /* Hard copy terminal */ 1161*1500Serics Lpp = 24; 1162*1500Serics } 1163*1500Serics if (tailequ (fnames[0], "page") || !hard && tgetflag("ns")) 1164*1500Serics noscroll++; 1165*1500Serics if ((Mcol = tgetnum("co")) < 0) 1166*1500Serics Mcol = 80; 1167*1500Serics Wrap = tgetflag("am"); 1168*1500Serics bad_so = tgetflag ("xs"); 1169*1500Serics clearptr = clearbuf; 1170*1500Serics eraseln = tgetstr("ce",&clearptr); 1171*1500Serics Clear = tgetstr("cl", &clearptr); 1172*1500Serics Senter = tgetstr("so", &clearptr); 1173*1500Serics Sexit = tgetstr("se", &clearptr); 1174*1500Serics if (padstr = tgetstr("pc", &clearptr)) 1175*1500Serics PC = *padstr; 1176*1500Serics } 1177*1500Serics if ((shell = getenv("SHELL")) == NULL) 1178*1500Serics shell = "/bin/sh"; 1179*1500Serics } 1180*1500Serics no_intty = gtty(0, &otty); 1181*1500Serics gtty(2, &otty); 1182*1500Serics ospeed = otty.sg_ospeed; 1183*1500Serics slow_tty = ospeed < B1200; 1184*1500Serics hardtabs = !(otty.sg_flags & XTABS); 1185*1500Serics if (!no_tty) { 1186*1500Serics otty.sg_flags &= ~ECHO; 1187*1500Serics if (MBIT == CBREAK || !slow_tty) 1188*1500Serics otty.sg_flags |= MBIT; 1189*1500Serics } 1190*1500Serics } 1191*1500Serics 1192*1500Serics readch () 1193*1500Serics { 1194*1500Serics char ch; 1195*1500Serics extern int errno; 1196*1500Serics 1197*1500Serics if (read (2, &ch, 1) <= 0) 1198*1500Serics if (errno != EINTR) 1199*1500Serics exit(0); 1200*1500Serics else 1201*1500Serics ch = otty.sg_kill; 1202*1500Serics return (ch); 1203*1500Serics } 1204*1500Serics 1205*1500Serics static char BS = '\b'; 1206*1500Serics static char CARAT = '^'; 1207*1500Serics 1208*1500Serics ttyin (buf, nmax, pchar) 1209*1500Serics char buf[]; 1210*1500Serics register int nmax; 1211*1500Serics char pchar; 1212*1500Serics { 1213*1500Serics register char *sptr; 1214*1500Serics register char ch; 1215*1500Serics register int slash = 0; 1216*1500Serics int maxlen; 1217*1500Serics char cbuf; 1218*1500Serics 1219*1500Serics sptr = buf; 1220*1500Serics maxlen = 0; 1221*1500Serics while (sptr - buf < nmax) { 1222*1500Serics if (promptlen > maxlen) maxlen = promptlen; 1223*1500Serics ch = readch (); 1224*1500Serics if (ch == '\\') { 1225*1500Serics slash++; 1226*1500Serics } 1227*1500Serics else if ((ch == otty.sg_erase) && !slash) { 1228*1500Serics if (sptr > buf) { 1229*1500Serics --promptlen; 1230*1500Serics write (2, &BS, 1); 1231*1500Serics --sptr; 1232*1500Serics if ((*sptr < ' ' && *sptr != '\n') || *sptr == RUBOUT) { 1233*1500Serics --promptlen; 1234*1500Serics write (2, &BS, 1); 1235*1500Serics } 1236*1500Serics continue; 1237*1500Serics } 1238*1500Serics else { 1239*1500Serics if (!eraseln) promptlen = maxlen; 1240*1500Serics longjmp (restore, 1); 1241*1500Serics } 1242*1500Serics } 1243*1500Serics else if ((ch == otty.sg_kill) && !slash) { 1244*1500Serics if (hard) { 1245*1500Serics show (ch); 1246*1500Serics putchar ('\n'); 1247*1500Serics putchar (pchar); 1248*1500Serics } 1249*1500Serics else { 1250*1500Serics putchar ('\r'); 1251*1500Serics putchar (pchar); 1252*1500Serics if (eraseln) 1253*1500Serics erase (1); 1254*1500Serics promptlen = 1; 1255*1500Serics } 1256*1500Serics sptr = buf; 1257*1500Serics fflush (stdout); 1258*1500Serics continue; 1259*1500Serics } 1260*1500Serics if (slash && (ch == otty.sg_kill || ch == otty.sg_erase)) { 1261*1500Serics write (2, &BS, 1); 1262*1500Serics --sptr; 1263*1500Serics } 1264*1500Serics if (ch != '\\') 1265*1500Serics slash = 0; 1266*1500Serics *sptr++ = ch; 1267*1500Serics if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { 1268*1500Serics ch += ch == RUBOUT ? -0100 : 0100; 1269*1500Serics write (2, &CARAT, 1); 1270*1500Serics promptlen++; 1271*1500Serics } 1272*1500Serics cbuf = ch; 1273*1500Serics if (ch != '\n' && ch != ESC) { 1274*1500Serics write (2, &cbuf, 1); 1275*1500Serics promptlen++; 1276*1500Serics } 1277*1500Serics else 1278*1500Serics break; 1279*1500Serics } 1280*1500Serics *--sptr = '\0'; 1281*1500Serics if (!eraseln) promptlen = maxlen; 1282*1500Serics if (sptr - buf >= nmax - 1) 1283*1500Serics error ("Line too long"); 1284*1500Serics } 1285*1500Serics 1286*1500Serics expand (outbuf, inbuf) 1287*1500Serics char *outbuf; 1288*1500Serics char *inbuf; 1289*1500Serics { 1290*1500Serics register char *instr; 1291*1500Serics register char *outstr; 1292*1500Serics register char ch; 1293*1500Serics char temp[200]; 1294*1500Serics int changed = 0; 1295*1500Serics 1296*1500Serics instr = inbuf; 1297*1500Serics outstr = temp; 1298*1500Serics while ((ch = *instr++) != '\0') 1299*1500Serics switch (ch) { 1300*1500Serics case '%': 1301*1500Serics if (!no_intty) { 1302*1500Serics strcpy (outstr, fnames[fnum]); 1303*1500Serics outstr += strlen (fnames[fnum]); 1304*1500Serics changed++; 1305*1500Serics } 1306*1500Serics else 1307*1500Serics *outstr++ = ch; 1308*1500Serics break; 1309*1500Serics case '!': 1310*1500Serics if (!shellp) 1311*1500Serics error ("No previous command to substitute for"); 1312*1500Serics strcpy (outstr, shell_line); 1313*1500Serics outstr += strlen (shell_line); 1314*1500Serics changed++; 1315*1500Serics break; 1316*1500Serics case '\\': 1317*1500Serics if (*instr == '%' || *instr == '!') { 1318*1500Serics *outstr++ = *instr++; 1319*1500Serics break; 1320*1500Serics } 1321*1500Serics default: 1322*1500Serics *outstr++ = ch; 1323*1500Serics } 1324*1500Serics *outstr++ = '\0'; 1325*1500Serics strcpy (outbuf, temp); 1326*1500Serics return (changed); 1327*1500Serics } 1328*1500Serics 1329*1500Serics show (ch) 1330*1500Serics register char ch; 1331*1500Serics { 1332*1500Serics char cbuf; 1333*1500Serics 1334*1500Serics if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) { 1335*1500Serics ch += ch == RUBOUT ? -0100 : 0100; 1336*1500Serics write (2, &CARAT, 1); 1337*1500Serics promptlen++; 1338*1500Serics } 1339*1500Serics cbuf = ch; 1340*1500Serics write (2, &cbuf, 1); 1341*1500Serics promptlen++; 1342*1500Serics } 1343*1500Serics 1344*1500Serics error (mess) 1345*1500Serics char *mess; 1346*1500Serics { 1347*1500Serics kill_line (); 1348*1500Serics promptlen += strlen (mess); 1349*1500Serics if (Senter && Sexit) { 1350*1500Serics tputs (Senter, 1, putch); 1351*1500Serics pr(mess); 1352*1500Serics tputs (Sexit, 1, putch); 1353*1500Serics } 1354*1500Serics else 1355*1500Serics pr (mess); 1356*1500Serics fflush(stdout); 1357*1500Serics errors++; 1358*1500Serics longjmp (restore, 1); 1359*1500Serics } 1360*1500Serics 1361*1500Serics 1362*1500Serics set_tty () 1363*1500Serics { 1364*1500Serics otty.sg_flags |= MBIT; 1365*1500Serics otty.sg_flags &= ~ECHO; 1366*1500Serics stty(2, &otty); 1367*1500Serics } 1368*1500Serics 1369*1500Serics reset_tty () 1370*1500Serics { 1371*1500Serics otty.sg_flags |= ECHO; 1372*1500Serics otty.sg_flags &= ~MBIT; 1373*1500Serics stty(2, &otty); 1374*1500Serics } 1375*1500Serics 1376*1500Serics rdline (f) 1377*1500Serics register FILE *f; 1378*1500Serics { 1379*1500Serics register char c; 1380*1500Serics register char *p; 1381*1500Serics 1382*1500Serics p = Line; 1383*1500Serics while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1) 1384*1500Serics *p++ = c; 1385*1500Serics if (c == '\n') 1386*1500Serics Currline++; 1387*1500Serics *p = '\0'; 1388*1500Serics } 1389*1500Serics 1390*1500Serics /* Come here when we get a suspend signal from the terminal */ 1391*1500Serics 1392*1500Serics #ifdef SIGTSTP 1393*1500Serics onsusp () 1394*1500Serics { 1395*1500Serics reset_tty (); 1396*1500Serics fflush (stdout); 1397*1500Serics /* Send the TSTP signal to suspend our process group */ 1398*1500Serics kill (0, SIGTSTP); 1399*1500Serics /* Pause for station break */ 1400*1500Serics 1401*1500Serics /* We're back */ 1402*1500Serics signal (SIGTSTP, onsusp); 1403*1500Serics set_tty (); 1404*1500Serics if (inwait) 1405*1500Serics longjmp (restore); 1406*1500Serics } 1407*1500Serics #endif 1408