Wolfram's replacement for the oldish ugly catman(1) program. The new

one is much more intelligent, not only that it would accept multiple
man page locations, it also behaves like ``make'' in that it will only
deal with cat pages that are out of date (by default).

Wolfram also wrote a man page for it.

Submitted by:	wosch@cs.tu-berlin.de (Wolfram Schneider)
This commit is contained in:
Joerg Wunsch 1995-03-15 22:47:38 +00:00
parent 66b0ec7d86
commit 01e694c2e2
3 changed files with 487 additions and 23 deletions

View File

@ -1,26 +1,7 @@
FILES= catman
NOMAN= noman
MAN1= catman.1
CLEANFILES+= ${FILES}
all: ${FILES}
# XXX null suffixes are currently broken
# .SUFFIXES:
# .SUFFIXES: .sh
# .sh:
# sed -e 's,%compress%,${compress},' \
# -e 's,%compext%,${compext},' \
# -e 's,%zcat%,${zcat},' \
# ${.IMPSRC} > ${.TARGET}
catman: catman.sh
sed -e 's,%compress%,${compress},' \
-e 's,%compext%,${compext},' \
-e 's,%zcat%,${zcat},' \
${.CURDIR}/${.TARGET}.sh > ${.TARGET}
install:
install -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
${FILES} ${DESTDIR}${BINDIR}
beforeinstall:
${INSTALL} -c -o ${BINOWN} -g ${BINGRP} -m ${BINMODE} \
${.CURDIR}/catman.perl ${DESTDIR}${BINDIR}/catman
.include <bsd.prog.mk>

View File

@ -0,0 +1,146 @@
.\"
.\" (c) Copyright 1995 Wolfram Schneider. All rights reserved.
.\"
.\" Redistribution and use in source and binary forms, with or without
.\" modification, are permitted provided that the following conditions
.\" are met:
.\" 1. Redistributions of source code must retain the above copyright
.\" notice, this list of conditions and the following disclaimer.
.\" 2. Redistributions in binary form must reproduce the above copyright
.\" notice, this list of conditions and the following disclaimer in the
.\" documentation and/or other materials provided with the distribution.
.\" 3. All advertising materials mentioning features or use of this software
.\" must display the following acknowledgement:
.\" This product includes software developed by Wolfram Schneider
.\" 4. The name of the author may not be used to endorse or promote products
.\" derived from this software without specific prior written permission
.\"
.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.\"
.\" /usr/bin/catman - preformat man pages
.\"
.\" E-mail: Wolfram Schneider <wosch@cs.tu-berlin.de>
.\"
.\" $Id: catman.1,v 1.5 1995/03/14 18:09:55 w Exp w $
.\"
.Dd Mar 12, 1995
.Dt CATMAN 1
.Os
.Sh NAME
.Nm catman
.Nd preformat man pages
.Sh SYNOPSIS
.Nm catman
.Op Fl h | Fl help
.Op Fl f | Fl force
.Op Fl p | Fl print
.Op Fl v | Fl verbose
.Op Fl directories...
.Sh DESCRIPTION
.Nm Catman
format man pages to ASCII/Latin-1. It's like typing
.Sq man program
for all man pages in
.Ar directories .
.Ar Directories
is a list of man directories or subdirectories separated
by spaces or colons.
Use
.Ar /usr/share/man
if no
.Ar directories
defined.
.Sh OPTIONS
.Bl -tag -width Ds
.It Fl h , Fl help
Print options and exit.
.It Fl v , Fl verbose
More warnings.
.It Fl f , Fl force
Force overwriting old cat pages. Normally only those pages will be formatted
which are not up to date. This option is a waste of time, CPU and RAM.
.It Fl p , Fl print
Don't actually format man pages. Show what would be done.
.Sh EXAMPLES
.Pp
.Dl $ catman
.Pp
Format man pages in
.Ar /usr/share/man
if neccessary.
.Pp
.Dl $ catman $MANPATH
.Pp
Format all your man pages if neccessary.
.Pp
.Dl $ catman -o /usr/local/man/man1 /usr/local/man/manl
.Pp
Force reformatting of all man pages in
.Pa /usr/local/man/man1
and
.Pa /usr/local/man/manl .
.Pp
.Dl $ catman -p /usr/X11/man
.Pp
Show only.
.Sh FILES
.Bl -tag -width /etc/master.passwdxx -compact
.Pa /etc/weekly :
start this program
.Po
or
.Pa /etc/daily
.Pc
.El
.Sh FEATURES
Very fast if all man pages already formatted.
.Sh BUGS
.Xr man 1
is a setuid program. Be careful that user
.Sq man
has write permissions to the catman directories.
.Nm Catman
does not check for any
.Sq .so
in man page sources. Use hard or symlinks
to avoid redundant formatted man pages.
.Sh SEE ALSO
.Xr man 1 ,
.Xr manpath 1 ,
.Xr makewhatis 1 .
.Sh HISTORY
This version of
.Nm catman
command appeared in FreeBSD 2.1
.Sh AUTHOR
Wolfram Schneider
.Aq wosch@cs.tu-berlin.de ,
Germany.

