📄 more.c
字号:
ringbell(); return (-1); } putchar ('\r'); erasep (0); if (nlines == 0) nlines++; skipf (-nlines); return (0); case '!': do_shell (filename); return (-1); case 'q': case 'Q': end_it (0); default: ringbell(); return (-1); }}/*** Read a decimal number from the terminal. Set cmd to the non-digit which** terminates the number.*/int number(char *cmd){ register int i; i = 0; ch = otty.c_cc[VKILL]; for (;;) { ch = readch (); if (isdigit(ch)) i = i*10 + ch - '0'; else if ((cc_t) ch == otty.c_cc[VKILL]) i = 0; else { *cmd = ch; break; } } return (i);}void do_shell (char *filename){ char cmdbuf[200]; int rc; char *expanded; kill_line (); putchar('!'); fflush (stdout); promptlen = 1; if (lastp) putsout(shell_line); else { ttyin (cmdbuf, sizeof(cmdbuf)-2, '!'); expanded = 0; rc = expand (&expanded, cmdbuf); if (expanded) { if (strlen(expanded) < sizeof(shell_line)) strcpy(shell_line, expanded); else rc = -1; free(expanded); } if (rc < 0) { putserr(_(" Overflow\n")); prompt (filename); return; } else if (rc > 0) { kill_line (); promptlen = printf("!%s", shell_line); } } fflush (stdout); putcerr('\n'); promptlen = 0; shellp = 1; execute (filename, shell, shell, "-c", shell_line, 0);}/*** Search for nth ocurrence of regular expression contained in buf in the file*/void search(char buf[], FILE *file, register int n){ long startline = Ftell (file); register long line1 = startline; register long line2 = startline; register long line3 = startline; register int lncount; int saveln, rv; char *s; context.line = saveln = Currline; context.chrctr = startline; lncount = 0; if ((s = re_comp (buf)) != 0) error (s); while (!feof (file)) { line3 = line2; line2 = line1; line1 = Ftell (file); rdline (file); lncount++; if ((rv = re_exec (Line)) == 1) { if (--n == 0) { if (lncount > 3 || (lncount > 1 && no_intty)) { putchar('\n'); if (clreol) cleareol (); putsout(_("...skipping\n")); } 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 (); } puts(Line); } break; } } else if (rv == -1) error (_("Regular expression botch")); } if (feof (file)) { if (!no_intty) {#ifndef __linux__ /* No longer in libc 4.5.8. . . */ file->_flags &= ~STDIO_S_EOF_SEEN; /* why doesn't fseek do this ??!!??! */#endif Currline = saveln; Fseek (file, startline); } else { putsout(_("\nPattern not found\n")); end_it (0); } error (_("Pattern not found")); }}/*VARARGS2*/void execute (char *filename, char *cmd, ...){ int id; int n; va_list argp; char * arg; char ** args; int argcount; fflush (stdout); reset_tty (); for (n = 10; (id = fork ()) < 0 && n > 0; n--) sleep (5); if (id == 0) { if (!isatty(0)) { close(0); open("/dev/tty", 0); } va_start(argp, cmd); arg = va_arg(argp, char *); argcount = 0; while (arg) { argcount++; arg = va_arg(argp, char *); } va_end(argp); args = alloca(sizeof(char *) * (argcount + 1)); args[argcount] = NULL; va_start(argp, cmd); arg = va_arg(argp, char *); argcount = 0; while (arg) { args[argcount] = arg; argcount++; arg = va_arg(argp, char *); } va_end(argp); execvp (cmd, args); putserr(_("exec failed\n")); exit (1); } if (id > 0) { signal (SIGINT, SIG_IGN); signal (SIGQUIT, SIG_IGN); if (catch_susp) signal(SIGTSTP, SIG_DFL); while (wait(0) > 0); signal (SIGINT, end_it); signal (SIGQUIT, onquit); if (catch_susp) signal(SIGTSTP, onsusp); } else putserr(_("can't fork\n")); set_tty (); puts("------------------------"); prompt (filename);}/*** Skip n lines in the file f*/void skiplns (register int n, register FILE *f){ register int c; while (n > 0) { while ((c = Getc (f)) != '\n') if (c == EOF) return; n--; Currline++; }}/*** Skip nskip files in the file list (from the command line). Nskip may be** negative.*/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;}/*----------------------------- Terminal I/O -------------------------------*/void initterm(){ int ret; char *padstr; char *term; struct winsize win;#ifdef do_SIGTTOUretry:#endif no_tty = tcgetattr(fileno(stdout), &otty); if (!no_tty) { docrterase = (otty.c_cc[VERASE] != 255); docrtkill = (otty.c_cc[VKILL] != 255);#ifdef do_SIGTTOU { int tgrp; /* * Wait until we're in the foreground before we save the * the terminal modes. */ if ((tgrp = tcgetpgrp(fileno(stdout))) < 0) { perror("tcgetpgrp"); exit(1); } if (tgrp != getpgrp(0)) { kill(0, SIGTTOU); goto retry; } }#endif if ((term = getenv("TERM")) == 0) { dumb++; ul_opt = 0; } my_setupterm(term, 1, &ret); if (ret <= 0) { dumb++; ul_opt = 0; } else {#ifdef TIOCGWINSZ if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {#endif Lpp = my_tgetnum("li","lines"); Mcol = my_tgetnum("co","cols");#ifdef TIOCGWINSZ } else { if ((Lpp = win.ws_row) == 0) Lpp = my_tgetnum("li","lines"); if ((Mcol = win.ws_col) == 0) Mcol = my_tgetnum("co","cols"); }#endif if ((Lpp <= 0) || my_tgetflag("hc","hc")) { hard++; /* Hard copy terminal */ Lpp = 24; } if (my_tgetflag("xn","xenl")) eatnl++; /* Eat newline at last column + 1; dec, concept */ if (Mcol <= 0) Mcol = 80; if (tailequ (fnames[0], "page")) noscroll++; Wrap = my_tgetflag("am","am"); bad_so = my_tgetflag ("xs","xhp"); eraseln = my_tgetstr("ce","el"); Clear = my_tgetstr("cl","clear"); Senter = my_tgetstr("so","smso"); Sexit = my_tgetstr("se","rmso"); if ((soglitch = my_tgetnum("sg","xmc")) < 0) soglitch = 0; /* * Set up for underlining: some terminals don't need it; * others have start/stop sequences, still others have an * underline char sequence which is assumed to move the * cursor forward one character. If underline sequence * isn't available, settle for standout sequence. */ if (my_tgetflag("ul","ul") || my_tgetflag("os","os")) ul_opt = 0; if ((chUL = my_tgetstr("uc","uc")) == NULL ) chUL = ""; if (((ULenter = my_tgetstr("us","smul")) == NULL || (ULexit = my_tgetstr("ue","rmul")) == NULL) && !*chUL) { if ((ULenter = Senter) == NULL || (ULexit = Sexit) == NULL) { ULenter = ""; ULexit = ""; } else ulglitch = soglitch; } else { ulglitch = 0; } if ((padstr = my_tgetstr("pc","pad")) != NULL) PC = *padstr; Home = my_tgetstr("ho","home"); if (Home == 0 || *Home == '\0') { if ((cursorm = my_tgetstr("cm","cup")) != NULL) { const char *t = (const char *)my_tgoto(cursorm, 0, 0); xstrncpy(cursorhome, t, sizeof(cursorhome)); Home = cursorhome; } } EodClr = my_tgetstr("cd","ed"); if ((chBS = my_tgetstr("le","cub1")) == NULL) chBS = "\b"; } if ((shell = getenv("SHELL")) == NULL) shell = "/bin/sh"; } no_intty = tcgetattr(fileno(stdin), &otty); tcgetattr(fileno(stderr), &otty); savetty0 = otty; slow_tty = (otty.c_cflag & CBAUD) < B1200; hardtabs = (otty.c_oflag & TABDLY) != XTABS; if (!no_tty) { otty.c_lflag &= ~(ICANON|ECHO); otty.c_cc[VMIN] = 1; otty.c_cc[VTIME] = 0; }}int readch () { unsigned char c; errno = 0; if (read (fileno(stderr), &c, 1) <= 0) { if (errno != EINTR) end_it(0); else c = otty.c_cc[VKILL]; } return (c);}static char *BS = "\b";static char *BSB = "\b \b";static char *CARAT = "^";#define ERASEONECOLUMN \ if (docrterase) \ putserr(BSB); \ else \ putserr(BS);void ttyin (unsigned char buf[], register int nmax, char pchar) { unsigned char *sp; int c; int slash = 0; int maxlen; sp = buf; maxlen = 0; while (sp - buf < nmax) { if (promptlen > maxlen) maxlen = promptlen; c = readch (); if (c == '\\') { slash++; } else if (((cc_t) c == otty.c_cc[VERASE]) && !slash) { if (sp > buf) {#ifdef ENABLE_WIDECHAR if (MB_CUR_MAX > 1) { wchar_t wc; size_t pos = 0, mblength; mbstate_t state, state_bak; memset (&state, '\0', sizeof (mbstate_t)); while (1) { state_bak = state; mblength = mbrtowc (&wc, buf + pos, sp - buf, &state); state = (mblength == (size_t)-2 || mblength == (size_t)-1) ? state_bak : state; mblength = (mblength == (size_t)-2 || mblength == (size_t)-1 || mblength == 0) ? 1 : mblength; if (buf + pos + mblength >= sp) break; pos += mblength; } if (mblength == 1) { ERASEONECOLUMN } else { int wc_width; wc_width = wcwidth (wc); wc_width = (wc_width < 1) ? 1 : wc_width; while (wc_width--) { ERASEONECOLUMN } } while (mblength--) { --promptlen; --sp; } } else#endif { --promptlen; ERASEONECOLUMN --sp; } if ((*sp < ' ' && *sp != '\n') || *sp == RUBOUT) { --promptlen; ERASEONECOLUMN } continue; } else { if (!eraseln) promptlen = maxlen; siglongjmp (restore, 1); } } else if (((cc_t) c == otty.c_cc[VKILL]) && !slash) { if (hard) { show (c); putchar ('\n'); putchar (pchar); } else { putchar ('\r'); putchar (pchar); if (eraseln) erasep (1); else if (docrtkill) while (promptlen-- > 1) putserr(BSB); promptlen = 1; } sp = buf; fflush (stdout); continue; } if (slash && ((cc_t) c == otty.c_cc[VKILL] || (cc_t) c == otty.c_cc[VERASE])) { ERASEONECOLUMN --sp; } if (c != '\\') slash = 0; *sp++ = c; if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) { c += (c == RUBOUT) ? -0100 : 0100; putserr(CARAT); promptlen++; } if (c != '\n' && c != ESC) { putcerr(c); promptlen++; } else break; } *--sp = '\0'; if (!eraseln) promptlen = maxlen; if (sp - buf >= nmax - 1) error (_("Line too long"));}/* return: 0 - unchanged, 1 - changed, -1 - overflow (unchanged) */int expand (char **outbuf, char *inbuf) { char *inpstr; char *outstr; char c; char *temp; int changed = 0; int tempsz, xtra, offset; xtra = strlen (fnames[fnum]) + strlen (shell_line) + 1; tempsz = 200 + xtra; temp = malloc(tempsz); if (!temp) { error (_("Out of memory")); return -1; } inpstr = inbuf; outstr = temp; while ((c = *inpstr++) != '\0'){ offset = outstr-temp; if (tempsz-offset-1 < xtra) { tempsz += 200 + xtra; temp = realloc(temp, tempsz); if (!temp) { error (_("Out of memory")); return -1; } outstr = temp + offset; } switch (c) { case '%': if (!no_intty) { strcpy (outstr, fnames[fnum]); outstr += strlen (fnames[fnum]); changed++; } else *outstr++ = c; break; case '!': if (!shellp) error (_("No previous command to substitute for")); strcpy (outstr, shell_line); outstr += strlen (shell_line); changed++; break; case '\\': if (*inpstr == '%' || *inpstr == '!') { *outstr++ = *inpstr++; break; } default: *outstr++ = c; } } *outstr++ = '\0'; *outbuf = temp; return (changed);}void show (char c) { if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) { c += (c == RUBOUT) ? -0100 : 0100; putserr(CARAT); promptlen++; } putcerr(c); promptlen++;}void error (char *mess){ if (clreol) cleareol (); else kill_line (); promptlen += strlen (mess); if (Senter && Sexit) { my_putstring (Senter); putsout(mess); my_putstring (Sexit); } else putsout(mess); fflush(stdout); errors++; siglongjmp (restore, 1);}void set_tty () { otty.c_lflag &= ~(ICANON|ECHO); otty.c_cc[VMIN] = 1; /* read at least 1 char */ otty.c_cc[VTIME] = 0; /* no timeout */ stty(fileno(stderr), &otty);}static intourputch(int c) { return putc(c, stdout);}voidreset_tty () { if (no_tty) return; if (pstate) { tputs(ULexit, 1, ourputch); /* putchar - if that isnt a macro */ fflush(stdout); pstate = 0; } otty.c_lflag |= ICANON|ECHO; otty.c_cc[VMIN] = savetty0.c_cc[VMIN]; otty.c_cc[VTIME] = savetty0.c_cc[VTIME]; stty(fileno(stderr), &savetty0);}void rdline (register FILE *f){ register int c; register char *p; p = Line; while ((c = Getc (f)) != '\n' && c != EOF && p - Line < LINSIZ - 1) *p++ = c; if (c == '\n') Currline++; *p = '\0';}/* Come here when we get a suspend signal from the terminal */void onsusp (int dummy) { sigset_t signals, oldmask; /* ignore SIGTTOU so we don't get stopped if csh grabs the tty */ signal(SIGTTOU, SIG_IGN); reset_tty (); fflush (stdout); signal(SIGTTOU, SIG_DFL); /* Send the TSTP signal to suspend our process group */ signal(SIGTSTP, SIG_DFL); /* unblock SIGTSTP or we won't be able to suspend ourself */ sigemptyset(&signals); sigaddset(&signals, SIGTSTP); sigprocmask(SIG_UNBLOCK, &signals, &oldmask); kill (0, SIGTSTP); /* Pause for station break */ sigprocmask(SIG_SETMASK, &oldmask, NULL); /* We're back */ signal (SIGTSTP, onsusp); set_tty (); if (inwait) siglongjmp (restore, 1);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -