Initial revision
[oweals/busybox.git] / more.c
1 #include "internal.h"
2 #include <stdio.h>
3 #include <sys/types.h>
4 #include <sys/stat.h>
5 #include <sys/ioctl.h>
6 #include <fcntl.h>
7
8 #define BB_MORE_TERM
9
10 #ifdef BB_MORE_TERM
11         #include <termios.h>
12         #include <signal.h>
13
14         FILE *cin;
15         struct termios initial_settings, new_settings;
16
17         void gotsig(int sig) { 
18                 tcsetattr(fileno(cin), TCSANOW, &initial_settings);
19                 exit(0);
20         }
21 #endif
22
23 const char      more_usage[] = "more [file]\n"
24 "\n"
25 "\tDisplays a file, one page at a time.\n"
26 "\tIf there are no arguments, the standard input is displayed.\n";
27
28 extern int
29 more_fn(const struct FileInfo * i)
30 {
31         FILE *  f = stdin;
32         int     c;
33         int     lines = 0, tlines = 0;
34         int     next_page = 0;
35         int     rows = 24, cols = 79;
36 #ifdef BB_MORE_TERM
37         long sizeb = 0;
38         struct stat st; 
39         struct winsize win;
40 #endif
41         
42         if ( i ) {
43                 if (! (f = fopen(i->source, "r") )) {
44                         name_and_error(i->source);
45                         return 1;
46                 }
47                 fstat(fileno(f), &st);
48                 sizeb = st.st_size / 100;
49         }
50                 
51 #ifdef BB_MORE_TERM
52         cin = fopen("/dev/tty", "r");
53         tcgetattr(fileno(cin),&initial_settings);
54         new_settings = initial_settings;
55         new_settings.c_lflag &= ~ICANON;
56         new_settings.c_lflag &= ~ECHO;
57         tcsetattr(fileno(cin), TCSANOW, &new_settings);
58         
59         (void) signal(SIGINT, gotsig);
60
61         ioctl(STDOUT_FILENO, TIOCGWINSZ, &win);
62         if (win.ws_row > 4)     rows = win.ws_row - 2;
63         if (win.ws_col > 0)     cols = win.ws_col - 1;
64
65
66 #endif
67
68         while ( (c = getc(f)) != EOF ) {
69                 if ( next_page ) {
70                         char    garbage;
71                         int     len;
72                         tlines += lines;
73                         lines = 0;
74                         next_page = 0;          //Percentage is based on bytes, not lines.
75                         if ( i && i->source )   //It is not very acurate, but still useful.
76                                 len = printf("%s - %%%2ld - line: %d", i->source, (ftell(f) - sizeb - sizeb) / sizeb, tlines);
77                         else
78                                 len = printf("line: %d", tlines);
79                                 
80                         fflush(stdout);
81 #ifndef BB_MORE_TERM            
82                         read(2, &garbage, 1);
83 #else                           
84                         do {
85                                 fread(&garbage, 1, 1, cin);     
86                         } while ((garbage != ' ') && (garbage != '\n'));
87                         
88                         if (garbage == '\n') {
89                                 lines = rows;
90                                 tlines -= rows;
91                         }                                       
92                         garbage = 0;                            
93                         //clear line, since tabs don't overwrite.
94                         while(len-- > 0)        putchar('\b');
95                         while(len++ < cols)     putchar(' ');
96                         while(len-- > 0)        putchar('\b');
97                         fflush(stdout);
98 #endif                                                          
99                 }
100                 putchar(c);
101                 if ( c == '\n' && ++lines == (rows + 1) )
102                         next_page = 1;
103         }
104         if ( f != stdin )
105                 fclose(f);
106 #ifdef BB_MORE_TERM
107         gotsig(0);
108 #endif  
109         return 0;
110 }