|
|
1.1.1.2 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>
1.1.1.3 root 27: #include "system.h"
1.1.1.2 root 28: #endif
29: #ifdef sco
30: #include <sys/stream.h>
31: #include <sys/ptem.h>
1.1.1.3 root 32: FILE *popen();
1.1.1.2 root 33: #endif
34: #include "mpilib.h"
35: #include "language.h"
36: #include "fileio.h"
37: #include "pgp.h"
1.1.1.3 root 38: #include "more.h"
39: #include "charset.h"
1.1.1.2 root 40:
41: #ifdef MSDOS
1.1.1.4 ! root 42: #ifndef __GO32__
1.1.1.3 root 43: #include <conio.h>
1.1.1.4 ! root 44: #endif
1.1.1.2 root 45: #define DEFAULT_LINES 25 /* MSDOS actually has a 25-line screen */
46: #else
47: #define DEFAULT_LINES 24
48: #endif /* MSDOS */
49: #define DEFAULT_COLUMNS 80
50:
1.1.1.3 root 51: static int screen_lines = DEFAULT_LINES, screen_columns = DEFAULT_COLUMNS;
1.1.1.2 root 52:
53: #define TAB 0x09 /* ASCII tab char */
54: #define CR '\r' /* Carriage return char */
55: #define LF '\n' /* Linefeed */
56:
57: /* Get the screen size for 'more'. The environment variables $LINES and
58: $COLUMNS will be used if they exist. If not, then the TIOCGWINSZ call to
59: ioctl() is used (if it is defined). If not, then the TIOCGSIZE call to
60: ioctl() is used (if it is defined). If not, then the WIOCGETD call to
61: ioctl() is used (if it is defined). If not, then get the info from
62: terminfo/termcap (if it is there). Otherwise, assume we have a 24x80
63: model 33.
64:
65: That was for Unix.
66:
67: For DOS, just assume 24x80. */
68:
69: #ifdef UNIX
70: /* Try to access terminfo through the termcap-interface in the curses library
71: (which requires linking with -lcurses) or use termcap directly (which
72: requires linking with -ltermcap) */
73:
74: #ifndef USE_TERMCAP
75: #ifdef USE_TERMINFO
76: #define USE_TERMCAP
77: #endif
78: #ifdef USE_CURSES
79: #define USE_TERMCAP
80: #endif
81: #endif
82:
83: #ifdef USE_TERMCAP
84: #define TERMBUFSIZ 1024
85: #define UNKNOWN_TERM "unknown"
86: #define DUMB_TERMBUF "dumb:co#80:hc:"
87:
88: extern int tgetent(), tgetnum();
89: #endif
90:
91: /* Try to get TIOCGWINSZ from termios.h, then from sys/ioctl.h */
92: #ifndef NOTERMIO
93: #ifdef SVR2
94: #include <termio.h>
95: #else
96: #include <termios.h>
97: #endif /* SVR2 */
98: #endif
99:
100: #ifndef SVR2
101: #ifndef TIOCGWINSZ
102: #ifndef TIOCGSIZE
103: #ifndef WIOCGETD
104: #include <sys/ioctl.h>
105: #endif /* not WIOCGETD */
106: #endif /* not TIOCGSIZE */
107: #endif /* not TIOCGWINSZ */
108:
109: /* If we still dont have TIOCGWINSZ (or TIOCGSIZE) try for WIOCGETD */
110: #ifndef TIOCGWINSZ
111: #ifndef TIOCGSIZE
112: #ifndef WIOCGETD
113: #include <sgtty.h>
114: #endif /* not WIOCGETD */
115: #endif /* not TIOCGSIZE */
116: #endif /* not TIOCGWINSZ */
117: #endif /* not SVR2 */
118: #endif /* UNIX */
119:
120: static void getScreenSize(void) /* Rot bilong kargo */
121: /* Return the screen size */
122: {
123: char *envLines, *envColumns;
124: long rowTemp = 0, colTemp = 0;
125: #ifdef UNIX
126: #ifdef USE_TERMCAP
127: char termBuffer[TERMBUFSIZ], *termInfo;
128: #endif
129: #ifdef TIOCGWINSZ
130: struct winsize windowInfo;
131: #else
132: #ifdef TIOCGSIZE
133: struct ttysize windowInfo;
134: #else
135: #ifdef WIOCGETD
136: struct uwdata windowInfo;
137: #endif /* WIOCGETD */
138: #endif /* TIOCGSIZE */
139: #endif /* TIOCGWINSZ */
140:
141: /* Make sure that we're outputting to a terminal */
142: if (!isatty(fileno(stderr)))
143: {
144: screen_lines = DEFAULT_LINES;
145: screen_columns = DEFAULT_COLUMNS;
146: return;
147: }
148: screen_lines = screen_columns = 0;
149: #endif /* UNIX */
150:
151: /* LINES & COLUMNS environment variables override everything else */
152: envLines = getenv("LINES");
153: if (envLines != NULL && (rowTemp = atol(envLines)) > 0 )
154: screen_lines = (int)rowTemp;
155:
156: envColumns = getenv("COLUMNS");
157: if (envColumns != NULL && (colTemp = atol(envColumns)) > 0 )
158: screen_columns = (int)colTemp;
159:
160: #ifdef UNIX
161: #ifdef TIOCGWINSZ
162: /* See what ioctl() has to say (overrides terminfo & termcap) */
163: if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGWINSZ,&windowInfo) != -1)
164: { if (!screen_lines && windowInfo.ws_row > 0)
165: screen_lines = (int)windowInfo.ws_row;
166:
167: if (!screen_columns && windowInfo.ws_col > 0 )
168: screen_columns = (int)windowInfo.ws_col;
169: }
170: #else
171: #ifdef TIOCGSIZE
172: /* See what ioctl() has to say (overrides terminfo & termcap) */
173: if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGSIZE,&windowInfo) != -1)
174: { if (!screen_lines && windowInfo.ts_lines > 0)
175: screen_lines = (int)windowInfo.ts_lines;
176:
177: if (!screen_columns && windowInfo.ts_cols > 0)
178: screen_columns = (int)windowInfo.ts_cols;
179: }
180: #else
181: #ifdef WIOCGETD
182: /* See what ioctl() has to say (overrides terminfo & termcap) */
183: if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),WIOCGETD,&windowInfo) != -1)
184: { if (!screen_lines && windowInfo.uw_height > 0)
185: screen_lines = (int)(windowInfo.uw_height / windowInfo.uw_vs);
186:
187: if (!screen_columns && windowInfo.uw_width > 0)
188: screen_columns = (int)(windowInfo.uw_width / windowInfo.uw_hs);
189: } /* You are in a twisty maze of standards, all different */
190: #endif
191: #endif
192: #endif
193:
194: #ifdef USE_TERMCAP
195: /* See what terminfo/termcap has to say */
196: if (!screen_lines || !screen_columns)
197: { if ((termInfo = getenv("TERM")) == (char *)NULL)
198: termInfo = UNKNOWN_TERM;
199:
200: if ((tgetent(termBuffer, termInfo) <= 0))
201: strcpy(termBuffer,DUMB_TERMBUF);
202:
203: if (!screen_lines && (rowTemp = tgetnum("li")) > 0)
204: screen_lines = (int)rowTemp;
205:
206: if (!screen_columns && (colTemp = tgetnum("co")) > 0)
207: screen_columns = (int)colTemp;
208: }
209: #endif
210: if (screen_lines == 0) /* nothing worked, use defaults */
211: screen_lines = DEFAULT_LINES;
212: if (screen_columns == 0)
213: screen_columns = DEFAULT_COLUMNS;
214: #endif /* UNIX */
215: }
216:
217: /* Certain systems need to go into a "break" mode */
218: #ifdef UNIX
219: #define NEEDBREAK
220: #endif
221: #ifdef AMIGA
222: #define NEEDBREAK
223: #endif
224: #ifdef ATARI
225: #define reverse_attr() printf("\033p")
226: #define norm_attr() printf("\033q")
227: #else
228: #define reverse_attr()
229: #define norm_attr()
230: #endif
231:
232:
233: #ifdef VMS
234: char pager[80] = "Type/Page"; /* default pager for VMS */
235: #else /* not VMS */
236: char pager[80] = "";
237: #endif /* not VMS */
238:
239:
240: int more_file(char *fileName)
241: /* Blort a file to the screen with page breaks, intelligent handling of line
242: terminators, truncation of overly long lines, and zapping of illegal
243: chars */
244: {
245: FILE *inFile;
246: int lines = 0,ch,i,chars = 0, c;
247: long fileLen;
248: char cmd[MAX_PATH];
249: char buf[16];
250: int lineno;
251: char *p;
252:
253: if ((inFile = fopen(fileName,FOPRBIN)) == NULL)
254: /* Can't see how this could fail since we just created the file */
255: return(-1);
256:
257: fread(buf, 1, 16, inFile);
1.1.1.3 root 258: if (compressSignature( (byte *) buf) >= 0)
1.1.1.2 root 259: { fprintf(pgpout, PSTR("\n\007File '%s' is not a text file; cannot display.\n"),
260: fileName);
261: return(-1);
262: }
263:
264: /* PAGER set in config.txt overrides environment variable,
265: set PAGER in config.txt to 'pgp' to use builtin pager */
266: if (pager[0] == '\0')
267: {
268: if ((p = getenv("PAGER")) != NULL)
269: strncpy(pager, p, sizeof(pager) - 1);
270: }
1.1.1.3 root 271: if (strcmp(pager, "cat") == 0)
272: { fclose(inFile);
273: writePhantomOutput(fileName);
274: return 0;
275: }
276:
277: /* Use built-in pager if PAGER is not set or if this is for your eyes only,
278: this currently doesn't work, the _CONSOLE filename isn't used as the real
279: filename anymore */
1.1.1.2 root 280: if ((strcmp(fileName,CONSOLE_FILENAME) != 0)
281: && (strlen(pager) != 0) && strcmp("pgp", pager))
282: {
283: fclose(inFile);
284: #ifdef UNIX
285: if (strchr(fileName, '\'') != NULL)
286: return(-1);
287: sprintf(cmd, "%s '%s'", pager, fileName);
288: #else
289: sprintf(cmd, "%s %s", pager, fileName);
290: #ifdef MSDOS
291: for (p = cmd; *p; ++p)
292: if (*p == '/')
293: *p = '\\';
294: #endif
295: #endif
1.1.1.3 root 296: fflush(pgpout);
1.1.1.2 root 297: return(system(cmd));
298: }
299:
300: #ifdef UNIX
301: if (!isatty(fileno(stdout)))
302: { fclose(inFile);
303: writePhantomOutput(fileName);
304: return 0;
305: }
306: #endif /* UNIX */
307:
308: getScreenSize();
309:
310: /* Get file length */
311: fseek(inFile,0L,SEEK_END);
312: fileLen = ftell(inFile);
313: rewind(inFile);
314: lineno = 1;
315:
316: #ifdef NEEDBREAK
317: ttycbreak();
318: #endif
319: putchar('\n');
320: while (TRUE)
321: { ch = getc(inFile);
322: if (ch == LF)
323: { lines++;
324: putchar('\n');
325: chars = 0;
326: ++lineno;
327: }
328: else
329: if (ch == CR)
330: { lines++;
331: putchar('\n');
332: chars = 0;
333: ++lineno;
334:
335: /* Skip following LF if there is one */
336: if ((ch = getc(inFile)) != LF && ch != EOF)
337: ungetc(ch,inFile);
338: }
339: else
340: if (((unsigned char) ch >= ' ' && ch != EOF) || ch == TAB)
341: { /* Legal char or tab, print it */
342: putchar(ch);
343: chars += (ch == TAB) ? 8 : 1;
344: }
345:
346: /* If we've reach the max.no of columns we can handle, skip the
347: rest of the line */
348: if (chars == screen_columns - 1)
349: { chars = 0;
1.1.1.3 root 350: while ((ch = getc(inFile)) != CR && ch != LF && ch != EOF )
351: ;
1.1.1.2 root 352: if (ch != EOF)
353: ungetc(ch,inFile);
354: }
355:
356: /* If we've reached the max.no of rows we can handle, wait for the
357: user to hit a key */
358: while (ch == EOF || lines == screen_lines - 1)
359: { /* Print prompt at end of screen */
360: reverse_attr();
361: if (ch == EOF)
362: printf(PSTR("\nDone...hit any key\r"));
363: else
364: printf(PSTR("More -- %d%% -- Hit space for next screen, Enter for new line, 'Q' to quit --\r"),
365: ( 100 * ftell( inFile ) ) / fileLen );
366: norm_attr();
367: fflush(stdout);
368: c = getch();
369: c = to_upper(c);
370:
371: /* Blank out prompt */
372: for (i=0; i<79; i++)
373: putchar(' ');
374: putchar('\r');
375: fflush(stdout);
376: if (c == 'B' && lineno > screen_lines) /* go Back a page */
377: { int seek_line = lineno - 2*screen_lines + 3;
378: lineno = 1;
379: rewind(inFile);
380: if (seek_line > 1)
381: { printf("...skipping\n");
382: while ((ch = getc(inFile)) != EOF)
383: if (ch == '\n')
384: if (++lineno == seek_line)
385: break;
386: }
387: ch = '\0';
388: lines = 0;
389: }
390: else
391: { if (c == 'Q' || ch == EOF)
392: goto done;
393: if (c == ' ' || c == '\n' || c == '\r' || c == 'J')
394: lines -= (c == ' ') ? screen_lines - 2 : 1; /* Do n more lines */
395: }
396: }
397: }
398: done:
399: #ifdef NEEDBREAK
400: ttynorm();
401: #endif
402: fclose(inFile);
403: return(0);
404: } /* more_file */
405:
406:
407: /*
408: * open_more() and close_more() redirect pgpout to the pager.
409: *
410: */
411:
412: static char *mfile = NULL;
413: static boolean piping = FALSE;
414: static FILE *savepgpout;
415:
416:
417: int
1.1.1.3 root 418: open_more(void)
1.1.1.2 root 419: {
1.1.1.3 root 420: #ifdef UNIX
1.1.1.2 root 421: char *p;
1.1.1.3 root 422: #endif
1.1.1.2 root 423:
424: if (mfile || piping)
425: close_more();
426:
427: savepgpout = pgpout;
428: #ifdef UNIX
1.1.1.3 root 429: fflush(pgpout);
1.1.1.2 root 430: if (pager[0] == '\0')
431: {
432: if ((p = getenv("PAGER")) != NULL)
433: strncpy(pager, p, sizeof(pager) - 1);
434: }
435: /* Use built-in pager if PAGER is not set or set to "pgp" */
436: if ((strlen(pager) != 0) && strcmp("pgp", pager))
437: {
438: if ((pgpout = popen(pager, "w")) != NULL)
439: { piping = TRUE;
440: return 0;
441: }
442: perror("popen");
443: pgpout = savepgpout;
444: }
445: #endif
446: if ((mfile = tempfile(TMP_TMPDIR|TMP_WIPE)) == NULL)
447: return -1;
448: if ((pgpout = fopen(mfile, FOPWTXT)) == NULL)
449: {
450: pgpout = savepgpout;
451: rmtemp(mfile);
452: return -1;
453: }
454: /* user will not see anything until close_more() is called */
455: fprintf(savepgpout,PSTR("Just a moment..."));
456: fflush(savepgpout);
457: return 0;
458: }
459:
460: int
1.1.1.3 root 461: close_more(void)
1.1.1.2 root 462: {
463: if (!mfile && !piping)
464: return 0;
465:
466: #ifdef UNIX
467: if (piping)
468: pclose(pgpout);
469: else
470: #endif
471: fclose(pgpout);
472: pgpout = savepgpout;
473: if (mfile)
474: {
475: fprintf(pgpout,"\n");
476: more_file(mfile);
477: rmtemp(mfile);
478: mfile = NULL;
479: }
480: piping = FALSE;
481: return 0;
482: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.