Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 26 Jul 1995 00:27:46 +0200
From:      Wolfram Schneider <w@cs.tu-berlin.de>
To:        current@freebsd.org
Subject:   Manual page checker
Message-ID:  <199507252227.AAA06375@localhost.cs.tu-berlin.de>

next in thread | raw e-mail | index | archive | help


$ ./manck.pl /usr/share/man/man2/* 

/usr/share/man/man2/execve.2.gz
No entry for `exit' in section 2 (mandir /usr/share/man)
/usr/share/man/cat3/exit.3.gz (source: /usr/share/man/man3/exit.3.gz)
/usr/share/man/man2/fsync.2.gz
No entry for `update' in section 8 (mandir /usr/share/man)
/usr/share/man/man2/getegid.2.gz
No entry for `setgid' in section 3 (mandir /usr/share/man)
/usr/share/man/cat2/setgid.2.gz (source: /usr/share/man/man2/setgid.2.gz)
[...]
/usr/share/man/man2/quotactl.2.gz
ufs/quota.h: include does not exist in: /usr/include /usr/local/include
[...]

$ ./manck.pl /usr/share/man/man1/tic.1.gz 
/usr/share/man/man1/tic.1.gz
/usr/lib/terminfo: file does not exist
/usr/lib/terminfo/terminfo.src: file does not exist
No entry for `infocmp' in section 1M (mandir /usr/share/man)
No entry for `term' in section 4 (mandir /usr/share/man)
/usr/share/man/cat5/term.5.gz (source: /usr/share/man/man5/term.5.gz)
No entry for `termcap' in section 4 (mandir /usr/share/man)
/usr/share/man/cat3/termcap.3.gz (source: /usr/share/man/man3/termcap.3.gz)
No entry for `terminfo' in section 4 (mandir /usr/share/man)
/usr/share/man/cat5/terminfo.5.gz (source: /usr/share/man/man5/terminfo.5.gz)


# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	manck.pl
#	manck.1
#
echo x - manck.pl
sed 's/^X//' >manck.pl << 'END-of-manck.pl'
X:
Xeval "exec perl -S $0 $*"
X         if $running_under_some_shell;
X
X#
X# Copyright (c) 1995 Wolfram Schneider <wosch@cs.tu-berlin.de>
X# All rights reserved. Alle Rechte vorbehalten. 
X#
X# $Id: manck.pl,v 1.5 1995/07/25 22:21:05 w Exp w $
X#
X# manck - check manual pages
X
Xsub var {
X    $ENV{'PATH'} = '/bin:/usr/bin';
X
X    $path = '/bin:/sbin:/usr/bin:/usr/sbin';
X    @man = ('/usr/bin/man', '-w');
X
X    $manpath = '/usr/share/man';
X    $incpath = '/usr/include:/usr/local/include';
X
X    #$manpath = '/usr/tmp/man';
X    
X    $ext = '.gz';
X    $zcat = 'gzcat';
X
X    # 0: only errors 1: some more information 2: verbose
X    $debug = 0;
X
X    require "stat.pl";
X    $| = 1;
X}
X
Xsub usage {
X
X    warn <<EOF;
Xusage: manck [-d|-debug] [-d|-debug] [-h|-help] [-bin path] 
X             [-i|-include includepath] [-M mandir] [manpages ...]
XEOF
X    exit 1;
X}
X
Xsub parse {
X    local(*argv) = @_;
X
X    while ($_ = $argv[0], /^-/) {
X	shift @argv;
X	last if /^--$/;
X	if    (/^--?(d|debug)$/)        { $debug++ }
X	elsif (/^--?(h|help|\?)$/)      { &usage }
X	elsif (/^--?(b|bin)$/)          { exit(&bin($argv[0] || $path));  }
X	elsif (/^-M$/)		        { $manpath = $argv[0]; shift @argv;
X					  $manpath =~ s=/+$==; }
X	elsif (/^-r$/)                  {
X	    require "find.pl";
X	    eval 'sub wanted { 
X		$name =~ /^$manpath(\/man.*)?\/[^.\/]+\.[^\/]+$/ && 
X		    &manpage($name);
X	    }';
X	    $wanted = 1;
X	    #&find($manpath); 	        
X	}
X	elsif (/^-i|-include$/)         { $incpath = $argv[0]; shift @argv; }
X
X	else                            { &usage }
X    }
X
X    @include = split(/:/, $incpath);
X
X    # use absolute path
X    if ($manpath !~ "^/") {	
X	$manpath = ($ENV{'PWD'} || `pwd`) . '/' . $manpath;
X	$manpath =~ s/\n//g;
X    }
X
X    &find($manpath) if $wanted;
X}
X
X
X#
X# check if binaries in $path have their own manpages
X# use `man -w program' 
X#
Xsub bin {
X    local($path) = @_;
X    local($dir);
X
X    # dup
X    open(SAVEOUT, ">&STDOUT");
X    open(SAVEERR, ">&STDERR");
X
X    # swap stdin and stdout
X    # close stdout, redirect stderr to old stdout
X    close STDOUT;
X    open(STDERR, ">&SAVEOUT");
X
X    foreach $dir (split(/:/, $path)) {
X	warn "$dir\n";
X	opendir(DIR, $dir) || die "opendir: $dir $!\n";
X	foreach (readdir(DIR)) {
X	    next if $_ eq '.';
X	    next if $_ eq '..';
X
X	    system @man, $_;	# call man(1)
X	}
X	closedir DIR;
X    }
X
X    # restore stdout
X    open(STDOUT, ">&SAVEOUT");	
X    open(STDERR, ">&SAVEERR");
X}
X
X
X
X%sh = (
X'AUTHOR',            0,
X'AUTHORS',           0,
X'BUGS',              0,
X'CAVEATS',           0,
X'COMPATIBILITY',     0,
X'DESCRIPTION',       0,
X'DIAGNOSTICS',       0,
X'ENVIRONMENT',       0,
X'ERRORS',            0,
X'EXAMPLE',           0,
X'EXAMPLES',          0,
X'FILES',             '&files',
X'HISTORY',           0,
X'NAME',              0,
X'NOTES',             0,
X'OPTIONS',           0,
X'RETURN VALUE',      0,
X'RETURN VALUES',     0,
X'SEE ALSO',          '&see_also',
X'STANDARDS',         0,
X'SYNOPSIS',          '&synopsis',
X       );
X       
X# 
X# parse single manpage
X# and analyze
X#
Xsub manpage {
X    local($file) = @_;
X    local(@stat, $do, @list);
X
X    # cache
X    @stat = stat($file);
X    if (defined $cached_file{$stat[$ST_DEV],$stat[$ST_INO]}) {
X	&err("$file already visit: " . 
X	    "$cached_file{$stat[$ST_DEV],$stat[$ST_INO]}\n") if $debug > 1;
X	return 1;
X    }
X    $cached_file{$stat[$ST_DEV],$stat[$ST_INO]} = $file;
X
X    if ($file =~ /$ext$/o) {
X	$file = "$zcat $file |";
X    }
X    open(MANPAGE, "$file") || do {
X	warn "open: $file $!\n";
X	return 0;
X    };
X
X
X    while(<MANPAGE>) {
X	next if /^\.\\\"/o;	#" comment
X
X	if (/^\.S[hH]\s+/o) {	# .SH or .Sh
X	    # start action $do with following lines (until next .SH)
X	    eval $do;
X
X	    # reset action and array
X	    $do = ''; @list = ();
X
X	    $name = $_;
X	    $name =~ s/^\.S[hH]\s+\"?//; #"
X	    $name =~ s/\"?\s*$//;        #"
X
X	    if ($sh{$name}) {
X		&err("parse   $name\n") if $debug > 0;
X		$do = $sh{$name}; # save action
X
X	    } elsif (defined $sh{$name}) {
X		&err("defined $name\n") if $debug > 1;
X	    } else {
X		&err("undef   $name\n") if $debug > 0;
X	    }
X	} elsif ($do) {
X	    # \fBcurs_kernel\fR
X	    s=\\f[BRPI]==g;
X
X	    push(@list, $_);
X	}
X    }
X    eval $do;			# last .SH in file
X    close MANPAGE;
X}
X
X#
X# locate manpage, 
X# may be from cache or with stat
X#
Xsub find_manpage {
X    local($manpage, $section) = @_;
X
X    # failed from cache
X    if (defined $cached_mp{$manpage,$section} &&
X	!$cached_mp{$manpage,$section}) {
X	&err("man $section $manpage failed\n");
X	return 0;
X    }
X
X    # cache
X    &err("CACHE $manpage\n")
X	if $debug > 2 && $cached_mp{$manpage,$section};
X    return 1
X	if $cached_mp{$manpage,$section};
X
X    $cached_mp{$manpage,$section} = 1;
X
X    # test if manpage exist
X    if (-e "$manpath/man$section/$manpage.$section" ||
X	-e "$manpath/man$section/$manpage.$section$ext") {
X	return 1;
X    }
X
X    # may be wrong section, eg. '3X' instead '3'
X    if ($section =~ /^(.).$/ && -d "$manpath/man$1" &&
X	(-e "$manpath/man$1/$manpage.$1" ||
X	 -e "$manpath/man$1/$manpage.$1$ext")) {
X	return 1 if $debug < 1;
X	&err("manpage `$manpage' is in section `$1' and not $section\n");
X    }
X
X    # try with man(1)
X    print "@man $section $manpage\n" if $debug > 1;
X    open(SAVEERR, ">&STDERR"); close STDERR; 
X    system @man, $section, $manpage;	# call man(1) with section
X    open(STDERR, ">&SAVEERR");	
X    return 1 unless $?;
X    &err("No entry for `$manpage' in section $section (mandir $manpath)\n");
X
X    # second try with man(1), without explicit section
X    print "@man $manpage\n" if $debug > 1;
X    open(SAVEERR, ">&STDERR"); close STDERR; 
X    system @man, $manpage;	# call man(1) whithout section
X    open(STDERR, ">&SAVEERR");	
X    return 1 unless $?;
X
X    # manpage not found
X    return 0;
X}
X
X# print error messages
Xsub err {
X    if (!$cache_err{$file}) {
X	local($f) = $file; $f =~ s/^$zcat\s//; 	$f =~ s/\s+\|$//;
X	print "$f\n";
X	$cache_err{$file} = 1;
X    }
X    print @_;
X}
X
X#
X# .SH SEE ALSO
X# test if manpages exist
X#
Xsub see_also {
X    foreach (@list) {
X	s/\s+$//;		# strip ending blanks
X	s/\"//g;		# remove '"'
X
X	#if (/^$/) {
X	#    &err("stop SEE ALSO empty line\n") if $debug > 1;
X	#    return;
X	#}
X
X	foreach (split(/,/)) {
X	    s/^\s+//;
X
X	    # BSD
X	    if (/^\.(Xr|Fn)\s+(\S+)\s+(\S+)/o) {
X		&find_manpage($2, $3) && $debug > 1 &&
X		    &err("found manpage: $3 $2\n"); 
X		
X	    } 
X	    # GNU
X	    elsif (/^(\.[BI]R\s)?\s*(\S+)\s*\(\s*(\S+)\s*\)/o) {
X		&find_manpage($2, $3) && $debug > 1 &&
X		    &err("fond manpage: $3 $2\n");
X	    } 
X	    # Doku follow, break
X	    elsif (/^\.(sp|Rs|LP|br|TP|RB|PP|Pp|%)/o || 
X		   /^RFC/o) {
X		&err("stop SEE ALSO: $_\n") if $debug > 1;
X		return;
X	    }
X
X	    # Hm
X	    elsif (/^\.(Bl|It)/) {
X		&err("skip: `$_'\n") if $debug > 0;
X	    }
X
X	    # Garbage
X	    else {
X		&err("unknown: `$_'\n") if $debug > 0;
X	    }
X	}
X    }
X}
X
X#
X# .SH FILES
X# test if files exist
X#
Xsub files {
X    foreach (@list) {
X	next if /^\.(Bl|El|\\\")/;
X
X	# .TP \w'/etc/manpath.config'u+2n
X	s/\s\\w'([^\']+)'.*/ $1/; #"
X
X	if (s=.*\s(\S+)\s*$=$1= && /\//) {
X	    s/\s+$//;
X	    s/[\s\'\"].*//;	# "
X	    
X	    next unless $_;
X	    next if $debug < 1 && !/^\//;
X
X	    &err("test -e $_\n") if $debug > 1;
X	    if (! -e $_) {
X		# spool/temp files
X		return 1 if $debug < 1 && /[X?*\]\#]$/o;
X		return 1 if $debug < 1 && /[\$\[\?]/;
X
X		&err("$_: file does not exist\n");
X	    }
X	}
X    }
X}
X
X#
X# .SH SYNOPSIS
X# test for include files
X#
Xsub synopsis {
X    local($inc);
X
X    foreach (@list) {
X	if (/\#include\s+[<"](\S+)[>"]/) { #
X	    if ($cached_file{$1}) {
X		&err("CACHED file: $1\n") if $debug > 2;
X		next;
X	    }
X
X	    $cached_file{$1} = 1;
X	    
X	    &err("$1: include does not exist in: @include\n")
X		unless &include_test($1);
X	} 
X    }
X}
X
Xsub include_test {
X    foreach $inc (@include) {
X	&err("test -f $inc/$1\n") if $debug > 1;
X	return 1
X	    if -f "$inc/$1";
X    }
X    return 0;
X}
X
X
X##
X## Main
X##
X# read enviroment
X&var;
X
X# check /usr/share/man if no arguments given
Xpush(@ARGV, '-M', $manpath) if $#ARGV < 0;
X
X# parse
X&parse(*ARGV);
X&usage if $#ARGV < 0 && !$wanted;
X
X# check single manpages
Xforeach (@ARGV) { &manpage($_); }
X
END-of-manck.pl
echo x - manck.1
sed 's/^X//' >manck.1 << 'END-of-manck.1'
X.\"
X.\" Copyright (c) 1995 Wolfram Schneider <wosch@cs.tu-berlin.de>
X.\" All rights reserved. Alle Rechte vorbehalten. 
X.\"
X.\" $Id: manck.1,v 1.2 1995/07/25 22:03:33 w Exp $
X.\"
X.\" manck - check manual pages
X.Dd July 25, 1995
X.Os FreeBSD 2.2 
X.Dt MANCK 1
X.Sh NAME
X.Nm manck
X.Nd check manual pages
X.Sh SYNOPSIS
X.Nm manck
X.Op Fl d 
X.Op Fl h \&| Ns Fl \&?
X.Op Fl help
X.Op Fl bin Ar path
X.Op Fl i \&| Ns Fl include Ar includepath
X.Op Fl M Ar mandir
X.Op Ar manpages ...
X.Sh DESCRIPTION
X.Nm Manck
Xcheck manual pages. Currently supported section FILES, SEE ALSO, and
XSYNOPSIS.
X
X.Pp
XThe options are as follows:
X
X.Bl -tag -width 10n -offset indent
X.It Fl d \&| Ns Fl debug
XBe more verbose about what will be done.  For a single
X.Fl d
Xoption, print more errors and warnings. If the option
X.Fl d
Xhas been specified at least twice, print verbose errors and warnings.
XOne
X.Fl d
Xis recommend for carefully review.
X
X.It Fl h \&| Ns Fl \&?
X.It Fl help
XGive a help on the command usage and exit.
X
X.It Fl i \&| Ns Fl include Ar includepath
XPath where include files located. 
XColons in 
X.Ar includepath
Xallowed. Default /usr/include:/usr/local/include.
X
X.It Fl M Ar mandir
XUse 
X.Ar mandir 
Xas directory, where manpages located.
X.It Fl bin Ar path
XLook for binaries in 
X.Ar path
Xwhithout manpage. Colons in 
X.Ar path 
Xallowed. Default /bin:/sbin:/usr/bin:/usr/sbin
X
X.It Fl r
XTraverse recursive mandir (default /usr/share/man).
X.El
X
X.Sh EXAMPLES
X.Pp
X.Dl $ manck -bin 
X.Pp
XTest if all binaries in /bin:/sbin:/usr/bin:/usr/sbin have their own
Xmanpages
X
X.Pp
X.Dl $ manck -M /usr/share/man  /usr/share/man/man1/z*
X.Pp
XCheck all manpages with leading 'z' in /usr/share/man/man1.
X
X.Pp
X.Dl $ manck -r
X.Pp
XCheck recursive all manpages in /usr/share/man.
X
X.Sh FILES
X.Bl -tag -width /usr/share/man -compact
X.Pa /usr/share/man
Xdirectory for manual pages.
X.El
X
X.Sh ENVIROMENT
X.Bl -tag -width ENVIROMENT
X.Pa MANPATH
Xenviroment variable for man(1).
X
X.El
X
X.Sh SEE ALSO
X.Xr man 1 ,
X.Xr hier 7 .
X
X.Sh HISTORY
X.Nm manck
Xappeared in late July 1995.
X
X.Sh AUTHOR
XWolfram Schneider <wosch@cs.tu-berlin.de>
X
END-of-manck.1
exit




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199507252227.AAA06375>