138451Smsmith/*-
238451Smsmith * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
338451Smsmith * All rights reserved.
438451Smsmith *
538451Smsmith * Redistribution and use in source and binary forms, with or without
638451Smsmith * modification, are permitted provided that the following conditions
738451Smsmith * are met:
838451Smsmith * 1. Redistributions of source code must retain the above copyright
938451Smsmith *    notice, this list of conditions and the following disclaimer.
1038451Smsmith * 2. Redistributions in binary form must reproduce the above copyright
1138451Smsmith *    notice, this list of conditions and the following disclaimer in the
1238451Smsmith *    documentation and/or other materials provided with the distribution.
1338451Smsmith *
1438451Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1538451Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1638451Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1738451Smsmith * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1838451Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1938451Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2038451Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2138451Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2238451Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2338451Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2438451Smsmith * SUCH DAMAGE.
2538451Smsmith */
2638451Smsmith/*
2738451Smsmith * Simple paged-output and paged-viewing functions
2838451Smsmith */
2938451Smsmith
3084221Sdillon#include <sys/cdefs.h>
3184221Sdillon__FBSDID("$FreeBSD: stable/11/stand/libsa/pager.c 329132 2018-02-11 19:51:29Z kevans $");
3284221Sdillon
3338451Smsmith#include "stand.h"
3438451Smsmith#include <string.h>
3538451Smsmith
3638451Smsmithstatic int	p_maxlines = -1;
3738451Smsmithstatic int	p_freelines;
3838451Smsmith
3938451Smsmithstatic char *pager_prompt1 = " --more--  <space> page down <enter> line down <q> quit ";
4038451Smsmithstatic char *pager_blank   = "                                                        ";
4138451Smsmith
4238451Smsmith/*
4338451Smsmith * 'open' the pager
4438451Smsmith */
4538451Smsmithvoid
4638451Smsmithpager_open(void)
4738451Smsmith{
4838451Smsmith    int		nlines;
4938451Smsmith    char	*cp, *lp;
5038451Smsmith
5138451Smsmith    nlines = 24;		/* sensible default */
5238451Smsmith    if ((cp = getenv("LINES")) != NULL) {
5338451Smsmith	nlines = strtol(cp, &lp, 0);
5438451Smsmith    }
5538451Smsmith
5638451Smsmith    p_maxlines = nlines - 1;
5738451Smsmith    if (p_maxlines < 1)
5838451Smsmith	p_maxlines = 1;
5938451Smsmith    p_freelines = p_maxlines;
6038451Smsmith}
6138451Smsmith
6238451Smsmith/*
6338451Smsmith * 'close' the pager
6438451Smsmith */
6538451Smsmithvoid
6638451Smsmithpager_close(void)
6738451Smsmith{
6838451Smsmith    p_maxlines = -1;
6938451Smsmith}
7038451Smsmith
7138451Smsmith/*
7238451Smsmith * Emit lines to the pager; may not return until the user
7338451Smsmith * has responded to the prompt.
7438451Smsmith *
7538451Smsmith * Will return nonzero if the user enters 'q' or 'Q' at the prompt.
7638451Smsmith *
7738451Smsmith * XXX note that this watches outgoing newlines (and eats them), but
7838451Smsmith *     does not handle wrap detection (req. count of columns).
7938451Smsmith */
8038451Smsmith
8138451Smsmithint
8238451Smsmithpager_output(const char *cp)
8338451Smsmith{
8438451Smsmith    int		action;
8538451Smsmith
8638451Smsmith    if (cp == NULL)
8738451Smsmith	return(0);
8838451Smsmith
8938451Smsmith    for (;;) {
9038451Smsmith	if (*cp == 0)
9138451Smsmith	    return(0);
9238451Smsmith
9338451Smsmith	putchar(*cp);			/* always emit character */
9438451Smsmith
9538451Smsmith	if (*(cp++) == '\n') {		/* got a newline? */
9638451Smsmith	    p_freelines--;
9738451Smsmith	    if (p_freelines <= 0) {
9872621Skris		printf("%s", pager_prompt1);
9938451Smsmith		action = 0;
10038451Smsmith		while (action == 0) {
10138451Smsmith		    switch(getchar()) {
10238451Smsmith		    case '\r':
10338451Smsmith		    case '\n':
10438451Smsmith			p_freelines = 1;
10538451Smsmith			action = 1;
10638451Smsmith			break;
10738451Smsmith		    case ' ':
10838451Smsmith			p_freelines = p_maxlines;
10938451Smsmith			action = 1;
11038451Smsmith			break;
11138451Smsmith		    case 'q':
11238451Smsmith		    case 'Q':
11338451Smsmith			action = 2;
11438451Smsmith			break;
11538451Smsmith		    default:
11638451Smsmith			break;
11738451Smsmith		    }
11838451Smsmith		}
11938451Smsmith		printf("\r%s\r", pager_blank);
12038451Smsmith		if (action == 2)
12138451Smsmith		    return(1);
12238451Smsmith	    }
12338451Smsmith	}
12438451Smsmith    }
12538451Smsmith}
12638451Smsmith
12738451Smsmith/*
12838451Smsmith * Display from (fd).
12938451Smsmith */
13038451Smsmithint
13139468Smsmithpager_file(const char *fname)
13238451Smsmith{
13338451Smsmith    char	buf[80];
13438451Smsmith    size_t	hmuch;
13538451Smsmith    int		fd;
13638451Smsmith    int		result;
13738451Smsmith
13838451Smsmith    if ((fd = open(fname, O_RDONLY)) == -1) {
13938451Smsmith	printf("can't open '%s': %s\n", fname, strerror(errno));
14038451Smsmith	return(-1);
14138451Smsmith    }
14238451Smsmith
14338451Smsmith    for (;;) {
14438451Smsmith	hmuch = read(fd, buf, sizeof(buf) - 1);
14538451Smsmith	if (hmuch == -1) {
14638451Smsmith	    result = -1;
14738451Smsmith	    break;
14838451Smsmith	}
14938451Smsmith	if (hmuch == 0) {
15038451Smsmith	    result = 0;
15138451Smsmith	    break;
15238451Smsmith	}
15338451Smsmith	buf[hmuch] = 0;
15438451Smsmith	if (pager_output(buf)) {
15538451Smsmith	    result = 1;
15638451Smsmith	    break;
15738451Smsmith	}
15838451Smsmith    }
15938451Smsmith    close(fd);
16038451Smsmith    return(result);
16138451Smsmith}
162