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