Annotation of pgp/src/more.c, revision 1.1.1.7

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.