--- config.h.in +++ config.h.in 2007-12-07 15:50:23.000000000 +0100 @@ -454,6 +454,9 @@ /* Define to 1 if you have the `z' library (-lz). */ #undef HAVE_LIBZ +/* Define to 1 if you have libzio for opening compressed manuals */ +#undef HAVE_ZIO + /* Define to 1 if you have the header file. */ #undef HAVE_LIMITS_H --- configure.ac +++ configure.ac 2008-04-21 13:18:38.854059561 +0200 @@ -94,7 +94,18 @@ AC_ARG_WITH(sections, sections="$withval" fi], [: ${sections=1 n l 8 3 2 5 4 9 6 7}]) - +AC_ARG_WITH(zio, +[AS_HELP_STRING([--with-zio=LIBRARY], [use zlib/libbz2 wrapper library LIBRARY (libzio)])], + [if test -z "$withval" -o "$withval" = "yes" + then + zio=libzio + elif test "$withval" = "no" + then + AC_MSG_ERROR(--with-zio requires an argument) + else + zio=$withval + fi], + : ${zio=no}) # Finish the argument parsing. AC_SUBST(man_owner)dnl AC_SUBST(man_mode)dnl @@ -294,6 +305,29 @@ AC_SUBST(gunzip) AC_SUBST(uncompress) AC_SUBST(bunzip2) MAN_COMPRESS_LIB([z], [gzopen]) +dnl Check for zlib and libbz2 libraries to use this together +dnl with SuSE's libzio to open compressed info files. +dnl +if test "$zio" = "no" || test -n "$zio" +then + AC_CHECK_HEADER(zio.h,[ + for lib in ${zio#lib} zio + do + AC_CHECK_LIB($lib, fzopen, [LIBS="-l$lib $LIBS" + AC_DEFINE([COMP_SRC],[],[Define if you have compressors and want to support compressed cat files.]) + AC_DEFINE([HAVE_ZIO],[],[Define to 1 if you have libzio for opening compressed manuals])]) + done]) + AC_CHECK_HEADER(zlib.h,[ + for lib in z gz + do + AC_CHECK_LIB($lib, gzopen, [LIBS="$LIBS -Wl,--no-as-needed -l$lib" ; break]) + done]) + AC_CHECK_HEADER(bzlib.h,[ + for lib in bz2 bzip2 + do + AC_CHECK_LIB($lib, BZ2_bzopen, [LIBS="$LIBS -Wl,--no-as-needed -l$lib" ; break]) + done]) +fi dnl To add more decompressors just follow the scheme above. # Work out which manual page hierarchy scheme might be in use. --- lib/decompress.c +++ lib/decompress.c 2008-04-23 10:48:04.431353342 +0000 @@ -36,6 +36,10 @@ # include "zlib.h" #endif /* HAVE_LIBZ */ +#ifdef HAVE_ZIO +# include "zio.h" +#endif /* HAVE_ZIO */ + #include "manconfig.h" #include "comp_src.h" #include "pipeline.h" @@ -66,6 +70,32 @@ static void decompress_zlib (void *data #endif /* HAVE_LIBZ */ +#ifdef HAVE_ZIO + +static void decompress_zio (void *data) +{ + const char *what = (const char*)data; + FILE *file; + + file = fdzopen(dup (fileno (stdin)), "r", what); + if (!file) + return; + + for (;;) { + char buffer[4096]; + int r = fread(buffer, sizeof(char), sizeof(buffer), file); + if (r <= 0) + break; + if (fwrite (buffer, 1, (size_t) r, stdout) < (size_t) r) + break; + } + + fclose(file); + return; +} + +#endif /* HAVE_ZIO */ + pipeline *decompress_open (const char *filename) { command *cmd; @@ -77,9 +107,53 @@ pipeline *decompress_open (const char *f char *ext; struct compression *comp; - if (stat (filename, &st) < 0 && !S_ISDIR (st.st_mode)) + if (stat (filename, &st) < 0 || S_ISDIR (st.st_mode)) return NULL; +#ifdef HAVE_ZIO + ext = strrchr(filename, '.'); + if (ext && STREQ (ext, ".gz")) { + /* informational only; no shell quoting concerns */ + char *name = appendstr (NULL, "zcat < ", filename, NULL); + cmd = command_new_function (name, &decompress_zio, "g"); + free (name); + p = pipeline_new_commands (cmd, NULL); + if (strcmp(program_name, "mandb") == 0) + p->libzio = 1; + goto got_pipeline; + } + if (ext && STREQ (ext, ".z")) { + /* informational only; no shell quoting concerns */ + char *name = appendstr (NULL, "zcat < ", filename, NULL); + cmd = command_new_function (name, &decompress_zio, "z"); + free (name); + p = pipeline_new_commands (cmd, NULL); + if (strcmp(program_name, "mandb") == 0) + p->libzio = 1; + goto got_pipeline; + } + if (ext && STREQ (ext, ".bz2")) { + /* informational only; no shell quoting concerns */ + char *name = appendstr (NULL, "bzcat < ", filename, NULL); + cmd = command_new_function (name, &decompress_zio, "b"); + free (name); + p = pipeline_new_commands (cmd, NULL); + if (strcmp(program_name, "mandb") == 0) + p->libzio = 1; + goto got_pipeline; + } + if (ext && STREQ (ext, ".Z")) { + /* informational only; no shell quoting concerns */ + char *name = appendstr (NULL, "zcat < ", filename, NULL); + cmd = command_new_function (name, &decompress_zio, "Z"); + free (name); + p = pipeline_new_commands (cmd, NULL); + if (strcmp(program_name, "mandb") == 0) + p->libzio = 1; + goto got_pipeline; + } +#endif /* HAVE_ZIO */ + #ifdef HAVE_LIBZ filename_len = strlen (filename); if (filename_len > 3 && STREQ (filename + filename_len - 3, ".gz")) { --- lib/pipeline.c +++ lib/pipeline.c 2008-04-23 10:52:16.655715088 +0000 @@ -50,6 +50,10 @@ #include "error.h" #include "pipeline.h" +#ifdef HAVE_ZIO +# include "zio.h" +#endif /* HAVE_ZIO */ + /* ---------------------------------------------------------------------- */ /* Functions to build individual commands. */ @@ -441,6 +445,9 @@ pipeline *pipeline_new (void) p->commands = xnmalloc (p->commands_max, sizeof *p->commands); p->pids = NULL; p->statuses = NULL; +#ifdef HAVE_ZIO + p->libzio = 0; +#endif p->want_in = p->want_out = 0; p->want_infile = p->want_outfile = NULL; p->infd = p->outfd = -1; @@ -479,6 +486,9 @@ pipeline *pipeline_join (pipeline *p1, p pipeline *p = XMALLOC (pipeline); int i; +#ifdef HAVE_ZIO + assert (p->libzio); +#endif assert (!p1->pids); assert (!p2->pids); assert (!p1->statuses); @@ -614,6 +624,9 @@ void pipeline_commands (pipeline *p, ... FILE *pipeline_get_infile (pipeline *p) { +#ifdef HAVE_ZIO + assert (!p->libzio); +#endif assert (p->pids); /* pipeline started */ assert (p->statuses); if (p->infile) @@ -627,6 +640,12 @@ FILE *pipeline_get_infile (pipeline *p) FILE *pipeline_get_outfile (pipeline *p) { +#ifdef HAVE_ZIO + if (p->libzio) { + assert (p->outfile != (FILE*)0); + return p->outfile; + } +#endif assert (p->pids); /* pipeline started */ assert (p->statuses); if (p->outfile) @@ -707,6 +726,24 @@ void pipeline_start (pipeline *p) int infd[2]; sigset_t set, oset; +#ifdef HAVE_ZIO + if (p->ncommands != 1) /* A pipe to the following commands required */ + p->libzio = 0; + + if (p->libzio) { + struct command_function *cmdf; + + assert (p->ncommands == 1); + assert (p->commands[0]->tag == COMMAND_FUNCTION); + assert (p->want_infile != NULL); + + cmdf = &p->commands[0]->u.function; + + p->outfile = fzopen(p->want_infile, "r"); + + return; + } +#endif /* Flush all pending output so that subprocesses don't inherit it. */ fflush (NULL); @@ -1009,6 +1046,19 @@ int pipeline_wait (pipeline *p) pipeline_dump (p, stderr); } +#ifdef HAVE_ZIO + if (p->libzio) { + assert (p->outfile != (FILE*)0); + if (fclose (p->outfile)) { + error (0, errno, _("closing pipeline output stream failed")); + ret = 1; + } + p->outfile = (FILE*)0; + p->outfd = -1; + return ret; + } +#endif + assert (p->pids); /* pipeline started */ assert (p->statuses); @@ -1549,11 +1599,20 @@ static const char *get_block (pipeline * if (!peek) p->peek_offset = 0; - +#ifdef HAVE_ZIO + if (p->libzio) { + assert (p->outfile != (FILE*)0); + r = fread (p->buffer + readstart, sizeof(char), toread, p->outfile); + goto out; + } +#endif assert (p->outfd != -1); r = read (p->outfd, p->buffer + readstart, toread); if (r == -1) return NULL; +#ifdef HAVE_ZIO +out: +#endif p->buflen = readstart + r; if (peek) p->peek_offset += r; --- lib/pipeline.h +++ lib/pipeline.h 2008-04-22 13:52:44.846881571 +0000 @@ -60,6 +60,14 @@ typedef struct pipeline { pid_t *pids; int *statuses; /* -1 until command exits */ +#ifdef HAVE_ZIO + /* + * Uses for e.g. simple decompression the help of libzio. + * Do not fork in this case but open the compressed files. + */ + int libzio; +#endif + /* To be set by the caller. If positive, these contain * caller-supplied file descriptors for the input and output of the * whole pipeline. If negative, pipeline_start() will create pipes