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

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

unix.superglobalmegacorp.com

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