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