Example #1
0
/*
 * 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)
{
	int ch;

	if (cmd == 0)
		ch = readch();
	else
		ch = cmd;
	lastcolon = ch;
	switch (ch) {
	case 'f':
		kill_line();
		if (!no_intty)
			promptlen =
			    printf("\"%s\" line %lld", fnames[fnum],
				(long long)Currline);
		else
			promptlen = printf("[Not a file] line %lld",
			    (long long)Currline);
		fflush(stdout);
		return (-1);
	case 'n':
		if (nlines == 0) {
			if (fnum >= nfiles - 1)
				end_it();
			nlines++;
		}
		putchar('\r');
		erasep(0);
		skipf(nlines);
		return (0);
	case 'p':
		if (no_intty) {
			write(STDERR_FILENO, &bell, 1);
			return (-1);
		}
		putchar('\r');
		erasep(0);
		if (nlines == 0)
			nlines++;
		skipf (-nlines);
		return (0);
	case '!':
		if (do_shell(filename) < 0) {
			kill_line();
			prompt(filename);
		}
		return (-1);
	case 'q':
	case 'Q':
		end_it();
		/*FALLTHROUGH*/
	default:
		write(STDERR_FILENO, &bell, 1);
		return (-1);
	}
}
Example #2
0
File: more.c Project: aalm/obsd-src
/*
 * Erase the current line entirely
 */
void
kill_line(void)
{
	erasep(0);
	if (!eraseln || dumb)
		putchar('\r');
}
Example #3
0
File: more.c Project: aalm/obsd-src
/*
 * 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);
}
Example #4
0
File: more.c Project: aalm/obsd-src
/*
 * 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);
	}
}
Example #5
0
File: more.c Project: aalm/obsd-src
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);
}
Example #6
0
File: more.c Project: aalm/obsd-src
int
ttyin(char *buf, int nmax, char pchar)
{
	char	cbuf, ch, *sptr;
	int	maxlen, slash;

	sptr = buf;
	slash = maxlen = 0;
	while (sptr - buf < nmax) {
		if (promptlen > maxlen)
			maxlen = promptlen;
		ch = readch();
		if (ch == '\\')
			slash++;
		else if ((ch == otty.c_cc[VERASE]) && !slash) {
			if (sptr > buf) {
				--promptlen;
				ERASEONECHAR;
				--sptr;
				if ((*sptr < ' ' && *sptr != '\n') ||
				    *sptr == RUBOUT) {
					--promptlen;
					ERASEONECHAR;
				}
				continue;
			} else {
				if (!eraseln)
					promptlen = maxlen;
				return (-1);
			}
		} else if ((ch == otty.c_cc[VKILL]) && !slash) {
			if (hard) {
				show(ch);
				putchar('\n');
				putchar(pchar);
			} else {
				putchar('\r');
				putchar(pchar);
				if (eraseln)
					erasep(1);
				else if (docrtkill) {
					while (promptlen-- > 1)
						write(STDERR_FILENO, BSB,
						    sizeof(BSB) - 1);
				}
				promptlen = 1;
			}
			sptr = buf;
			fflush(stdout);
			continue;
		}
		if (slash && (ch == otty.c_cc[VKILL] ||
		    ch == otty.c_cc[VERASE])) {
			ERASEONECHAR;
			--sptr;
		}
		if (ch != '\\')
			slash = 0;
		*sptr++ = ch;
		if ((ch < ' ' && ch != '\n' && ch != ESC) || ch == RUBOUT) {
			ch += ch == RUBOUT ? -0100 : 0100;
			write(STDERR_FILENO, &CARAT, 1);
			promptlen++;
		}
		cbuf = ch;
		if (ch != '\n' && ch != ESC) {
			write(STDERR_FILENO, &cbuf, 1);
			promptlen++;
		} else
			break;
	}
	*--sptr = '\0';
	if (!eraseln)
		promptlen = maxlen;
	if (sptr - buf >= nmax - 1)
		error("Line too long");

	return (0);
}
Example #7
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);
}
Example #8
0
static void ttyin(char buf[], register int nmax, char pchar)
{
	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;
				}

				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;
			}
			sp = buf;
			fflush(stdout);
			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;
	}
	*--sp = '\0';
	if (!eraseln)
		promptlen = maxlen;
	if (sp - buf >= nmax - 1)
		more_error(_("Line too long"));
}