--- .pkgextract +++ .pkgextract 2008-04-21 13:24:22.000000000 +0200 @@ -0,0 +1,10 @@ +bzcat ../man-db_2.5.2-2.diff.bz2 | patch -p1 -s --suffix=.debian +patch -p0 -s --suffix=.groff < ../man-db-2.3.19deb4.0-groff.dif +patch -p0 -s --suffix=.sect < ../man-db-2.4.3-section.dif +patch -p0 -s --suffix=.secu4 < ../man-db-2.5.1-security4.dif +patch -p0 -s --suffix=.firefox< ../man-db-2.4.3-firefox.dif +patch -p0 -s --suffix=.chinese< ../man-db-2.5.2-chinese.dif +patch -p0 -s --suffix=.glob < ../man-db-2.5.1-globbing.dif +patch -p0 -s --suffix=.zio < ../man-db-2.5.1-zio.dif +patch -p0 -s --suffix=.listall< ../man-db-2.5.1-listall.dif +patch -p0 -s --suffix=.catp < ../man-db-2.5.2-catp.dif --- configure.ac +++ configure.ac 2008-08-12 15:32:24.000000000 +0200 @@ -14,13 +14,26 @@ fi AC_CONFIG_HEADER(config.h) AC_CANONICAL_HOST - +dnl +dnl Check $PATH for the following progs and append suitable options. +dnl +AC_PROG_CC +AC_PROG_CPP +AC_GNU_SOURCE +dnl +dnl check for system defaults +dnl +AC_AIX +AC_MINIX +AC_ISC_POSIX +dnl # Define below date and version information to be put into man pages etc. datemark=20080505 date=`LANG=C date -d $datemark +'%Y-%m-%d'` AC_SUBST(date)dnl roff_version=`echo AC_PACKAGE_VERSION | sed 's/-/\\-/g'` AC_SUBST(roff_version)dnl +m4_pattern_allow([AC_DEFINE_UNQUOTED]) # We have to be a bit naughty here and supply options. # The autoconf literature states that only features that can be separately @@ -41,12 +54,12 @@ AS_HELP_STRING([--disable-setuid], [don' man_owner=$enableval man_mode="4755" AC_MSG_NOTICE([Man will be installed setuid $enableval]) - AC_DEFINE_UNQUOTED(SECURE_MAN_UID, "$man_owner", + AC_DEFINE_UNQUOTED([SECURE_MAN_UID], "$man_owner", [Define as the setuid owner of man or undefine if not installing setuid.]) fi], [man_owner=man man_mode="4755" - AC_DEFINE_UNQUOTED(SECURE_MAN_UID, "$man_owner")]) + AC_DEFINE_UNQUOTED([SECURE_MAN_UID], "$man_owner")]) AC_ARG_ENABLE(undoc, [AS_HELP_STRING([--enable-undoc=COMMAND], [suggest COMMAND for missing manual pages])], [if test "$enableval" = "yes" || test "$enableval" = "no" @@ -54,7 +67,7 @@ AC_ARG_ENABLE(undoc, AC_MSG_ERROR(--enable-undoc requires an argument) else AC_MSG_NOTICE([Suggesting '$enableval' for missing manual pages]) - AC_DEFINE_UNQUOTED(UNDOC_COMMAND, "$enableval", + AC_DEFINE_UNQUOTED([UNDOC_COMMAND], "$enableval", [Define as the name of a command you want to suggest when a non-existent page is requested.]) fi]) AC_ARG_WITH(device, @@ -115,10 +128,7 @@ AC_SUBST(config_file_dirname)dnl AC_SUBST(sections)dnl # Check $PATH for the following programs and append suitable options. -AC_GNU_SOURCE -AC_PROG_CC gl_EARLY -AC_PROG_CPP CFLAGS="$CFLAGS -Wall" if test "$GCC" = yes then @@ -255,6 +265,14 @@ then fi MAN_CHECK_PROGS([eqn], [EQN], [use EQN to preprocess equations], [eqn geqn]) +MAN_CHECK_PROGS([geqn], [GEQN], [use GEQN to preprocess equations], [geqn]) +dnl +dnl if geqn is found and geqn is identical with eqn we use a GNU eqn +dnl which its self can use -Tlatin1 +dnl +if test -n "$geqn" -a -n "$eqn" ; then + test $geqn -ef $eqn && neqn="$eqn -T$nroff_device" +fi MAN_CHECK_PROGS([neqn], [NEQN], [use NEQN to preprocess equations for character devices], [neqn gneqn]) # If we fail to find an neqn, use eqn and try to force it to output for an # ascii device. As this is only relevant for equations (?), not using latin1 @@ -280,9 +298,15 @@ then compress_ext="gz" fi MAN_CHECK_PROGS([compress], [COMPRESS], [use COMPRESS as UNIX compression utility], [compress]) -if test -n "$compress" +if test -n "$compress" || test -n "$gzip" then - uncompress="$compress -dc" + if test -n "$gzip" + then + uncompress="$gzip -dc" + elif test -n "$compress" + then + uncompress="$compress -dc" + fi if test -z "$gzip" then compressor="$compress -c" @@ -334,7 +358,7 @@ dnl To add more decompressors just follo AC_ARG_ENABLE(mandirs, [AS_HELP_STRING([--enable-mandirs=OS], [select manual page hierarchy organization (GNU, HPUX, IRIX, Solaris, BSD)])], [AC_MSG_NOTICE([Using $enableval hierarchy organization(s)]) - AC_DEFINE_UNQUOTED(MANDIR_LAYOUT, "$enableval", + AC_DEFINE_UNQUOTED([MANDIR_LAYOUT], "$enableval", [Define to the manual page hierarchy organization(s) in use.])], [case $host in *-gnu) mandirs=GNU;; @@ -346,7 +370,7 @@ AC_ARG_ENABLE(mandirs, esac if test -n "$mandirs"; then AC_MSG_NOTICE([Using $mandirs hierarchy organization]) - AC_DEFINE_UNQUOTED(MANDIR_LAYOUT, "$mandirs") + AC_DEFINE_UNQUOTED([MANDIR_LAYOUT], "$mandirs") else AC_MSG_NOTICE([Allowing any hierarchy organization]) AC_DEFINE(MANDIR_LAYOUT, "") @@ -362,8 +386,7 @@ AC_HEADER_DIRENT AC_CHECK_HEADERS(fcntl.h sys/file.h) # Internationalization support. -AM_GNU_GETTEXT -AM_GNU_GETTEXT_VERSION([0.17]) +AM_GNU_GETTEXT([external]) AC_SUBST(LINGUAS) AM_ICONV AM_CONDITIONAL([NLS], [test "$USE_NLS" = yes]) @@ -491,6 +514,5 @@ AC_CONFIG_FILES(Makefile tools/Makefile include/comp_src.h include/manconfig.h - intl/Makefile po/Makefile.in) AC_OUTPUT --- mk_catdirs +++ mk_catdirs 2007-12-10 12:51:50.000000000 +0100 @@ -0,0 +1,24 @@ +#!/bin/sh + +OLDPWD="`pwd`" +CACHE="$1/var/cache/man" + + cats="cat{0,1,2,3,4,5,6,7,8,9,n}" +locale="{ca,cs,da,de,en,es,et,fi,fr,ga,hu,is,it,ja,ko,nl,no,pl,pt,ru,sk,sr,sv,uk}" + dirs="{local,opt}" + +umask 022 +test -d ${CACHE} && rm -rf ${CACHE} +mkdir -p ${CACHE} + +cd ${CACHE} +eval echo ${cats} \ + ${locale}/${cats} \ + ${dirs}/${cats} \ + ${dirs}/${locale}/${cats} \ + | xargs mkdir -p +sync +cd ${OLDPWD} + +test "$(id -u)" -ne 0 || chown man:daemon -R ${CACHE} + --- include/comp_src.h.in +++ include/comp_src.h.in 2007-12-10 12:51:50.000000000 +0100 @@ -53,7 +53,7 @@ struct compression comp_list[] = { #endif /* HAVE_GZIP */ /* If we have compress, incorporate the following */ -#ifdef HAVE_COMPRESS +#if defined(HAVE_COMPRESS) || defined(HAVE_GZIP) {UNCOMPRESS, "Z", NULL}, #endif /* HAVE_COMPRESS */ --- include/manconfig.h.in +++ include/manconfig.h.in 2008-08-12 16:59:18.600458442 +0200 @@ -73,7 +73,7 @@ #undef MAN_DB_CREATES #define MAN_DB_UPDATES -#define MAN_CATS +#undef MAN_CATS /* By default, man-db will store a whatis referenced manual page in favour of a stray cat page when they both share identical namespace. If you --- intl/Makefile.in +++ intl/Makefile.in 2007-12-10 12:51:51.000000000 +0100 @@ -181,7 +181,7 @@ libgnuintl.h.msvc-shared Makefile.msvc all: all-@USE_INCLUDED_LIBINTL@ all-yes: libintl.$la libintl.h charset.alias ref-add.sed ref-del.sed -all-no: all-no-@BUILD_INCLUDED_LIBINTL@ +all-no: all-no-@USE_INCLUDED_LIBINTL@ all-no-yes: libgnuintl.$la all-no-no: --- libdb/db_storage.h +++ libdb/db_storage.h 2008-04-21 15:18:56.000000000 +0200 @@ -70,10 +70,10 @@ struct mandata { }; /* used by the world */ -extern inline struct mandata *dblookup_all (const char *page, +extern struct mandata *dblookup_all (const char *page, const char *section, int match_case); -extern inline struct mandata *dblookup_exact (const char *page, +extern struct mandata *dblookup_exact (const char *page, const char *section, int match_case); extern int dbstore (struct mandata *in, const char *base); @@ -85,10 +85,10 @@ extern void split_content (char *cont_pt extern int compare_ids (char a, char b); /* local to db routines */ -extern inline void gripe_lock (char *filename); -extern inline void gripe_corrupt_data (void); +extern void gripe_lock (char *filename); +extern void gripe_corrupt_data (void); extern datum make_multi_key (const char *page, const char *ext); -extern inline struct mandata *infoalloc (void); +extern struct mandata *infoalloc (void); extern char *name_to_key (const char *name); extern char **split_data (char *content, char *start[]); extern datum make_content (struct mandata *in); --- libdb/mydbm.h +++ libdb/mydbm.h 2008-04-21 15:20:08.000000000 +0200 @@ -42,7 +42,7 @@ # include # ifndef HAVE_GDBM_EXISTS -extern inline int gdbm_exists(GDBM_FILE dbf, datum key); +extern int gdbm_exists(GDBM_FILE dbf, datum key); # endif /* !HAVE_GDBM_EXISTS */ /* gdbm_nextkey() is not lexicographically sorted, so we need to keep the @@ -133,14 +133,14 @@ extern int ndbm_flclose(DBM *dbf); typedef DBT datum; extern DB *btree_flopen(char *filename, int flags, int mode); -extern inline int btree_close(DB *db); -extern inline int btree_exists(DB *db, datum key); -extern inline datum btree_fetch(DB *db, datum key); +extern int btree_close(DB *db); +extern int btree_exists(DB *db, datum key); +extern datum btree_fetch(DB *db, datum key); extern int btree_insert(DB *db, datum key, datum cont); -extern inline datum btree_firstkey(DB *db); -extern inline datum btree_nextkey(DB *db); -extern inline int btree_replace(DB *db, datum key, datum content); -extern inline int btree_nextkeydata(DB *db, datum *key, datum *cont); +extern datum btree_firstkey(DB *db); +extern datum btree_nextkey(DB *db); +extern int btree_replace(DB *db, datum key, datum content); +extern int btree_nextkeydata(DB *db, datum *key, datum *cont); # define DB_EXT ".bt" # define MYDBM_FILE DB* @@ -148,7 +148,7 @@ extern inline int btree_nextkeydata(DB * # define MYDBM_SET_DPTR(d, value) ((d).data = (char *) (value)) # define MYDBM_DSIZE(d) ((d).size) # define MYDBM_CTRWOPEN(file) btree_flopen(file, O_TRUNC|O_CREAT|O_RDWR, DBMODE) -# define MYDBM_CRWOPEN(file) btree_flopen(file, O_CREAT|O_RDWR, DBMODE) +# define MYDBM_CRWOPEN(file) btree_flopen(file, O_CREAT|O_RDWR, DBMODE) # define MYDBM_RWOPEN(file) btree_flopen(file, O_RDWR, DBMODE) # define MYDBM_RDOPEN(file) btree_flopen(file, O_RDONLY, DBMODE) # define MYDBM_INSERT(db, key, cont) btree_insert(db, key, cont) --- man/de/man1/man.man1 +++ man/de/man1/man.man1 2008-04-21 13:41:49.000000000 +0200 @@ -97,6 +97,7 @@ der Manualseiten gefolgt vom Typ der dor .TS tab (@); l l. +0@Dateiheader (gewöhnlich in \fI/usr/include\fR) 1@Ausführbare Programme oder Shellbefehle 2@Systemaufrufe (Kernelfunktionen) 3@Bibliotheksaufrufe (Funktionen in System-Bibliotheken) --- man/es/man1/man.man1 +++ man/es/man1/man.man1 2008-04-21 13:41:57.000000000 +0200 @@ -101,6 +101,7 @@ del manual y los tipos de páginas que c .TS tab (@); l l. +0@Ficheros (se encuentran generalmente en \fI/usr/include\fR) 1@Programas ejecutables y guiones del intérprete de @órdenes 2@Llamadas del sistema (funciones servidas por el núcleo) --- man/it/man1/man.man1 +++ man/it/man1/man.man1 2008-04-21 13:42:02.000000000 +0200 @@ -124,6 +124,7 @@ del manuale seguiti dai tipi di pagine c .TS tab (@); l l. +0@File (di solito trovabili in \fI/usr/include\fR) 1@Programmi eseguibili e comandi della shell 2@Chiamate al sistema (funzioni fornite dal kernel) 3@Chiamate alle librerie (funzioni all'interno delle --- man/ja/man1/man.man1 +++ man/ja/man1/man.man1 2008-04-21 13:42:05.000000000 +0200 @@ -104,6 +104,7 @@ .TS tab (@); l l. +0@ 1@実行プログラムまたはシェルのコマンド 2@システムコール (カーネルが提供する関数) 3@ライブラリコール (システムライブラリに含まれる関数) --- man/man1/man.man1 +++ man/man1/man.man1 2007-12-10 12:53:31.000000000 +0100 @@ -119,6 +119,7 @@ numbers of the manual followed by the ty .TS tab (@); l l. +0@Header files (usually found in \fI/usr/include\fR) 1@Executable programs or shell commands 2@System calls (functions provided by the kernel) 3@Library calls (functions within program libraries) --- src/Makefile.am +++ src/Makefile.am 2008-04-21 16:44:47.000000000 +0200 @@ -170,15 +170,11 @@ apropos$(EXEEXT): whatis$(EXEEXT) all-am: apropos$(EXEEXT) install-exec-hook: - -test -z "$(man_owner)" || \ - chown $(man_owner) \ - $(DESTDIR)$(bindir)/$(TRANS_MAN) \ - $(DESTDIR)$(bindir)/$(TRANS_MANDB) - chmod $(man_mode) \ - $(DESTDIR)$(bindir)/$(TRANS_MAN) \ - $(DESTDIR)$(bindir)/$(TRANS_MANDB) - cd $(DESTDIR)$(bindir) && rm -f $(TRANS_APROPOS)$(EXEEXT) && \ - $(LN_S) $(TRANS_WHATIS)$(EXEEXT) $(TRANS_APROPOS)$(EXEEXT) + $(INSTALL_PROGRAM) $(TRANS_MAN) $(DESTDIR)$(pkglibexecdir)/$(TRANS_MAN) + $(INSTALL_PROGRAM) $(TRANS_MANDB) $(DESTDIR)$(pkglibexecdir)/$(TRANS_MANDB) + $(INSTALL_PROGRAM) wrapper $(DESTDIR)$(bindir)/$(TRANS_MANDB) + ln -f $(DESTDIR)$(bindir)/$(TRANS_MANDB) $(DESTDIR)$(bindir)/$(TRANS_MAN) + $(LN_S) $(TRANS_WHATIS) $(DESTDIR)$(bindir)/$(TRANS_APROPOS) install-data-hook: @if test -f $(DESTDIR)$(config_file); then \ --- src/check_mandirs.c +++ src/check_mandirs.c 2007-12-10 13:15:49.000000000 +0100 @@ -379,10 +379,10 @@ static short testmandirs (const char *pa } if (!quiet) { - fprintf (stderr, "\r"); fprintf (stderr, _("Updating index cache for path " "`%s/%s'. Wait..."), path, mandir->d_name); + putc ('\n', stderr); } add_dir_entries (path, mandir->d_name); MYDBM_CLOSE (dbf); @@ -571,7 +571,7 @@ short update_db (const char *manpath) return new; } - debug ("failed to open %s O_RDONLY\n", database); + debug ("failed to open database %s O_RDONLY\n", database); return EOF; } @@ -747,6 +747,7 @@ static short purge_whatis (const char *p "would delete\n", name, info->ext); return 1; } + return 1; } /* Check that multi keys are correctly constructed. */ @@ -809,6 +810,11 @@ short purge_missing (const char *manpath gripe_rwopen_failed (); return 0; } + if (dbver_rd (dbf)) { + MYDBM_CLOSE (dbf); + dbf = NULL; + return 0; + } key = MYDBM_FIRSTKEY (dbf); @@ -827,6 +833,14 @@ short purge_missing (const char *manpath continue; } + /* Ignore db identifier keys. */ + if (*key.dptr == '.' && *(key.dptr+1) == 0) { + nextkey = MYDBM_NEXTKEY (dbf, key); + MYDBM_FREE (key.dptr); + key = nextkey; + continue; + } + content = MYDBM_FETCH (dbf, key); if (!MYDBM_DPTR (content)) { nextkey = MYDBM_NEXTKEY (dbf, key); --- src/fake_security.c +++ src/fake_security.c 2007-12-10 12:53:31.000000000 +0100 @@ -43,6 +43,7 @@ #include "security.h" uid_t ruid, euid, uid; +gid_t rgid, egid; #ifdef SECURE_MAN_UID static struct passwd *man_owner; --- src/lexgrog.l +++ src/lexgrog.l 2008-08-12 15:33:28.000000000 +0200 @@ -51,7 +51,7 @@ #include "security.h" #include "encodings.h" -#define YY_READ_BUF_SIZE 1024 +#define YY_READ_BUF_SIZE YY_BUF_SIZE #define MAX_NAME 2048 #ifdef PROFILE @@ -59,10 +59,10 @@ static int ctr[YY_NUM_RULES]; # define YY_USER_ACTION ++ctr[yy_act]; #endif -static void add_str_to_whatis (const char *string, size_t length); -static void add_char_to_whatis (unsigned char c); -static void add_separator_to_whatis (void); -static void newline_found (void); +static __inline__ void add_str_to_whatis (const char *string, size_t length); +static __inline__ void add_char_to_whatis (unsigned char c); +static __inline__ void add_separator_to_whatis (const char *, size_t); +static __inline__ void newline_found (void); static char newname[MAX_NAME]; static char *p_name; @@ -71,6 +71,7 @@ static char filters[MAX_FILTERS]; static int fill_mode; static int waiting_for_quote; +static int have_separator; static pipeline *decomp; @@ -87,7 +88,7 @@ static pipeline *decomp; %} %option ecs meta-ecs -%option 8bit batch caseful never-interactive +%option 8bit batch caseful never-interactive align %option nostdinit %option warn %option noyywrap nounput @@ -116,8 +117,9 @@ font_change \\f([[:upper:]1-4]|\({upper} size_change \\s[+-]?{digit} style_change ({font_change}{size_change}?|{size_change}{font_change}?) typeface \.(B[IR]?|I[BR]?|R[BI]) +paragr \.[PITLH][Pp] sec_request \.[Ss][HhYySs] -comment ['.]\\{dbl_quote} +comment (['.]\\{dbl_quote}|\'\-+|\\&) /* Please add to this list if you know how. */ /* Note that, since flex only supports UTF-8 by accident, character classes @@ -150,7 +152,26 @@ vi_name TÊN zh_CN_name 名{blank}?称{blank}?.* zh_TW_name (名{blank}?稱|命令名){blank}?.* name ({bg_name}|{cs_name}|{da_name}|{de_name}|{en_name}|{es_name}|{fi_name}|{fr_name}|{hu_name}|{id_name}|{it_name}|{ja_name}|{ko_name}|{latin_name}|{nl_name}|{pl_name}|{ru_name}|{sk_name}|{sr_name}|{sv_name}|{tr_name}|{vi_name}|{zh_CN_name}|{zh_TW_name}) -name_sec {dbl_quote}?{style_change}?{name}{style_change}?({blank}*{dbl_quote})? +name_sec {dbl_quote}?{style_change}?{name}{style_change}?({blank}*{dbl_quote})?\r? +start {sec_request}{blank_eol}+{name_sec} + +N N(\bN)? +n (N(\bN)?|n(\bn)?) +a (A(\bA)?|a(\ba)?) +o (O(\bO)?|o(\bo)?) +m (M(\bM)?|M(\bM)?) +e (E(\bE)?|e(\be)?) +B B(\bB) +b (B(\bB)?|b(\bb)?) +r (R(\bR)?|r(\br)?) +z (Z(\bZ)?|z(\bz)?) +i (I(\bI)?|i(\bi)?) +c (C(\bC)?|c(\bc)?) +h (H(\bH)?|h(\bh)?) +u (U(\bU)?|u(\bu)?) +g (G(\bG)?|g(\bg)?) + +cname (({N}({a}|{o}){m}({n}|{e})|{N}{o}{m}|{N}{o}{m}{b}{r}{e}|{B}{e}{z}{e}{i}{c}{h}{n}{u}{n}{g})|{bg_name}|{cs_name}|{hu_name}|{ko_name}|{ru_name}|{sr_name}|{tr_name}|{vi_name}|{ja_name}|{zh_CN_name}|{zh_TW_name}) /* eptgrv : eqn, pic, tbl, grap, refer, vgrind */ tbl_request \.TS @@ -164,8 +185,13 @@ vgrind_request \.vS %% /* begin NAME section processing */ -{sec_request}{blank_eol}+{name_sec}{blank}* BEGIN (MAN_PRENAME); -{empty}{2,}{name}{blank}*{indent} BEGIN (CAT_NAME); +{ + {start}{blank}*{bol}{blank}*{paragr} | /* strange format */ + {start}{blank}* { /* default */ + BEGIN (MAN_PRENAME); + } +} +{empty}{2,}{cname}{blank}*{indent} BEGIN (CAT_NAME); /* general text matching */ \.[^Ss\r\n].* | @@ -216,6 +242,7 @@ vgrind_request \.vS {bol}\.sp{blank}* | /* vertical spacing */ {bol}\.ig{blank}* | /* block comment */ {bol}\.de[1i]?{blank}* | /* macro definition */ +{bol}\.V[be]{blank}* | /* special in perl pages */ {bol}\.i[ef]{blank}* | /* conditional */ {empty}{bol}.+ | <> { /* terminate the string */ @@ -242,28 +269,31 @@ vgrind_request \.vS {bol}{typeface}{blank}+ | /* type face commands */ {bol}\.ft{blank}.* | /* font change */ {bol}\.V[be]{blank}.* | /* pod2man, verbatim mode */ - {bol}\.IX{blank}.* | /* .IX line */ + {bol}\.IX{blank}.* | /* index request */ {next}{comment}.* { /* per line comments */ newline_found (); } } /* No-op requests */ -{bol}\.{blank}*$ newline_found (); -{bol}\.\.$ newline_found (); +{bol}\.{blank}*/{eol} newline_found (); +{bol}\.\./{eol} newline_found (); /* Toggle fill mode */ -{bol}\.nf.* fill_mode = 0; -{bol}\.fi.* fill_mode = 1; +{bol}\.(nf|de).* fill_mode = 0; +{bol}\.(fi|\.).* fill_mode = 1; -{eol}{blank_eol}* /* strip continuations */ /* convert to DASH */ {next}{blank}*\\\((mi|hy|em){blank}* | +{bol}\.sp{bol}{blank}+\\-{blank}* | /* strange spacing in NAME section */ +{blank}+[-\\]?-{bol} | /* dash at end of line */ +{next}{blank_eol}+(\\?-){2}{blank}+ | /* some man pages use -- as dash */ {next}{blank_eol}+[-\\]-{blank}* | {next}{blank_eol}*[-\\]-{blank}+ | {next}{blank}+-{1,2}{blank_eol}+ | -{bol}\.Nd{blank}* add_separator_to_whatis (); +{bol}\.Nd{blank}* add_separator_to_whatis (yytext, yyleng); /* escape sequences and special characters */ { @@ -279,6 +309,7 @@ vgrind_request \.vS {next}\\[|^&!%acdpruz{}\r\n] /* various useless control chars */ {next}\\[bhlLvx]{blank}*'[^']+' /* various inline functions */ + {next}\\\\\$[1-9] /* roff macro argument */ {next}\\\$[1-9] /* interpolate arg */ {next}\\\*(\({alpha})?{alpha} /* interpolate string */ @@ -307,11 +338,8 @@ vgrind_request \.vS for later processing */ { {bol}\.br{blank}* | - {bol}\.LP{blank}* | - {bol}\.PP{blank}* | + {bol}{paragr}{blank}* | {bol}\.P{blank}* | - {bol}\.IP{blank}.* | - {bol}\.HP{blank}.* | {bol}\.RS{blank}.* | {bol}\.RE{blank}.* add_char_to_whatis ((char) 0x11); } @@ -324,7 +352,7 @@ vgrind_request \.vS [[:alnum:]]* add_str_to_whatis (yytext, yyleng); /* normalise the period (,) separators */ -{blank}*,[ \t\r\n]* | +{blank}*,{blank_eol}* | {blank}*,{blank}* add_str_to_whatis (", ", 2); {bol}. { @@ -340,7 +368,7 @@ vgrind_request \.vS %% /* print warning and force scanner to terminate */ -static void too_big (void) +static __inline__ void too_big (void) { error (0, 0, _("warning: whatis for %s exceeds %d bytes, truncating."), @@ -350,7 +378,7 @@ static void too_big (void) } /* append a string to newname if enough room */ -static void add_str_to_whatis (const char *string, size_t length) +static __inline__ void add_str_to_whatis (const char *string, size_t length) { if (p_name - newname + length >= MAX_NAME) too_big (); @@ -361,8 +389,10 @@ static void add_str_to_whatis (const cha } /* append a char to newname if enough room */ -static void add_char_to_whatis (unsigned char c) +static __inline__ void add_char_to_whatis (unsigned char c) { + if (c == (char) 0x11 && *p_name == (char) 0x11) + return; if (p_name - newname + 1 >= MAX_NAME) too_big (); else if (waiting_for_quote && c == '"') @@ -374,14 +404,30 @@ static void add_char_to_whatis (unsigned /* append the " - " separator to newname, trimming the first space if one's * already there */ -static void add_separator_to_whatis (void) +static __inline__ void add_separator_to_whatis (const char *string, size_t len) { + if (have_separator) { + unsigned int n; + unsigned char c; + + for (n = 0; (n < len) && (c = string[n]); n++) { + switch (c) { + case '-': + case ' ': + add_char_to_whatis (c); + default: + break; + } + } + return; + } + have_separator = 1; if (p_name != newname && *(p_name - 1) != ' ') add_char_to_whatis (' '); add_str_to_whatis ("- ", 2); } -static void newline_found (void) +static __inline__ void newline_found (void) { /* If we are mid p_name and the last added char was not a space, * best add one. @@ -457,6 +503,7 @@ int find_name_decompressed (pipeline *p, fill_mode = 1; waiting_for_quote = 0; + have_separator = 0; if (p_lg->type) BEGIN (CAT_FILE); --- src/man.c +++ src/man.c 2008-08-12 16:59:18.640462210 +0200 @@ -66,6 +66,7 @@ static char *cwd; #include #include #include +#include #include "argp.h" #include "dirname.h" @@ -104,6 +105,8 @@ static char *cwd; #ifdef SECURE_MAN_UID extern uid_t ruid; extern uid_t euid; +extern gid_t rgid; +extern gid_t egid; #endif /* SECURE_MAN_UID */ /* the default preprocessor sequence */ @@ -134,6 +137,10 @@ const char *lang; static int global_manpath = -1; /* global or user manual page hierarchy? */ static int skip; /* page exists but has been skipped */ +static struct termios tms; /* To save terminal settings in */ +static int tms_set = 0; /* Do we have saved terminal settings? */ + +static void set_term(void) { if (tms_set) tcsetattr(fileno(stdin), TCSANOW, &tms); } #if defined _AIX || defined __sgi char **global_argv; @@ -224,12 +231,12 @@ static char *tmp_cat_file; /* for open_c static int tmp_cat_fd; static int created_tmp_cat; /* dto. */ static int man_modtime; /* modtime of man page, for commit_tmp_cat() */ -#endif +#endif /* MAN_CATS */ # ifdef TROFF_IS_GROFF -static int ditroff; +static int ditroff = 0; static const char *gxditview; -static int htmlout; +static int htmlout = 0; static const char *html_pager; # endif /* TROFF_IS_GROFF */ @@ -537,25 +544,6 @@ static void gripe_no_name (const char *s exit (FAIL); } -static struct termios tms; -static int tms_set = 0; - -static void set_term (void) -{ - if (tms_set) - tcsetattr (STDIN_FILENO, TCSANOW, &tms); -} - -static void get_term (void) -{ - if (isatty (STDOUT_FILENO)) { - debug ("is a tty\n"); - tcgetattr (STDIN_FILENO, &tms); - if (!tms_set++) - atexit (set_term); - } -} - static int get_roff_line_length (void) { int line_length = get_line_length (); @@ -640,11 +628,11 @@ static inline char **manopt_to_env (int { char *manopt, *opt_start, **argv; - manopt = getenv ("MANOPT"); + opt_start = manopt = getenv ("MANOPT"); if (manopt == NULL || *manopt == '\0') return NULL; - opt_start = manopt = xstrdup (manopt); + manopt = xstrdup (manopt); /* allocate space for the program name */ *argc = 0; @@ -760,30 +748,43 @@ static int local_man_loop (const char *a display (NULL, "", NULL, "(stdin)", NULL); else { struct stat st; + char *pwd = cwd; + char *file = basename((char*)argv); - if (cwd[0]) { - debug ("chdir %s\n", cwd); - if (chdir (cwd)) { - error (0, errno, _("can't chdir to %s"), cwd); + if (strcmp(argv, file)) { + char *dlm; + pwd = strdupa(argv); + + if ((dlm = strrchr(pwd, '/'))) + *dlm = '\0'; + } + + if (pwd[0]) { + debug ("chdir %s\n", pwd); + if (chdir (pwd)) { + error (0, errno, _("can't chdir to %s"), pwd); regain_effective_privs (); return 0; } } /* Check that the file exists and isn't e.g. a directory */ - if (stat (argv, &st)) { + if (stat (file, &st)) { error (0, errno, "%s", argv); + regain_effective_privs (); return NOT_FOUND; } if (S_ISDIR (st.st_mode)) { error (0, EISDIR, "%s", argv); + regain_effective_privs (); return NOT_FOUND; } if (S_ISCHR (st.st_mode) || S_ISBLK (st.st_mode)) { /* EINVAL is about the best I can do. */ error (0, EINVAL, "%s", argv); + regain_effective_privs (); return NOT_FOUND; } @@ -801,8 +802,10 @@ static int local_man_loop (const char *a argv_abs = xstrdup (argv); } lang = lang_dir (argv_abs); + if (!lang || !*lang) + lang = internal_locale; free (argv_abs); - if (!display (NULL, argv, NULL, argv_base, NULL)) { + if (!display (NULL, file, NULL, argv_base, NULL)) { if (local_mf) error (0, errno, "%s", argv); exit_status = NOT_FOUND; @@ -834,7 +837,16 @@ int main (int argc, char *argv[]) bindtextdomain (PACKAGE "-gnulib", LOCALEDIR); textdomain (PACKAGE); - internal_locale = setlocale (LC_MESSAGES, NULL); + internal_locale = setlocale (LC_MESSAGES, ""); +#if defined(__GLIBC__) +# if (__GLIBC__ < 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 2) + if (!internal_locale) { + if ( !(internal_locale = getenv ("LC_ALL")) + && !(internal_locale = getenv ("LC_MESSAGES"))) + internal_locale = getenv ("LANG"); + } +# endif +#endif /* Use LANGUAGE only when LC_MESSAGES locale category is * neither "C" nor "POSIX". */ if (internal_locale && strcmp (internal_locale, "C") && @@ -904,9 +916,13 @@ int main (int argc, char *argv[]) if (external) do_extern (argc, argv); - get_term (); /* stores terminal settings */ #ifdef SECURE_MAN_UID debug ("real user = %d; effective user = %d\n", ruid, euid); + if (isatty(fileno(stdin)) && isatty(fileno(stdout))) { + tcgetattr(fileno(stdin), &tms); + if (!tms_set++) + atexit(set_term); + } #endif /* SECURE_MAN_UID */ /* close this locale and reinitialise if a new locale was @@ -924,6 +940,7 @@ int main (int argc, char *argv[]) setenv ("LANGUAGE", internal_locale, 1); ++_nl_msg_cat_cntr; multiple_locale = NULL; +#define MULTIPLE_LOCALE_IS_NULL 1 } } @@ -978,6 +995,22 @@ int main (int argc, char *argv[]) } if (manp == NULL) { +#if MULTIPLE_LOCALE_IS_NULL + char * tmp_locale = xstrdup(internal_locale); + char * ptr; + + manp = get_manpath (alt_system_name); + + /* + * Use strsep () to not intermix with strtok () + */ + for (ptr = strsep (&tmp_locale, ":"); ptr; ptr = strsep (&tmp_locale, ":")) { + if (debug_level) + fprintf (stderr, "checking for locale %s\n", ptr); + manp = add_nls_manpath (manp, ptr); + } + free(tmp_locale); +#else char tmp_locale[3]; int idx; @@ -999,6 +1032,7 @@ int main (int argc, char *argv[]) debug ("checking for locale %s\n", tmp_locale); manp = add_nls_manpath (manp, tmp_locale); } +#endif } else free (get_manpath (NULL)); @@ -1155,7 +1189,7 @@ static inline const char *is_section (co } /* Snarf pre-processors from file, return (static) string or NULL on failure */ -static const char *get_preprocessors_from_file (pipeline *decomp) +static const char *get_preprocessors_from_file (pipeline *decomp, char * pp_encoding) { static char *directive = NULL; @@ -1174,7 +1208,8 @@ static const char *get_preprocessors_fro if (!line) return NULL; - if (!strncmp (line, PP_COOKIE, 4)) { + if (!strncmp (line, PP_COOKIE, 4) || + (strlen(line) == 6 && !strncmp(line, ".\\\" ", 4))) { const char *newline = strchr (line, '\n'); if (newline) directive = xstrndup (line + 4, newline - (line + 4)); @@ -1182,6 +1217,25 @@ static const char *get_preprocessors_fro directive = xstrdup (line + 4); } + if (directive && strstr (directive, "-*-")) { + const char *pp_search = strstr (directive, "-*-") + 3; + while (*pp_search == ' ') + ++pp_search; + if (STRNEQ (pp_search, "coding:", 7)) { + const char *pp_encoding_end; + pp_search += 7; + while (*pp_search == ' ') + ++pp_search; + pp_encoding_end = strchr (pp_search, ' '); + if (pp_encoding_end) { + size_t len = pp_encoding_end - pp_search; + pp_encoding = xstrndup (pp_search, len); + } else + pp_encoding = xstrdup (pp_search); + debug ("preprocessor encoding: %s\n", pp_encoding); + } + } + /* if we didn't find PP_COOKIE, then directive == NULL */ #endif return directive; @@ -1190,7 +1244,7 @@ static const char *get_preprocessors_fro /* Determine pre-processors, set save_cat and return (static) string */ -static const char *get_preprocessors (pipeline *decomp, const char *dbfilters) +static const char *get_preprocessors (pipeline *decomp, const char *dbfilters, char * pp_encoding) { const char *pp_string; const char *pp_source; @@ -1204,7 +1258,7 @@ static const char *get_preprocessors (pi } else if ((pp_string = preprocessors)) { pp_source = "command line"; save_cat = 0; - } else if ((pp_string = get_preprocessors_from_file (decomp))) { + } else if ((pp_string = get_preprocessors_from_file (decomp, pp_encoding))) { pp_source = "file"; save_cat = 1; } else if ((pp_string = getenv ("MANROFFSEQ"))) { @@ -1230,6 +1284,7 @@ static pipeline *make_roff_command (cons { const char *pp_string; const char *roff_opt; + const char *pp_encoding; char *fmt_prog; pipeline *p = pipeline_new (); command *cmd; @@ -1239,8 +1294,8 @@ static pipeline *make_roff_command (cons #ifndef ALT_EXT_FORMAT dir = dir; /* not used unless looking for formatters in catdir */ #endif - - pp_string = get_preprocessors (decomp, dbfilters); + pp_encoding = (char*)0; + pp_string = get_preprocessors (decomp, dbfilters, pp_encoding); roff_opt = getenv ("MANROFFOPT"); if (!roff_opt) @@ -1295,8 +1350,10 @@ static pipeline *make_roff_command (cons if (!recode) pipeline_command_argstr (p, get_def ("soelim", SOELIM)); - - page_encoding = get_page_encoding (lang); + if (pp_encoding) + page_encoding = pp_encoding; + else + page_encoding = get_page_encoding (lang); source_encoding = get_source_encoding (lang); debug ("page_encoding = %s\n", page_encoding); debug ("source_encoding = %s\n", source_encoding); @@ -1652,6 +1709,18 @@ static void setenv_less (const char *tit free (less_opts); } +static void disable_x(void) +{ + char *bname = basename((char*)pager); + if (bname) { + if (!strcmp(bname, "less")) + unsetenv("DISPLAY"); +#if 0 + free(bname); +#endif + } +} + /* Return pipeline to display file. NULL means stdin. * * TODO: htmlout case is pretty weird now. I'd like the intelligence to be @@ -1664,6 +1733,9 @@ static pipeline *make_display_command (c setenv_less (title); + if (!htmlout) + disable_x(); + if (file) { if (ascii) { p = pipeline_new (); @@ -1706,7 +1778,7 @@ static pipeline *make_display_command (c return p; } - +#ifdef MAN_CATS /* return a (malloced) temporary name in cat_file's directory */ static char *tmp_cat_filename (const char *cat_file) { @@ -1809,8 +1881,6 @@ static int commit_tmp_cat (const char *c return status; } -#ifdef MAN_CATS - /* Return pipeline to write formatted manual page to for saving as cat file. */ static pipeline *open_cat_stream (const char *cat_file) { @@ -1884,6 +1954,7 @@ static int close_cat_stream (pipeline *c free (tmp_cat_file); return status; } +#endif /* MAN_CATS */ /* TODO: This should all be refactored after work on the decompression * library is complete. @@ -1896,6 +1967,7 @@ void discard_stderr (pipeline *p) p->commands[i]->discard_err = 1; } +#ifdef MAN_CATS /* * format a manual page with format_cmd, display it with disp_cmd, and * save it to cat_file @@ -2057,6 +2129,7 @@ static void format_display (pipeline *de regain_effective_privs (); } +#ifdef MAN_CATS /* "Display" a page in catman mode, which amounts to saving it. */ /* TODO: merge with format_display_and_save? */ static void display_catman (const char *cat_file, pipeline *decomp, @@ -2095,6 +2168,7 @@ static void display_catman (const char * pop_cleanup(); free (tmpcat); } +#endif /* MAN_CATS */ /* * optionally chdir to dir, if necessary update cat_file from man_file @@ -2117,10 +2191,18 @@ static int display (const char *dir, con if (dir) { debug ("chdir %s\n", dir); + if (global_manpath) + drop_effective_privs(); + if (chdir (dir)) { error (0, errno, _("can't chdir to %s"), dir); + if (global_manpath) + regain_effective_privs(); return 0; } + + if (global_manpath) + regain_effective_privs(); } /* define format_cmd */ @@ -2133,11 +2215,10 @@ static int display (const char *dir, con if (decomp) { pipeline_start (decomp); - format_cmd = make_roff_command (dir, man_file, decomp, - dbfilters); + format_cmd = make_roff_command (dir, man_file, decomp, dbfilters); } else format_cmd = NULL; - +#ifdef MAN_CATS /* Get modification time, for commit_tmp_cat(). */ if (man_file && *man_file) { struct stat stb; @@ -2146,7 +2227,7 @@ static int display (const char *dir, con else man_modtime = stb.st_mtime; } - +#endif /* MAN_CATS */ display_to_stdout = troff; #ifdef TROFF_IS_GROFF if (htmlout) @@ -2263,6 +2344,7 @@ static int display (const char *dir, con } if (printed) putchar ('\n'); +#ifdef MAN_CATS } else if (catman) { if (format) { if (!save_cat) @@ -2274,6 +2356,7 @@ static int display (const char *dir, con display_catman (cat_file, decomp, format_cmd); } +#endif /* MAN_CATS */ } else if (format) { /* no cat or out of date */ pipeline *disp_cmd; @@ -2324,8 +2407,10 @@ static int display (const char *dir, con } } - pipeline_free (format_cmd); - pipeline_free (decomp); + if (format_cmd) + pipeline_free (format_cmd); + if (decomp) + pipeline_free (decomp); if (!prompt) prompt = found; @@ -2923,7 +3008,7 @@ static int display_database_check (struc #ifdef MAN_DB_UPDATES if (!exists && !skip) { debug ("dbdelete_wrapper (%s, %p)\n", - candp->req_name, candp->source); + candp->req_name, candp->source->addr); dbdelete_wrapper (candp->req_name, candp->source); } #endif /* MAN_DB_UPDATES */ --- src/man_db.conf.in +++ src/man_db.conf.in 2008-08-12 15:35:48.000000000 +0200 @@ -20,6 +20,14 @@ MANDATORY_MANPATH /usr/man MANDATORY_MANPATH /usr/share/man MANDATORY_MANPATH /usr/local/share/man +MANDATORY_MANPATH /opt/man +MANDATORY_MANPATH /opt/dx/man +MANDATORY_MANPATH /opt/lsb/man +MANDATORY_MANPATH /opt/cross/share/man +MANDATORY_MANPATH /opt/mpich/man +MANDATORY_MANPATH /opt/lsb-tet3-lite/share/man +MANDATORY_MANPATH /opt/snavigator/man +MANDATORY_MANPATH /opt/novell/man #--------------------------------------------------------- # set up PATH to MANPATH mapping # ie. what man tree holds man pages for what binary directory. @@ -34,8 +42,10 @@ MANPATH_MAP /usr/local/bin /usr/local/m MANPATH_MAP /usr/local/bin /usr/local/share/man MANPATH_MAP /usr/local/sbin /usr/local/man MANPATH_MAP /usr/local/sbin /usr/local/share/man -MANPATH_MAP /usr/X11R6/bin /usr/X11R6/man -MANPATH_MAP /usr/bin/X11 /usr/X11R6/man +MANPATH_MAP /usr/X11R6/bin /usr/share/man +MANPATH_MAP /usr/X11/bin /usr/share/man +MANPATH_MAP /usr/bin/X11 /usr/share/man +MANPATH_MAP /usr/bin/mh /usr/share/man MANPATH_MAP /usr/games /usr/share/man MANPATH_MAP /opt/bin /opt/man MANPATH_MAP /opt/sbin /opt/man @@ -63,12 +73,133 @@ MANPATH_MAP /opt/sbin /opt/man # # *MANPATH* -> *CATPATH* # -MANDB_MAP /usr/man /var/cache/man/fsstnd +MANDB_MAP /usr/share/man/ca /var/cache/man/ca +MANDB_MAP /usr/share/man/cs /var/cache/man/cs +MANDB_MAP /usr/share/man/cs_CZ /var/cache/man/cs +MANDB_MAP /usr/share/man/da /var/cache/man/da +MANDB_MAP /usr/share/man/de /var/cache/man/de +MANDB_MAP /usr/share/man/de_AT /var/cache/man/de +MANDB_MAP /usr/share/man/de_DE /var/cache/man/de +MANDB_MAP /usr/share/man/en /var/cache/man/en +MANDB_MAP /usr/share/man/es /var/cache/man/es +MANDB_MAP /usr/share/man/es_ES /var/cache/man/es +MANDB_MAP /usr/share/man/et /var/cache/man/et +MANDB_MAP /usr/share/man/fi /var/cache/man/fi +MANDB_MAP /usr/share/man/fr_FR /var/cache/man/fr +MANDB_MAP /usr/share/man/ga /var/cache/man/ga +MANDB_MAP /usr/share/man/is /var/cache/man/is +MANDB_MAP /usr/share/man/it /var/cache/man/it +MANDB_MAP /usr/share/man/ja /var/cache/man/ja +MANDB_MAP /usr/share/man/ja_JP /var/cache/man/ja +MANDB_MAP /usr/share/man/ja_JP.eucJP /var/cache/man/ja +MANDB_MAP /usr/share/man/ko /var/cache/man/ko +MANDB_MAP /usr/share/man/nl /var/cache/man/nl +MANDB_MAP /usr/share/man/no /var/cache/man/no +MANDB_MAP /usr/share/man/pl /var/cache/man/pl +MANDB_MAP /usr/share/man/pt /var/cache/man/pt +MANDB_MAP /usr/share/man/pt_BR /var/cache/man/pt +MANDB_MAP /usr/share/man/ru /var/cache/man/ru +MANDB_MAP /usr/share/man/sk /var/cache/man/sk +MANDB_MAP /usr/share/man/sr /var/cache/man/sr +MANDB_MAP /usr/share/man/sv /var/cache/man/sv +MANDB_MAP /usr/share/man/uk /var/cache/man/uk MANDB_MAP /usr/share/man /var/cache/man -MANDB_MAP /usr/local/man /var/cache/man/oldlocal -MANDB_MAP /usr/local/share/man /var/cache/man/local -MANDB_MAP /usr/X11R6/man /var/cache/man/X11R6 -MANDB_MAP /opt/man /var/cache/man/opt +# +MANDB_MAP /usr/local/man/ca /var/cache/man/local/ca +MANDB_MAP /usr/local/man/cs /var/cache/man/local/cs +MANDB_MAP /usr/local/man/cs_CZ /var/cache/man/local/cs +MANDB_MAP /usr/local/man/da /var/cache/man/local/da +MANDB_MAP /usr/local/man/de /var/cache/man/local/de +MANDB_MAP /usr/local/man/de_AT /var/cache/man/local/de +MANDB_MAP /usr/local/man/de_DE /var/cache/man/local/de +MANDB_MAP /usr/local/man/en /var/cache/man/local/en +MANDB_MAP /usr/local/man/es /var/cache/man/local/es +MANDB_MAP /usr/local/man/es_ES /var/cache/man/local/es +MANDB_MAP /usr/local/man/et /var/cache/man/local/et +MANDB_MAP /usr/local/man/fi /var/cache/man/local/fi +MANDB_MAP /usr/local/man/fr_FR /var/cache/man/local/fr +MANDB_MAP /usr/local/man/ga /var/cache/man/local/ga +MANDB_MAP /usr/local/man/is /var/cache/man/local/is +MANDB_MAP /usr/local/man/it /var/cache/man/local/it +MANDB_MAP /usr/local/man/ja /var/cache/man/local/ja +MANDB_MAP /usr/local/man/ja_JP /var/cache/man/local/ja +MANDB_MAP /usr/local/man/ja_JP.eucJP /var/cache/man/local/ja +MANDB_MAP /usr/local/man/ko /var/cache/man/local/ko +MANDB_MAP /usr/local/man/nl /var/cache/man/local/nl +MANDB_MAP /usr/local/man/no /var/cache/man/local/no +MANDB_MAP /usr/local/man/pl /var/cache/man/local/pl +MANDB_MAP /usr/local/man/pt /var/cache/man/local/pt +MANDB_MAP /usr/local/man/pt_BR /var/cache/man/local/pt +MANDB_MAP /usr/local/man/ru /var/cache/man/local/ru +MANDB_MAP /usr/local/man/sk /var/cache/man/local/sk +MANDB_MAP /usr/local/man/sr /var/cache/man/local/sr +MANDB_MAP /usr/local/man/sv /var/cache/man/local/sv +MANDB_MAP /usr/local/man/uk /var/cache/man/local/uk +MANDB_MAP /usr/local/man /var/cache/man/local +# +MANDB_MAP /usr/local/share/man/ca /var/cache/man/local/ca +MANDB_MAP /usr/local/share/man/cs /var/cache/man/local/cs +MANDB_MAP /usr/local/share/man/cs_CZ /var/cache/man/local/cs +MANDB_MAP /usr/local/share/man/da /var/cache/man/local/da +MANDB_MAP /usr/local/share/man/de /var/cache/man/local/de +MANDB_MAP /usr/local/share/man/de_AT /var/cache/man/local/de +MANDB_MAP /usr/local/share/man/de_DE /var/cache/man/local/de +MANDB_MAP /usr/local/share/man/en /var/cache/man/local/en +MANDB_MAP /usr/local/share/man/es /var/cache/man/local/es +MANDB_MAP /usr/local/share/man/es_ES /var/cache/man/local/es +MANDB_MAP /usr/local/share/man/et /var/cache/man/local/et +MANDB_MAP /usr/local/share/man/fi /var/cache/man/local/fi +MANDB_MAP /usr/local/share/man/fr_FR /var/cache/man/local/fr +MANDB_MAP /usr/local/share/man/ga /var/cache/man/local/ga +MANDB_MAP /usr/local/share/man/is /var/cache/man/local/is +MANDB_MAP /usr/local/share/man/it /var/cache/man/local/it +MANDB_MAP /usr/local/share/man/ja /var/cache/man/local/ja +MANDB_MAP /usr/local/share/man/ja_JP /var/cache/man/local/ja +MANDB_MAP /usr/local/share/man/ja_JP.eucJP /var/cache/man/local/ja +MANDB_MAP /usr/local/share/man/ko /var/cache/man/local/ko +MANDB_MAP /usr/local/share/man/nl /var/cache/man/local/nl +MANDB_MAP /usr/local/share/man/no /var/cache/man/local/no +MANDB_MAP /usr/local/share/man/pl /var/cache/man/local/pl +MANDB_MAP /usr/local/share/man/pt /var/cache/man/local/pt +MANDB_MAP /usr/local/share/man/pt_BR /var/cache/man/local/pt +MANDB_MAP /usr/local/share/man/ru /var/cache/man/local/ru +MANDB_MAP /usr/local/share/man/sk /var/cache/man/local/sk +MANDB_MAP /usr/local/share/man/sr /var/cache/man/local/sr +MANDB_MAP /usr/local/share/man/sv /var/cache/man/local/sv +MANDB_MAP /usr/local/share/man/uk /var/cache/man/local/uk +MANDB_MAP /usr/local/share/man /var/cache/man/local +# +MANDB_MAP /opt/share/man/ca /var/cache/man/opt/ca +MANDB_MAP /opt/share/man/cs /var/cache/man/opt/cs +MANDB_MAP /opt/share/man/cs_CZ /var/cache/man/opt/cs +MANDB_MAP /opt/share/man/da /var/cache/man/opt/da +MANDB_MAP /opt/share/man/de /var/cache/man/opt/de +MANDB_MAP /opt/share/man/de_AT /var/cache/man/opt/de +MANDB_MAP /opt/share/man/de_DE /var/cache/man/opt/de +MANDB_MAP /opt/share/man/en /var/cache/man/opt/en +MANDB_MAP /opt/share/man/es /var/cache/man/opt/es +MANDB_MAP /opt/share/man/es /var/cache/man/opt/es +MANDB_MAP /opt/share/man/et /var/cache/man/opt/et +MANDB_MAP /opt/share/man/fi /var/cache/man/opt/fi +MANDB_MAP /opt/share/man/fr_FR /var/cache/man/opt/fr +MANDB_MAP /opt/share/man/ga /var/cache/man/opt/ga +MANDB_MAP /opt/share/man/is /var/cache/man/opt/is +MANDB_MAP /opt/share/man/it /var/cache/man/opt/it +MANDB_MAP /opt/share/man/ja /var/cache/man/opt/ja +MANDB_MAP /opt/share/man/ja_JP /var/cache/man/opt/ja +MANDB_MAP /opt/share/man/ja_JP.eucJP /var/cache/man/opt/ja +MANDB_MAP /opt/share/man/ko /var/cache/man/opt/ko +MANDB_MAP /opt/share/man/nl /var/cache/man/opt/nl +MANDB_MAP /opt/share/man/no /var/cache/man/opt/no +MANDB_MAP /opt/share/man/pl /var/cache/man/opt/pl +MANDB_MAP /opt/share/man/pt /var/cache/man/opt/pt +MANDB_MAP /opt/share/man/pt_BR /var/cache/man/opt/pt +MANDB_MAP /opt/share/man/ru /var/cache/man/opt/ru +MANDB_MAP /opt/share/man/sk /var/cache/man/opt/sk +MANDB_MAP /opt/share/man/sr /var/cache/man/opt/sr +MANDB_MAP /opt/share/man/sv /var/cache/man/opt/sv +MANDB_MAP /opt/share/man/uk /var/cache/man/opt/uk +MANDB_MAP /opt/share/man /var/cache/man/opt # #--------------------------------------------------------- # Program definitions. These are commented out by default as the value --- src/mandb.c +++ src/mandb.c 2008-08-12 16:59:18.688466727 +0200 @@ -185,6 +185,8 @@ static const char *xtmpfile; #ifdef SECURE_MAN_UID extern uid_t ruid; extern uid_t euid; +extern gid_t rgid; +extern gid_t egid; #endif /* SECURE_MAN_UID */ static char *manpathlist[MAXDIRS]; @@ -518,7 +520,7 @@ static short process_manpath (const char if (!opt_test && amount) { finish_up (); #ifdef SECURE_MAN_UID - if (global_manpath && euid == 0) + if (global_manpath && (euid == 0 || ruid == 0)) do_chown (man_owner->pw_uid); #endif /* SECURE_MAN_UID */ } @@ -586,8 +588,14 @@ int main (int argc, char *argv[]) error (FAIL, 0, _("the setuid man user \"%s\" does not exist"), MAN_OWNER); - if (!user && euid != 0 && euid != man_owner->pw_uid) - user = 1; + if (!user) { + if (!ruid && euid != man_owner->pw_uid) { + seteuid(man_owner->pw_uid); + euid = geteuid(); + } + if (euid != man_owner->pw_uid) + user = 1; + } #endif /* SECURE_MAN_UID */ --- src/manp.c +++ src/manp.c 2008-08-12 16:59:18.712468986 +0200 @@ -70,6 +70,7 @@ #include "security.h" #include "encodings.h" #include "manp.h" +#include "security.h" struct list { char *key; @@ -673,6 +674,8 @@ char *get_manpath (const char *systems) #ifdef SECURE_MAN_UID extern uid_t ruid; /* initial real user id */ extern uid_t euid; /* initial effective user id */ +extern gid_t rgid; /* initial real group id */ +extern gid_t egid; /* initial effective group id */ #endif /* SECURE_MAN_UID */ /* create the catman hierarchy if it doesn't exist */ @@ -701,6 +704,8 @@ mkcatdirs (const char *mandir, const cha #ifdef SECURE_MAN_UID if (ruid == 0) chown (catdir, man_owner->pw_uid, 0); + if (rgid == 0) + chown (catdir, -1, man_owner->pw_gid); #endif /* SECURE_MAN_UID */ drop_effective_privs (); } @@ -711,9 +716,14 @@ mkcatdirs (const char *mandir, const cha int j; regain_effective_privs (); debug ("creating catdir hierarchy %s ", catdir); - for (j = 1; j <= 9; j++) { - catname[strlen (catname) - 1] = '0' + j; - manname[strlen (manname) - 1] = '0' + j; + for (j = 0; j <= 10; j++) { + unsigned int c; + if (j < 10) + c = '0' + j; + else + c = 'n'; + catname[strlen (catname) - 1] = c; + manname[strlen (manname) - 1] = c; if ((is_directory (manname) == 1) && (is_directory (catname) != 1)) { if (mkdir (catname, @@ -722,11 +732,12 @@ mkcatdirs (const char *mandir, const cha error (0, 0, _("warning: cannot create catdir %s"), catname); debug ("warning: cannot create catdir %s\n", catname); } else - debug (" cat%d", j); + debug (" cat%c", c); #ifdef SECURE_MAN_UID if (ruid == 0) - chown (catname, - man_owner->pw_uid, 0); + chown (catname, man_owner->pw_uid, 0); + if (rgid == 0) + chown (catname, -1, man_owner->pw_gid); #endif /* SECURE_MAN_UID */ } } @@ -865,7 +876,7 @@ static char *def_path (int flag) /* If we have complete config file failure... */ if (!manpath) - return xstrdup ("/usr/man"); + return xstrdup ("/usr/share/man"); return manpath; } --- src/security.c +++ src/security.c 2007-12-10 14:24:24.000000000 +0100 @@ -76,10 +76,13 @@ # ifdef POSIX_SAVED_IDS # if defined (HAVE_SETEUID) # define SET_EUID(euid) seteuid(euid) +# define SET_EGID(egid) setegid(egid) # elif defined (HAVE_SETREUID) # define SET_EUID(euid) setreuid(-1, euid) +# define SET_EGID(egid) setregid(-1, egid) # elif defined (HAVE_SETRESUID) # define SET_EUID(euid) setresuid(-1, euid, -1) +# define SET_EGID(egid) setresgid(-1, egid, -1) # endif /* HAVE_SETEUID */ /* Sort out the function to use to swap ruid with euid. Used if no suid. */ @@ -87,8 +90,10 @@ # else /* !POSIX_SAVED_IDS */ # if defined (HAVE_SETREUID) # define SWAP_UIDS(ida, idb) setreuid(idb, ida) +# define SWAP_GIDS(ida, idb) setregid(idb, ida) # elif defined (HAVE_SETRESUID) # define SWAP_UIDS(ida, idb) setresuid(idb, ida, -1) +# define SWAP_GIDS(ida, idb) setresgid(idb, ida, -1) # warning Using setresuid() whithout _POSIX_SAVED_IDS! # endif /* HAVE_SETREUID */ # endif /* POSIX_SAVED_IDS */ @@ -100,7 +105,10 @@ uid_t ruid; /* initial real user id */ uid_t euid; /* initial effective user id */ +gid_t rgid; /* initial real group id */ +gid_t egid; /* initial effective group id */ uid_t uid; /* current euid */ +gid_t gid; /* current egid */ static struct passwd *man_owner; @@ -114,10 +122,17 @@ static inline void gripe_set_euid (void) error (FATAL, errno, _("can't set effective uid")); } +static __inline__ void gripe_set_egid () +{ + error (FATAL, errno, _( "can't set effective gid")); +} + void init_security (void) { ruid = getuid (); + rgid = getgid (); uid = euid = geteuid (); + gid = egid = getegid (); debug ("ruid=%d, euid=%d\n", (int) ruid, (int) euid); priv_drop_count = 0; drop_effective_privs (); @@ -191,6 +206,28 @@ void regain_effective_privs (void) uid = euid; } + + if (gid != rgid) { +# ifdef POSIX_SAVED_IDS + if (SET_EGID (rgid)) +# else + if (SWAP_GIDS (egid, rgid)) +# endif + gripe_set_egid(); + + gid = rgid; + } + + if (gid != egid) { +# ifdef POSIX_SAVED_IDS + if (SET_EGID (egid)) +# else + if (SWAP_GIDS (rgid, egid)) +# endif + gripe_set_egid(); + + gid = egid; + } #endif /* SECURE_MAN_UID */ } --- src/security.h +++ src/security.h 2008-04-21 15:19:19.000000000 +0200 @@ -25,8 +25,8 @@ #include /* security.c */ -extern inline void drop_effective_privs (void); -extern inline void regain_effective_privs (void); +extern void drop_effective_privs (void); +extern void regain_effective_privs (void); extern int do_system_drop_privs (struct pipeline *p); extern int remove_with_dropped_privs (const char *filename); extern void init_security (void); --- src/straycats.c +++ src/straycats.c 2008-08-12 16:59:18.780475384 +0200 @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef HAVE_DIRENT_H # include @@ -268,13 +269,17 @@ static int check_for_stray (void) if (lg.whatis) free (lg.whatis); - pipeline_free (decomp); + if (decomp) + pipeline_free (decomp); next_exists: - free_mandata_struct (exists); - free (mandir_base); + if (exists) + free_mandata_struct (exists); + if (mandir_base) + free (mandir_base); } next_section: - free (section); + if (section) + free (section); } closedir (cdir); return strays; --- src/ult_src.c +++ src/ult_src.c 2007-12-10 14:34:00.000000000 +0100 @@ -289,12 +289,17 @@ const char *ult_src (const char *name, c } pipeline_start (decomp); - /* make sure that we skip over any comments */ + /* + * make sure that we skip over any comments + * ... even if we handle TCL/TK manual pages + */ do { buffer = pipeline_readline (decomp); - } while (buffer && STRNEQ (buffer, ".\\\"", 3)); + } while (buffer && *buffer && + (STRNEQ (buffer, ".\\\"", 3) || + STRNEQ (buffer, "'\\\"", 3))); - if (buffer) { + if (buffer && *buffer) { char *include = test_for_include (buffer); if (include) { const char *ult; --- src/ult_src.h +++ src/ult_src.h 2007-12-10 13:24:30.000000000 +0100 @@ -21,9 +21,10 @@ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ -#define SO_LINK 0001 -#define SOFT_LINK 0002 -#define HARD_LINK 0004 +#define SO_LINK 0x0001 +#define SOFT_LINK 0x0002 +#define HARD_LINK 0x0004 +#define WHATISBUF 0x0008 extern const char *ult_src (const char *name, const char *path, struct stat *buf, int flags); --- src/util.c +++ src/util.c 2007-12-10 13:24:30.000000000 +0100 @@ -43,6 +43,9 @@ #include #include +#include +#define _(String) gettext (String) + #include "manconfig.h" #include "pipeline.h" --- src/wrapper.c +++ src/wrapper.c 2008-01-07 13:06:02.000000000 +0100 @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -48,7 +49,7 @@ * it is fixed at compile time to avoid a full class of * dangers ... */ -struct { +static struct { const char *prog; const char *run; const char *user; @@ -64,10 +65,11 @@ struct { char *program_name; -int main (int argc, char **argv) +int main (int argc, char **argv, char *envp[]) { - uid_t ruid; - char *fakeroot; + uid_t ruid, euid; + gid_t rgid; +// char *fakeroot; struct passwd *pwd; argc = argc; /* not used */ @@ -84,57 +86,56 @@ int main (int argc, char **argv) program_name = base_name (argv[0]); ruid = getuid (); - fakeroot = getenv ("FAKEROOTKEY"); + euid = geteuid(); + rgid = getgid (); +// fakeroot = getenv ("FAKEROOTKEY"); #ifdef DEBUG printf ("%s:\n", program_name); - printf ("real = %d, = %d, fakeroot = %d\n", - (int) ruid, (fakeroot != 0)); +// printf ("real = %d, = %d, fakeroot = %d\n", (int) ruid, (fakeroot != 0)); #endif - for (wlp = wrapped_list; wlp->prog && strcmp (program_name, wlp->prog); - ++wlp) - ; + for (wlp = wrapped_list; wlp->prog && strcmp (program_name, wlp->prog); ++wlp) + /* __asm__ __volatile__("": : :"memory") */; if (!wlp->prog) { fprintf (stderr, _("Don't know which program should I run being >%s<\n"), program_name); return -ENOENT; } - - if (!fakeroot && ruid == 0) { +#ifdef DEBUG + printf ("%s\n", wlp->run); +#endif + if (/* !fakeroot && */ (ruid == 0 || euid == 0)) { pwd = getpwnam (wlp->user); - /* - if (!pwd - || setgid (pwd->pw_gid) - || initgroups (wlp->user, pwd->pw_gid) - || setuid (pwd->pw_uid)) { - fprintf (stderr, _("%s: Failed su to user %s\n"), - wlp->prog, wlp->user); - return -EACCES; - } - */ if (!pwd) { - fprintf (stderr, _("%s: Failed su to user %s\n"), - wlp->prog, wlp->user); + fprintf (stderr, _("%s: Failed su to user %s\n"), wlp->prog, wlp->user); return -EACCES; } - if (setgid (pwd->pw_gid)) { - fprintf (stderr, _("%s: Failed su to user %s\n"), - wlp->prog, wlp->user); + if (ruid == 0) { + ruid = pwd->pw_uid; + rgid = pwd->pw_gid; + } else { +#ifndef MAN_CATS + /* No permissions required to create files + * under the sub directories of /var/chache/man */ + pwd->pw_uid = ruid; + pwd->pw_gid = rgid; +#endif + } + if (setregid (rgid, pwd->pw_gid)) { + fprintf (stderr, _("%s: Failed su to user %s\n"), wlp->prog, wlp->user); return -EACCES; } - if (initgroups (wlp->user, pwd->pw_gid)) { - fprintf (stderr, _("%s: Failed su to user %s\n"), - wlp->prog, wlp->user); + if (initgroups (wlp->user, rgid)) { + fprintf (stderr, _("%s: Failed su to user %s\n"), wlp->prog, wlp->user); return -EACCES; } - if (setuid (pwd->pw_uid)) { - fprintf (stderr, _("%s: Failed su to user %s\n"), - wlp->prog, wlp->user); + if (setreuid (ruid, pwd->pw_uid)) { + fprintf (stderr, _("%s: Failed su to user %s\n"), wlp->prog, wlp->user); return -EACCES; } } - execv (wlp->run, argv); - perror ("execv"); + execve (wlp->run, argv, envp); + perror ("execve"); return -errno; }