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