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