* [PATCH 1/2] more: remove function prototypes
@ 2018-04-19 21:46 Sami Kerola
2018-04-19 21:46 ` [PATCH 2/2] more: reorder global declarations Sami Kerola
2018-05-23 8:42 ` [PATCH 1/2] more: remove function prototypes Karel Zak
0 siblings, 2 replies; 3+ messages in thread
From: Sami Kerola @ 2018-04-19 21:46 UTC (permalink / raw)
To: util-linux; +Cc: Sami Kerola
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
text-utils/more.c | 2482 ++++++++++++++++++++++-----------------------
1 file changed, 1226 insertions(+), 1256 deletions(-)
diff --git a/text-utils/more.c b/text-utils/more.c
index 0b2db22f3..7df04de7b 100644
--- a/text-utils/more.c
+++ b/text-utils/more.c
@@ -89,38 +89,6 @@
#define stty(fd,argp) tcsetattr(fd,TCSANOW,argp)
-/* some function declarations */
-void initterm(void);
-void kill_line(void);
-void doclear(void);
-void cleareol(void);
-void clreos(void);
-void home(void);
-void more_error(char *mess);
-void do_shell(char *filename);
-int colon(char *filename, int cmd, int nlines);
-int expand(char **outbuf, char *inbuf);
-void argscan(char *s);
-void rdline(register FILE *f);
-void copy_file(register FILE *f);
-void search(char buf[], FILE *file, register int n);
-void skipf(register int nskip);
-void skiplns(register int n, register FILE *f);
-void screen(register FILE *f, register int num_lines);
-int command(char *filename, register FILE *f);
-void erasep(register int col);
-void show(register char ch);
-void set_tty(void);
-void reset_tty(void);
-void ttyin(char buf[], register int nmax, char pchar);
-int number(char *cmd);
-int readch(void);
-int get_line(register FILE *f, int *length);
-void prbuf(register char *s, register int n);
-void execute(char *filename, char *cmd, ...);
-FILE *checkf(char *, int *);
-void prepare_line_buffer(void);
-
#define TBUFSIZ 1024
#define LINSIZ 256 /* minimal Line buffer size */
#define ctrl(letter) (letter & 077)
@@ -253,204 +221,8 @@ static void __attribute__((__noreturn__)) usage(void)
exit(EXIT_SUCCESS);
}
-int main(int argc, char **argv)
-{
- FILE *f;
- char *s;
- int ch;
- int left;
- int prnames = 0;
- int initopt = 0;
- int srchopt = 0;
- int clearit = 0;
- int initline = 0;
- char *initbuf = NULL;
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
- atexit(close_stdout);
-
- if (argc > 1) {
- /* first arg may be one of our standard longopts */
- if (!strcmp(argv[1], "--help"))
- usage();
- if (!strcmp(argv[1], "--version")) {
- printf(UTIL_LINUX_VERSION);
- exit(EXIT_SUCCESS);
- }
- }
-
- 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++;
- initbuf = xstrdup(s + 1);
- } 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) {
- warnx(_("bad usage"));
- errtryhelp(EXIT_FAILURE);
- } else
- f = stdin;
- if (!no_tty) {
- signal(SIGQUIT, onquit);
- signal(SIGINT, end_it);
-#ifdef SIGWINCH
- signal(SIGWINCH, chgwinsz);
-#endif
- 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) {
- free(previousre);
- previousre = xstrdup(initbuf);
- 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) {
- free(previousre);
- previousre = xstrdup(initbuf);
- 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;
- }
- free(previousre);
- free(initbuf);
- free(Line);
- reset_tty();
- exit(EXIT_SUCCESS);
-}
-void argscan(char *s)
+static void argscan(char *s)
{
int seen_num = 0;
@@ -510,9 +282,15 @@ void argscan(char *s)
}
}
+/* force clear to end of line */
+static void cleareol(void)
+{
+ putstring(eraseln);
+}
+
/* 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(register char *fs, int *clearfirst)
+static FILE *checkf(register char *fs, int *clearfirst)
{
struct stat stbuf;
register FILE *f;
@@ -577,200 +355,13 @@ static int magic(FILE *f, char *fs)
return 0;
}
-/* Print out the contents of the file f, one screenful at a time. */
-#define STOP -10
-void screen(register FILE *f, register int num_lines)
+static void prepare_line_buffer(void)
{
- register int c;
- register int nchars;
- int length; /* length of current line */
- static int prev_len = 1; /* length of previous line */
+ char *nline;
+ size_t nsz = Mcol * 4;
- 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(nchars); /* erasep () sets promptlen to 0 */
- else
- promptlen = 0;
- /* is this needed?
- * if (clreol)
- * cleareol(); * must clear again in case we wrapped *
- */
- if (nchars < Mcol || !fold_opt)
- prbuf("\n", 1); /* will turn off UL if necessary */
- if (nchars == STOP)
- break;
- num_lines--;
- }
- if (pstate) {
- putstring(ULexit);
- pstate = 0;
- }
- fflush(stdout);
- if ((c = Getc(f)) == EOF) {
- if (clreol)
- clreos();
- return;
- }
-
- if (Pause && clreol)
- clreos();
- Ungetc(c, f);
- sigsetjmp(restore, 1);
- 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();
- }
- screen_start.line = Currline;
- screen_start.chrctr = Ftell(f);
- }
-}
-
-/* Come here if a quit signal is received */
-static void onquit(int dummy __attribute__((__unused__)))
-{
- signal(SIGQUIT, SIG_IGN);
- if (!inwait) {
- putchar('\n');
- if (!startup) {
- signal(SIGQUIT, onquit);
- siglongjmp(restore, 1);
- } else
- Pause++;
- } else if (!dum_opt && notell) {
- promptlen += fprintf(stderr, _("[Use q or Q to quit]"));
- notell = 0;
- }
- signal(SIGQUIT, onquit);
-}
-
-/* Come here if a signal for a window size change is received */
-#ifdef SIGWINCH
-static void chgwinsz(int dummy __attribute__((__unused__)))
-{
- struct winsize win;
-
- signal(SIGWINCH, SIG_IGN);
- if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
- if (win.ws_row != 0) {
- Lpp = win.ws_row;
- nscroll = Lpp / 2 - 1;
- if (nscroll <= 0)
- nscroll = 1;
- dlines = Lpp - 1; /* was: Lpp - (noscroll ? 1 : 2) */
- }
- if (win.ws_col != 0)
- Mcol = win.ws_col;
- }
- signal(SIGWINCH, chgwinsz);
-}
-#endif /* SIGWINCH */
-
-/* Clean up terminal state and exit. Also come here if interrupt signal received */
-static void __attribute__((__noreturn__)) end_it(int dummy __attribute__((__unused__)))
-{
- /* May be executed as a signal handler as well as by main process.
- *
- * The _exit() may wait for pending I/O for really long time, be sure
- * that signal handler is not executed in this time to avoid double
- * de-initialization (free() calls, etc.).
- */
- signal(SIGINT, SIG_IGN);
-
- reset_tty();
- if (clreol) {
- putchar('\r');
- clreos();
- fflush(stdout);
- } else if (!clreol && (promptlen > 0)) {
- kill_line();
- fflush(stdout);
- } else
- putcerr('\n');
- free(previousre);
- free(Line);
- _exit(EXIT_SUCCESS);
-}
-
-void copy_file(register FILE *f)
-{
- char buf[BUFSIZ];
- size_t sz;
-
- while ((sz = fread(&buf, sizeof(char), sizeof(buf), f)) > 0)
- fwrite(&buf, sizeof(char), sz, stdout);
-}
-
-#define ringbell() putcerr('\007')
-
-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++;
-}
-
-void prepare_line_buffer(void)
-{
- char *nline;
- size_t nsz = Mcol * 4;
-
- if (LineLen >= nsz)
- return;
+ if (LineLen >= nsz)
+ return;
if (nsz < LINSIZ)
nsz = LINSIZ;
@@ -782,7 +373,7 @@ void prepare_line_buffer(void)
}
/* Get a logical line */
-int get_line(register FILE *f, int *length)
+static int get_line(register FILE *f, int *length)
{
int c;
char *p;
@@ -992,8 +583,13 @@ int get_line(register FILE *f, int *length)
return (column);
}
+static void clreos(void)
+{
+ putstring(EodClr);
+}
+
/* Erase the rest of the prompt, assuming we are starting at column col. */
-void erasep(register int col)
+static void erasep(register int col)
{
if (promptlen == 0)
@@ -1011,26 +607,6 @@ void erasep(register int col)
promptlen = 0;
}
-/* Erase the current line entirely */
-void kill_line(void)
-{
- erasep(0);
- if (!eraseln || dumb)
- putchar('\r');
-}
-
-/* force clear to end of line */
-void cleareol(void)
-{
- putstring(eraseln);
-}
-
-void clreos(void)
-{
- putstring(EodClr);
-}
-
-
#ifdef HAVE_WIDECHAR
static UL_ASAN_BLACKLIST size_t xmbrtowc(wchar_t *wc, const char *s, size_t n,
mbstate_t *mbstate)
@@ -1043,7 +619,7 @@ static UL_ASAN_BLACKLIST size_t xmbrtowc(wchar_t *wc, const char *s, size_t n,
#endif
/* Print a buffer of n characters */
-void prbuf(register char *s, register int n)
+static void prbuf(register char *s, register int n)
{
register char c; /* next output character */
register int state; /* next output char's UL state */
@@ -1097,398 +673,437 @@ void prbuf(register char *s, register int n)
}
}
-/* Clear the screen */
-void doclear(void)
+/* Erase the current line entirely */
+static void kill_line(void)
{
- if (Clear && !hard) {
- putstring(Clear);
- /* Put out carriage return so that system doesn't get
- * confused by escape sequences when expanding tabs */
+ erasep(0);
+ if (!eraseln || dumb)
putchar('\r');
+}
+
+#define ringbell() putcerr('\007')
+
+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++;
}
-/* Go to home position */
-void home(void)
+static int readch(void)
{
- putstring(Home);
+ 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 int lastcmd, lastarg, lastp;
-static int lastcolon;
-static char shell_line[SHELL_LINE];
+static char ch;
-/* 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, register FILE *f)
+/* Read a decimal number from the terminal. Set cmd to the non-digit
+ * which terminates the number. */
+static int number(char *cmd)
{
- register int nlines;
- register int retval = 0;
- register int c;
- char colonch;
- int done;
- char comchar, cmdbuf[INIT_BUF];
-
-#define ret(val) retval=val;done++;break
+ register int i;
- done = 0;
- if (!errors)
- prompt(filename);
- else
- errors = 0;
+ i = 0;
+ ch = otty.c_cc[VKILL];
for (;;) {
- nlines = number(&comchar);
- lastp = colonch = 0;
- if (comchar == '.') { /* Repeat last command */
- lastp++;
- comchar = lastcmd;
- nlines = lastarg;
- if (lastcmd == ':')
- colonch = lastcolon;
+ 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;
}
- lastcmd = comchar;
- lastarg = nlines;
- if ((cc_t) 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'):
- {
- register int initline;
+ }
+ return (i);
+}
- if (no_intty) {
- ringbell();
- return (-1);
- }
+/* 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;
+}
- if (nlines == 0)
- nlines++;
+static char *BS = "\b";
+static char *BSB = "\b \b";
+static char *CARAT = "^";
+#define ERASEONECOLUMN(x) \
+ do { \
+ if (x) \
+ putserr(BSB); \
+ else \
+ putserr(BS); \
+ } while(0)
- putchar('\r');
- erasep(0);
- putchar('\n');
- if (clreol)
- cleareol();
- printf(P_("...back %d page",
- "...back %d pages", nlines),
- nlines);
- if (clreol)
- cleareol();
- putchar('\n');
+static void show(char c)
+{
+ if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
+ c += (c == RUBOUT) ? -0100 : 0100;
+ putserr(CARAT);
+ promptlen++;
+ }
+ putcerr(c);
+ promptlen++;
+}
- initline = Currline - dlines * (nlines + 1);
- if (!noscroll)
- --initline;
- if (initline < 0)
- initline = 0;
- Fseek(f, 0L);
- Currline = 0; /* skiplns() will make Currline correct */
- skiplns(initline, f);
- if (!noscroll) {
- ret(dlines + 1);
- } else {
- 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(0);
- case 's':
- case 'f':
- case ctrl('F'):
- if (nlines == 0)
- nlines++;
- if (comchar == 'f')
- nlines *= dlines;
- putchar('\r');
- erasep(0);
- putchar('\n');
- if (clreol)
- cleareol();
- printf(P_("...skipping %d line",
- "...skipping %d lines", nlines),
- nlines);
+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);
+}
- if (clreol)
- cleareol();
- putchar('\n');
+static void ttyin(char buf[], register int nmax, char pchar)
+{
+ char *sp;
+ int c;
+ int slash = 0;
+ int maxlen;
- while (nlines > 0) {
- while ((c = Getc(f)) != '\n')
- if (c == EOF) {
- retval = 0;
- done++;
- goto endsw;
+ 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 HAVE_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;
}
- 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);
+
+ if (mblength == 1) {
+ ERASEONECOLUMN(docrterase);
+ } else {
+ int wc_width;
+ wc_width = wcwidth(wc);
+ wc_width =
+ (wc_width <
+ 1) ? 1 : wc_width;
+ while (wc_width--) {
+ ERASEONECOLUMN(docrterase);
+ }
+ }
+
+ while (mblength--) {
+ --promptlen;
+ --sp;
+ }
+ } else
+#endif /* HAVE_WIDECHAR */
+ {
+ --promptlen;
+ ERASEONECOLUMN(docrterase);
+ --sp;
+ }
+
+ if ((*sp < ' ' && *sp != '\n') || *sp == RUBOUT) {
+ --promptlen;
+ ERASEONECOLUMN(docrterase);
+ }
+ continue;
} else {
- ringbell();
- break;
+ if (!eraseln)
+ promptlen = maxlen;
+ siglongjmp(restore, 1);
}
- case '\'':
- if (!no_intty) {
- kill_line();
- putsout(_("\n***Back***\n\n"));
- Fseek(f, context.chrctr);
- Currline = context.line;
- ret(dlines);
+ } else if (((cc_t) c == otty.c_cc[VKILL]) && !slash) {
+ if (hard) {
+ show(c);
+ putchar('\n');
+ putchar(pchar);
} else {
- ringbell();
- break;
- }
- case '=':
- kill_line();
- promptlen = printf("%d", Currline);
- fflush(stdout);
- break;
- case 'n':
- if (!previousre) {
- more_error(_("No previous regular expression"));
- break;
+ putchar('\r');
+ putchar(pchar);
+ if (eraseln)
+ erasep(1);
+ else if (docrtkill)
+ while (promptlen-- > 1)
+ putserr(BSB);
+ promptlen = 1;
}
- lastp++;
- /* fallthrough */
- case '/':
- if (nlines == 0)
- nlines++;
- kill_line();
- putchar('/');
- promptlen = 1;
+ sp = buf;
fflush(stdout);
- if (lastp) {
- putcerr('\r');
- search(previousre, f, nlines);
- } else {
- ttyin(cmdbuf, sizeof(cmdbuf) - 2, '/');
- putcerr('\r');
- free(previousre);
- previousre = xstrdup(cmdbuf);
- search(cmdbuf, f, nlines);
- }
- ret(dlines - 1);
- case '!':
- do_shell(filename);
- break;
- case '?':
- case 'h':
- if (noscroll)
- doclear();
- putsout(_("\n"
- "Most commands optionally preceded by integer argument k. "
- "Defaults in brackets.\n"
- "Star (*) indicates argument becomes new default.\n"));
- puts("---------------------------------------"
- "----------------------------------------");
- putsout(_
- ("<space> Display next k lines of text [current screen size]\n"
- "z Display next k lines of text [current screen size]*\n"
- "<return> Display next k lines of text [1]*\n"
- "d or ctrl-D Scroll k lines [current scroll size, initially 11]*\n"
- "q or Q or <interrupt> Exit from more\n"
- "s Skip forward k lines of text [1]\n"
- "f Skip forward k screenfuls of text [1]\n"
- "b or ctrl-B Skip backwards k screenfuls of text [1]\n"
- "' Go to place where previous search started\n"
- "= Display current line number\n"
- "/<regular expression> Search for kth occurrence of regular expression [1]\n"
- "n Search for kth occurrence of last r.e [1]\n"
- "!<cmd> or :!<cmd> Execute <cmd> in a subshell\n"
- "v Start up /usr/bin/vi at current line\n"
- "ctrl-L Redraw screen\n"
- ":n Go to kth next file [1]\n"
- ":p Go to kth previous file [1]\n"
- ":f Display current file name and line number\n"
- ". Repeat previous command\n"));
- puts("---------------------------------------"
- "----------------------------------------");
- prompt(filename);
+ continue;
+ }
+ if (slash && ((cc_t) c == otty.c_cc[VKILL]
+ || (cc_t) c == otty.c_cc[VERASE])) {
+ ERASEONECOLUMN(docrterase);
+ --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;
- case 'v': /* This case should go right before default */
- if (!no_intty) {
- /* Earlier: call vi +n file. This also
- * works for emacs. POSIX: call vi -c n
- * file (when editor is vi or ex). */
- char *editor, *p;
- int n = (Currline - dlines <= 0 ? 1 :
- Currline - (dlines + 1) / 2);
- int split = 0;
+ }
+ *--sp = '\0';
+ if (!eraseln)
+ promptlen = maxlen;
+ if (sp - buf >= nmax - 1)
+ more_error(_("Line too long"));
+}
- editor = getenv("VISUAL");
- if (editor == NULL || *editor == '\0')
- editor = getenv("EDITOR");
- if (editor == NULL || *editor == '\0')
- editor = VI;
+static int lastcmd, lastarg, lastp;
+static int lastcolon;
+static char shell_line[SHELL_LINE];
- p = strrchr(editor, '/');
- if (p)
- p++;
- else
- p = editor;
- if (!strcmp(p, "vi") || !strcmp(p, "ex")) {
- sprintf(cmdbuf, "-c %d", n);
- split = 1;
- } else {
- sprintf(cmdbuf, "+%d", n);
- }
+/* return: 0 - unchanged, 1 - changed, -1 - overflow (unchanged) */
+static int expand(char **outbuf, char *inbuf)
+{
+ char *inpstr;
+ char *outstr;
+ char c;
+ char *temp;
+ int changed = 0;
+ int tempsz, xtra, offset;
- kill_line();
- printf("%s %s %s", editor, cmdbuf,
- fnames[fnum]);
- if (split) {
- cmdbuf[2] = 0;
- execute(filename, editor, editor,
- cmdbuf, cmdbuf + 3,
- fnames[fnum], (char *)0);
- } else
- execute(filename, editor, editor,
- cmdbuf, fnames[fnum],
- (char *)0);
+ xtra = strlen(fnames[fnum]) + strlen(shell_line) + 1;
+ tempsz = 200 + xtra;
+ temp = xmalloc(tempsz);
+ inpstr = inbuf;
+ outstr = temp;
+ while ((c = *inpstr++) != '\0') {
+ offset = outstr - temp;
+ if (tempsz - offset - 1 < xtra) {
+ tempsz += 200 + xtra;
+ temp = xrealloc(temp, tempsz);
+ 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)
+ more_error(_
+ ("No previous command to substitute for"));
+ strcpy(outstr, shell_line);
+ outstr += strlen(shell_line);
+ changed++;
+ break;
+ case '\\':
+ if (*inpstr == '%' || *inpstr == '!') {
+ *outstr++ = *inpstr++;
break;
}
/* fallthrough */
default:
- if (dum_opt) {
- kill_line();
- if (Senter && Sexit) {
- putstring(Senter);
- promptlen =
- printf(_
- ("[Press 'h' for instructions.]"))
- + 2 * soglitch;
- putstring(Sexit);
- } else
- promptlen =
- printf(_
- ("[Press 'h' for instructions.]"));
- fflush(stdout);
- } else
- ringbell();
- break;
+ *outstr++ = c;
}
- if (done)
- break;
}
- putchar('\r');
- endsw:
- inwait = 0;
- notell++;
- return (retval);
+ *outstr++ = '\0';
+ *outbuf = temp;
+ return (changed);
}
-static char ch;
-/* Execute a colon-prefixed command. Returns <0 if not a command that
- * should cause more of the file to be printed. */
-int colon(char *filename, int cmd, int nlines)
+static int ourputch(int c)
{
- if (cmd == 0)
- ch = readch();
- else
- ch = cmd;
- lastcolon = ch;
- switch (ch) {
- case 'f':
- kill_line();
- if (!no_intty)
- promptlen =
- printf(_("\"%s\" line %d"), fnames[fnum], Currline);
- else
- promptlen = printf(_("[Not a file] line %d"), Currline);
+ return putc(c, stdout);
+}
+
+static void reset_tty(void)
+{
+ if (no_tty)
+ return;
+ if (pstate) {
+ /* putchar - if that isn't a macro */
+ tputs(ULexit, fileno(stdout), ourputch);
fflush(stdout);
- return (-1);
- case 'n':
- if (nlines == 0) {
- if (fnum >= nfiles - 1)
- end_it(0);
- nlines++;
- }
- putchar('\r');
- erasep(0);
- skipf(nlines);
- return (0);
- case 'p':
- if (no_intty) {
- 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);
+ 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);
}
-/* Read a decimal number from the terminal. Set cmd to the non-digit
- * which terminates the number. */
-int number(char *cmd)
+static void set_tty(void)
{
- register int i;
+ 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);
+}
- 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;
+static 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) {
+ int errsv;
+ 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);
+ errsv = errno;
+ putserr(_("exec failed\n"));
+ exit(errsv == ENOENT ? EX_EXEC_ENOENT : EX_EXEC_FAILED);
}
- return (i);
+ if (id > 0) {
+ signal(SIGINT, SIG_IGN);
+ signal(SIGQUIT, SIG_IGN);
+ if (catch_susp)
+ signal(SIGTSTP, SIG_DFL);
+ while (wait(NULL) > 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);
}
-void do_shell(char *filename)
+static void do_shell(char *filename)
{
char cmdbuf[COMMAND_BUF];
int rc;
@@ -1527,9 +1142,109 @@ void do_shell(char *filename)
execute(filename, shell, shell, "-c", shell_line, 0);
}
+/* Execute a colon-prefixed command. Returns <0 if not a command that
+ * should cause more of the file to be printed. */
+static int colon(char *filename, int cmd, int nlines)
+{
+ if (cmd == 0)
+ ch = readch();
+ else
+ ch = cmd;
+ lastcolon = ch;
+ switch (ch) {
+ case 'f':
+ kill_line();
+ if (!no_intty)
+ promptlen =
+ printf(_("\"%s\" line %d"), fnames[fnum], Currline);
+ else
+ promptlen = printf(_("[Not a file] line %d"), Currline);
+ fflush(stdout);
+ return (-1);
+ case 'n':
+ if (nlines == 0) {
+ if (fnum >= nfiles - 1)
+ end_it(0);
+ nlines++;
+ }
+ putchar('\r');
+ erasep(0);
+ skipf(nlines);
+ return (0);
+ case 'p':
+ if (no_intty) {
+ 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);
+ }
+}
+
+/* Skip n lines in the file f */
+static 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++;
+ }
+}
+
+/* Clear the screen */
+static void doclear(void)
+{
+ if (Clear && !hard) {
+ putstring(Clear);
+ /* Put out carriage return so that system doesn't get
+ * confused by escape sequences when expanding tabs */
+ putchar('\r');
+ promptlen = 0;
+ }
+}
+
+static void rdline(register FILE *f)
+{
+ register int c;
+ register char *p;
+
+ prepare_line_buffer();
+
+ p = Line;
+ while ((c = Getc(f)) != '\n' && c != EOF
+ && (size_t)(p - Line) < LineLen - 1)
+ *p++ = c;
+ if (c == '\n')
+ Currline++;
+ *p = '\0';
+}
+
+/* Go to home position */
+static void home(void)
+{
+ putstring(Home);
+}
+
/* Search for nth occurrence of regular expression contained in buf in
* the file */
-void search(char buf[], FILE *file, register int n)
+static void search(char buf[], FILE *file, register int n)
{
long startline = Ftell(file);
register long line1 = startline;
@@ -1605,526 +1320,584 @@ notfound:
}
}
-void execute(char *filename, char *cmd, ...)
+/* 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. */
+static int command(char *filename, register FILE *f)
{
- int id;
- int n;
- va_list argp;
- char *arg;
- char **args;
- int argcount;
+ register int nlines;
+ register int retval = 0;
+ register int c;
+ char colonch;
+ int done;
+ char comchar, cmdbuf[INIT_BUF];
- fflush(stdout);
- reset_tty();
- for (n = 10; (id = fork()) < 0 && n > 0; n--)
- sleep(5);
- if (id == 0) {
- int errsv;
- if (!isatty(0)) {
- close(0);
- open("/dev/tty", 0);
- }
+#define ret(val) retval=val;done++;break
- va_start(argp, cmd);
- arg = va_arg(argp, char *);
- argcount = 0;
- while (arg) {
- argcount++;
- arg = va_arg(argp, char *);
+ 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;
}
- 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 *);
+ lastcmd = comchar;
+ lastarg = nlines;
+ if ((cc_t) comchar == otty.c_cc[VERASE]) {
+ kill_line();
+ prompt(filename);
+ continue;
}
- va_end(argp);
-
- execvp(cmd, args);
- errsv = errno;
- putserr(_("exec failed\n"));
- exit(errsv == ENOENT ? EX_EXEC_ENOENT : EX_EXEC_FAILED);
- }
- if (id > 0) {
- signal(SIGINT, SIG_IGN);
- signal(SIGQUIT, SIG_IGN);
- if (catch_susp)
- signal(SIGTSTP, SIG_DFL);
- while (wait(NULL) > 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);
-}
+ switch (comchar) {
+ case ':':
+ retval = colon(filename, colonch, nlines);
+ if (retval >= 0)
+ done++;
+ break;
+ case 'b':
+ case ctrl('B'):
+ {
+ register int initline;
-/* Skip n lines in the file f */
-void skiplns(register int n, register FILE *f)
-{
- register int c;
+ if (no_intty) {
+ ringbell();
+ return (-1);
+ }
- while (n > 0) {
- while ((c = Getc(f)) != '\n')
- if (c == EOF)
- return;
- n--;
- Currline++;
- }
-}
+ if (nlines == 0)
+ nlines++;
-/* 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;
-}
+ putchar('\r');
+ erasep(0);
+ putchar('\n');
+ if (clreol)
+ cleareol();
+ printf(P_("...back %d page",
+ "...back %d pages", nlines),
+ nlines);
+ if (clreol)
+ cleareol();
+ putchar('\n');
-/*----------------------------- Terminal I/O -------------------------------*/
-void initterm(void)
-{
- int ret;
- char *padstr;
- char *term;
- struct winsize win;
+ initline = Currline - dlines * (nlines + 1);
+ if (!noscroll)
+ --initline;
+ if (initline < 0)
+ initline = 0;
+ Fseek(f, 0L);
+ Currline = 0; /* skiplns() will make Currline correct */
+ skiplns(initline, f);
+ if (!noscroll) {
+ ret(dlines + 1);
+ } else {
+ 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(0);
+ case 's':
+ case 'f':
+ case ctrl('F'):
+ if (nlines == 0)
+ nlines++;
+ if (comchar == 'f')
+ nlines *= dlines;
+ putchar('\r');
+ erasep(0);
+ putchar('\n');
+ if (clreol)
+ cleareol();
+ printf(P_("...skipping %d line",
+ "...skipping %d lines", nlines),
+ nlines);
-#ifdef do_SIGTTOU
- retry:
-#endif
+ if (clreol)
+ cleareol();
+ putchar('\n');
-#ifndef NON_INTERACTIVE_MORE
- no_tty = tcgetattr(fileno(stdout), &otty);
-#endif
- 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 terminal modes. */
- if ((tgrp = tcgetpgrp(fileno(stdout))) < 0)
- err(EXIT_FAILURE, "tcgetpgrp");
- if (tgrp != getpgrp(0)) {
- kill(0, SIGTTOU);
- goto retry;
+ while (nlines > 0) {
+ while ((c = Getc(f)) != '\n')
+ if (c == EOF) {
+ retval = 0;
+ done++;
+ goto endsw;
+ }
+ Currline++;
+ nlines--;
}
- }
-#endif /* do_SIGTTOU */
- if ((term = getenv("TERM")) == NULL) {
- dumb++;
- ul_opt = 0;
- }
- setupterm(term, 1, &ret);
- if (ret <= 0) {
- dumb++;
- ul_opt = 0;
- } else {
-#ifdef TIOCGWINSZ
- if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
-#endif
- Lpp = tigetnum(TERM_LINES);
- Mcol = tigetnum(TERM_COLS);
-#ifdef TIOCGWINSZ
+ 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 {
- if ((Lpp = win.ws_row) == 0)
- Lpp = tigetnum(TERM_LINES);
- if ((Mcol = win.ws_col) == 0)
- Mcol = tigetnum(TERM_COLS);
+ ringbell();
+ break;
}
-#endif
- if ((Lpp <= 0) || tigetflag(TERM_HARD_COPY)) {
- hard++; /* Hard copy terminal */
- Lpp = LINES_PER_PAGE;
+ case '\'':
+ if (!no_intty) {
+ kill_line();
+ putsout(_("\n***Back***\n\n"));
+ Fseek(f, context.chrctr);
+ Currline = context.line;
+ ret(dlines);
+ } else {
+ ringbell();
+ break;
}
-
- if (tigetflag(TERM_EAT_NEW_LINE))
- /* Eat newline at last column + 1; dec, concept */
- eatnl++;
- if (Mcol <= 0)
- Mcol = NUM_COLUMNS;
-
- Wrap = tigetflag(TERM_AUTO_RIGHT_MARGIN);
- bad_so = tigetflag(TERM_CEOL);
- eraseln = tigetstr(TERM_CLEAR_TO_LINE_END);
- Clear = tigetstr(TERM_CLEAR);
- Senter = tigetstr(TERM_STANDARD_MODE);
- Sexit = tigetstr(TERM_EXIT_STANDARD_MODE);
- if ((soglitch = tigetnum(TERM_STD_MODE_GLITCH)) < 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 (tigetflag(TERM_UNDERLINE)
- || tigetflag(TERM_OVER_STRIKE))
- ul_opt = 0;
- if ((chUL = tigetstr(TERM_UNDERLINE_CHAR)) == NULL)
- chUL = "";
- if (((ULenter =
- tigetstr(TERM_ENTER_UNDERLINE)) == NULL
- || (ULexit =
- tigetstr(TERM_EXIT_UNDERLINE)) == NULL)
- && !*chUL) {
- if ((ULenter = Senter) == NULL
- || (ULexit = Sexit) == NULL) {
- ULenter = "";
- ULexit = "";
- } else
- ulglitch = soglitch;
+ case '=':
+ kill_line();
+ promptlen = printf("%d", Currline);
+ fflush(stdout);
+ break;
+ case 'n':
+ if (!previousre) {
+ more_error(_("No previous regular expression"));
+ break;
+ }
+ lastp++;
+ /* fallthrough */
+ case '/':
+ if (nlines == 0)
+ nlines++;
+ kill_line();
+ putchar('/');
+ promptlen = 1;
+ fflush(stdout);
+ if (lastp) {
+ putcerr('\r');
+ search(previousre, f, nlines);
} else {
- ulglitch = 0;
+ ttyin(cmdbuf, sizeof(cmdbuf) - 2, '/');
+ putcerr('\r');
+ free(previousre);
+ previousre = xstrdup(cmdbuf);
+ search(cmdbuf, f, nlines);
}
+ ret(dlines - 1);
+ case '!':
+ do_shell(filename);
+ break;
+ case '?':
+ case 'h':
+ if (noscroll)
+ doclear();
+ putsout(_("\n"
+ "Most commands optionally preceded by integer argument k. "
+ "Defaults in brackets.\n"
+ "Star (*) indicates argument becomes new default.\n"));
+ puts("---------------------------------------"
+ "----------------------------------------");
+ putsout(_
+ ("<space> Display next k lines of text [current screen size]\n"
+ "z Display next k lines of text [current screen size]*\n"
+ "<return> Display next k lines of text [1]*\n"
+ "d or ctrl-D Scroll k lines [current scroll size, initially 11]*\n"
+ "q or Q or <interrupt> Exit from more\n"
+ "s Skip forward k lines of text [1]\n"
+ "f Skip forward k screenfuls of text [1]\n"
+ "b or ctrl-B Skip backwards k screenfuls of text [1]\n"
+ "' Go to place where previous search started\n"
+ "= Display current line number\n"
+ "/<regular expression> Search for kth occurrence of regular expression [1]\n"
+ "n Search for kth occurrence of last r.e [1]\n"
+ "!<cmd> or :!<cmd> Execute <cmd> in a subshell\n"
+ "v Start up /usr/bin/vi at current line\n"
+ "ctrl-L Redraw screen\n"
+ ":n Go to kth next file [1]\n"
+ ":p Go to kth previous file [1]\n"
+ ":f Display current file name and line number\n"
+ ". Repeat previous command\n"));
+ puts("---------------------------------------"
+ "----------------------------------------");
+ prompt(filename);
+ break;
+ case 'v': /* This case should go right before default */
+ if (!no_intty) {
+ /* Earlier: call vi +n file. This also
+ * works for emacs. POSIX: call vi -c n
+ * file (when editor is vi or ex). */
+ char *editor, *p;
+ int n = (Currline - dlines <= 0 ? 1 :
+ Currline - (dlines + 1) / 2);
+ int split = 0;
- if ((padstr = tigetstr(TERM_PAD_CHAR)) != NULL)
- PC = *padstr;
- Home = tigetstr(TERM_HOME);
- if (Home == NULL || *Home == '\0') {
- if ((cursorm =
- tigetstr(TERM_CURSOR_ADDRESS)) != NULL) {
- const char *t =
- (const char *)tparm(cursorm, 0,
- 0);
- xstrncpy(cursorhome, t,
- sizeof(cursorhome));
- Home = cursorhome;
+ editor = getenv("VISUAL");
+ if (editor == NULL || *editor == '\0')
+ editor = getenv("EDITOR");
+ if (editor == NULL || *editor == '\0')
+ editor = VI;
+
+ p = strrchr(editor, '/');
+ if (p)
+ p++;
+ else
+ p = editor;
+ if (!strcmp(p, "vi") || !strcmp(p, "ex")) {
+ sprintf(cmdbuf, "-c %d", n);
+ split = 1;
+ } else {
+ sprintf(cmdbuf, "+%d", n);
}
- }
- EodClr = tigetstr(TERM_CLEAR_TO_SCREEN_END);
- if ((chBS = tigetstr(TERM_LINE_DOWN)) == NULL)
- chBS = "\b";
+ kill_line();
+ printf("%s %s %s", editor, cmdbuf,
+ fnames[fnum]);
+ if (split) {
+ cmdbuf[2] = 0;
+ execute(filename, editor, editor,
+ cmdbuf, cmdbuf + 3,
+ fnames[fnum], (char *)0);
+ } else
+ execute(filename, editor, editor,
+ cmdbuf, fnames[fnum],
+ (char *)0);
+ break;
+ }
+ /* fallthrough */
+ default:
+ if (dum_opt) {
+ kill_line();
+ if (Senter && Sexit) {
+ putstring(Senter);
+ promptlen =
+ printf(_
+ ("[Press 'h' for instructions.]"))
+ + 2 * soglitch;
+ putstring(Sexit);
+ } else
+ promptlen =
+ printf(_
+ ("[Press 'h' for instructions.]"));
+ fflush(stdout);
+ } else
+ ringbell();
+ break;
}
- if ((shell = getenv("SHELL")) == NULL)
- shell = "/bin/sh";
- }
- no_intty = tcgetattr(fileno(stdin), &otty);
- tcgetattr(fileno(stderr), &otty);
- savetty0 = otty;
- 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(void)
-{
- unsigned char c;
-
- errno = 0;
- if (read(fileno(stderr), &c, 1) <= 0) {
- if (errno != EINTR)
- end_it(0);
- else
- c = otty.c_cc[VKILL];
+ if (done)
+ break;
}
- return (c);
+ putchar('\r');
+ endsw:
+ inwait = 0;
+ notell++;
+ return (retval);
}
-static char *BS = "\b";
-static char *BSB = "\b \b";
-static char *CARAT = "^";
-#define ERASEONECOLUMN(x) \
- do { \
- if (x) \
- putserr(BSB); \
- else \
- putserr(BS); \
- } while(0)
-
-void ttyin(char buf[], register int nmax, char pchar)
+/* Print out the contents of the file f, one screenful at a time. */
+#define STOP -10
+static void screen(register FILE *f, register int num_lines)
{
- 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 HAVE_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(docrterase);
- } else {
- int wc_width;
- wc_width = wcwidth(wc);
- wc_width =
- (wc_width <
- 1) ? 1 : wc_width;
- while (wc_width--) {
- ERASEONECOLUMN(docrterase);
- }
- }
-
- while (mblength--) {
- --promptlen;
- --sp;
- }
- } else
-#endif /* HAVE_WIDECHAR */
- {
- --promptlen;
- ERASEONECOLUMN(docrterase);
- --sp;
- }
+ register int c;
+ register int nchars;
+ int length; /* length of current line */
+ static int prev_len = 1; /* length of previous line */
- if ((*sp < ' ' && *sp != '\n') || *sp == RUBOUT) {
- --promptlen;
- ERASEONECOLUMN(docrterase);
- }
- 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;
+ for (;;) {
+ while (num_lines > 0 && !Pause) {
+ if ((nchars = get_line(f, &length)) == EOF) {
+ if (clreol)
+ clreos();
+ return;
}
- sp = buf;
- fflush(stdout);
- continue;
+ 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(nchars); /* erasep () sets promptlen to 0 */
+ else
+ promptlen = 0;
+ /* is this needed?
+ * if (clreol)
+ * cleareol(); * must clear again in case we wrapped *
+ */
+ if (nchars < Mcol || !fold_opt)
+ prbuf("\n", 1); /* will turn off UL if necessary */
+ if (nchars == STOP)
+ break;
+ num_lines--;
}
- if (slash && ((cc_t) c == otty.c_cc[VKILL]
- || (cc_t) c == otty.c_cc[VERASE])) {
- ERASEONECOLUMN(docrterase);
- --sp;
+ if (pstate) {
+ putstring(ULexit);
+ pstate = 0;
}
- if (c != '\\')
- slash = 0;
- *sp++ = c;
- if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
- c += (c == RUBOUT) ? -0100 : 0100;
- putserr(CARAT);
- promptlen++;
+ fflush(stdout);
+ if ((c = Getc(f)) == EOF) {
+ if (clreol)
+ clreos();
+ return;
}
- if (c != '\n' && c != ESC) {
- putcerr(c);
- promptlen++;
- } else
- break;
+
+ if (Pause && clreol)
+ clreos();
+ Ungetc(c, f);
+ sigsetjmp(restore, 1);
+ 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();
+ }
+ screen_start.line = Currline;
+ screen_start.chrctr = Ftell(f);
}
- *--sp = '\0';
- if (!eraseln)
- promptlen = maxlen;
- if (sp - buf >= nmax - 1)
- more_error(_("Line too long"));
}
-/* return: 0 - unchanged, 1 - changed, -1 - overflow (unchanged) */
-int expand(char **outbuf, char *inbuf)
+/* Come here if a quit signal is received */
+static void onquit(int dummy __attribute__((__unused__)))
{
- 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 = xmalloc(tempsz);
- inpstr = inbuf;
- outstr = temp;
- while ((c = *inpstr++) != '\0') {
- offset = outstr - temp;
- if (tempsz - offset - 1 < xtra) {
- tempsz += 200 + xtra;
- temp = xrealloc(temp, tempsz);
- 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)
- more_error(_
- ("No previous command to substitute for"));
- strcpy(outstr, shell_line);
- outstr += strlen(shell_line);
- changed++;
- break;
- case '\\':
- if (*inpstr == '%' || *inpstr == '!') {
- *outstr++ = *inpstr++;
- break;
- }
- /* fallthrough */
- default:
- *outstr++ = c;
- }
+ signal(SIGQUIT, SIG_IGN);
+ if (!inwait) {
+ putchar('\n');
+ if (!startup) {
+ signal(SIGQUIT, onquit);
+ siglongjmp(restore, 1);
+ } else
+ Pause++;
+ } else if (!dum_opt && notell) {
+ promptlen += fprintf(stderr, _("[Use q or Q to quit]"));
+ notell = 0;
}
- *outstr++ = '\0';
- *outbuf = temp;
- return (changed);
+ signal(SIGQUIT, onquit);
}
-void show(char c)
+/* Come here if a signal for a window size change is received */
+#ifdef SIGWINCH
+static void chgwinsz(int dummy __attribute__((__unused__)))
{
- if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
- c += (c == RUBOUT) ? -0100 : 0100;
- putserr(CARAT);
- promptlen++;
+ struct winsize win;
+
+ signal(SIGWINCH, SIG_IGN);
+ if (ioctl(fileno(stdout), TIOCGWINSZ, &win) != -1) {
+ if (win.ws_row != 0) {
+ Lpp = win.ws_row;
+ nscroll = Lpp / 2 - 1;
+ if (nscroll <= 0)
+ nscroll = 1;
+ dlines = Lpp - 1; /* was: Lpp - (noscroll ? 1 : 2) */
+ }
+ if (win.ws_col != 0)
+ Mcol = win.ws_col;
}
- putcerr(c);
- promptlen++;
+ signal(SIGWINCH, chgwinsz);
}
+#endif /* SIGWINCH */
-void more_error(char *mess)
+/* Clean up terminal state and exit. Also come here if interrupt signal received */
+static void __attribute__((__noreturn__)) end_it(int dummy __attribute__((__unused__)))
{
- if (clreol)
- cleareol();
- else
+ /* May be executed as a signal handler as well as by main process.
+ *
+ * The _exit() may wait for pending I/O for really long time, be sure
+ * that signal handler is not executed in this time to avoid double
+ * de-initialization (free() calls, etc.).
+ */
+ signal(SIGINT, SIG_IGN);
+
+ reset_tty();
+ if (clreol) {
+ putchar('\r');
+ clreos();
+ fflush(stdout);
+ } else if (!clreol && (promptlen > 0)) {
kill_line();
- promptlen += strlen(mess);
- if (Senter && Sexit) {
- putstring(Senter);
- putsout(mess);
- putstring(Sexit);
+ fflush(stdout);
} else
- putsout(mess);
- fflush(stdout);
- errors++;
- siglongjmp(restore, 1);
+ putcerr('\n');
+ free(previousre);
+ free(Line);
+ _exit(EXIT_SUCCESS);
}
-void set_tty(void)
+static void copy_file(register FILE *f)
{
- 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);
+ char buf[BUFSIZ];
+ size_t sz;
+
+ while ((sz = fread(&buf, sizeof(char), sizeof(buf), f)) > 0)
+ fwrite(&buf, sizeof(char), sz, stdout);
}
-static int ourputch(int c)
-{
- return putc(c, stdout);
-}
-void reset_tty(void)
-{
- if (no_tty)
- return;
- if (pstate) {
- /* putchar - if that isn't a macro */
- tputs(ULexit, fileno(stdout), ourputch);
- fflush(stdout);
- pstate = 0;
+/*----------------------------- Terminal I/O -------------------------------*/
+static void initterm(void)
+{
+ int ret;
+ char *padstr;
+ char *term;
+ struct winsize win;
+
+#ifdef do_SIGTTOU
+ retry:
+#endif
+
+#ifndef NON_INTERACTIVE_MORE
+ no_tty = tcgetattr(fileno(stdout), &otty);
+#endif
+ 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 terminal modes. */
+ if ((tgrp = tcgetpgrp(fileno(stdout))) < 0)
+ err(EXIT_FAILURE, "tcgetpgrp");
+ if (tgrp != getpgrp(0)) {
+ kill(0, SIGTTOU);
+ goto retry;
+ }
+ }
+#endif /* do_SIGTTOU */
+ if ((term = getenv("TERM")) == NULL) {
+ dumb++;
+ ul_opt = 0;
+ }
+ setupterm(term, 1, &ret);
+ if (ret <= 0) {
+ dumb++;
+ ul_opt = 0;
+ } else {
+#ifdef TIOCGWINSZ
+ if (ioctl(fileno(stdout), TIOCGWINSZ, &win) < 0) {
+#endif
+ Lpp = tigetnum(TERM_LINES);
+ Mcol = tigetnum(TERM_COLS);
+#ifdef TIOCGWINSZ
+ } else {
+ if ((Lpp = win.ws_row) == 0)
+ Lpp = tigetnum(TERM_LINES);
+ if ((Mcol = win.ws_col) == 0)
+ Mcol = tigetnum(TERM_COLS);
+ }
+#endif
+ if ((Lpp <= 0) || tigetflag(TERM_HARD_COPY)) {
+ hard++; /* Hard copy terminal */
+ Lpp = LINES_PER_PAGE;
+ }
+
+ if (tigetflag(TERM_EAT_NEW_LINE))
+ /* Eat newline at last column + 1; dec, concept */
+ eatnl++;
+ if (Mcol <= 0)
+ Mcol = NUM_COLUMNS;
+
+ Wrap = tigetflag(TERM_AUTO_RIGHT_MARGIN);
+ bad_so = tigetflag(TERM_CEOL);
+ eraseln = tigetstr(TERM_CLEAR_TO_LINE_END);
+ Clear = tigetstr(TERM_CLEAR);
+ Senter = tigetstr(TERM_STANDARD_MODE);
+ Sexit = tigetstr(TERM_EXIT_STANDARD_MODE);
+ if ((soglitch = tigetnum(TERM_STD_MODE_GLITCH)) < 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 (tigetflag(TERM_UNDERLINE)
+ || tigetflag(TERM_OVER_STRIKE))
+ ul_opt = 0;
+ if ((chUL = tigetstr(TERM_UNDERLINE_CHAR)) == NULL)
+ chUL = "";
+ if (((ULenter =
+ tigetstr(TERM_ENTER_UNDERLINE)) == NULL
+ || (ULexit =
+ tigetstr(TERM_EXIT_UNDERLINE)) == NULL)
+ && !*chUL) {
+ if ((ULenter = Senter) == NULL
+ || (ULexit = Sexit) == NULL) {
+ ULenter = "";
+ ULexit = "";
+ } else
+ ulglitch = soglitch;
+ } else {
+ ulglitch = 0;
+ }
+
+ if ((padstr = tigetstr(TERM_PAD_CHAR)) != NULL)
+ PC = *padstr;
+ Home = tigetstr(TERM_HOME);
+ if (Home == NULL || *Home == '\0') {
+ if ((cursorm =
+ tigetstr(TERM_CURSOR_ADDRESS)) != NULL) {
+ const char *t =
+ (const char *)tparm(cursorm, 0,
+ 0);
+ xstrncpy(cursorhome, t,
+ sizeof(cursorhome));
+ Home = cursorhome;
+ }
+ }
+ EodClr = tigetstr(TERM_CLEAR_TO_SCREEN_END);
+ if ((chBS = tigetstr(TERM_LINE_DOWN)) == NULL)
+ chBS = "\b";
+
+ }
+ if ((shell = getenv("SHELL")) == NULL)
+ shell = "/bin/sh";
+ }
+ no_intty = tcgetattr(fileno(stdin), &otty);
+ tcgetattr(fileno(stderr), &otty);
+ savetty0 = otty;
+ hardtabs = (otty.c_oflag & TABDLY) != XTABS;
+ if (!no_tty) {
+ otty.c_lflag &= ~(ICANON | ECHO);
+ otty.c_cc[VMIN] = 1;
+ otty.c_cc[VTIME] = 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;
-
- prepare_line_buffer();
-
- p = Line;
- while ((c = Getc(f)) != '\n' && c != EOF
- && (size_t)(p - Line) < LineLen - 1)
- *p++ = c;
- if (c == '\n')
- Currline++;
- *p = '\0';
}
/* Come here when we get a suspend signal from the terminal */
-void onsusp(int dummy __attribute__((__unused__)))
+static void onsusp(int dummy __attribute__((__unused__)))
{
sigset_t signals, oldmask;
@@ -2152,3 +1925,200 @@ void onsusp(int dummy __attribute__((__unused__)))
if (inwait)
siglongjmp(restore, 1);
}
+
+int main(int argc, char **argv)
+{
+ FILE *f;
+ char *s;
+ int chr;
+ int left;
+ int prnames = 0;
+ int initopt = 0;
+ int srchopt = 0;
+ int clearit = 0;
+ int initline = 0;
+ char *initbuf = NULL;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+ atexit(close_stdout);
+
+ if (argc > 1) {
+ /* first arg may be one of our standard longopts */
+ if (!strcmp(argv[1], "--help"))
+ usage();
+ if (!strcmp(argv[1], "--version")) {
+ printf(UTIL_LINUX_VERSION);
+ exit(EXIT_SUCCESS);
+ }
+ }
+
+ 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 ((chr = (*++fnames)[0]) == '-') {
+ argscan(*fnames + 1);
+ } else if (chr == '+') {
+ s = *fnames;
+ if (*++s == '/') {
+ srchopt++;
+ initbuf = xstrdup(s + 1);
+ } 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) {
+ warnx(_("bad usage"));
+ errtryhelp(EXIT_FAILURE);
+ } else
+ f = stdin;
+ if (!no_tty) {
+ signal(SIGQUIT, onquit);
+ signal(SIGINT, end_it);
+#ifdef SIGWINCH
+ signal(SIGWINCH, chgwinsz);
+#endif
+ 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 ((chr = Getc(f)) == '\f')
+ doclear();
+ else {
+ Ungetc(chr, f);
+ if (noscroll && (chr != EOF)) {
+ if (clreol)
+ home();
+ else
+ doclear();
+ }
+ }
+ if (srchopt) {
+ free(previousre);
+ previousre = xstrdup(initbuf);
+ 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) {
+ free(previousre);
+ previousre = xstrdup(initbuf);
+ 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;
+ }
+ free(previousre);
+ free(initbuf);
+ free(Line);
+ reset_tty();
+ exit(EXIT_SUCCESS);
+}
--
2.17.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] more: reorder global declarations
2018-04-19 21:46 [PATCH 1/2] more: remove function prototypes Sami Kerola
@ 2018-04-19 21:46 ` Sami Kerola
2018-05-23 8:42 ` [PATCH 1/2] more: remove function prototypes Karel Zak
1 sibling, 0 replies; 3+ messages in thread
From: Sami Kerola @ 2018-04-19 21:46 UTC (permalink / raw)
To: util-linux; +Cc: Sami Kerola
Group include, defines and such together, and move items inbetween functions
on top of the source file so that everything can be seen easily.
Signed-off-by: Sami Kerola <kerolasa@iki.fi>
---
text-utils/more.c | 96 +++++++++++++++++++++++------------------------
1 file changed, 48 insertions(+), 48 deletions(-)
diff --git a/text-utils/more.c b/text-utils/more.c
index 7df04de7b..d3317cf9c 100644
--- a/text-utils/more.c
+++ b/text-utils/more.c
@@ -59,6 +59,15 @@
#include <sys/stat.h>
#include <sys/file.h>
#include <sys/wait.h>
+#include <regex.h>
+
+#if defined(HAVE_NCURSESW_TERM_H)
+# include <ncursesw/term.h>
+#elif defined(HAVE_NCURSES_TERM_H)
+# include <ncurses/term.h>
+#elif defined(HAVE_TERM_H)
+# include <term.h>
+#endif
#include "strutils.h"
#include "nls.h"
@@ -66,8 +75,6 @@
#include "widechar.h"
#include "closestream.h"
-#include <regex.h>
-
#ifdef TEST_PROGRAM
# define NON_INTERACTIVE_MORE 1
#endif
@@ -89,6 +96,14 @@
#define stty(fd,argp) tcsetattr(fd,TCSANOW,argp)
+#define ERASEONECOLUMN(x) \
+ do { \
+ if (x) \
+ putserr(BSB); \
+ else \
+ putserr(BS); \
+ } while(0)
+
#define TBUFSIZ 1024
#define LINSIZ 256 /* minimal Line buffer size */
#define ctrl(letter) (letter & 077)
@@ -103,6 +118,29 @@
#define SHELL_LINE 1000
#define COMMAND_BUF 200
#define REGERR_BUF NUM_COLUMNS
+#define STOP -10
+
+#define TERM_AUTO_RIGHT_MARGIN "am"
+#define TERM_CEOL "xhp"
+#define TERM_CLEAR "clear"
+#define TERM_CLEAR_TO_LINE_END "el"
+#define TERM_CLEAR_TO_SCREEN_END "ed"
+#define TERM_COLS "cols"
+#define TERM_CURSOR_ADDRESS "cup"
+#define TERM_EAT_NEW_LINE "xenl"
+#define TERM_ENTER_UNDERLINE "smul"
+#define TERM_EXIT_STANDARD_MODE "rmso"
+#define TERM_EXIT_UNDERLINE "rmul"
+#define TERM_HARD_COPY "hc"
+#define TERM_HOME "home"
+#define TERM_LINE_DOWN "cud1"
+#define TERM_LINES "lines"
+#define TERM_OVER_STRIKE "os"
+#define TERM_PAD_CHAR "pad"
+#define TERM_STANDARD_MODE "smso"
+#define TERM_STD_MODE_GLITCH "xmc"
+#define TERM_UNDERLINE_CHAR "uc"
+#define TERM_UNDERLINE "ul"
static struct termios otty, savetty0;
static long file_pos, file_size;
@@ -158,35 +196,15 @@ static struct {
} context, screen_start;
extern char PC; /* pad character */
-#if defined(HAVE_NCURSESW_TERM_H)
-# include <ncursesw/term.h>
-#elif defined(HAVE_NCURSES_TERM_H)
-# include <ncurses/term.h>
-#elif defined(HAVE_TERM_H)
-# include <term.h>
-#endif
+static char *BS = "\b";
+static char *BSB = "\b \b";
+static char *CARAT = "^";
+
+static char ch;
+static int lastcmd, lastarg, lastp;
+static int lastcolon;
+static char shell_line[SHELL_LINE];
-#define TERM_AUTO_RIGHT_MARGIN "am"
-#define TERM_CEOL "xhp"
-#define TERM_CLEAR "clear"
-#define TERM_CLEAR_TO_LINE_END "el"
-#define TERM_CLEAR_TO_SCREEN_END "ed"
-#define TERM_COLS "cols"
-#define TERM_CURSOR_ADDRESS "cup"
-#define TERM_EAT_NEW_LINE "xenl"
-#define TERM_ENTER_UNDERLINE "smul"
-#define TERM_EXIT_STANDARD_MODE "rmso"
-#define TERM_EXIT_UNDERLINE "rmul"
-#define TERM_HARD_COPY "hc"
-#define TERM_HOME "home"
-#define TERM_LINE_DOWN "cud1"
-#define TERM_LINES "lines"
-#define TERM_OVER_STRIKE "os"
-#define TERM_PAD_CHAR "pad"
-#define TERM_STANDARD_MODE "smso"
-#define TERM_STD_MODE_GLITCH "xmc"
-#define TERM_UNDERLINE_CHAR "uc"
-#define TERM_UNDERLINE "ul"
static void putstring(char *s)
{
@@ -733,8 +751,6 @@ static int readch(void)
return (c);
}
-static char ch;
-
/* Read a decimal number from the terminal. Set cmd to the non-digit
* which terminates the number. */
static int number(char *cmd)
@@ -785,17 +801,6 @@ static void skipf(register int nskip)
--fnum;
}
-static char *BS = "\b";
-static char *BSB = "\b \b";
-static char *CARAT = "^";
-#define ERASEONECOLUMN(x) \
- do { \
- if (x) \
- putserr(BSB); \
- else \
- putserr(BS); \
- } while(0)
-
static void show(char c)
{
if ((c < ' ' && c != '\n' && c != ESC) || c == RUBOUT) {
@@ -952,10 +957,6 @@ static void ttyin(char buf[], register int nmax, char pchar)
more_error(_("Line too long"));
}
-static int lastcmd, lastarg, lastp;
-static int lastcolon;
-static char shell_line[SHELL_LINE];
-
/* return: 0 - unchanged, 1 - changed, -1 - overflow (unchanged) */
static int expand(char **outbuf, char *inbuf)
{
@@ -1615,7 +1616,6 @@ static int command(char *filename, register FILE *f)
}
/* Print out the contents of the file f, one screenful at a time. */
-#define STOP -10
static void screen(register FILE *f, register int num_lines)
{
register int c;
--
2.17.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 1/2] more: remove function prototypes
2018-04-19 21:46 [PATCH 1/2] more: remove function prototypes Sami Kerola
2018-04-19 21:46 ` [PATCH 2/2] more: reorder global declarations Sami Kerola
@ 2018-05-23 8:42 ` Karel Zak
1 sibling, 0 replies; 3+ messages in thread
From: Karel Zak @ 2018-05-23 8:42 UTC (permalink / raw)
To: Sami Kerola; +Cc: util-linux
On Thu, Apr 19, 2018 at 10:46:26PM +0100, Sami Kerola wrote:
> text-utils/more.c | 2482 ++++++++++++++++++++++-----------------------
> 1 file changed, 1226 insertions(+), 1256 deletions(-)
The both patches applied.
Karel
--
Karel Zak <kzak@redhat.com>
http://karelzak.blogspot.com
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2018-05-23 8:43 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-19 21:46 [PATCH 1/2] more: remove function prototypes Sami Kerola
2018-04-19 21:46 ` [PATCH 2/2] more: reorder global declarations Sami Kerola
2018-05-23 8:42 ` [PATCH 1/2] more: remove function prototypes Karel Zak
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).