1 /*-
   2  * Copyright (c) 1998 Michael Smith <msmith@freebsd.org>
   3  * All rights reserved.
   4  *
   5  * Redistribution and use in source and binary forms, with or without
   6  * modification, are permitted provided that the following conditions
   7  * are met:
   8  * 1. Redistributions of source code must retain the above copyright
   9  *    notice, this list of conditions and the following disclaimer.
  10  * 2. Redistributions in binary form must reproduce the above copyright
  11  *    notice, this list of conditions and the following disclaimer in the
  12  *    documentation and/or other materials provided with the distribution.
  13  *
  14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24  * SUCH DAMAGE.
  25  */
  26 /*
  27  * Simple paged-output and paged-viewing functions
  28  */
  29 
  30 #include <sys/cdefs.h>
  31 __FBSDID("$FreeBSD$");
  32 
  33 #include "stand.h"
  34 #include <string.h>
  35 
  36 static int      p_maxlines = -1;
  37 static int      p_freelines;
  38 
  39 static char *pager_prompt1 = " --more--  <space> page down <enter> line down <q> quit ";
  40 static char *pager_blank   = "                                                        ";
  41 
  42 /*
  43  * 'open' the pager
  44  */
  45 void
  46 pager_open(void)
  47 {
  48     int         nlines;
  49     char        *cp, *lp;
  50     
  51     nlines = 24;                /* sensible default */
  52     if ((cp = getenv("LINES")) != NULL) {
  53         nlines = strtol(cp, &lp, 0);
  54     }
  55 
  56     p_maxlines = nlines - 1;
  57     if (p_maxlines < 1)
  58         p_maxlines = 1;
  59     p_freelines = p_maxlines;
  60 }
  61 
  62 /*
  63  * 'close' the pager
  64  */
  65 void
  66 pager_close(void)
  67 {
  68     p_maxlines = -1;
  69 }
  70 
  71 /*
  72  * Emit lines to the pager; may not return until the user
  73  * has responded to the prompt.
  74  *
  75  * Will return nonzero if the user enters 'q' or 'Q' at the prompt.
  76  *
  77  * XXX note that this watches outgoing newlines (and eats them), but
  78  *     does not handle wrap detection (req. count of columns).
  79  */
  80 
  81 int
  82 pager_output(const char *cp)
  83 {
  84     int         action;
  85 
  86     if (cp == NULL)
  87         return(0);
  88     
  89     for (;;) {
  90         if (*cp == 0)
  91             return(0);
  92         
  93         putchar(*cp);                   /* always emit character */
  94 
  95         if (*(cp++) == '\n') {          /* got a newline? */
  96             p_freelines--;
  97             if (p_freelines <= 0) {
  98                 printf("%s", pager_prompt1);
  99                 action = 0;
 100                 while (action == 0) {
 101                     switch(getchar()) {
 102                     case '\r':
 103                     case '\n':
 104                         p_freelines = 1;
 105                         action = 1;
 106                         break;
 107                     case ' ':
 108                         p_freelines = p_maxlines;
 109                         action = 1;
 110                         break;
 111                     case 'q':
 112                     case 'Q':
 113                         action = 2;
 114                         break;
 115                     default:
 116                         break;
 117                     }
 118                 }
 119                 printf("\r%s\r", pager_blank);
 120                 if (action == 2)
 121                     return(1);
 122             }
 123         }
 124     }
 125 }
 126 
 127 /*
 128  * Display from (fd).
 129  */
 130 int
 131 pager_file(const char *fname)
 132 {
 133     char        buf[80];
 134     size_t      hmuch;
 135     int         fd;
 136     int         result;
 137     
 138     if ((fd = open(fname, O_RDONLY)) == -1) {
 139         printf("can't open '%s': %s\n", fname, strerror(errno));
 140         return(-1);
 141     }
 142 
 143     for (;;) {
 144         hmuch = read(fd, buf, sizeof(buf) - 1);
 145         if (hmuch == -1) {
 146             result = -1;
 147             break;
 148         }
 149         if (hmuch == 0) {
 150             result = 0;
 151             break;
 152         }
 153         buf[hmuch] = 0;
 154         if (pager_output(buf)) {
 155             result = 1;
 156             break;
 157         }
 158     }
 159     close(fd);
 160     return(result);
 161 }