|
|
1.1 root 1: /* more.c - Unix-style "more" paging output for PGP.
2: PGP: Pretty Good(tm) Privacy - public key cryptography for the masses.
3:
4: (c) Copyright 1990-1992 by Philip Zimmermann. All rights reserved.
5: The author assumes no liability for damages resulting from the use
6: of this software, even if the damage results from defects in this
7: software. No warranty is expressed or implied.
8:
9: All the source code Philip Zimmermann wrote for PGP is available for
10: free under the "Copyleft" General Public License from the Free
11: Software Foundation. A copy of that license agreement is included in
12: the source release package of PGP. Code developed by others for PGP
13: is also freely available. Other code that has been incorporated into
14: PGP from other sources was either originally published in the public
15: domain or was used with permission from the various authors. See the
16: PGP User's Guide for more complete information about licensing,
17: patent restrictions on certain algorithms, trademarks, copyrights,
18: and export controls.
19: */
20:
21: #include <ctype.h>
22: #include <stdio.h>
23: #include <stdlib.h>
24: #include <string.h>
25: #ifdef UNIX
26: #include <sys/types.h>
27: #endif
28: #include "mpilib.h"
29: #include "language.h"
30: #include "fileio.h"
31: #include "pgp.h"
32:
33: /* Prototype for getch() */
34:
35: int getch( void );
36:
37: #ifdef MSDOS
38: #define DEFAULT_LINES 25 /* MSDOS actually has a 25-line screen */
39: #else
40: #define DEFAULT_LINES 24
41: #endif /* MSDOS */
42: #define DEFAULT_COLUMNS 80
43:
44: int screen_lines = DEFAULT_LINES, screen_columns = DEFAULT_COLUMNS;
45:
46: #define TAB 0x09 /* ASCII tab char */
47: #define CR '\r' /* Carriage return char */
48: #define LF '\n' /* Linefeed */
49:
50: /* Get the screen size for 'more'. The environment variables $LINES and
51: $COLUMNS will be used if they exist. If not, then the TIOCGWINSZ call to
52: ioctl() is used (if it is defined). If not, then the TIOCGSIZE call to
53: ioctl() is used (if it is defined). If not, then the WIOCGETD call to
54: ioctl() is used (if it is defined). If not, then get the info from
55: terminfo/termcap (if it is there). Otherwise, assume we have a 24x80
56: model 33.
57:
58: That was for Unix.
59:
60: For DOS, just assume 24x80. */
61:
62: #ifdef UNIX
63: /* Try to access terminfo through the termcap-interface in the curses library
64: (which requires linking with -lcurses) or use termcap directly (which
65: requires linking with -ltermcap) */
66:
67: #ifndef USE_TERMCAP
68: #ifdef USE_TERMINFO
69: #define USE_TERMCAP
70: #endif
71: #ifdef USE_CURSES
72: #define USE_TERMCAP
73: #endif
74: #endif
75:
76: #ifdef USE_TERMCAP
77: #define TERMBUFSIZ 1024
78: #define UNKNOWN_TERM "unknown"
79: #define DUMB_TERMBUF "dumb:co#80:hc:"
80:
81: extern int tgetent(), tgetnum();
82: #endif
83:
84: /* Try to get TIOCGWINSZ from termios.h, then from sys/ioctl.h */
85: #ifndef NOTERMIO
86: #ifndef M_XENIX
87: #include <termios.h>
88: #else
89: #include <termio.h>
90: #endif /* not M_XENIX */
91: #endif
92:
93: #ifndef M_XENIX
94: #ifndef TIOCGWINSZ
95: #ifndef TIOCGSIZE
96: #ifndef WIOCGETD
97: #include <sys/ioctl.h>
98: #endif /* not WIOCGETD */
99: #endif /* not TIOCGSIZE */
100: #endif /* not TIOCGWINSZ */
101:
102: /* If we still dont have TIOCGWINSZ (or TIOCGSIZE) try for WIOCGETD */
103: #ifndef TIOCGWINSZ
104: #ifndef TIOCGSIZE
105: #ifndef WIOCGETD
106: #include <sgtty.h>
107: #endif /* not WIOCGETD */
108: #endif /* not TIOCGSIZE */
109: #endif /* not TIOCGWINSZ */
110: #endif /* not M_XENIX */
111:
112: static void getScreenSize(void) /* Rot bilong kargo */
113: /* Return the screen size */
114: {
115: char *envLines, *envColumns;
116: long rowTemp = 0, colTemp = 0;
117: #ifdef USE_TERMCAP
118: char termBuffer[TERMBUFSIZ], *termInfo;
119: #endif
120: #ifdef TIOCGWINSZ
121: struct winsize windowInfo;
122: #else
123: #ifdef TIOCGSIZE
124: struct ttysize windowInfo;
125: #else
126: #ifdef WIOCGETD
127: struct uwdata windowInfo;
128: #endif /* WIOCGETD */
129: #endif /* TIOCGSIZE */
130: #endif /* TIOCGWINSZ */
131:
132: /* Make sure that we're outputting to a terminal */
133: if (!isatty(fileno(stderr)))
134: {
135: screen_lines = DEFAULT_LINES;
136: screen_columns = DEFAULT_COLUMNS;
137: return;
138: }
139: screen_lines = screen_columns = 0;
140:
141: /* LINES & COLUMNS environment variables override everything else */
142: envLines = getenv("LINES");
143: if (envLines != NULL && (rowTemp = atol(envLines)) > 0 )
144: screen_lines = (int)rowTemp;
145:
146: envColumns = getenv("COLUMNS");
147: if (envColumns != NULL && (colTemp = atol(envColumns)) > 0 )
148: screen_columns = (int)colTemp;
149:
150: #ifdef TIOCGWINSZ
151: /* See what ioctl() has to say (overrides terminfo & termcap) */
152: if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGWINSZ,&windowInfo) != -1)
153: { if (!screen_lines && windowInfo.ws_row > 0)
154: screen_lines = (int)windowInfo.ws_row;
155:
156: if (!screen_columns && windowInfo.ws_col > 0 )
157: screen_columns = (int)windowInfo.ws_col;
158: }
159: #else
160: #ifdef TIOCGSIZE
161: /* See what ioctl() has to say (overrides terminfo & termcap) */
162: if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGSIZE,&windowInfo) != -1)
163: { if (!screen_lines && windowInfo.ts_lines > 0)
164: screen_lines = (int)windowInfo.ts_lines;
165:
166: if (!screen_columns && windowInfo.ts_cols > 0)
167: screen_columns = (int)windowInfo.ts_cols;
168: }
169: #else
170: #ifdef WIOCGETD
171: /* See what ioctl() has to say (overrides terminfo & termcap) */
172: if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),WIOCGETD,&windowInfo) != -1)
173: { if (!screen_lines && windowInfo.uw_height > 0)
174: screen_lines = (int)(windowInfo.uw_height / windowInfo.uw_vs);
175:
176: if (!screen_columns && windowInfo.uw_width > 0)
177: screen_columns = (int)(windowInfo.uw_width / windowInfo.uw_hs);
178: } /* You are in a twisty maze of standards, all different */
179: #endif
180: #endif
181: #endif
182:
183: #ifdef USE_TERMCAP
184: /* See what terminfo/termcap has to say */
185: if (!screen_lines || !screen_columns)
186: { if ((termInfo = getenv("TERM")) == (char *)NULL)
187: termInfo = UNKNOWN_TERM;
188:
189: if ((tgetent(termBuffer, termInfo) <= 0))
190: strcpy(termBuffer,DUMB_TERMBUF);
191:
192: if (!screen_lines && (rowTemp = tgetnum("li")) > 0)
193: screen_lines = (int)rowTemp;
194:
195: if (!screen_columns && (colTemp = tgetnum("co")) > 0)
196: screen_columns = (int)colTemp;
197: }
198: #endif
199: if (screen_lines == 0) /* nothing worked, use defaults */
200: screen_lines = DEFAULT_LINES;
201: if (screen_columns == 0)
202: screen_columns = DEFAULT_COLUMNS;
203: }
204: #else
205: #define getScreenSize()
206: #endif /* UNIX */
207:
208: /* Certain systems need to go into a "break" mode */
209: #ifdef UNIX
210: #define NEEDBREAK
211: #endif
212: #ifdef AMIGA
213: #define NEEDBREAK
214: #endif
215: #ifdef ATARI
216: #define reverse_attr() printf("\033p")
217: #define norm_attr() printf("\033q")
218: #else
219: #define reverse_attr()
220: #define norm_attr()
221: #endif
222:
223: char pager[80] = "";
224:
225: int more_file(char *fileName)
226: /* Blort a file to the screen with page breaks, intelligent handling of line
227: terminators, truncation of overly long lines, and zapping of illegal
228: chars */
229: {
230: FILE *inFile;
231: int lines = 0,ch,i,chars = 0, c;
232: long fileLen;
233: char cmd[MAX_PATH];
234: char buf[16];
235: int lineno;
236: char *p;
237:
238: if ((inFile = fopen(fileName,"rb")) == NULL)
239: /* Can't see how this could fail since we just created the file */
240: return(-1);
241:
242: fread(buf, 1, 16, inFile);
243: if (compressSignature(buf) >= 0)
244: { fprintf(pgpout, PSTR("\n\007File '%s' is not a text file; cannot display.\n"),
245: fileName);
246: return(-1);
247: }
248:
249: /* PAGER set in config.txt overrides environment variable,
250: set PAGER in config.txt to 'pgp' to use builtin pager */
251: if (pager[0] == '\0')
252: {
253: if ((p = getenv("PAGER")) != NULL)
254: strncpy(pager, p, sizeof(pager) - 1);
255: }
256: /* Use built-in pager if PAGER is not set or if this is for your eyes only */
257: if ((strcmp(fileName,CONSOLE_FILENAME) != 0)
258: && (strlen(pager) != 0) && strcmp("pgp", pager))
259: {
260: fclose(inFile);
261: #ifdef UNIX
262: if (strchr(fileName, '\'') != NULL)
263: return(-1);
264: sprintf(cmd, "%s '%s'", pager, fileName);
265: #else
266: sprintf(cmd, "%s %s", pager, fileName);
267: #ifdef MSDOS
268: for (p = cmd; *p; ++p)
269: if (*p == '/')
270: *p = '\\';
271: #endif
272: #endif
273: return(system(cmd));
274: }
275:
276: getScreenSize();
277:
278: /* Get file length */
279: fseek(inFile,0L,SEEK_END);
280: fileLen = ftell(inFile);
281: rewind(inFile);
282: lineno = 1;
283:
284: #ifdef NEEDBREAK
285: ttycbreak();
286: #endif
287: putchar('\n');
288: while (TRUE)
289: { ch = getc(inFile);
290: if (ch == LF)
291: { lines++;
292: putchar('\n');
293: chars = 0;
294: ++lineno;
295: }
296: else
297: if (ch == CR)
298: { lines++;
299: putchar('\n');
300: chars = 0;
301: ++lineno;
302:
303: /* Skip following LF if there is one */
304: if ((ch = getc(inFile)) != LF && ch != EOF)
305: ungetc(ch,inFile);
306: }
307: else
308: if (((unsigned char) ch >= ' ' && ch != EOF) || ch == TAB)
309: { /* Legal char or tab, print it */
310: putchar(ch);
311: chars += (ch == TAB) ? 8 : 1;
312: }
313:
314: /* If we've reach the max.no of columns we can handle, skip the
315: rest of the line */
316: if (chars == screen_columns - 1)
317: { chars = 0;
318: while ((ch = getc(inFile)) != CR && ch != LF && ch != EOF );
319: if (ch != EOF)
320: ungetc(ch,inFile);
321: }
322:
323: /* If we've reached the max.no of rows we can handle, wait for the
324: user to hit a key */
325: while (ch == EOF || lines == screen_lines - 1)
326: { /* Print prompt at end of screen */
327: reverse_attr();
328: if (ch == EOF)
329: printf(PSTR("\nDone...hit any key\r"));
330: else
331: printf(PSTR("More -- %d%% -- Hit space for next screen, Enter for new line, 'Q' to quit --\r"),
332: ( 100 * ftell( inFile ) ) / fileLen );
333: norm_attr();
334: fflush(stdout);
335: c = getch();
336: c = toupper(c);
337:
338: /* Blank out prompt */
339: for (i=0; i<79; i++)
340: putchar(' ');
341: putchar('\r');
342: fflush(stdout);
343: if (c == 'B' && lineno > screen_lines) /* go Back a page */
344: { int seek_line = lineno - 2*screen_lines + 3;
345: lineno = 1;
346: rewind(inFile);
347: if (seek_line > 1)
348: { printf("...skipping\n");
349: while ((ch = getc(inFile)) != EOF)
350: if (ch == '\n')
351: if (++lineno == seek_line)
352: break;
353: }
354: ch = '\0';
355: lines = 0;
356: }
357: else
358: { if (c == 'Q' || ch == EOF)
359: goto done;
360: if (c == ' ' || c == '\n' || c == '\r' || c == 'J')
361: lines -= (c == ' ') ? screen_lines - 2 : 1; /* Do n more lines */
362: }
363: }
364: }
365: done:
366: #ifdef NEEDBREAK
367: ttynorm();
368: #endif
369: fclose(inFile);
370: return(0);
371: } /* more_file */
372:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.