/* Skip nskip files in the file list (from the command line). Nskip may * be negative. */ static void skipf(register int nskip) { if (nskip == 0) return; if (nskip > 0) { if (fnum + nskip > nfiles - 1) nskip = nfiles - fnum - 1; } else if (within) ++fnum; fnum += nskip; if (fnum < 0) fnum = 0; puts(_("\n...Skipping ")); if (clreol) cleareol(); if (nskip > 0) putsout(_("...Skipping to file ")); else putsout(_("...Skipping back to file ")); puts(fnames[fnum]); if (clreol) cleareol(); putchar('\n'); --fnum; }
void prompt(char *filename) { if (clreol) cleareol(); else if (promptlen > 0) kill_line(); if (!hard) { promptlen = 8; if (Senter && Sexit) { tputs(Senter, 1, putch); promptlen += (2 * soglitch); } if (clreol) cleareol(); fputs("--More--", stdout); if (filename != NULL) promptlen += printf("(Next file: %s)", filename); else if (!no_intty) promptlen += printf("(%d%%)", (int)((file_pos * 100) / file_size)); if (dum_opt) { fputs(DUM_PROMPT, stdout); promptlen += sizeof(DUM_PROMPT) - 1; } if (Senter && Sexit) tputs(Sexit, 1, putch); if (clreol) clreos(); fflush(stdout); } else write(STDERR_FILENO, &bell, 1); inwait++; }
static void prompt(char *filename) { if (clreol) cleareol(); else if (promptlen > 0) kill_line(); if (!hard) { promptlen = 0; if (Senter && Sexit) { putstring(Senter); promptlen += (2 * soglitch); } if (clreol) cleareol(); promptlen += printf(_("--More--")); if (filename != NULL) { promptlen += printf(_("(Next file: %s)"), filename); } else if (!no_intty) { promptlen += printf("(%d%%)", (int)((file_pos * 100) / file_size)); } if (dum_opt) { promptlen += printf(_("[Press space to continue, 'q' to quit.]")); } if (Senter && Sexit) putstring(Sexit); if (clreol) clreos(); fflush(stdout); } else ringbell(); inwait++; }
/* * 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. */ FILE * checkf(char *fs, int *clearfirst) { struct stat stbuf; FILE *f; int ch; if (stat(fs, &stbuf) == -1) { (void)fflush(stdout); if (clreol) cleareol(); perror(fs); return (NULL); } if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { printf("\n*** %s: directory ***\n\n", fs); return (NULL); } if ((f = Fopen(fs, "r")) == NULL) { (void)fflush(stdout); perror(fs); return (NULL); } if (magic(f, fs)) return (NULL); ch = Getc(f); *clearfirst = (ch == '\f'); Ungetc(ch, f); if ((file_size = stbuf.st_size) == 0) file_size = LONG_MAX; return (f); }
/* 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. */ static FILE *checkf(register char *fs, int *clearfirst) { struct stat stbuf; register FILE *f; int c; if (stat(fs, &stbuf) == -1) { fflush(stdout); if (clreol) cleareol(); warn(_("stat of %s failed"), fs); return ((FILE *)NULL); } if ((stbuf.st_mode & S_IFMT) == S_IFDIR) { printf(_("\n*** %s: directory ***\n\n"), fs); return ((FILE *)NULL); } if ((f = Fopen(fs, "r")) == NULL) { fflush(stdout); warn(_("cannot open %s"), fs); return ((FILE *)NULL); } if (magic(f, fs)) { fclose(f); return ((FILE *)NULL); } fcntl(fileno(f), F_SETFD, FD_CLOEXEC); c = Getc(f); *clearfirst = (c == '\f'); Ungetc(c, f); if ((file_size = stbuf.st_size) == 0) file_size = LONG_MAX; return (f); }
/* * Skip nskip files in the file list (from the command line). * Nskip may be negative. */ void skipf(int nskip) { if (nskip == 0) return; if (nskip > 0) { if (fnum + nskip > nfiles - 1) nskip = nfiles - fnum - 1; } else if (within) ++fnum; fnum += nskip; if (fnum < 0) fnum = 0; fputs("\n...Skipping \n", stdout); /* XXX huh? */ if (clreol) cleareol(); printf("...Skipping %sto file %s\n", nskip > 0 ? "" : "back ", fnames[fnum]); if (clreol) cleareol(); putchar('\n'); --fnum; }
void error(char *mess) { if (clreol) cleareol(); else kill_line(); promptlen += strlen (mess); if (Senter && Sexit) { tputs(Senter, 1, putch); fputs(mess, stdout); tputs(Sexit, 1, putch); } else fputs(mess, stdout); fflush(stdout); errors++; }
static void more_error(char *mess) { if (clreol) cleareol(); else kill_line(); promptlen += strlen(mess); if (Senter && Sexit) { putstring(Senter); putsout(mess); putstring(Sexit); } else putsout(mess); fflush(stdout); errors++; siglongjmp(restore, 1); }
/* ** redisplay the line */ void refreshline() { int i; /* ** starting at the current location going to the end of the line ** print out the characters */ for(i=current_loc;i<end_of_buffer;i++){ putc(input_buffer[i],stdout); } /* ** clear out the rest of the characters on that line of the display */ cleareol(); /* ** reposition the cursor at the current location by doing ** backspaces */ for(i=current_loc;i<end_of_buffer;i++){ backspace(); } fflush(stdout); }
/* * Read a command and do it. A command consists of an optional integer * argument followed by the command character. Return the number of lines * to display in the next screenful. If there is nothing more to display * in the current file, zero is returned. */ int command(char *filename, FILE *f) { int nlines; int retval; int ch; char colonch; int done; char comchar, cmdbuf[80]; #define ret(val) retval=val;done++;break retval = done = 0; if (!errors) prompt(filename); else errors = 0; for (;;) { nlines = number(&comchar); lastp = colonch = 0; if (comchar == '.') { /* Repeat last command */ lastp++; comchar = lastcmd; nlines = lastarg; if (lastcmd == ':') colonch = lastcolon; } lastcmd = comchar; lastarg = nlines; if (comchar == otty.c_cc[VERASE]) { kill_line(); prompt(filename); continue; } switch (comchar) { case ':': retval = colon(filename, colonch, nlines); if (retval >= 0) done++; break; case 'b': case ctrl('B'): { int initline; if (no_intty) { write(STDERR_FILENO, &bell, 1); return (-1); } if (nlines == 0) nlines++; putchar('\r'); erasep(0); putchar('\n'); if (clreol) cleareol(); printf("...back %d page", nlines); if (nlines > 1) fputs("s\n", stdout); else putchar('\n'); if (clreol) cleareol(); putchar('\n'); initline = Currline - (off_t)dlines * (nlines + 1); if (!noscroll) --initline; if (initline < 0) initline = 0; Fseek(f, (off_t)0); Currline = 0; /* skiplns() will make Currline correct */ skiplns(initline, f); ret(dlines); } case ' ': case 'z': if (nlines == 0) nlines = dlines; else if (comchar == 'z') dlines = nlines; ret(nlines); case 'd': case ctrl('D'): if (nlines != 0) nscroll = nlines; ret(nscroll); case 'q': case 'Q': end_it(); case 's': case 'f': if (nlines == 0) nlines++; if (comchar == 'f') nlines *= dlines; putchar('\r'); erasep(0); putchar('\n'); if (clreol) cleareol(); printf("...skipping %d line", nlines); if (nlines > 1) fputs("s\n", stdout); else putchar('\n'); if (clreol) cleareol(); putchar('\n'); while (nlines > 0) { while ((ch = Getc(f)) != '\n') { if (ch == EOF) { retval = 0; done++; goto endsw; } } Currline++; nlines--; } ret(dlines); case '\n': if (nlines != 0) dlines = nlines; else nlines = 1; ret(nlines); case '\f': if (!no_intty) { doclear(); Fseek(f, screen_start.chrctr); Currline = screen_start.line; ret(dlines); } else { write(STDERR_FILENO, &bell, 1); break; } case '\'': if (!no_intty) { kill_line(); fputs("\n***Back***\n\n", stdout); Fseek(f, context.chrctr); Currline = context.line; ret(dlines); } else { write(STDERR_FILENO, &bell, 1); break; } case '=': kill_line(); promptlen = printf("%lld", (long long)Currline); fflush(stdout); break; case 'n': lastp++; case '/': if (nlines == 0) nlines++; kill_line(); putchar('/'); promptlen = 1; fflush(stdout); if (lastp) { /* Use previous r.e. */ write(STDERR_FILENO, "\r", 1); if (search(NULL, f, nlines) < 0) break; } else { if (ttyin(cmdbuf, sizeof(cmdbuf) - 2, '/') < 0) { kill_line(); prompt(filename); continue; } write(STDERR_FILENO, "\r", 1); if (search(cmdbuf, f, nlines) < 0) break; } ret(dlines-1); case '?': case 'h': if (noscroll) doclear(); fputs(more_help, stdout); prompt(filename); break; default: if (dum_opt) { kill_line(); if (Senter && Sexit) { tputs(Senter, 1, putch); fputs(DUM_ERROR, stdout); promptlen = sizeof(DUM_ERROR) - 1 + (2 * soglitch); tputs(Sexit, 1, putch); } else { fputs(DUM_ERROR, stdout); promptlen = sizeof(DUM_ERROR) - 1; } fflush(stdout); } else write(STDERR_FILENO, &bell, 1); break; } if (done) break; } putchar('\r'); endsw: inwait = 0; notell++; return (retval); }
/* * Print out the contents of the file f, one screenful at a time. */ void screen(FILE *f, int num_lines) { int ch; int nchars; int length; /* length of current line */ static int prev_len = 1; /* length of previous line */ for (;;) { while (num_lines > 0 && !Pause) { if ((nchars = get_line(f, &length)) == EOF) { if (clreol) clreos(); return; } if (ssp_opt && length == 0 && prev_len == 0) continue; prev_len = length; if (bad_so || (Senter && *Senter == ' ' && promptlen > 0)) erasep(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) { /* erasep() sets promptlen to 0 */ erasep(nchars); } else promptlen = 0; #if 0 /* XXX - is this needed? */ if (clreol) { /* must clear again in case we wrapped * */ cleareol(); } #endif if (nchars < Mcol || !fold_opt) { /* will turn off UL if necessary */ prbuf("\n", 1); } if (nchars == STOP) break; num_lines--; } if (pstate) { tputs(ULexit, 1, putch); pstate = 0; } fflush(stdout); if ((ch = Getc(f)) == EOF) { if (clreol) clreos(); return; } if (Pause && clreol) clreos(); Ungetc(ch, f); Pause = 0; startup = 0; if ((num_lines = command(NULL, f)) == 0) return; if (hard && promptlen > 0) erasep(0); if (noscroll && num_lines >= dlines) { if (clreol) home(); else doclear(); } /* * XXX - should store the *first* line on the screen, * not the last (but we don't know the file position). * Fixing this requires keeping an arry of dline off_ts * and updating each one when a new line is started. */ screen_start.line = Currline; screen_start.chrctr = Ftell(f); } }
int main(int argc, char **argv) { FILE * volatile f; char *s; volatile int left; volatile off_t initline; volatile int prnames = 0; volatile int initopt = 0; volatile int srchopt = 0; int clearit = 0; int ch; char initbuf[80]; if (pledge("stdio rpath tty", NULL) == -1) { perror("pledge"); exit(1); } setlocale(LC_ALL, ""); /* all signals just use a stub handler and interrupt syscalls */ sigemptyset(&sa.sa_mask); sa.sa_flags = 0; sa.sa_handler = onsignal; nfiles = argc; fnames = argv; initterm(); nscroll = Lpp/2 - 1; if (nscroll <= 0) nscroll = 1; if ((s = getenv("MORE")) != NULL && *s != '\0') argscan(s); while (--nfiles > 0) { if ((ch = (*++fnames)[0]) == '-') argscan(*fnames + 1); else if (ch == '+') { s = *fnames; if (*++s == '/') { srchopt++; (void)strlcpy(initbuf, ++s, sizeof(initbuf)); } else { initopt++; for (initline = 0; *s != '\0'; s++) { if (isdigit((unsigned char)*s)) initline = initline * 10 + *s - '0'; } --initline; } } 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 == NULL || *Home == '\0' || eraseln == NULL || *eraseln == '\0' || EodClr == NULL || *EodClr == '\0') clreol = 0; else noscroll = 1; } if (dlines == 0) dlines = Lpp - 1; left = dlines; if (nfiles > 1) prnames++; if (!no_intty && nfiles == 0) usage(); else f = stdin; if (!no_tty) { struct sigaction osa; (void)sigaction(SIGQUIT, &sa, NULL); (void)sigaction(SIGINT, &sa, NULL); (void)sigaction(SIGWINCH, &sa, NULL); if (sigaction(SIGTSTP, &osa, NULL) == 0 && osa.sa_handler == SIG_DFL) { (void)sigaction(SIGTSTP, &sa, NULL); (void)sigaction(SIGTTIN, &sa, NULL); (void)sigaction(SIGTTOU, &sa, NULL); catch_susp++; } set_tty(); } if (no_intty) { if (no_tty) copy_file(stdin); else { if ((ch = Getc(f)) == '\f') doclear(); else { Ungetc(ch, f); if (noscroll && ch != EOF) { if (clreol) home(); else doclear(); } } if (srchopt) { if (search(initbuf, stdin, 1) == 0 && noscroll) left--; } else if (initopt) skiplns(initline, stdin); screen(stdin, left); } no_intty = 0; dup2(STDERR_FILENO, STDIN_FILENO); /* stderr is a tty */ prnames++; firstf = 0; } while (fnum < nfiles) { if ((f = checkf(fnames[fnum], &clearit)) != NULL) { context.line = context.chrctr = 0; Currline = 0; restart: if (firstf) { firstf = 0; if (srchopt) { if (search(initbuf, f, 1) < 0) goto restart; if (noscroll) left--; } else if (initopt) skiplns(initline, f); } else if (fnum < nfiles && !no_tty) left = command(fnames[fnum], f); if (left != 0) { if ((noscroll || clearit) && (file_size != LONG_MAX)) { if (clreol) home(); else doclear(); } if (prnames) { if (bad_so) erasep(0); if (clreol) cleareol(); fputs("::::::::::::::", stdout); if (promptlen > 14) erasep(14); putchar('\n'); if (clreol) cleareol(); printf("%s\n", fnames[fnum]); if (clreol) cleareol(); fputs("::::::::::::::\n", stdout); if (left > Lpp - 4) left = Lpp - 4; } if (no_tty) copy_file(f); else { within++; screen(f, left); within = 0; } } fflush(stdout); fclose(f); screen_start.line = screen_start.chrctr = 0L; context.line = context.chrctr = 0L; } fnum++; firstf = 0; } reset_tty(); exit(0); }
/* * Search for nth occurrence of regular expression contained in buf in the file */ int search(char *buf, FILE *file, int n) { off_t startline = Ftell(file); off_t line1 = startline; off_t line2 = startline; off_t line3 = startline; off_t saveln; int lncount, rv; char ebuf[BUFSIZ]; static regex_t reg; static int initialized; context.line = saveln = Currline; context.chrctr = startline; lncount = 0; if (buf != NULL && *buf != '\0') { if ((rv = regcomp(®, buf, REG_NOSUB)) != 0) { initialized = 0; regerror(rv, ®, ebuf, sizeof(ebuf)); regfree(®); error(ebuf); return (-1); } initialized = 1; } else if (!initialized) { error("No previous regular expression"); return (-1); } while (!feof(file)) { line3 = line2; line2 = line1; line1 = Ftell(file); rdline(file); lncount++; if ((rv = regexec(®, Line, 0, NULL, 0)) == 0) { if (--n == 0) { if (lncount > 3 || (lncount > 1 && no_intty)) { putchar('\n'); if (clreol) cleareol(); fputs("...skipping\n", stdout); } if (!no_intty) { Currline -= (lncount >= 3 ? 3 : lncount); Fseek(file, line3); if (noscroll) { if (clreol) { home(); cleareol(); } else doclear(); } } else { kill_line(); if (noscroll) { if (clreol) { home(); cleareol(); } else doclear(); } fputs(Line, stdout); putchar('\n'); } break; } } else if (rv != REG_NOMATCH) { regerror(rv, ®, ebuf, sizeof(ebuf)); error(ebuf); return (-1); } } if (feof(file)) { if (!no_intty) { Currline = saveln; Fseek(file, startline); } else { fputs("\nPattern not found\n", stdout); end_it(); } error("Pattern not found"); return (-1); } return (0); }
int main(int argc, char **argv) { FILE *f; char *s; char *p; int ch; int left; int prnames = 0; int initopt = 0; int srchopt = 0; int clearit = 0; int initline = 0; char initbuf[INIT_BUF]; setlocale(LC_ALL, ""); bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); nfiles = argc; fnames = argv; setlocale(LC_ALL, ""); initterm (); /* Auto set no scroll on when binary is called page */ if (!(strcmp(program_invocation_short_name, "page"))) noscroll++; prepare_line_buffer(); nscroll = Lpp/2 - 1; if (nscroll <= 0) nscroll = 1; if ((s = getenv("MORE")) != NULL) argscan(s); while (--nfiles > 0) { if ((ch = (*++fnames)[0]) == '-') { argscan(*fnames+1); } else if (ch == '+') { s = *fnames; if (*++s == '/') { srchopt++; for (++s, p = initbuf; p < initbuf + (INIT_BUF - 1) && *s != '\0';) *p++ = *s++; *p = '\0'; } else { initopt++; for (initline = 0; *s != '\0'; s++) if (isdigit (*s)) initline = initline*10 + *s -'0'; --initline; } } 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 == NULL) || (*Home == '\0') || (eraseln == NULL) || (*eraseln == '\0') || (EodClr == NULL) || (*EodClr == '\0') ) clreol = 0; else noscroll = 1; } if (dlines == 0) dlines = Lpp - 1; /* was: Lpp - (noscroll ? 1 : 2) */ left = dlines; if (nfiles > 1) prnames++; if (!no_intty && nfiles == 0) usage(stderr); else f = stdin; if (!no_tty) { signal(SIGQUIT, onquit); signal(SIGINT, end_it); #ifdef SIGWINCH signal(SIGWINCH, chgwinsz); #endif /* SIGWINCH */ if (signal (SIGTSTP, SIG_IGN) == SIG_DFL) { signal(SIGTSTP, onsusp); catch_susp++; } stty (fileno(stderr), &otty); } if (no_intty) { if (no_tty) copy_file (stdin); else { if ((ch = Getc (f)) == '\f') doclear(); else { Ungetc (ch, f); if (noscroll && (ch != EOF)) { if (clreol) home (); else doclear (); } } if (srchopt) { search (initbuf, stdin, 1); if (noscroll) left--; } else if (initopt) skiplns (initline, stdin); screen (stdin, left); } no_intty = 0; prnames++; firstf = 0; } while (fnum < nfiles) { if ((f = checkf (fnames[fnum], &clearit)) != NULL) { context.line = context.chrctr = 0; Currline = 0; if (firstf) sigsetjmp (restore, 1); if (firstf) { firstf = 0; if (srchopt) { search (initbuf, f, 1); if (noscroll) left--; } else if (initopt) skiplns (initline, f); } else if (fnum < nfiles && !no_tty) { sigsetjmp (restore, 1); left = command (fnames[fnum], f); } if (left != 0) { if ((noscroll || clearit) && (file_size != LONG_MAX)) { if (clreol) home (); else doclear (); } if (prnames) { if (bad_so) erasep (0); if (clreol) cleareol (); putsout("::::::::::::::"); if (promptlen > 14) erasep (14); putchar('\n'); if(clreol) cleareol(); puts(fnames[fnum]); if(clreol) cleareol(); puts("::::::::::::::"); if (left > Lpp - 4) left = Lpp - 4; } if (no_tty) copy_file (f); else { within++; screen(f, left); within = 0; } } sigsetjmp (restore, 1); fflush(stdout); fclose(f); screen_start.line = screen_start.chrctr = 0L; context.line = context.chrctr = 0L; } fnum++; firstf = 0; } reset_tty (); exit(EXIT_SUCCESS); }