--- man-db-2.3.10/src/man.c     Sat Dec 19 02:24:03 1998
+++ man-db-hacked/src/man.c     Sat Dec 19 02:30:09 1998
@@ -1135,13 +1135,102 @@
        return pp_string;
 }

+/* This is so that we can store the temp file name used when input is
+ * stdin and remove it on exit.
+ */
+static char *stdin_tmpfile;
+static int stdin_tmpfile_fd;
+
+static void remove_stdintmp(void)
+{
+        if (stdin_tmpfile) {
+                if (stdin_tmpfile_fd >= 0)
+                        close(stdin_tmpfile_fd);
+                (void) remove_with_dropped_privs(stdin_tmpfile);
+        }
+        stdin_tmpfile = NULL;
+}
+
+static __inline__ void create_stdintmp(void)
+{
+        /* This is basically copied from create_ztemp() in compression.c;
+         * it therefore shouldn't introduce any new security holes -- PMM
+         */
+        int oldmask = umask(022);
+        drop_effective_privs();
+        errno = 0;                                /* failing tempname() might fail to set errno */
+        stdin_tmpfile = tempnam(NULL, "sman");
+        if (stdin_tmpfile)
+                stdin_tmpfile_fd = open(stdin_tmpfile, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL, 0644);
+        if (!stdin_tmpfile || (stdin_tmpfile_fd < 0))
+                error (FATAL, errno, _( "can't crete a temporary filename"));
+        regain_effective_privs();
+        umask(oldmask);
+        atexit( remove_stdintmp);
+}

 /* Return command (malloced string) to format file to stdout */
 static __inline__ char *make_roff_command (char *dir, char *file)
 {
-       char *pp_string = get_preprocessors (file);
+       char *pp_string;
        char *fmt_prog;
        char *command;
+        char *tmpfile;
+
+        if (!*file) {
+                /* file == "": this means we are reading input from stdin.
+                 * Unfortunately we need to read the first line or so to
+                 * determine the preprocessor filename. So we read a bit
+                 * into a temporary file which we give to get_preprocessors
+                 * and then prepend to the rest of stdin by putting cat
+                 * in the beginning of the pipeline we pass to system().
+                 * I can't think of a better way to do this :-<
+                 * [this code seems remarkably hairy for what it does...]
+                 */
+                /* get_preprocessors uses 128 byte buffer, no point using more here */
+#define STDIN_SNARFLEN 128
+                char bf[STDIN_SNARFLEN];
+                int ct = 0;                       /* number of bytes in bf[] */
+                int ctot, r;
+                /* Ignore SIGPIPE; we want to be notified by write returning EPIPE. */
+                RETSIGTYPE (*old_handler)() = signal(SIGPIPE, SIG_IGN);
+
+                /* read data into bf; we don't want to use the stream stuff because
+                 * we don't want data to be lost in the buffers, not read here or
+                 * by the system()-run pipeline.
+                 */
+                do {
+                        errno = 0;
+                        r = read(STDIN_FILENO, bf+ct, (128-ct));
+                        if (r != -1)
+                                ct += r;
+                        /* stop on EOF (r==0), bf full (ct==128) or error (errno not 0 or EINTR) */
+                } while (r != 0 && ct < STDIN_SNARFLEN && (errno == 0 || errno == EINTR));
+
+                if (errno != 0)
+                        error(FATAL, errno, _( "error trying to read from stdin"));
+
+                create_stdintmp();
+                /* write bf to stdin_tmpfile_fd */
+                ctot = ct;
+                do {
+                        errno = 0;
+                        r = write(stdin_tmpfile_fd, bf+(ctot-ct), ct);
+                        if (r != -1)
+                                ct -= r;
+                } while (ct > 0 && (errno == 0 || errno == EINTR));
+                if (errno != 0)
+                        error(FATAL, errno, _( "error writing to temporary file %s"), stdin_tmpfile);
+
+                close(stdin_tmpfile_fd);
+                stdin_tmpfile_fd = -1;            /* ensure we don't try to close it again */
+                signal(SIGPIPE, old_handler);
+
+                pp_string = get_preprocessors(stdin_tmpfile);
+        }
+        else
+                pp_string = get_preprocessors(file);
+

 #ifdef ALT_EXT_FORMAT
        /* Check both external formatter locations */
@@ -1201,9 +1290,15 @@
                if (*file)
                        command = strappend (NULL, SOELIM " '",
                                             file, "'", NULL);
-               else
-                       command = xstrdup (SOELIM);
-
+               else {
+                        /* Reading from stdin: use cat to pick up the part we
+                         * read in to figure out the format pipeline.
+                         * ? is '-' as a cat argument standard?
+                         * If not we could try "(cat tempfile; cat) | SOELIM..."
+                         */
+                        command = strappend(NULL, "cat ", stdin_tmpfile, " - | ", SOELIM, NULL);
+                }
+
                do {
                        char *filter;
                        int wants_dev = 0; /* filter wants a dev argument */
@@ -1591,6 +1686,8 @@
  * optionally chdir to dir, if necessary update cat_file from man_file
  * and display it.  if man_file is NULL cat_file is a stray cat.  If
  * !save_cat or cat_file is NULL we must not save the formatted cat.
+ * If man_file is "" this is a special case -- we expect the man page
+ * on standard input.
  */
 static int display (char *dir, char *man_file, char *cat_file, char *title)
 {
@@ -1697,7 +1794,15 @@
                        free (cat_dir);
                }

-               found = !access (format ? man_file : cat_file, R_OK);
+                /* if we're trying to read stdin via '-l -' then man_file will be ""
+                 * which access() obviously barfs on, but all is well because the
+                 * roff_cmd will have been created to expect input via stdin.
+                 * So we special-case this to avoid the bogus access() check.
+                 */
+                if (format == 1 && *man_file == '\0')
+                   found = 1;
+                else
+                   found = !access (format ? man_file : cat_file, R_OK);

                if (debug)
                        fprintf(stderr, "format: %d, save_cat: %d, found: %d\n",
