summaryrefslogtreecommitdiff
path: root/textproc
diff options
context:
space:
mode:
authorwiz <wiz@pkgsrc.org>2004-12-17 18:53:54 +0000
committerwiz <wiz@pkgsrc.org>2004-12-17 18:53:54 +0000
commit8bda91c73b5495b119f5ddba1e5cb7e2020d60a9 (patch)
treefb69e428def0a23325bb986fd4473e81aa5926c8 /textproc
parent076834489ad28d7aecd1ed06eec22743633b73c0 (diff)
downloadpkgsrc-8bda91c73b5495b119f5ddba1e5cb7e2020d60a9.tar.gz
Fix insecure temporary file handling in groffer. Bump PKGREVISION.
Diffstat (limited to 'textproc')
-rw-r--r--textproc/groff/Makefile4
-rw-r--r--textproc/groff/distinfo3
-rw-r--r--textproc/groff/patches/patch-ad723
3 files changed, 727 insertions, 3 deletions
diff --git a/textproc/groff/Makefile b/textproc/groff/Makefile
index 81056f0a7ed..d77d2b7e726 100644
--- a/textproc/groff/Makefile
+++ b/textproc/groff/Makefile
@@ -1,8 +1,8 @@
-# $NetBSD: Makefile,v 1.20 2004/11/13 22:04:53 jlam Exp $
+# $NetBSD: Makefile,v 1.21 2004/12/17 18:53:54 wiz Exp $
#
DISTNAME= groff-1.19.1
-PKGREVISION= 1
+PKGREVISION= 2
CATEGORIES= textproc
MASTER_SITES= ${MASTER_SITE_GNU:=groff/}
diff --git a/textproc/groff/distinfo b/textproc/groff/distinfo
index 149ae38b0e5..887fe811f3f 100644
--- a/textproc/groff/distinfo
+++ b/textproc/groff/distinfo
@@ -1,10 +1,11 @@
-$NetBSD: distinfo,v 1.8 2004/08/02 16:14:24 wiz Exp $
+$NetBSD: distinfo,v 1.9 2004/12/17 18:53:55 wiz Exp $
SHA1 (groff-1.19.1.tar.gz) = 82ba1b29b01c36bf41149ce8813cea712e3e6cbf
Size (groff-1.19.1.tar.gz) = 2629152 bytes
SHA1 (patch-aa) = d0d1f387fefbb376eeec8ba824365cab2c1667fd
SHA1 (patch-ab) = 3c50a8b758cf3ad9d31e449864bf07c09b396b92
SHA1 (patch-ac) = 38f75d8261ca39aff8a37771a283c99ad39142bd
+SHA1 (patch-ad) = 3480c6ebf29aa986cffcf9bba705153e5335224d
SHA1 (patch-ae) = 18d553fe99ca6915d42de5f6edf74fc56e2fc650
SHA1 (patch-ba) = cdafeefbde9490d0ed599a118fd34c06afac0f96
SHA1 (patch-bb) = ddd9ef807a09eaaf7b09a3c05be3443945c67379
diff --git a/textproc/groff/patches/patch-ad b/textproc/groff/patches/patch-ad
new file mode 100644
index 00000000000..ff30832dce3
--- /dev/null
+++ b/textproc/groff/patches/patch-ad
@@ -0,0 +1,723 @@
+$NetBSD: patch-ad,v 1.3 2004/12/17 18:53:55 wiz Exp $
+
+--- contrib/groffer/groffer.sh.orig 2004-05-04 07:03:01.000000000 +0200
++++ contrib/groffer/groffer.sh
+@@ -25,18 +25,21 @@
+ # Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+ _PROGRAM_NAME='groffer';
+-_PROGRAM_VERSION='0.9.7';
+-_LAST_UPDATE='30 Apr 2004';
++_PROGRAM_VERSION='0.9.12';
++_LAST_UPDATE='15 November 2004';
+
+
+ ########################################################################
+-# Determine the shell under which to run this script;
+-# if `ash' is available restart the script using `ash';
+-# otherwise just go on.
++# Determine the shell under which to run this script from the command
++# line arguments or $GROFF_OPT; if none is specified, just go on with
++# the starting shell.
+
+-if test "${_groffer_run}" = ''; then
++if test _"${_groffer_run}"_ = __; then
+ # only reached during the first run of the script
+
++ export _groffer_run; # counter for the runs of groffer
++ _groffer_run='first';
++
+ export _PROGRAM_NAME;
+ export _PROGRAM_VERSION;
+ export _LAST_UPDATE;
+@@ -44,9 +47,9 @@ if test "${_groffer_run}" = ''; then
+ export GROFFER_OPT; # option environment for groffer
+ export _GROFFER_SH; # file name of this shell script
+ export _OUTPUT_FILE_NAME; # output generated, see main_set_res..()
+- export _groffer_run; # counter for the runs of groffer
+
+- _groffer_run='first';
++ export _CONFFILES; # configuration files
++ _CONFFILES="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf";
+
+ case "$0" in
+ *${_PROGRAM_NAME}*)
+@@ -103,18 +106,33 @@ if test "${_groffer_run}" = ''; then
+ #
+ _test_on_shell()
+ {
+- if test "$#" -le 0 || test "$1" = ''; then
++ if test "$#" -le 0 || test _"$1"_ = __; then
+ return 1;
+ fi;
+ # do not quote $1 to allow arguments
+- test "$($1 -c 's=ok; echo -n "$s"' 2>/dev/null)" = 'ok';
++ test _"$($1 -c 's=ok; echo -n "$s"' 2>/dev/null)"_ = _ok_;
+ }
+
+- # do the shell determination
++ # do the shell determination from command line and $GROFFER_OPT
+ _shell="$(_get_opt_shell "$@")";
+- if test "${_shell}" = ''; then
+- _shell='ash';
++
++ if test _"${_shell}"_ = __; then
++ # none found, so look at the `--shell' lines in configuration files
++ export f;
++ for f in ${_CONFFILES}; do
++ if test -f $f; then
++ _all="$(cat $f | sed -n -e '/^--shell[= ] *\([^ ]*\)$/s//\1/p')"
++ for s in ${_all}; do
++ _shell=$s;
++ done;
++ fi;
++ done;
++ unset f;
++ unset s;
++ unset _all;
+ fi;
++
++ # restart the script with the last found $_shell, if it is a shell
+ if _test_on_shell "${_shell}"; then
+ _groffer_run='second';
+ # do not quote $_shell to allow arguments
+@@ -122,26 +140,17 @@ if test "${_groffer_run}" = ''; then
+ exit;
+ fi;
+
+- # clean-up of shell determination
++ _groffer_run='second';
+ unset _shell;
+- unset _GROFFER_SH;
+- unset _groffer_run;
+- _get_opt_shell()
+- {
+- return 0;
+- }
+- _test_on_shell()
+- {
+- return 0;
+- }
+
+ fi; # end of first run
+
+-if test "${_groffer_run}" != 'second';
++if test _"${_groffer_run}"_ != _second_;
+ then
+ echo "$_groffer_run should be 'second' here." >&2
+ exit 1
+ fi;
++
+ unset _groffer_run
+
+
+@@ -241,9 +250,6 @@ return_no="func_pop; return ${_NO}";
+ return_error="func_pop; return ${_ERROR}";
+
+
+-export _CONFFILES;
+-_CONFFILES="/etc/groff/groffer.conf ${HOME}/.groff/groffer.conf";
+-
+ export _DEFAULT_MODES;
+ _DEFAULT_MODES='x,ps,tty';
+ export _DEFAULT_RESOLUTION;
+@@ -328,18 +334,18 @@ _OPTS_GROFFER_LONG_NA="'auto' 'debug' 'd
+
+ _OPTS_GROFFER_LONG_ARG="\
+ 'apropos' 'apropos-data' 'apropos-devel' 'apropos-progs' \
+-'default-modes' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
++'default-modes' 'device' 'dvi-viewer' 'extension' 'fg' 'fn' 'font' \
+ 'foreground' 'html-viewer' 'mode' 'pdf-viewer' 'ps-viewer' 'shell' \
+ 'tty-viewer' 'www-viewer' 'x-viewer' 'X-viewer'";
+
+ ##### groffer options inhereted from groff
+
+ _OPTS_GROFF_SHORT_NA="'a' 'b' 'c' 'C' 'e' 'E' 'g' 'G' 'i' 'l' 'N' 'p' \
+-'R' 's' 'S' 't' 'U' 'V' 'z'";
++'R' 's' 'S' 't' 'U' 'z'";
+ _OPTS_GROFF_SHORT_ARG="'d' 'f' 'F' 'I' 'L' 'm' 'M' 'n' 'o' 'P' 'r' \
+ 'w' 'W'";
+-_OPTS_GROFF_LONG_NA="'source'";
+-_OPTS_GROFF_LONG_ARG="'device' 'macro-file'";
++_OPTS_GROFF_LONG_NA="";
++_OPTS_GROFF_LONG_ARG="";
+
+ ##### groffer options inhereted from the X Window toolkit
+
+@@ -467,8 +473,7 @@ export _OPT_WHATIS; # print the one-lin
+ export _OPT_XRM; # specify X resource.
+ export _OPT_Z; # groff option -Z.
+ # _TMP_* temporary files
+-export _TMP_DIR; # groff directory for temporary files
+-export _TMP_DIR_SUB; # groffer directory for temporary files
++export _TMP_DIR; # groffer directory for temporary files
+ export _TMP_CAT; # stores concatenation of everything
+ export _TMP_STDIN; # stores stdin, if any
+
+@@ -490,7 +495,7 @@ test "a" = "a" || exit 1;
+ # Test of `echo' and the `$()' construct.
+ #
+ echo -n '' >/dev/null || exit "${_ERROR}";
+-if test "$(echo -n 'te' && echo -n '' && echo -n 'st')" != "test"; then
++if test _"$(echo -n 'te' && echo -n '' && echo -n 'st')"_ != _test_; then
+ exit "${_ERROR}";
+ fi;
+
+@@ -527,7 +532,6 @@ _HAS_OPTS_POSIX='';
+
+ # _TMP_* temporary files
+ _TMP_DIR='';
+-_TMP_DIR_SUB='';
+ _TMP_CAT='';
+ _TMP_STDIN='';
+
+@@ -631,7 +635,7 @@ reset;
+ #
+ landmark()
+ {
+- if test "${_DEBUG_LM}" = 'yes'; then
++ if test _"${_DEBUG_LM}"_ = _yes_; then
+ echo ">>> $*" >&2;
+ fi;
+ }
+@@ -647,8 +651,7 @@ landmark "1: debugging functions";
+ clean_up()
+ {
+ if test -d "${_TMP_DIR}"; then
+- rm -f "${_TMP_DIR}"/*;
+- rmdir "${_TMP_DIR}";
++ rm -f -r "${_TMP_DIR}";
+ fi;
+ }
+
+@@ -709,7 +712,7 @@ error()
+ ;;
+ *) echo2 'groffer error: wrong number of arguments in error().'; ;;
+ esac;
+- if test "${_DEBUG}" = 'yes'; then
++ if test _"${_DEBUG}"_ = _yes_; then
+ func_stack_dump;
+ fi;
+ clean_up;
+@@ -803,7 +806,7 @@ func_check()
+ error \
+ "${_fname}"'() needs '"${_comp} ${_nargs}"' argument'"${_s}"'.';
+ fi;
+- if test "${_DEBUG}" = 'yes'; then
++ if test _"${_DEBUG}"_ = _yes_; then
+ func_push "${_fname} $*";
+ fi;
+ }
+@@ -822,7 +825,7 @@ func_check()
+ #
+ func_pop()
+ {
+- if test "${_DEBUG}" = 'yes'; then
++ if test _"${_DEBUG}"_ = _yes_; then
+ if test "$#" -ne 0; then
+ error 'func_pop() does not have arguments.';
+ fi;
+@@ -856,7 +859,7 @@ func_pop()
+ func_push()
+ {
+ local _element;
+- if test "${_DEBUG}" = 'yes'; then
++ if test _"${_DEBUG}"_ = _yes_; then
+ if test "$#" -ne 1; then
+ error 'func_push() needs 1 argument.';
+ fi;
+@@ -869,7 +872,7 @@ func_push()
+ _element="$1";
+ ;;
+ esac;
+- if test "${_FUNC_STACK}" = ''; then
++ if test _"${_FUNC_STACK}"_ = __; then
+ _FUNC_STACK="${_element}";
+ else
+ _FUNC_STACK="${_element}!${_FUNC_STACK}";
+@@ -889,7 +892,7 @@ func_stack_dump()
+ case "${_FUNC_STACK}" in
+ *!*)
+ _rest="${_FUNC_STACK}";
+- while test "${_rest}" != ''; do
++ while test _"${_rest}"_ != __; do
+ # get part before the first bang `!'.
+ diag "$(echo -n "${_rest}" | sed -e 's/!.*$//')";
+ # delete part before and including the first bang `!'.
+@@ -934,7 +937,7 @@ fi;
+ # Test of `unset'.
+ #
+ _test='test';
+-if unset _test >/dev/null 2>&1 && test "${_test}" = ''; then
++if unset _test >/dev/null 2>&1 && test _"${_test}"_ = __; then
+ true;
+ else
+ unset()
+@@ -960,7 +963,7 @@ if _t_e_s_t_f_u_n_c_; then
+ else
+ local()
+ {
+- if test "$1" != ''; then
++ if test _"$1"_ != __; then
+ error "overriding global variable \`$1' with local value.";
+ fi;
+ }
+@@ -981,7 +984,7 @@ _t_e_s_t_f_u_n_c_()
+ }
+
+ _t_e_s_t_f_u_n_c_;
+-if test "${_global}" != 'inside' || test "${_clobber}" != 'outside';
++if test _"${_global}"_ != _inside_ || test _"${_clobber}"_ != _outside_;
+ then
+ error "Cannot assign to global variables from within functions.";
+ fi;
+@@ -993,9 +996,10 @@ unset _clobber;
+ ########################################################################
+ # Test of function `sed'.
+ #
+-if test "$(echo xTesTx \
++
++if test _"$(echo xTesTx \
+ | sed -e 's/^.\([Tt]e*x*sTT*\).*$/\1/' \
+- | sed -e '\|T|s||t|g')" != 'test';
++ | sed -e '\|T|s|T|t|g')"_ != _test_;
+ then
+ error 'Test of "sed" command failed.';
+ fi;
+@@ -1004,7 +1008,7 @@ fi;
+ ########################################################################
+ # Test of function `cat'.
+ #
+-if test "$(echo test | cat)" != "test"; then
++if test _"$(echo test | cat)"_ != _test_; then
+ error 'Test of "cat" command failed.';
+ fi;
+
+@@ -1012,12 +1016,12 @@ fi;
+ ########################################################################
+ # Test for compression.
+ #
+-if test "$(echo 'test' | gzip -c -d -f - 2>/dev/null)" = 'test'; then
++if test _"$(echo 'test' | gzip -c -d -f - 2>/dev/null)"_ = _test_; then
+ _HAS_COMPRESSION='yes';
+ if echo 'test' | bzip2 -c 2>/dev/null | bzip2 -t 2>/dev/null \
+- && test "$(echo 'test' | bzip2 -c 2>/dev/null \
+- | bzip2 -d -c 2>/dev/null)" \
+- = 'test'; then
++ && test _"$(echo 'test' | bzip2 -c 2>/dev/null \
++ | bzip2 -d -c 2>/dev/null)"_ \
++ = _test_; then
+ _HAS_BZIP='yes';
+ else
+ _HAS_BZIP='no';
+@@ -1083,7 +1087,7 @@ base_name()
+ case "$f" in
+ */)
+ # delete all final slashes
+- f="$(echo -n "$f" | sed -e '\|//*$|s|||')";
++ f="$(echo -n "$f" | sed -e '\|.*|s|//*$||')";
+ ;;
+ esac;
+ case "$f" in
+@@ -1092,7 +1096,7 @@ base_name()
+ ;;
+ */*)
+ # delete everything before and including the last slash `/'.
+- echo -n "$f" | sed -e '\|^.*//*\([^/]*\)$|s||\1|';
++ echo -n "$f" | sed -e '\|.*|s|^.*//*\([^/]*\)$|\1|';
+ ;;
+ *)
+ echo -n "$f";
+@@ -1112,7 +1116,7 @@ base_name()
+ # Arguments: 1, a file name.
+ # Output: the content of <file>, possibly decompressed.
+ #
+-if test "${_HAS_COMPRESSION}" = 'yes'; then
++if test _"${_HAS_COMPRESSION}"_ = _yes_; then
+ catz()
+ {
+ func_check catz = 1 "$@";
+@@ -1202,11 +1206,11 @@ dirname_chop()
+ local _res;
+ local _sep;
+ # replace all multiple slashes by a single slash `/'.
+- _res="$(echo -n "$1" | sed -e '\|///*|s||/|g')";
++ _res="$(echo -n "$1" | sed -e '\|.*|s|///*|/|g')";
+ case "${_res}" in
+ ?*/)
+ # remove trailing slash '/';
+- echo -n "${_res}" | sed -e '\|/$|s|||';
++ echo -n "${_res}" | sed -e '\|.*|s|/$||';
+ ;;
+ *) echo -n "${_res}"; ;;
+ esac;
+@@ -1426,7 +1430,7 @@ is_dir()
+ is_empty()
+ {
+ func_check is_empty = 1 "$@";
+- if test "$1" = ''; then
++ if test _"$1"_ = __; then
+ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+@@ -1444,7 +1448,25 @@ is_empty()
+ is_equal()
+ {
+ func_check is_equal = 2 "$@";
+- if test "$1" = "$2"; then
++ if test _"$1"_ = _"$2"_; then
++ eval "${return_yes}";
++ fi;
++ eval "${return_no}";
++}
++
++
++########################################################################
++# is_existing (<name>)
++#
++# Test whether `name' is an existing file or directory.
++#
++# Arguments : 1
++# Return : `0' if arg1 exists, `1' otherwise.
++#
++is_existing()
++{
++ func_check is_existing = 1 "$@";
++ if test -e "$1"; then
+ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+@@ -1481,11 +1503,9 @@ is_file()
+ #
+ is_non_empty_file()
+ {
+- func_check is_empty = 1 "$@";
+- if is_file "$1"; then
+- if is_not_empty "$(cat "$1" | sed -e '/./q')"; then
+- eval "${return_yes}";
+- fi;
++ func_check is_non_empty_file = 1 "$@";
++ if is_file "$1" && test -s "$1"; then
++ eval "${return_yes}";
+ fi;
+ eval "${return_no}";
+ }
+@@ -1754,7 +1774,7 @@ list_append()
+
+
+ ########################################################################
+-# list_from_cmdline (<s_n> <s_a> <l_n> <l_a> [<cmdline_arg>...])
++# list_from_cmdline (<pre_name_of_opt_lists> [<cmdline_arg>...])
+ #
+ # Transform command line arguments into a normalized form.
+ #
+@@ -1762,32 +1782,25 @@ list_append()
+ # output each as a single-quoted argument of its own. Options and
+ # file parameters are separated by a '--' argument.
+ #
+-# Arguments: >=4
+-# <s_n>: space-separated list of short options without an arg.
+-# <s_a>: space-separated list of short options that have an arg.
+-# <l_n>: space-separated list of long options without an arg.
+-# <l_a>: space-separated list of long options that have an arg.
++# Arguments: >=1
++# <pre_name>: common part of a set of 4 environment variable names:
++# $<pre_name>_SHORT_NA: list of short options without an arg.
++# $<pre_name>_SHORT_ARG: list of short options that have an arg.
++# $<pre_name>_LONG_NA: list of long options without an arg.
++# $<pre_name>_LONG_ARG: list of long options that have an arg.
+ # <cmdline_arg>...: the arguments from a command line, such as "$@",
+ # the content of a variable, or direct arguments.
+ #
+-# Globals: $POSIXLY_CORRECT (only kept for compatibility).
+-#
+ # Output: ['-[-]opt' ['optarg']]... '--' ['filename']...
+ #
+ # Example:
+-# list_normalize 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
+-# will result in printing:
++# list_from_cmdline PRE 'a b' 'c' '' 'long' -a f1 -bcarg --long=larg f2
++# If $PRE_SHORT_NA, $PRE_SHORT_ARG, $PRE_LONG_NA, and $PRE_LONG_ARG are
++# none-empty option lists, this will result in printing:
+ # '-a' '-b' '-c' 'arg' '--long' 'larg' '--' 'f1' 'f2'
+-# If $POSIXLY_CORRECT is not empty, the result will be:
+-# '-a' '--' 'f1' '-bcarg' '--long=larg' 'f2'
+-#
+-# Rationale:
+-# In POSIX, the first non-option ends the option processing.
+-# In GNU mode, used by default, non-option arguments are sorted
+-# behind the options.
+ #
+-# Use this function only in the following way:
+-# eval set -- "$(args_norm '...' '...' '...' '...' "$@")";
++# Use this function in the following way:
++# eval set -- "$(args_norm PRE_NAME "$@")";
+ # while test "$1" != '--'; do
+ # case "$1" in
+ # ...
+@@ -1799,19 +1812,31 @@ list_append()
+ #
+ list_from_cmdline()
+ {
+- func_check list_from_cmdline '>=' 4 "$@";
++ func_check list_from_cmdline '>=' 1 "$@";
+ local _fparams;
+ local _fn;
+- local _result;
+- local _long_a;
+- local _long_n;
+ local _short_a;
+ local _short_n;
+- _short_n="$(list_get "$1")"; # short options, no argument
+- _short_a="$(list_get "$2")"; # short options with argument
+- _long_n="$(list_get "$3")"; # long options, no argument
+- _long_a="$(list_get "$4")"; # long options with argument
+- shift 4;
++ local _long_a;
++ local _long_n;
++ local _result;
++ _short_n="$(obj_data "$1"_SHORT_NA)"; # short options, no argument
++ _short_a="$(obj_data "$1"_SHORT_ARG)"; # short options, with argument
++ _long_n="$(obj_data "$1"_LONG_NA)"; # long options, no argument
++ _long_a="$(obj_data "$1"_LONG_ARG)"; # long options, with argument
++ if obj _short_n is_empty; then
++ error 'list_from_cmdline(): no $'"$1"'_SHORT_NA options.';
++ fi;
++ if obj _short_a is_empty; then
++ error 'list_from_cmdline(): no $'"$1"'_SHORT_ARG options.';
++ fi;
++ if obj _long_n is_empty; then
++ error 'list_from_cmdline(): no $'"$1"'_LONG_NA options.';
++ fi;
++ if obj _long_a is_empty; then
++ error 'list_from_cmdline(): no $'"$1"'_LONG_ARG options.';
++ fi;
++ shift;
+ _fn='list_from_cmdline():'; # for error messages
+ if is_equal "$#" 0; then
+ echo -n "'--'";
+@@ -1887,13 +1912,12 @@ list_from_cmdline()
+ ;;
+ *)
+ # Here, $_arg is not an option, so a file parameter.
+- # When $POSIXLY_CORRECT is set this ends option parsing;
+- # otherwise, the argument is stored as a file parameter and
+- # option processing is continued.
+ list_append _fparams "${_arg}";
+- if obj POSIXLY_CORRECT is_not_empty; then
+- break;
+- fi;
++
++ # Ignore the strange option handling of $POSIXLY_CORRECT to
++ # end option parsing after the first file name argument. To
++ # reuse it, do a `break' here if $POSIXLY_CORRECT is
++ # non-empty.
+ ;;
+ esac;
+ done;
+@@ -1930,7 +1954,7 @@ list_from_split()
+ # replace split character of string by the list separator ` ' (space).
+ case "$2" in
+ /) # cannot use normal `sed' separator
+- echo -n "${_s}" | sed -e '\|'"$2"'|s|| |g';
++ echo -n "${_s}" | sed -e '\|.*|s|'"$2"'| |g';
+ ;;
+ ?) # use normal `sed' separator
+ echo -n "${_s}" | sed -e 's/'"$2"'/ /g';
+@@ -1968,8 +1992,8 @@ list_get()
+ eval _list='"${'$1'}"';
+ # remove leading and final space characters
+ _list="$(echo -n "${_list}" | \
+- sed -e '/^['"${_SPACE}${_TAB}"']*/s///' | \
+- sed -e '/['"${_SPACE}${_TAB}"']*$/s///')";
++ sed -e 's/^['"${_SPACE}${_TAB}"']*//' | \
++ sed -e 's/['"${_SPACE}${_TAB}"']*$//')";
+ case "${_list}" in
+ '')
+ eval "${return_ok}";
+@@ -2483,7 +2507,7 @@ manpath_set_from_path()
+ eval set -- "$(path_split "${PATH}")";
+ for d in "$@"; do
+ # delete the final `/bin' part
+- _base="$(echo -n "$d" | sed -e '\|//*bin/*$|s|||')";
++ _base="$(echo -n "$d" | sed -e '\|.*|s|//*bin/*$||')";
+ for e in /share/man /man; do
+ _mandir="${_base}$e";
+ if test -d "${_mandir}" && test -r "${_mandir}"; then
+@@ -3200,7 +3224,7 @@ where()
+ #
+ # set exit trap and create temporary files
+ #
+-# Globals: $_TMP_CAT, $_TMP_STDIN
++# Globals: $_TMP_DIR, $_TMP_CAT, $_TMP_STDIN
+ #
+ landmark '13: main_init()';
+ main_init()
+@@ -3209,32 +3233,52 @@ main_init()
+ # call clean_up() on any signal
+ trap_set clean_up;
+
+- # determine temporary directory
+- umask 000;
++ # create temporary directory
++ umask 0022;
+ _TMP_DIR='';
+ for d in "${GROFF_TMPDIR}" "${TMPDIR}" "${TMP}" "${TEMP}" \
+ "${TEMPDIR}" "${HOME}"'/tmp' '/tmp' "${HOME}" '.';
+ do
+- if is_not_empty "$d"; then
+- if obj d is_dir && obj d is_writable; then
+- _TMP_DIR="${d}/${_PROGRAM_NAME}${_PROCESS_ID}";
+- if obj _TMP_DIR is_dir; then
+- rm -f "${_TMP_DIR}"/*;
+- break;
+- else
+- mkdir "${_TMP_DIR}";
+- if obj _TMP_DIR is_not_dir; then
+- _TMP_DIR='';
+- continue;
+- fi;
+- break;
+- fi;
++ if obj d is_empty || obj d is_not_dir || obj d is_not_writable; then
++ continue;
++ fi;
++ case "$d" in
++ */)
++ _TMP_DIR="${d}";
++ ;;
++ *)
++ _TMP_DIR="${d}"'/';
++ ;;
++ esac;
++ _TMP_DIR="${_TMP_DIR}${_PROGRAM_NAME}${_PROCESS_ID}";
++ while obj _TMP_DIR is_existing; do
++ rm -f -r "${_TMP_DIR}" 2>/dev/null;
++ if obj _TMP_DIR is_existing; then
++ # $_TMP_DIR could not be removed
++ _TMP_DIR="${_TMP_DIR}"'X';
++ continue;
++ else
++ # $_TMP_DIR was removed
++ break;
+ fi;
+- if obj _TMP_DIR is_not_writable; then
+- _TMP_DIR='';
+- continue;
++ done;
++ mkdir "${_TMP_DIR}";
++ if is_not_equal "$?" 0; then
++ if obj _TMP_DIR is_existing; then
++ rm -f -r "${_TMP_DIR}" 2>/dev/null;
+ fi;
++ _TMP_DIR='';
++ continue;
++ fi;
++ if obj _TMP_DIR is_dir && obj _TMP_DIR is_writable; then
++ # $_TMP_DIR can now be used as temporary directory
++ break;
++ fi;
++ if obj _TMP_DIR is_existing; then
++ rm -f -r "${_TMP_DIR}" 2>/dev/null;
+ fi;
++ _TMP_DIR='';
++ continue;
+ done;
+ unset d;
+ if obj _TMP_DIR is_empty; then
+@@ -3250,7 +3294,7 @@ main_init()
+ echo '_groffer_opt=""' >>${_TMP_CAT};
+ # collect the lines starting with a minus
+ cat "$f" | sed -e \
+- '/^[ ]*\(-.*\)$/s//_groffer_opt="${_groffer_opt} \1"'/ \
++ 's/^[ ]*\(-.*\)$/_groffer_opt="${_groffer_opt} \1"'/ \
+ >>${_TMP_CAT};
+ # prepend the collected information to $GROFFER_OPT
+ echo 'GROFFER_OPT="${_groffer_opt} ${GROFFER_OPT}"' >>${_TMP_CAT};
+@@ -3289,10 +3333,7 @@ main_parse_MANOPT()
+ eval "${return_ok}";
+ fi;
+ # add arguments in $MANOPT by mapping them to groffer options
+- eval set -- "$(list_from_cmdline \
+- _OPTS_MANOPT_SHORT_NA _OPTS_MANOPT_SHORT_ARG \
+- _OPTS_MANOPT_LONG_NA _OPTS_MANOPT_LONG_ARG \
+- "${MANOPT}")";
++ eval set -- "$(list_from_cmdline _OPTS_MANOPT "${MANOPT}")";
+ until test "$#" -le 0 || is_equal "$1" '--'; do
+ _opt="$1";
+ shift;
+@@ -3424,10 +3465,7 @@ main_parse_args()
+
+ eval set -- "${GROFFER_OPT}" '"$@"';
+
+- eval set -- "$(list_from_cmdline \
+- _OPTS_CMDLINE_SHORT_NA _OPTS_CMDLINE_SHORT_ARG \
+- _OPTS_CMDLINE_LONG_NA _OPTS_CMDLINE_LONG_ARG \
+- "$@")";
++ eval set -- "$(list_from_cmdline _OPTS_CMDLINE "$@")";
+
+ # By the call of `eval', unnecessary quoting was removed. So the
+ # positional shell parameters ($1, $2, ...) are now guaranteed to
+@@ -3484,12 +3522,6 @@ main_parse_args()
+ --all)
+ _OPT_ALL="yes";
+ ;;
+- --ascii)
+- list_append _ADDOPTS_GROFF '-mtty-char';
+- if obj _mode is_empty; then
+- _mode='text';
+- fi;
+- ;;
+ --apropos) # run `apropos'
+ apropos_run "$1";
+ _code="$?";
+@@ -3497,23 +3529,29 @@ main_parse_args()
+ exit "${_code}";
+ ;;
+ --apropos-data) # run `apropos' for data sections
+- apropos_run "$1" | grep '^[^(]*([457])';
++ apropos_run "$1" | grep '^[^(]*([457][^)]*)';
+ _code="$?";
+ clean_up;
+ exit "${_code}";
+ ;;
+ --apropos-devel) # run `apropos' for development sections
+- apropos_run "$1" | grep '^[^(]*([239])';
++ apropos_run "$1" | grep '^[^(]*([239][^)]*)';
+ _code="$?";
+ clean_up;
+ exit "${_code}";
+ ;;
+ --apropos-progs) # run `apropos' for program sections
+- apropos_run "$1" | grep '^[^(]*([168])';
++ apropos_run "$1" | grep '^[^(]*([168][^)]*)';
+ _code="$?";
+ clean_up;
+ exit "${_code}";
+ ;;
++ --ascii)
++ list_append _ADDOPTS_GROFF '-mtty-char';
++ if obj _mode is_empty; then
++ _mode='text';
++ fi;
++ ;;
+ --auto) # the default automatic mode
+ _mode='';
+ ;;
+@@ -3691,6 +3729,7 @@ main_parse_args()
+ shift;
+ ;;
+ --shell)
++ # already done during the first run; so ignore the argument
+ shift;
+ ;;
+ --systems) # man pages for different OS's, arg
+@@ -4136,7 +4175,7 @@ main_set_resources()
+ continue;
+ ;;
+ ,*)
+- n="$(echo -n "$1" | sed -e '/^,,*/s///')";
++ n="$(echo -n "$1" | sed -e 's/^,,*//')";
+ ;;
+ esac
+ if obj n is_empty; then