pager.c revision 84221
1131826Sharti/*-
2131826Sharti * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
3131826Sharti * All rights reserved.
4131826Sharti *
5131826Sharti * Redistribution and use in source and binary forms, with or without
6131826Sharti * modification, are permitted provided that the following conditions
7131826Sharti * are met:
8131826Sharti * 1. Redistributions of source code must retain the above copyright
9131826Sharti *    notice, this list of conditions and the following disclaimer.
10131826Sharti * 2. Redistributions in binary form must reproduce the above copyright
11131826Sharti *    notice, this list of conditions and the following disclaimer in the
12131826Sharti *    documentation and/or other materials provided with the distribution.
13131826Sharti *
14131826Sharti * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15131826Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16131826Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17131826Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18131826Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19131826Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20131826Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21131826Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22131826Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23131826Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24131826Sharti * SUCH DAMAGE.
25131826Sharti */
26131826Sharti/*
27131826Sharti * Simple paged-output and paged-viewing functions
28131826Sharti */
29131826Sharti
30146539Sharti#include <sys/cdefs.h>
31131826Sharti__FBSDID("$FreeBSD: head/lib/libstand/pager.c 84221 2001-09-30 22:28:01Z dillon $");
32131826Sharti
33131826Sharti#include "stand.h"
34131826Sharti#include <string.h>
35131826Sharti
36131826Shartistatic int	p_maxlines = -1;
37131826Shartistatic int	p_freelines;
38131826Sharti
39131826Shartistatic char *pager_prompt1 = " --more--  <space> page down <enter> line down <q> quit ";
40131826Shartistatic char *pager_blank   = "                                                        ";
41131826Sharti
42131826Sharti/*
43131826Sharti * 'open' the pager
44131826Sharti */
45131826Shartivoid
46131826Shartipager_open(void)
47131826Sharti{
48131826Sharti    int		nlines;
49131826Sharti    char	*cp, *lp;
50131826Sharti
51131826Sharti    nlines = 24;		/* sensible default */
52131826Sharti    if ((cp = getenv("LINES")) != NULL) {
53131826Sharti	nlines = strtol(cp, &lp, 0);
54131826Sharti    }
55131826Sharti
56131826Sharti    p_maxlines = nlines - 1;
57131826Sharti    if (p_maxlines < 1)
58131826Sharti	p_maxlines = 1;
59131826Sharti    p_freelines = p_maxlines;
60131826Sharti}
61131826Sharti
62131826Sharti/*
63131826Sharti * 'close' the pager
64131826Sharti */
65131826Shartivoid
66131826Shartipager_close(void)
67131826Sharti{
68131826Sharti    p_maxlines = -1;
69131826Sharti}
70131826Sharti
71131826Sharti/*
72131826Sharti * Emit lines to the pager; may not return until the user
73131826Sharti * has responded to the prompt.
74131826Sharti *
75131826Sharti * Will return nonzero if the user enters 'q' or 'Q' at the prompt.
76131826Sharti *
77131826Sharti * XXX note that this watches outgoing newlines (and eats them), but
78131826Sharti *     does not handle wrap detection (req. count of columns).
79131826Sharti */
80131826Sharti
81131826Shartiint
82131826Shartipager_output(const char *cp)
83131826Sharti{
84131826Sharti    int		action;
85131826Sharti
86131826Sharti    if (cp == NULL)
87131826Sharti	return(0);
88131826Sharti
89131826Sharti    for (;;) {
90131826Sharti	if (*cp == 0)
91131826Sharti	    return(0);
92131826Sharti
93131826Sharti	putchar(*cp);			/* always emit character */
94131826Sharti
95131826Sharti	if (*(cp++) == '\n') {		/* got a newline? */
96131826Sharti	    p_freelines--;
97131826Sharti	    if (p_freelines <= 0) {
98131826Sharti		printf("%s", pager_prompt1);
99131826Sharti		action = 0;
100131826Sharti		while (action == 0) {
101131826Sharti		    switch(getchar()) {
102131826Sharti		    case '\r':
103131826Sharti		    case '\n':
104131826Sharti			p_freelines = 1;
105131826Sharti			action = 1;
106131826Sharti			break;
107131826Sharti		    case ' ':
108131826Sharti			p_freelines = p_maxlines;
109131826Sharti			action = 1;
110131826Sharti			break;
111131826Sharti		    case 'q':
112131826Sharti		    case 'Q':
113131826Sharti			action = 2;
114131826Sharti			break;
115131826Sharti		    default:
116131826Sharti			break;
117131826Sharti		    }
118131826Sharti		}
119131826Sharti		printf("\r%s\r", pager_blank);
120131826Sharti		if (action == 2)
121131826Sharti		    return(1);
122131826Sharti	    }
123131826Sharti	}
124131826Sharti    }
125131826Sharti}
126131826Sharti
127131826Sharti/*
128131826Sharti * Display from (fd).
129131826Sharti */
130131826Shartiint
131131826Shartipager_file(const char *fname)
132131826Sharti{
133131826Sharti    char	buf[80];
134131826Sharti    size_t	hmuch;
135131826Sharti    int		fd;
136131826Sharti    int		result;
137131826Sharti
138131826Sharti    if ((fd = open(fname, O_RDONLY)) == -1) {
139131826Sharti	printf("can't open '%s': %s\n", fname, strerror(errno));
140131826Sharti	return(-1);
141131826Sharti    }
142131826Sharti
143131826Sharti    for (;;) {
144131826Sharti	hmuch = read(fd, buf, sizeof(buf) - 1);
145131826Sharti	if (hmuch == -1) {
146131826Sharti	    result = -1;
147131826Sharti	    break;
148131826Sharti	}
149131826Sharti	if (hmuch == 0) {
150131826Sharti	    result = 0;
151131826Sharti	    break;
152131826Sharti	}
153131826Sharti	buf[hmuch] = 0;
154131826Sharti	if (pager_output(buf)) {
155131826Sharti	    result = 1;
156131826Sharti	    break;
157131826Sharti	}
158131826Sharti    }
159131826Sharti    close(fd);
160131826Sharti    return(result);
161131826Sharti}
162131826Sharti