|
|
1.1.1.5 ! 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-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: */ ! 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 ! 49: #endif /* MSDOS */ ! 50: #define DEFAULT_COLUMNS 80 ! 51: ! 52: static int screen_lines = DEFAULT_LINES, screen_columns = DEFAULT_COLUMNS; ! 53: ! 54: #define TAB 0x09 /* ASCII tab char */ ! 55: #define CR '\r' /* Carriage return char */ ! 56: #define LF '\n' /* Linefeed */ ! 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: ! 89: extern int tgetent(), tgetnum(); ! 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> ! 98: #endif /* SVR2 */ ! 99: #endif ! 100: ! 101: #ifndef SVR2 ! 102: #ifndef TIOCGWINSZ ! 103: #ifndef TIOCGSIZE ! 104: #ifndef WIOCGETD ! 105: #include <sys/ioctl.h> ! 106: #endif /* not WIOCGETD */ ! 107: #endif /* not TIOCGSIZE */ ! 108: #endif /* not TIOCGWINSZ */ ! 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> ! 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) /* Rot bilong kargo */ ! 122: /* Return the screen size */ ! 123: { ! 124: char *envLines, *envColumns; ! 125: long rowTemp = 0, colTemp = 0; ! 126: #ifdef UNIX ! 127: #ifdef USE_TERMCAP ! 128: char termBuffer[TERMBUFSIZ], *termInfo; ! 129: #endif ! 130: #ifdef TIOCGWINSZ ! 131: struct winsize windowInfo; ! 132: #else ! 133: #ifdef TIOCGSIZE ! 134: struct ttysize windowInfo; ! 135: #else ! 136: #ifdef WIOCGETD ! 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; ! 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: { ! 165: if (!screen_lines && windowInfo.ws_row > 0) ! 166: screen_lines = (int)windowInfo.ws_row; ! 167: ! 168: if (!screen_columns && windowInfo.ws_col > 0 ) ! 169: screen_columns = (int)windowInfo.ws_col; ! 170: } ! 171: #else ! 172: #ifdef TIOCGSIZE ! 173: /* See what ioctl() has to say (overrides terminfo & termcap) */ ! 174: if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),TIOCGSIZE,&windowInfo) != -1) ! 175: { ! 176: if (!screen_lines && windowInfo.ts_lines > 0) ! 177: screen_lines = (int)windowInfo.ts_lines; ! 178: ! 179: if (!screen_columns && windowInfo.ts_cols > 0) ! 180: screen_columns = (int)windowInfo.ts_cols; ! 181: } ! 182: #else ! 183: #ifdef WIOCGETD ! 184: /* See what ioctl() has to say (overrides terminfo & termcap) */ ! 185: if ((!screen_lines || !screen_columns) && ioctl(fileno(stderr),WIOCGETD,&windowInfo) != -1) ! 186: { ! 187: if (!screen_lines && windowInfo.uw_height > 0) ! 188: screen_lines = (int)(windowInfo.uw_height / windowInfo.uw_vs); ! 189: ! 190: if (!screen_columns && windowInfo.uw_width > 0) ! 191: screen_columns = (int)(windowInfo.uw_width / windowInfo.uw_hs); ! 192: } /* You are in a twisty maze of standards, all different */ ! 193: #endif ! 194: #endif ! 195: #endif ! 196: ! 197: #ifdef USE_TERMCAP ! 198: /* See what terminfo/termcap has to say */ ! 199: if (!screen_lines || !screen_columns) ! 200: { ! 201: if ((termInfo = getenv("TERM")) == (char *)NULL) ! 202: termInfo = UNKNOWN_TERM; ! 203: ! 204: if ((tgetent(termBuffer, termInfo) <= 0)) ! 205: strcpy(termBuffer,DUMB_TERMBUF); ! 206: ! 207: if (!screen_lines && (rowTemp = tgetnum("li")) > 0) ! 208: screen_lines = (int)rowTemp; ! 209: ! 210: if (!screen_columns && (colTemp = tgetnum("co")) > 0) ! 211: screen_columns = (int)colTemp; ! 212: } ! 213: #endif ! 214: if (screen_lines == 0) /* nothing worked, use defaults */ ! 215: screen_lines = DEFAULT_LINES; ! 216: if (screen_columns == 0) ! 217: screen_columns = DEFAULT_COLUMNS; ! 218: #endif /* UNIX */ ! 219: } ! 220: ! 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( (byte *) buf) >= 0) ! 256: { ! 257: fprintf(pgpout, LANG("\n\007File '%s' is not a text file; cannot display.\n"), ! 258: fileName); ! 259: return -1; ! 260: } ! 261: ! 262: /* PAGER set in config.txt overrides environment variable, ! 263: set PAGER in config.txt to 'pgp' to use builtin pager */ ! 264: if (pager[0] == '\0') { ! 265: if ((p = getenv("PAGER")) != NULL) ! 266: strncpy(pager, p, sizeof(pager) - 1); ! 267: } ! 268: if (strcmp(pager, "cat") == 0) { ! 269: fclose(inFile); ! 270: writePhantomOutput(fileName); ! 271: return 0; ! 272: } ! 273: ! 274: /* Use built-in pager if PAGER is not set or if this is for your eyes only, ! 275: this currently doesn't work, the _CONSOLE filename isn't used as the real ! 276: filename anymore */ ! 277: if ((strcmp(fileName,CONSOLE_FILENAME) != 0) ! 278: && (strlen(pager) != 0) && strcmp("pgp", pager)) ! 279: { ! 280: fclose(inFile); ! 281: #ifdef UNIX ! 282: if (strchr(fileName, '\'') != NULL) ! 283: return -1; ! 284: sprintf(cmd, "%s '%s'", pager, fileName); ! 285: #else ! 286: sprintf(cmd, "%s %s", pager, fileName); ! 287: #ifdef MSDOS ! 288: for (p = cmd; *p; ++p) ! 289: if (*p == '/') ! 290: *p = '\\'; ! 291: #endif ! 292: #endif ! 293: fflush(pgpout); ! 294: return system(cmd); ! 295: } ! 296: ! 297: #ifdef UNIX ! 298: if (!isatty(fileno(stdout))) { ! 299: fclose(inFile); ! 300: writePhantomOutput(fileName); ! 301: return 0; ! 302: } ! 303: #endif /* UNIX */ ! 304: ! 305: getScreenSize(); ! 306: ! 307: /* Get file length */ ! 308: fseek(inFile,0L,SEEK_END); ! 309: fileLen = ftell(inFile); ! 310: rewind(inFile); ! 311: lineno = 1; ! 312: ! 313: ttycbreak(); ! 314: ! 315: putchar('\n'); ! 316: for (;;) { ! 317: ch = getc(inFile); ! 318: if (ch == LF) { ! 319: lines++; ! 320: putchar('\n'); ! 321: chars = 0; ! 322: ++lineno; ! 323: } else if (ch == CR) { ! 324: lines++; ! 325: putchar('\n'); ! 326: chars = 0; ! 327: ++lineno; ! 328: ! 329: /* Skip following LF if there is one */ ! 330: if ((ch = getc(inFile)) != LF && ch != EOF) ! 331: ungetc(ch,inFile); ! 332: } else if (((unsigned char) ch >= ' ' && ch != EOF) || ch == TAB) ! 333: { ! 334: /* Legal char or tab, print it */ ! 335: putchar(ch); ! 336: chars += (ch == TAB) ? 8 : 1; ! 337: } ! 338: ! 339: /* If we've reach the max.no of columns we can handle, skip the ! 340: rest of the line */ ! 341: if (chars == screen_columns - 1) { ! 342: chars = 0; ! 343: while ((ch = getc(inFile)) != CR && ch != LF && ch != EOF ) ! 344: ; ! 345: if (ch != EOF) ! 346: ungetc(ch,inFile); ! 347: } ! 348: ! 349: /* If we've reached the max.no of rows we can handle, wait for the ! 350: user to hit a key */ ! 351: while (ch == EOF || lines == screen_lines - 1) { ! 352: /* Print prompt at end of screen */ ! 353: reverse_attr(); ! 354: if (ch == EOF) ! 355: printf(LANG("\nDone...hit any key\r")); ! 356: else ! 357: printf(LANG("More -- %d%% -- Hit space for next screen, Enter for new line, 'Q' to quit --\r"), ! 358: ( 100 * ftell( inFile ) ) / fileLen ); ! 359: norm_attr(); ! 360: fflush(stdout); ! 361: c = getch(); ! 362: c = to_upper(c); ! 363: ! 364: /* Blank out prompt */ ! 365: for (i=0; i<79; i++) ! 366: putchar(' '); ! 367: putchar('\r'); ! 368: fflush(stdout); ! 369: if (c == 'B' && lineno > screen_lines) { ! 370: /* go Back a page */ ! 371: int seek_line = lineno - 2*screen_lines + 3; ! 372: lineno = 1; ! 373: rewind(inFile); ! 374: if (seek_line > 1) { ! 375: printf("...skipping\n"); ! 376: while ((ch = getc(inFile)) != EOF) ! 377: if (ch == '\n') ! 378: if (++lineno == seek_line) ! 379: break; ! 380: } ! 381: ch = '\0'; ! 382: lines = 0; ! 383: } else { ! 384: if (c == 'Q' || ch == EOF) ! 385: goto done; ! 386: if (c == ' ' || c == '\n' || c == '\r' || c == 'J') ! 387: lines -= (c == ' ') ? screen_lines - 2 : 1; /* Do n more lines */ ! 388: } ! 389: } ! 390: } ! 391: done: ! 392: ttynorm(); ! 393: ! 394: fclose(inFile); ! 395: return 0; ! 396: } /* more_file */ ! 397: ! 398: ! 399: /* ! 400: * open_more() and close_more() redirect pgpout to the pager. ! 401: * ! 402: */ ! 403: ! 404: static char *mfile = NULL; ! 405: static boolean piping = FALSE; ! 406: static FILE *savepgpout; ! 407: ! 408: ! 409: int ! 410: open_more(void) ! 411: { ! 412: #ifdef UNIX ! 413: char *p; ! 414: #endif ! 415: ! 416: if (mfile || piping) ! 417: close_more(); ! 418: ! 419: savepgpout = pgpout; ! 420: #ifdef UNIX ! 421: fflush(pgpout); ! 422: if (pager[0] == '\0') { ! 423: if ((p = getenv("PAGER")) != NULL) ! 424: strncpy(pager, p, sizeof(pager) - 1); ! 425: } ! 426: /* Use built-in pager if PAGER is not set or set to "pgp" */ ! 427: if ((strlen(pager) != 0) && strcmp("pgp", pager)) { ! 428: if ((pgpout = popen(pager, "w")) != NULL) { ! 429: piping = TRUE; ! 430: return 0; ! 431: } ! 432: perror("popen"); ! 433: pgpout = savepgpout; ! 434: } ! 435: #endif ! 436: if ((mfile = tempfile(TMP_TMPDIR|TMP_WIPE)) == NULL) ! 437: return -1; ! 438: if ((pgpout = fopen(mfile, FOPWTXT)) == NULL) { ! 439: pgpout = savepgpout; ! 440: rmtemp(mfile); ! 441: return -1; ! 442: } ! 443: /* user will not see anything until close_more() is called */ ! 444: fprintf(savepgpout,LANG("Just a moment...")); ! 445: fflush(savepgpout); ! 446: return 0; ! 447: } ! 448: ! 449: int ! 450: close_more(void) ! 451: { ! 452: if (!mfile && !piping) ! 453: return 0; ! 454: ! 455: #ifdef UNIX ! 456: if (piping) ! 457: pclose(pgpout); ! 458: else ! 459: #endif ! 460: fclose(pgpout); ! 461: pgpout = savepgpout; ! 462: if (mfile) ! 463: { ! 464: fprintf(pgpout,"\n"); ! 465: more_file(mfile); ! 466: rmtemp(mfile); ! 467: mfile = NULL; ! 468: } ! 469: piping = FALSE; ! 470: return 0; ! 471: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.