made note of my recent changes
[oweals/busybox.git] / more.c
1 /*
2  * Mini more implementation for busybox
3  *
4  *
5  * Copyright (C) 1995, 1996 by Bruce Perens <bruce@pixar.com>.
6  *
7  * Latest version blended together by Erik Andersen <andersen@lineo.com>,
8  * based on the original more implementation by Bruce, and code from the 
9  * Debian boot-floppies team.
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 2 of the License, or
14  * (at your option) any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19  * General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24  *
25  */
26
27 #include "internal.h"
28 #include <stdio.h>
29 #include <fcntl.h>
30 #include <signal.h>
31 #include <sys/ioctl.h>
32
33 static const char more_usage[] = "more [file ...]\n";
34
35 /* ED: sparc termios is broken: revert back to old termio handling. */
36 #ifdef BB_FEATURE_USE_TERMIOS
37
38 #if #cpu(sparc)
39 #      define USE_OLD_TERMIO
40 #      include <termio.h>
41 #      define termios termio
42 #      define stty(fd,argp) ioctl(fd,TCSETAF,argp)
43 #else
44 #      include <termios.h>
45 #      define stty(fd,argp) tcsetattr(fd,TCSANOW,argp)
46 #endif
47
48     FILE *cin;
49     struct termios initial_settings, new_settings;
50
51     void gotsig(int sig) { 
52             stty(fileno(cin), &initial_settings);
53             fprintf(stdout, "\n");
54             exit( TRUE);
55     }
56 #endif
57
58
59
60 #define TERMINAL_WIDTH  79      /* not 80 in case terminal has linefold bug */
61 #define TERMINAL_HEIGHT 24
62
63
64 #if defined BB_FEATURE_AUTOWIDTH
65 static int terminal_width = 0, terminal_height = 0;
66 #else
67 #define terminal_width  TERMINAL_WIDTH
68 #define terminal_height TERMINAL_HEIGHT
69 #endif
70
71
72
73 extern int more_main(int argc, char **argv)
74 {
75     int c, lines=0, input=0;
76     int next_page=0;
77     struct stat st;     
78     FILE *file;
79 #ifdef BB_FEATURE_AUTOWIDTH
80     struct winsize win = {0,0};
81 #endif
82
83     argc--;
84     argv++;
85
86     if ( argc > 0 && (strcmp(*argv,"--help")==0 || strcmp(*argv,"-h")==0) ) {
87         usage (more_usage);
88     }
89     do {
90         if (argc==0) {
91             file = stdin;
92         }
93         else
94             file = fopen(*argv, "r");
95
96         if (file == NULL) {
97             perror(*argv);
98             exit(FALSE);
99         }
100         fstat(fileno(file), &st);
101
102 #ifdef BB_FEATURE_USE_TERMIOS
103         cin = fopen("/dev/tty", "r");
104         if (!cin)
105             cin = fopen("/dev/console", "r");
106 #ifdef USE_OLD_TERMIO
107         ioctl(fileno(cin),TCGETA,&initial_settings);
108 #else
109         tcgetattr(fileno(cin),&initial_settings);
110 #endif
111         new_settings = initial_settings;
112         new_settings.c_lflag &= ~ICANON;
113         new_settings.c_lflag &= ~ECHO;
114         stty(fileno(cin), &new_settings);
115
116 #ifdef BB_FEATURE_AUTOWIDTH     
117         ioctl(fileno(stdout), TIOCGWINSZ, &win);
118         if (win.ws_row > 4) 
119             terminal_height = win.ws_row - 2;
120         if (win.ws_col > 0) 
121             terminal_width = win.ws_col - 1;
122 #endif
123
124         (void) signal(SIGINT, gotsig);
125         (void) signal(SIGQUIT, gotsig);
126         (void) signal(SIGTERM, gotsig);
127
128 #endif
129         while ((c = getc(file)) != EOF) {
130             if ( next_page ) {
131                 int len=0;
132                 next_page = 0;
133                 lines=0;
134                 len = fprintf(stdout, "--More-- ");
135                 if (file != stdin) {
136                     len += fprintf(stdout, "(%d%% of %ld bytes)", 
137                         (int) (100*( (double) ftell(file) / (double) st.st_size )),
138                         st.st_size);
139                 }
140                 len += fprintf(stdout, "%s",
141 #ifdef BB_FEATURE_USE_TERMIOS
142                         ""
143 #else
144                         "\n"
145 #endif
146                         );
147
148                 fflush(stdout);
149                 input = getc( cin);
150
151 #ifdef BB_FEATURE_USE_TERMIOS
152                 /* Erase the "More" message */
153                 while(--len >= 0)
154                     putc('\b', stdout);
155                 while(++len <= terminal_width)
156                     putc(' ', stdout);
157                 while(--len >= 0)
158                     putc('\b', stdout);
159                 fflush(stdout);
160 #endif
161
162             }
163             if (c == '\n' ) {
164                 switch(input) {
165                     case 'q':
166                         goto end;
167                     case '\n':
168                         /* increment by just one line if we are at 
169                          * the end of this line*/
170                         next_page = 1;
171                         break;
172                 }
173                 if ( ++lines == terminal_height )
174                     next_page = 1;
175             }
176             putc(c, stdout);
177         }
178         fclose(file);
179         fflush(stdout);
180
181         argv++;
182     } while (--argc > 0);
183 end:
184 #ifdef BB_FEATURE_USE_TERMIOS
185     gotsig(0);
186 #endif  
187     exit(TRUE);
188 }
189