home *** CD-ROM | disk | FTP | other *** search
/ RISC DISC 2 / RISC_DISC_2.iso / pd_share / utilities / cli / pgp2 / src / c / more < prev    next >
Encoding:
Text File  |  1994-08-01  |  11.7 KB  |  464 lines

  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)
  122. {                /* Rot bilong kargo */
  123.     /* Return the screen size */
  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) &&
  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.     }
  172. #else
  173. #ifdef TIOCGSIZE
  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.     }
  183. #else
  184. #ifdef WIOCGETD
  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 */
  195. #endif
  196. #endif
  197. #endif
  198.  
  199. #ifdef USE_TERMCAP
  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 */
  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 */
  233. #else                /* not VMS */
  234. char pager[80] = "";
  235. #endif                /* not VMS */
  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 */
  240. int more_file(char *fileName)
  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.     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);
  278. #ifdef UNIX
  279.     if (strchr(fileName, '\'') != NULL)
  280.         return -1;
  281.     sprintf(cmd, "%s '%s'", pager, fileName);
  282. #else
  283.     sprintf(cmd, "%s %s", pager, fileName);
  284. #ifdef MSDOS
  285.     for (p = cmd; *p; ++p)
  286.         if (*p == '/')
  287.         *p = '\\';
  288. #endif
  289. #endif
  290.     fflush(pgpout);
  291.     return system(cmd);
  292.     }
  293. #ifdef UNIX
  294.     if (!isatty(fileno(stdout))) {
  295.     fclose(inFile);
  296.     writePhantomOutput(fileName);
  297.     return 0;
  298.     }
  299. #endif                /* UNIX */
  300.  
  301.     getScreenSize();
  302.  
  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;
  374.         }
  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 */
  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 open_more(void)
  405. {
  406. #ifdef UNIX
  407.     char *p;
  408. #endif
  409.  
  410.     if (mfile || piping)
  411.     close_more();
  412.  
  413.     savepgpout = pgpout;
  414. #ifdef UNIX
  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;
  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.     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;
  441. }
  442.  
  443. int close_more(void)
  444. {
  445.     if (!mfile && !piping)
  446.     return 0;
  447.  
  448. #ifdef UNIX
  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;
  463. }
  464.