View File

@ -0,0 +1,337 @@
#!/usr/bin/perl
#
# Copyright (c) March 1995 Wolfram Schneider. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
# 3. All advertising materials mentioning features or use of this software
# must display the following acknowledgement:
# This product includes software developed by Wolfram Schneider
# 4. The name of the author may not be used to endorse or promote products
# derived from this software without specific prior written permission
#
# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
# SUCH DAMAGE.
#
# /usr/bin/catman - preformat man pages
#
# /etc/weekly: catman `manpath -q`
#
# Bugs: sure
# Email: Wolfram Schneider <wosch@cs.tu-berlin.de>
#
# $Id: catman.perl,v 1.9 1995/03/15 01:27:11 w Exp $
#
sub usage {
warn <<EOF;
usage: catman [-h|-help] [-f|-force] [-p|-print]
[-v|-verbose] directories ...
EOF
exit 1;
}
sub variables {
$force = 0; # force overwriting existing catpages
$verbose = 0; # more warnings
$print = 0; # show only, do nothing
$remove = 0; # unlink forgotten man/catpages
# if no argument for directories given
@defaultmanpath = ( '/usr/share/man' );
$exit = 0; # exit code
$ext = ".gz"; # extension
umask(022);
# Signals
$SIG{'INT'} = 'Exit';
$SIG{'HUP'} = 'Exit';
$SIG{'TRAP'} = 'Exit';
$SIG{'QUIT'} = 'Exit';
$SIG{'TERM'} = 'Exit';
$tmp = ''; # tmp file
$ENV{'PATH'} = "/bin:/usr/bin:$ENV{'PATH'}";
}
sub Exit {
unlink($tmp) if $tmp =~ /^\//; # unlink if a filename
die "catman: die on signal SIG@_\n";
}
sub parse {
local(@argv) = @_;
while($_ = $argv[0], /^-/) {
shift @argv;
last if /^--$/;
if (/^--?(f|force)$/) { $force = 1 }
elsif (/^--?(p|print)$/) { $print = 1 }
# elsif (/^--?(r|remove)$/) { $remove = 1 }
elsif (/^--?(v|verbose)$/) { $verbose = 1 }
else { &usage }
}
return @argv if $#argv >= 0;
return @defaultmanpath if $#defaultmanpath >= 0;
warn "Missing directories\n"; &usage;
}
# stript unused '/'
# e.g.: //usr///home// -> /usr/home
sub stripdir {
local($dir) = @_;
$dir =~ s|/+|/|g; # delete double '/'
$dir =~ s|/$||; # delete '/' at end
return $dir if $dir ne "";
return '/';
}
# read man directory
sub parse_dir {
local($dir) = @_;
local($subdir, $catdir);
local($pwd);
# not absolute path
if ($dir !~ /^\//) {
chop($cwd = `pwd`);
$dir = "$cwd/$dir";
}
if ($dir =~ /man$/) {
warn "open manpath directory ``$dir''\n" if $verbose;
if (!opendir(DIR, $dir)) {
warn "opendir ``$dir'':$!\n"; $exit = 1; return 0;
}
foreach $subdir (sort(readdir(DIR))) {
if ($subdir =~ /^man\w+$/) {
$subdir = "$dir/$subdir";
&catdir_create($subdir) && &parse_subdir($subdir);
}
}
closedir DIR
} elsif ($dir =~ /man\w+$/) {
&catdir_create($dir) && &parse_subdir($dir);
} else {
warn "Assume ``$dir'' is not a man directory.\n";
$exit = 1;
}
}
# create cat subdirectory if neccessary
# e.g.: man9 exist, but cat9 not
sub catdir_create {
local($subdir) = @_;
local($catdir) = $subdir;
$catdir = &man2cat($subdir);
if (-d $catdir) {
return 1 if -w _;
if (!chmod(755, $catdir)) {
warn "Cannot write $catdir, chmod: $!\n";
$exit = 1;
return 0;
}
}
warn "mkdir ``$catdir''\n" if $verbose || $print;
unless ($print) {
unlink($catdir); # be paranoid
if (!mkdir($catdir, 0755)) {
warn "Cannot make $catdir: $!\n";
$exit = 1;
return 0;
}
}
return 1;
}
# I: /usr/share/man/man9
# O: usr/share/man/cat9
sub man2cat {
local($man) = @_;
$man =~ s/man(\w+)/cat$1/;
return $man;
}
sub parse_subdir {
local($subdir) = @_;
local($file, $f, $catdir, $catdir_short);
local($mtime_man, $mtime_cat);
local($read);
if (!opendir(D, $subdir)) {
warn "opendir ``$subdir'': $!\n"; return 0;
}
$catdir = &man2cat($subdir);
# optimize NAMI lookup, use short filenames
warn "chdir to: $subdir\n" if $verbose;
chdir($subdir);
$catdir_short = $catdir;
$catdir_short =~ s|.*/(.*)|../$1|;
warn "open man directory: ``$subdir''\n" if $verbose;
foreach $file (readdir(D)) {
next if $file =~ /^(\.|\.\.)$/; # skip current and parent directory
$read{$file} = 1;
# replace readable_file with stat && ...
# faster, hackers choise :-)
if (!(($mtime_man = ((stat("$file"))[9])) && -r _ && -f _)) {
if (! -d _) {
warn "Cannot read file: ``$subdir/$file''\n";
$exit = 1;
next;
}
warn "Ignore subsubdirectory: ``$subdir/$file''\n"
if $verbose;
next;
}
# fo_09-o.bar0
if ($file !~ /^[\w\-\[\.]+\.\w+$/) {
warn "Assume garbage: ``$subdir/$file''\n";
next;
}
# Assume catpages always compressed
# if ($mtime_cat = &readable_file("$catdir_short/$file")) {
if (($mtime_cat = ((stat("$catdir_short/$file"))[9]))
&& -r _ && -f _) {
if ($mtime_man > $mtime_cat || $force) {
&nroff("$subdir/$file", "$catdir/$file");
} else {
warn "up to date: $subdir/$file\n" if $verbose;
}
} elsif (($mtime_cat = ((stat("$catdir_short/$file$ext"))[9]))
&& -r _ && -f _) {
if ($mtime_man > $mtime_cat || $force) {
&nroff("$subdir/$file", "$catdir/$file");
} else {
warn "up to date: $subdir/$file\n" if $verbose;
}
} else {
# be paranoid
unlink("$catdir/$file");
&nroff("$subdir/$file", "$catdir/$file");
}
}
closedir D;
if (!opendir(D, $catdir)) {
warn "opendir ``$catdir'': $!\n"; return 0;
}
warn "open cat directory: ``$catdir''\n" if $verbose;
foreach $file (readdir(D)) {
next if $file =~ /^(\.|\.\.)$/; # skip current and parent directory
if ($file !~ /^[\w\-\[\.]+\.\w+$/) {
warn "Assume garbage: ``$catdir/$file''\n"
unless -d "$catdir/$file";
}
unless ($read{$file}) {
# maybe a bug in man(1)
# if both manpage and catpage are uncompressed, man reformats
# the manpage and puts a compressed catpage to the
# already existing uncompressed catpage
$f = $file; $f =~ s/$ext$//;
# man page is uncompressed
next if $read{$f};
warn "Catpage without manpage: $catdir/$file\n";
}
}
closedir D;
}
sub nroff {
local($man,$cat) = @_;
local($nroff) = "groff -Tlatin1 -man | col";
local($dev, $ino) = (stat($man))[01];
# It's a link
if ($link{"$dev.$ino"}) {
warn "Link: $link{\"$dev.$ino\"} -> $cat\n" if $verbose || $print;
if (!$print && !link($link{"$dev.$ino"}, $cat)) {
warn "Link $cat: $!\n";
$exit = 1;
}
} else {
$cat = "$cat$ext" if $cat !~ /$ext$/;
warn "Format: $man -> $cat\n" if $verbose || $print;
unless($print) {
# man page is compressed
if ($man =~ /$ext$/) {
$nroff = "zcat $man | tbl | $nroff";
} else {
$nroff = "tbl $man | $nroff";
}
# start formatting
$tmp = "$cat.$tmp"; # for cleanup after signals
system("$nroff | gzip > $cat.tmp");
if ($?) {
# assume a fatal signal to nroff
&Exit("INT to system() funktion") if ($? == 2);
} else {
rename("$cat.tmp", $cat);
}
}
}
# dev/ino from manpage, path from catpage
$link{"$dev.$ino"} = $cat;
}
#############
# main
warn "Don't start this program as root, use:\n" .
"echo $0 @ARGV | nice -5 su -m man\n" unless $>;
&variables;
foreach $dir (&parse(split(/[ :]/, join($", @ARGV)))) { #"
if (-e $dir && -d _ && -r _ && -x _) {
warn "``$dir'' is not writable for you,\n" .
"can only write to existing cat subdirs (if any)\n"
if ! -w _ && $verbose;
&parse_dir(&stripdir($dir));
} else {
warn "``$dir'' is not a directory or not read-/searchable for you\n";
$exit = 1;
}
}
exit($exit);