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