xref: /freebsd/contrib/openpam/misc/gendoc.pl (revision 3ba4c8c8)
146acc370SDag-Erling Smørgrav#!/usr/bin/perl -w
246acc370SDag-Erling Smørgrav#-
331c521e9SDag-Erling Smørgrav# Copyright (c) 2002-2003 Networks Associates Technology, Inc.
449e56509SDag-Erling Smørgrav# Copyright (c) 2004-2017 Dag-Erling Smørgrav
546acc370SDag-Erling Smørgrav# All rights reserved.
646acc370SDag-Erling Smørgrav#
746acc370SDag-Erling Smørgrav# This software was developed for the FreeBSD Project by ThinkSec AS and
8ee02aaa9SDag-Erling Smørgrav# Network Associates Laboratories, the Security Research Division of
9ee02aaa9SDag-Erling Smørgrav# Network Associates, Inc.  under DARPA/SPAWAR contract N66001-01-C-8035
10ee02aaa9SDag-Erling Smørgrav# ("CBOSS"), as part of the DARPA CHATS research program.
1146acc370SDag-Erling Smørgrav#
1246acc370SDag-Erling Smørgrav# Redistribution and use in source and binary forms, with or without
1346acc370SDag-Erling Smørgrav# modification, are permitted provided that the following conditions
1446acc370SDag-Erling Smørgrav# are met:
1546acc370SDag-Erling Smørgrav# 1. Redistributions of source code must retain the above copyright
1646acc370SDag-Erling Smørgrav#    notice, this list of conditions and the following disclaimer.
1746acc370SDag-Erling Smørgrav# 2. Redistributions in binary form must reproduce the above copyright
1846acc370SDag-Erling Smørgrav#    notice, this list of conditions and the following disclaimer in the
1946acc370SDag-Erling Smørgrav#    documentation and/or other materials provided with the distribution.
2046acc370SDag-Erling Smørgrav# 3. The name of the author may not be used to endorse or promote
2146acc370SDag-Erling Smørgrav#    products derived from this software without specific prior written
2246acc370SDag-Erling Smørgrav#    permission.
2346acc370SDag-Erling Smørgrav#
2446acc370SDag-Erling Smørgrav# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2546acc370SDag-Erling Smørgrav# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2646acc370SDag-Erling Smørgrav# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2746acc370SDag-Erling Smørgrav# ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2846acc370SDag-Erling Smørgrav# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2946acc370SDag-Erling Smørgrav# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3046acc370SDag-Erling Smørgrav# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3146acc370SDag-Erling Smørgrav# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3246acc370SDag-Erling Smørgrav# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3346acc370SDag-Erling Smørgrav# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3446acc370SDag-Erling Smørgrav# SUCH DAMAGE.
3546acc370SDag-Erling Smørgrav#
3646acc370SDag-Erling Smørgrav
3746acc370SDag-Erling Smørgravuse strict;
38ce77a8d6SDag-Erling Smørgravuse warnings;
39ce77a8d6SDag-Erling Smørgravuse open qw(:utf8);
40ce77a8d6SDag-Erling Smørgravuse utf8;
4146acc370SDag-Erling Smørgravuse Fcntl;
42ee02aaa9SDag-Erling Smørgravuse Getopt::Std;
43ce77a8d6SDag-Erling Smørgravuse POSIX qw(strftime);
44ce77a8d6SDag-Erling Smørgravuse vars qw(%AUTHORS $TODAY %FUNCTIONS %PAMERR);
45ee02aaa9SDag-Erling Smørgrav
467f106882SDag-Erling Smørgrav%AUTHORS = (
472f3ed619SDag-Erling Smørgrav    THINKSEC => "developed for the
482f3ed619SDag-Erling Smørgrav.Fx
492f3ed619SDag-Erling SmørgravProject by ThinkSec AS and Network Associates Laboratories, the
507f106882SDag-Erling SmørgravSecurity Research Division of Network Associates, Inc.\\& under
517f106882SDag-Erling SmørgravDARPA/SPAWAR contract N66001-01-C-8035
527f106882SDag-Erling Smørgrav.Pq Dq CBOSS ,
53ce77a8d6SDag-Erling Smørgravas part of the DARPA CHATS research program.
54ce77a8d6SDag-Erling Smørgrav.Pp
55ce77a8d6SDag-Erling SmørgravThe OpenPAM library is maintained by
56f3b0ac34SDag-Erling Smørgrav.An Dag-Erling Sm\\(/orgrav Aq Mt des\@des.no .",
57ce77a8d6SDag-Erling Smørgrav    UIO => "developed for the University of Oslo by
58f3b0ac34SDag-Erling Smørgrav.An Dag-Erling Sm\\(/orgrav Aq Mt des\@des.no .",
592f3ed619SDag-Erling Smørgrav    DES => "developed by
60f3b0ac34SDag-Erling Smørgrav.An Dag-Erling Sm\\(/orgrav Aq Mt des\@des.no .",
617f106882SDag-Erling Smørgrav);
627f106882SDag-Erling Smørgrav
6346acc370SDag-Erling Smørgrav%PAMERR = (
6446acc370SDag-Erling Smørgrav    PAM_SUCCESS			=> "Success",
6546acc370SDag-Erling Smørgrav    PAM_OPEN_ERR		=> "Failed to load module",
6646acc370SDag-Erling Smørgrav    PAM_SYMBOL_ERR		=> "Invalid symbol",
6746acc370SDag-Erling Smørgrav    PAM_SERVICE_ERR		=> "Error in service module",
6846acc370SDag-Erling Smørgrav    PAM_SYSTEM_ERR		=> "System error",
6946acc370SDag-Erling Smørgrav    PAM_BUF_ERR			=> "Memory buffer error",
7046acc370SDag-Erling Smørgrav    PAM_CONV_ERR		=> "Conversation failure",
7146acc370SDag-Erling Smørgrav    PAM_PERM_DENIED		=> "Permission denied",
7246acc370SDag-Erling Smørgrav    PAM_MAXTRIES		=> "Maximum number of tries exceeded",
7346acc370SDag-Erling Smørgrav    PAM_AUTH_ERR		=> "Authentication error",
7446acc370SDag-Erling Smørgrav    PAM_NEW_AUTHTOK_REQD	=> "New authentication token required",
7546acc370SDag-Erling Smørgrav    PAM_CRED_INSUFFICIENT	=> "Insufficient credentials",
7646acc370SDag-Erling Smørgrav    PAM_AUTHINFO_UNAVAIL	=> "Authentication information is unavailable",
7746acc370SDag-Erling Smørgrav    PAM_USER_UNKNOWN		=> "Unknown user",
7846acc370SDag-Erling Smørgrav    PAM_CRED_UNAVAIL		=> "Failed to retrieve user credentials",
7946acc370SDag-Erling Smørgrav    PAM_CRED_EXPIRED		=> "User credentials have expired",
8046acc370SDag-Erling Smørgrav    PAM_CRED_ERR		=> "Failed to set user credentials",
81b33ab329SDag-Erling Smørgrav    PAM_ACCT_EXPIRED		=> "User account has expired",
8246acc370SDag-Erling Smørgrav    PAM_AUTHTOK_EXPIRED		=> "Password has expired",
8346acc370SDag-Erling Smørgrav    PAM_SESSION_ERR		=> "Session failure",
8446acc370SDag-Erling Smørgrav    PAM_AUTHTOK_ERR		=> "Authentication token failure",
8546acc370SDag-Erling Smørgrav    PAM_AUTHTOK_RECOVERY_ERR	=> "Failed to recover old authentication token",
8646acc370SDag-Erling Smørgrav    PAM_AUTHTOK_LOCK_BUSY	=> "Authentication token lock busy",
8746acc370SDag-Erling Smørgrav    PAM_AUTHTOK_DISABLE_AGING	=> "Authentication token aging disabled",
8846acc370SDag-Erling Smørgrav    PAM_NO_MODULE_DATA		=> "Module data not found",
8946acc370SDag-Erling Smørgrav    PAM_IGNORE			=> "Ignore this module",
9046acc370SDag-Erling Smørgrav    PAM_ABORT			=> "General failure",
9146acc370SDag-Erling Smørgrav    PAM_TRY_AGAIN		=> "Try again",
9246acc370SDag-Erling Smørgrav    PAM_MODULE_UNKNOWN		=> "Unknown module type",
9346acc370SDag-Erling Smørgrav    PAM_DOMAIN_UNKNOWN		=> "Unknown authentication domain",
9449e56509SDag-Erling Smørgrav    PAM_BAD_HANDLE		=> "Invalid PAM handle",
9549e56509SDag-Erling Smørgrav    PAM_BAD_ITEM		=> "Unrecognized or restricted item",
9649e56509SDag-Erling Smørgrav    PAM_BAD_FEATURE		=> "Unrecognized or restricted feature",
9749e56509SDag-Erling Smørgrav    PAM_BAD_CONSTANT		=> "Bad constant",
9846acc370SDag-Erling Smørgrav);
9946acc370SDag-Erling Smørgrav
10046acc370SDag-Erling Smørgravsub parse_source($) {
10146acc370SDag-Erling Smørgrav    my $fn = shift;
10246acc370SDag-Erling Smørgrav
10346acc370SDag-Erling Smørgrav    local *FILE;
10446acc370SDag-Erling Smørgrav    my $source;
10546acc370SDag-Erling Smørgrav    my $func;
10646acc370SDag-Erling Smørgrav    my $descr;
10746acc370SDag-Erling Smørgrav    my $type;
10846acc370SDag-Erling Smørgrav    my $args;
10946acc370SDag-Erling Smørgrav    my $argnames;
11046acc370SDag-Erling Smørgrav    my $man;
11146acc370SDag-Erling Smørgrav    my $inlist;
1127f106882SDag-Erling Smørgrav    my $intaglist;
11346acc370SDag-Erling Smørgrav    my $inliteral;
1142f3ed619SDag-Erling Smørgrav    my $customrv;
1152f3ed619SDag-Erling Smørgrav    my $deprecated;
1162f3ed619SDag-Erling Smørgrav    my $experimental;
117ce77a8d6SDag-Erling Smørgrav    my $version;
11846acc370SDag-Erling Smørgrav    my %xref;
11949e56509SDag-Erling Smørgrav    my %errors;
1207f106882SDag-Erling Smørgrav    my $author;
12146acc370SDag-Erling Smørgrav
12246acc370SDag-Erling Smørgrav    if ($fn !~ m,\.c$,) {
12346acc370SDag-Erling Smørgrav	warn("$fn: not C source, ignoring\n");
124ee02aaa9SDag-Erling Smørgrav	return undef;
12546acc370SDag-Erling Smørgrav    }
12646acc370SDag-Erling Smørgrav
1277f106882SDag-Erling Smørgrav    open(FILE, "<", "$fn")
12846acc370SDag-Erling Smørgrav	or die("$fn: open(): $!\n");
12946acc370SDag-Erling Smørgrav    $source = join('', <FILE>);
13046acc370SDag-Erling Smørgrav    close(FILE);
13146acc370SDag-Erling Smørgrav
132ee02aaa9SDag-Erling Smørgrav    return undef
133ee02aaa9SDag-Erling Smørgrav	if ($source =~ m/^ \* NOPARSE\s*$/m);
13446acc370SDag-Erling Smørgrav
13549e56509SDag-Erling Smørgrav    if ($source =~ m/(\$OpenPAM:[^\$]+\$)/) {
136ce77a8d6SDag-Erling Smørgrav	$version = $1;
137ce77a8d6SDag-Erling Smørgrav    }
138ce77a8d6SDag-Erling Smørgrav
1397f106882SDag-Erling Smørgrav    $author = 'THINKSEC';
1402f3ed619SDag-Erling Smørgrav    if ($source =~ s/^ \* AUTHOR\s+(\w*)\s*$//m) {
1417f106882SDag-Erling Smørgrav	$author = $1;
1427f106882SDag-Erling Smørgrav    }
1437f106882SDag-Erling Smørgrav
1442f3ed619SDag-Erling Smørgrav    if ($source =~ s/^ \* DEPRECATED\s*(\w*)\s*$//m) {
1452f3ed619SDag-Erling Smørgrav	$deprecated = $1 // 0;
1462f3ed619SDag-Erling Smørgrav    }
1472f3ed619SDag-Erling Smørgrav
1482f3ed619SDag-Erling Smørgrav    if ($source =~ s/^ \* EXPERIMENTAL\s*$//m) {
1492f3ed619SDag-Erling Smørgrav	$experimental = 1;
1502f3ed619SDag-Erling Smørgrav    }
1512f3ed619SDag-Erling Smørgrav
15246acc370SDag-Erling Smørgrav    $func = $fn;
15346acc370SDag-Erling Smørgrav    $func =~ s,^(?:.*/)?([^/]+)\.c$,$1,;
15446acc370SDag-Erling Smørgrav    if ($source !~ m,\n \* ([\S ]+)\n \*/\n\n([\S ]+)\n$func\((.*?)\)\n\{,s) {
15546acc370SDag-Erling Smørgrav	warn("$fn: can't find $func\n");
156ee02aaa9SDag-Erling Smørgrav	return undef;
15746acc370SDag-Erling Smørgrav    }
15846acc370SDag-Erling Smørgrav    ($descr, $type, $args) = ($1, $2, $3);
15946acc370SDag-Erling Smørgrav    $descr =~ s,^([A-Z][a-z]),lc($1),e;
16046acc370SDag-Erling Smørgrav    $descr =~ s,[\.\s]*$,,;
16146acc370SDag-Erling Smørgrav    while ($args =~ s/^((?:[^\(]|\([^\)]*\))*),\s*/$1\" \"/g) {
16246acc370SDag-Erling Smørgrav	# nothing
16346acc370SDag-Erling Smørgrav    }
16446acc370SDag-Erling Smørgrav    $args =~ s/,\s+/, /gs;
16546acc370SDag-Erling Smørgrav    $args = "\"$args\"";
16646acc370SDag-Erling Smørgrav
16746acc370SDag-Erling Smørgrav    %xref = (
168b33ab329SDag-Erling Smørgrav	3 => { 'pam' => 1 },
16946acc370SDag-Erling Smørgrav    );
17046acc370SDag-Erling Smørgrav
17146acc370SDag-Erling Smørgrav    if ($type eq "int") {
17246acc370SDag-Erling Smørgrav	foreach (split("\n", $source)) {
17349e56509SDag-Erling Smørgrav	    next unless (m/^ \*\t(!?PAM_[A-Z_]+|=[a-z_]+)\s*(.*?)\s*$/);
17449e56509SDag-Erling Smørgrav	    $errors{$1} = $2;
17546acc370SDag-Erling Smørgrav	}
176ce77a8d6SDag-Erling Smørgrav	++$xref{3}->{pam_strerror};
17746acc370SDag-Erling Smørgrav    }
17846acc370SDag-Erling Smørgrav
17946acc370SDag-Erling Smørgrav    $argnames = $args;
180b33ab329SDag-Erling Smørgrav    # extract names of regular arguments
18146acc370SDag-Erling Smørgrav    $argnames =~ s/\"[^\"]+\*?\b(\w+)\"/\"$1\"/g;
182b33ab329SDag-Erling Smørgrav    # extract names of function pointer arguments
183b33ab329SDag-Erling Smørgrav    $argnames =~ s/\"([\w\s\*]+)\(\*?(\w+)\)\([^\)]+\)\"/\"$2\"/g;
184b33ab329SDag-Erling Smørgrav    # escape metacharacters (there shouldn't be any, but...)
18546acc370SDag-Erling Smørgrav    $argnames =~ s/([\|\[\]\(\)\.\*\+\?])/\\$1/g;
186b33ab329SDag-Erling Smørgrav    # separate argument names with |
18746acc370SDag-Erling Smørgrav    $argnames =~ s/\" \"/|/g;
188b33ab329SDag-Erling Smørgrav    # and surround with ()
1892f3ed619SDag-Erling Smørgrav    $argnames =~ s/^\"(.*)\"$/$1/;
190b33ab329SDag-Erling Smørgrav    # $argnames is now a regexp that matches argument names
1917f106882SDag-Erling Smørgrav    $inliteral = $inlist = $intaglist = 0;
19246acc370SDag-Erling Smørgrav    foreach (split("\n", $source)) {
19346acc370SDag-Erling Smørgrav	s/\s*$//;
19446acc370SDag-Erling Smørgrav	if (!defined($man)) {
19546acc370SDag-Erling Smørgrav	    if (m/^\/\*\*$/) {
19646acc370SDag-Erling Smørgrav		$man = "";
19746acc370SDag-Erling Smørgrav	    }
19846acc370SDag-Erling Smørgrav	    next;
19946acc370SDag-Erling Smørgrav	}
20046acc370SDag-Erling Smørgrav	last if (m/^ \*\/$/);
20146acc370SDag-Erling Smørgrav	s/^ \* ?//;
20246acc370SDag-Erling Smørgrav	s/\\(.)/$1/gs;
20346acc370SDag-Erling Smørgrav	if (m/^$/) {
2047f106882SDag-Erling Smørgrav	    # paragraph separator
2052f3ed619SDag-Erling Smørgrav	    if ($inlist || $intaglist) {
2062f3ed619SDag-Erling Smørgrav		# either a blank line between list items, or a blank
2072f3ed619SDag-Erling Smørgrav		# line after the final list item.  The latter case
2082f3ed619SDag-Erling Smørgrav		# will be handled further down.
2092f3ed619SDag-Erling Smørgrav		next;
2102f3ed619SDag-Erling Smørgrav	    }
2112f3ed619SDag-Erling Smørgrav	    if ($man =~ m/\n\.Sh [^\n]+\n$/s) {
2122f3ed619SDag-Erling Smørgrav		# a blank line after a section header
2132f3ed619SDag-Erling Smørgrav		next;
2142f3ed619SDag-Erling Smørgrav	    }
21546acc370SDag-Erling Smørgrav	    if ($man ne "" && $man !~ m/\.Pp\n$/s) {
21646acc370SDag-Erling Smørgrav		if ($inliteral) {
21746acc370SDag-Erling Smørgrav		    $man .= "\0\n";
21846acc370SDag-Erling Smørgrav		} else {
21946acc370SDag-Erling Smørgrav		    $man .= ".Pp\n";
22046acc370SDag-Erling Smørgrav		}
22146acc370SDag-Erling Smørgrav	    }
22246acc370SDag-Erling Smørgrav	    next;
22346acc370SDag-Erling Smørgrav	}
224b33ab329SDag-Erling Smørgrav	if (m/^>(\w+)(\s+\d)?$/) {
2257f106882SDag-Erling Smørgrav	    # "see also" cross-reference
226b33ab329SDag-Erling Smørgrav	    my ($page, $sect) = ($1, $2 ? int($2) : 3);
227b33ab329SDag-Erling Smørgrav	    ++$xref{$sect}->{$page};
22846acc370SDag-Erling Smørgrav	    next;
22946acc370SDag-Erling Smørgrav	}
2302f3ed619SDag-Erling Smørgrav	if (s/^([A-Z][0-9A-Z -]+)$/.Sh $1/) {
2312f3ed619SDag-Erling Smørgrav	    if ($1 eq "RETURN VALUES") {
2322f3ed619SDag-Erling Smørgrav		$customrv = $1;
2332f3ed619SDag-Erling Smørgrav	    }
2342f3ed619SDag-Erling Smørgrav	    $man =~ s/\n\.Pp$/\n/s;
2352f3ed619SDag-Erling Smørgrav	    $man .= "$_\n";
2362f3ed619SDag-Erling Smørgrav	    next;
2372f3ed619SDag-Erling Smørgrav	}
2387f106882SDag-Erling Smørgrav	if (s/^\s+-\s+//) {
2397f106882SDag-Erling Smørgrav	    # item in bullet list
24046acc370SDag-Erling Smørgrav	    if ($inliteral) {
24146acc370SDag-Erling Smørgrav		$man .= ".Ed\n";
24246acc370SDag-Erling Smørgrav		$inliteral = 0;
24346acc370SDag-Erling Smørgrav	    }
2447f106882SDag-Erling Smørgrav	    if ($intaglist) {
2457f106882SDag-Erling Smørgrav		$man .= ".El\n.Pp\n";
2467f106882SDag-Erling Smørgrav		$intaglist = 0;
2477f106882SDag-Erling Smørgrav	    }
24846acc370SDag-Erling Smørgrav	    if (!$inlist) {
24946acc370SDag-Erling Smørgrav		$man =~ s/\.Pp\n$//s;
2507f106882SDag-Erling Smørgrav		$man .= ".Bl -bullet\n";
25146acc370SDag-Erling Smørgrav		$inlist = 1;
25246acc370SDag-Erling Smørgrav	    }
2537f106882SDag-Erling Smørgrav	    $man .= ".It\n";
2547f106882SDag-Erling Smørgrav	    # fall through
2557f106882SDag-Erling Smørgrav	} elsif (s/^\s+(\S+):\s*/.It $1/) {
2567f106882SDag-Erling Smørgrav	    # item in tag list
2577f106882SDag-Erling Smørgrav	    if ($inliteral) {
2587f106882SDag-Erling Smørgrav		$man .= ".Ed\n";
2597f106882SDag-Erling Smørgrav		$inliteral = 0;
2607f106882SDag-Erling Smørgrav	    }
2617f106882SDag-Erling Smørgrav	    if ($inlist) {
2627f106882SDag-Erling Smørgrav		$man .= ".El\n.Pp\n";
2637f106882SDag-Erling Smørgrav		$inlist = 0;
2647f106882SDag-Erling Smørgrav	    }
2657f106882SDag-Erling Smørgrav	    if (!$intaglist) {
2667f106882SDag-Erling Smørgrav		$man =~ s/\.Pp\n$//s;
2677f106882SDag-Erling Smørgrav		$man .= ".Bl -tag -width 18n\n";
2687f106882SDag-Erling Smørgrav		$intaglist = 1;
2697f106882SDag-Erling Smørgrav	    }
270ce77a8d6SDag-Erling Smørgrav	    s/^\.It [=;]([A-Za-z][0-9A-Za-z_]+)$/.It Dv $1/gs;
27146acc370SDag-Erling Smørgrav	    $man .= "$_\n";
27246acc370SDag-Erling Smørgrav	    next;
2737f106882SDag-Erling Smørgrav	} elsif (($inlist || $intaglist) && m/^\S/) {
2747f106882SDag-Erling Smørgrav	    # regular text after list
275ee02aaa9SDag-Erling Smørgrav	    $man .= ".El\n.Pp\n";
2767f106882SDag-Erling Smørgrav	    $inlist = $intaglist = 0;
27746acc370SDag-Erling Smørgrav	} elsif ($inliteral && m/^\S/) {
2787f106882SDag-Erling Smørgrav	    # regular text after literal section
27946acc370SDag-Erling Smørgrav	    $man .= ".Ed\n";
280ac7e3b9dSDag-Erling Smørgrav	    $inliteral = 0;
28146acc370SDag-Erling Smørgrav	} elsif ($inliteral) {
2827f106882SDag-Erling Smørgrav	    # additional text within literal section
28346acc370SDag-Erling Smørgrav	    $man .= "$_\n";
28446acc370SDag-Erling Smørgrav	    next;
2857f106882SDag-Erling Smørgrav	} elsif ($inlist || $intaglist) {
2867f106882SDag-Erling Smørgrav	    # additional text within list
28746acc370SDag-Erling Smørgrav	    s/^\s+//;
28846acc370SDag-Erling Smørgrav	} elsif (m/^\s+/) {
2897f106882SDag-Erling Smørgrav	    # new literal section
29046acc370SDag-Erling Smørgrav	    $man .= ".Bd -literal\n";
29146acc370SDag-Erling Smørgrav	    $inliteral = 1;
29246acc370SDag-Erling Smørgrav	    $man .= "$_\n";
29346acc370SDag-Erling Smørgrav	    next;
29446acc370SDag-Erling Smørgrav	}
2952f3ed619SDag-Erling Smørgrav	s/\s*=($func)\b\s*/\n.Fn $1\n/gs;
2962f3ed619SDag-Erling Smørgrav	s/\s*=($argnames)\b\s*/\n.Fa $1\n/gs;
297f3b0ac34SDag-Erling Smørgrav	s/\s*=((?:enum|struct|union) \w+(?: \*)?)\b\s*/\n.Vt $1\n/gs;
298ce77a8d6SDag-Erling Smørgrav	s/\s*:([a-z][0-9a-z_]+)\b\s*/\n.Va $1\n/gs;
299ce77a8d6SDag-Erling Smørgrav	s/\s*;([a-z][0-9a-z_]+)\b\s*/\n.Dv $1\n/gs;
300ce77a8d6SDag-Erling Smørgrav	s/\s*=!([a-z][0-9a-z_]+)\b\s*/\n.Xr $1 3\n/gs;
301ce77a8d6SDag-Erling Smørgrav	while (s/\s*=([a-z][0-9a-z_]+)\b\s*/\n.Xr $1 3\n/s) {
302b33ab329SDag-Erling Smørgrav	    ++$xref{3}->{$1};
30346acc370SDag-Erling Smørgrav	}
30446acc370SDag-Erling Smørgrav	s/\s*\"(?=\w)/\n.Do\n/gs;
30546acc370SDag-Erling Smørgrav	s/\"(?!\w)\s*/\n.Dc\n/gs;
306ce77a8d6SDag-Erling Smørgrav	s/\s*=([A-Z][0-9A-Z_]+)\b\s*(?![\.,:;])/\n.Dv $1\n/gs;
307ce77a8d6SDag-Erling Smørgrav	s/\s*=([A-Z][0-9A-Z_]+)\b([\.,:;]+)\s*/\n.Dv $1 $2\n/gs;
30846acc370SDag-Erling Smørgrav	s/\s*{([A-Z][a-z] .*?)}\s*/\n.$1\n/gs;
30946acc370SDag-Erling Smørgrav	$man .= "$_\n";
31046acc370SDag-Erling Smørgrav    }
31146acc370SDag-Erling Smørgrav    if (defined($man)) {
3127f106882SDag-Erling Smørgrav	if ($inlist || $intaglist) {
313ac7e3b9dSDag-Erling Smørgrav	    $man .= ".El\n";
3147f106882SDag-Erling Smørgrav	    $inlist = $intaglist = 0;
315ac7e3b9dSDag-Erling Smørgrav	}
316ac7e3b9dSDag-Erling Smørgrav	if ($inliteral) {
317ac7e3b9dSDag-Erling Smørgrav	    $man .= ".Ed\n";
3187f106882SDag-Erling Smørgrav	    $inliteral = 0;
319ac7e3b9dSDag-Erling Smørgrav	}
3207f106882SDag-Erling Smørgrav	$man =~ s/\%/\\&\%/gs;
3212f3ed619SDag-Erling Smørgrav	$man =~ s/(\n\.[A-Z][a-z] [\w ]+)\n([.,:;-])\s+/$1 $2\n/gs;
32246acc370SDag-Erling Smørgrav	$man =~ s/\s*$/\n/gm;
32346acc370SDag-Erling Smørgrav	$man =~ s/\n+/\n/gs;
32446acc370SDag-Erling Smørgrav	$man =~ s/\0//gs;
325ac7e3b9dSDag-Erling Smørgrav	$man =~ s/\n\n\./\n\./gs;
32646acc370SDag-Erling Smørgrav	chomp($man);
32746acc370SDag-Erling Smørgrav    } else {
32846acc370SDag-Erling Smørgrav	$man = "No description available.";
32946acc370SDag-Erling Smørgrav    }
33046acc370SDag-Erling Smørgrav
33146acc370SDag-Erling Smørgrav    $FUNCTIONS{$func} = {
332ee02aaa9SDag-Erling Smørgrav	'source'	=> $fn,
333ce77a8d6SDag-Erling Smørgrav	'version'	=> $version,
33446acc370SDag-Erling Smørgrav	'name'		=> $func,
33546acc370SDag-Erling Smørgrav	'descr'		=> $descr,
33646acc370SDag-Erling Smørgrav	'type'		=> $type,
33746acc370SDag-Erling Smørgrav	'args'		=> $args,
33846acc370SDag-Erling Smørgrav	'man'		=> $man,
33946acc370SDag-Erling Smørgrav	'xref'		=> \%xref,
34049e56509SDag-Erling Smørgrav	'errors'	=> \%errors,
3417f106882SDag-Erling Smørgrav	'author'	=> $author,
3422f3ed619SDag-Erling Smørgrav	'customrv'	=> $customrv,
3432f3ed619SDag-Erling Smørgrav	'deprecated'	=> $deprecated,
3442f3ed619SDag-Erling Smørgrav	'experimental'	=> $experimental,
34546acc370SDag-Erling Smørgrav    };
34646acc370SDag-Erling Smørgrav    if ($source =~ m/^ \* NODOC\s*$/m) {
347ce77a8d6SDag-Erling Smørgrav	$FUNCTIONS{$func}->{nodoc} = 1;
34846acc370SDag-Erling Smørgrav    }
34946acc370SDag-Erling Smørgrav    if ($source !~ m/^ \* XSSO \d/m) {
350ce77a8d6SDag-Erling Smørgrav	$FUNCTIONS{$func}->{openpam} = 1;
35146acc370SDag-Erling Smørgrav    }
352ee02aaa9SDag-Erling Smørgrav    expand_errors($FUNCTIONS{$func});
353ee02aaa9SDag-Erling Smørgrav    return $FUNCTIONS{$func};
35446acc370SDag-Erling Smørgrav}
35546acc370SDag-Erling Smørgrav
35646acc370SDag-Erling Smørgravsub expand_errors($);
35746acc370SDag-Erling Smørgravsub expand_errors($) {
35846acc370SDag-Erling Smørgrav    my $func = shift;		# Ref to function hash
35946acc370SDag-Erling Smørgrav
36046acc370SDag-Erling Smørgrav    my %errors;
361ee02aaa9SDag-Erling Smørgrav    my $ref;
362ee02aaa9SDag-Erling Smørgrav    my $fn;
36346acc370SDag-Erling Smørgrav
364ce77a8d6SDag-Erling Smørgrav    if (defined($$func{recursed})) {
365ce77a8d6SDag-Erling Smørgrav	warn("$$func{name}(): loop in error spec\n");
36646acc370SDag-Erling Smørgrav	return qw();
36746acc370SDag-Erling Smørgrav    }
368ce77a8d6SDag-Erling Smørgrav    $$func{recursed} = 1;
36946acc370SDag-Erling Smørgrav
37049e56509SDag-Erling Smørgrav    foreach (keys %{$$func{errors}}) {
37146acc370SDag-Erling Smørgrav	if (m/^(PAM_[A-Z_]+)$/) {
37246acc370SDag-Erling Smørgrav	    if (!defined($PAMERR{$1})) {
373ce77a8d6SDag-Erling Smørgrav		warn("$$func{name}(): unrecognized error: $1\n");
37446acc370SDag-Erling Smørgrav		next;
37546acc370SDag-Erling Smørgrav	    }
37649e56509SDag-Erling Smørgrav	    $errors{$1} = $$func{errors}->{$_};
37746acc370SDag-Erling Smørgrav	} elsif (m/^!(PAM_[A-Z_]+)$/) {
37846acc370SDag-Erling Smørgrav	    # treat negations separately
37946acc370SDag-Erling Smørgrav	} elsif (m/^=([a-z_]+)$/) {
380ee02aaa9SDag-Erling Smørgrav	    $ref = $1;
381ee02aaa9SDag-Erling Smørgrav	    if (!defined($FUNCTIONS{$ref})) {
382ce77a8d6SDag-Erling Smørgrav		$fn = $$func{source};
383ce77a8d6SDag-Erling Smørgrav		$fn =~ s/$$func{name}/$ref/;
384ee02aaa9SDag-Erling Smørgrav		parse_source($fn);
385ee02aaa9SDag-Erling Smørgrav	    }
386ee02aaa9SDag-Erling Smørgrav	    if (!defined($FUNCTIONS{$ref})) {
387ce77a8d6SDag-Erling Smørgrav		warn("$$func{name}(): reference to unknown $ref()\n");
38846acc370SDag-Erling Smørgrav		next;
38946acc370SDag-Erling Smørgrav	    }
39049e56509SDag-Erling Smørgrav	    foreach (keys %{$FUNCTIONS{$ref}->{errors}}) {
39149e56509SDag-Erling Smørgrav		$errors{$_} //= $FUNCTIONS{$ref}->{errors}->{$_};
39246acc370SDag-Erling Smørgrav	    }
39346acc370SDag-Erling Smørgrav	} else {
394ce77a8d6SDag-Erling Smørgrav	    warn("$$func{name}(): invalid error specification: $_\n");
39546acc370SDag-Erling Smørgrav	}
39646acc370SDag-Erling Smørgrav    }
39749e56509SDag-Erling Smørgrav    foreach (keys %{$$func{errors}}) {
39846acc370SDag-Erling Smørgrav	if (m/^!(PAM_[A-Z_]+)$/) {
39946acc370SDag-Erling Smørgrav	    delete($errors{$1});
40046acc370SDag-Erling Smørgrav	}
40146acc370SDag-Erling Smørgrav    }
402ce77a8d6SDag-Erling Smørgrav    delete($$func{recursed});
40349e56509SDag-Erling Smørgrav    $$func{errors} = \%errors;
40446acc370SDag-Erling Smørgrav}
40546acc370SDag-Erling Smørgrav
406556dce83SDag-Erling Smørgravsub dictionary_order($$) {
407556dce83SDag-Erling Smørgrav    my ($a, $b) = @_;
408556dce83SDag-Erling Smørgrav
409556dce83SDag-Erling Smørgrav    $a =~ s/[^[:alpha:]]//g;
410556dce83SDag-Erling Smørgrav    $b =~ s/[^[:alpha:]]//g;
411556dce83SDag-Erling Smørgrav    $a cmp $b;
412556dce83SDag-Erling Smørgrav}
413556dce83SDag-Erling Smørgrav
414b33ab329SDag-Erling Smørgravsub genxref($) {
415b33ab329SDag-Erling Smørgrav    my $xref = shift;		# References
416b33ab329SDag-Erling Smørgrav
417b33ab329SDag-Erling Smørgrav    my $mdoc = '';
418b33ab329SDag-Erling Smørgrav    my @refs = ();
419b33ab329SDag-Erling Smørgrav    foreach my $sect (sort(keys(%{$xref}))) {
420556dce83SDag-Erling Smørgrav	foreach my $page (sort(dictionary_order keys(%{$xref->{$sect}}))) {
421b33ab329SDag-Erling Smørgrav	    push(@refs, "$page $sect");
422b33ab329SDag-Erling Smørgrav	}
423b33ab329SDag-Erling Smørgrav    }
424b33ab329SDag-Erling Smørgrav    while ($_ = shift(@refs)) {
425b33ab329SDag-Erling Smørgrav	$mdoc .= ".Xr $_" .
426b33ab329SDag-Erling Smørgrav	    (@refs ? " ,\n" : "\n");
427b33ab329SDag-Erling Smørgrav    }
428b33ab329SDag-Erling Smørgrav    return $mdoc;
429b33ab329SDag-Erling Smørgrav}
430b33ab329SDag-Erling Smørgrav
43146acc370SDag-Erling Smørgravsub gendoc($) {
43246acc370SDag-Erling Smørgrav    my $func = shift;		# Ref to function hash
43346acc370SDag-Erling Smørgrav
43446acc370SDag-Erling Smørgrav    local *FILE;
43549e56509SDag-Erling Smørgrav    my %errors;
43646acc370SDag-Erling Smørgrav    my $mdoc;
43746acc370SDag-Erling Smørgrav    my $fn;
43846acc370SDag-Erling Smørgrav
439ce77a8d6SDag-Erling Smørgrav    return if defined($$func{nodoc});
44046acc370SDag-Erling Smørgrav
441ce77a8d6SDag-Erling Smørgrav    $$func{source} =~ m/([^\/]+)$/;
442ce77a8d6SDag-Erling Smørgrav    $mdoc = ".\\\" Generated from $1 by gendoc.pl\n";
443ce77a8d6SDag-Erling Smørgrav    if ($$func{version}) {
444ce77a8d6SDag-Erling Smørgrav	$mdoc .= ".\\\" $$func{version}\n";
445ce77a8d6SDag-Erling Smørgrav    }
446ce77a8d6SDag-Erling Smørgrav    $mdoc .= ".Dd $TODAY
447ce77a8d6SDag-Erling Smørgrav.Dt " . uc($$func{name}) . " 3
44846acc370SDag-Erling Smørgrav.Os
44946acc370SDag-Erling Smørgrav.Sh NAME
450ce77a8d6SDag-Erling Smørgrav.Nm $$func{name}
451ce77a8d6SDag-Erling Smørgrav.Nd $$func{descr}
452f3b0ac34SDag-Erling Smørgrav";
453f3b0ac34SDag-Erling Smørgrav    if ($func =~ m/^(?:open)?pam_/) {
454f3b0ac34SDag-Erling Smørgrav	$mdoc .= ".Sh LIBRARY
45546acc370SDag-Erling Smørgrav.Lb libpam
456f3b0ac34SDag-Erling Smørgrav";
457f3b0ac34SDag-Erling Smørgrav    }
458f3b0ac34SDag-Erling Smørgrav    $mdoc .= ".Sh SYNOPSIS
459644f2b7cSDag-Erling Smørgrav.In sys/types.h
4602f3ed619SDag-Erling Smørgrav";
461ce77a8d6SDag-Erling Smørgrav    if ($$func{args} =~ m/\bFILE \*\b/) {
4622f3ed619SDag-Erling Smørgrav	$mdoc .= ".In stdio.h\n";
4632f3ed619SDag-Erling Smørgrav    }
464f3b0ac34SDag-Erling Smørgrav    if ($$func{name} =~ m/^(?:open)?pam/) {
4652f3ed619SDag-Erling Smørgrav	$mdoc .= ".In security/pam_appl.h
46646acc370SDag-Erling Smørgrav";
467f3b0ac34SDag-Erling Smørgrav    }
468ce77a8d6SDag-Erling Smørgrav    if ($$func{name} =~ m/_sm_/) {
4692f3ed619SDag-Erling Smørgrav	$mdoc .= ".In security/pam_modules.h\n";
47046acc370SDag-Erling Smørgrav    }
471ce77a8d6SDag-Erling Smørgrav    if ($$func{name} =~ m/openpam/) {
4722f3ed619SDag-Erling Smørgrav	$mdoc .= ".In security/openpam.h\n";
473ac7e3b9dSDag-Erling Smørgrav    }
474ce77a8d6SDag-Erling Smørgrav    $mdoc .= ".Ft \"$$func{type}\"
475ce77a8d6SDag-Erling Smørgrav.Fn $$func{name} $$func{args}
47646acc370SDag-Erling Smørgrav.Sh DESCRIPTION
47746acc370SDag-Erling Smørgrav";
478ce77a8d6SDag-Erling Smørgrav    if (defined($$func{deprecated})) {
4792f3ed619SDag-Erling Smørgrav	$mdoc .= ".Bf Sy\n" .
4802f3ed619SDag-Erling Smørgrav	    "This function is deprecated and may be removed " .
4812f3ed619SDag-Erling Smørgrav	    "in a future release without further warning.\n";
482ce77a8d6SDag-Erling Smørgrav	if ($$func{deprecated}) {
483ce77a8d6SDag-Erling Smørgrav	    $mdoc .= "The\n.Fn $$func{deprecated}\nfunction " .
4842f3ed619SDag-Erling Smørgrav		"may be used to achieve similar results.\n";
4852f3ed619SDag-Erling Smørgrav	}
4862f3ed619SDag-Erling Smørgrav	$mdoc .= ".Ef\n.Pp\n";
4872f3ed619SDag-Erling Smørgrav    }
488ce77a8d6SDag-Erling Smørgrav    if ($$func{experimental}) {
4892f3ed619SDag-Erling Smørgrav	$mdoc .= ".Bf Sy\n" .
4902f3ed619SDag-Erling Smørgrav	    "This function is experimental and may be modified or removed " .
491ce77a8d6SDag-Erling Smørgrav	    "in a future release without prior warning.\n";
4922f3ed619SDag-Erling Smørgrav	$mdoc .= ".Ef\n.Pp\n";
4932f3ed619SDag-Erling Smørgrav    }
494ce77a8d6SDag-Erling Smørgrav    $mdoc .= "$$func{man}\n";
49549e56509SDag-Erling Smørgrav    %errors = %{$$func{errors}};
496ce77a8d6SDag-Erling Smørgrav    if ($$func{customrv}) {
4972f3ed619SDag-Erling Smørgrav	# leave it
49849e56509SDag-Erling Smørgrav    } elsif ($$func{type} eq "int" && %errors) {
49946acc370SDag-Erling Smørgrav	$mdoc .= ".Sh RETURN VALUES
50046acc370SDag-Erling SmørgravThe
501ce77a8d6SDag-Erling Smørgrav.Fn $$func{name}
50246acc370SDag-Erling Smørgravfunction returns one of the following values:
50346acc370SDag-Erling Smørgrav.Bl -tag -width 18n
50446acc370SDag-Erling Smørgrav";
50549e56509SDag-Erling Smørgrav	delete($errors{PAM_SUCCESS});
50649e56509SDag-Erling Smørgrav	foreach ('PAM_SUCCESS', sort keys %errors) {
50749e56509SDag-Erling Smørgrav	    $mdoc .= ".It Bq Er $_\n" .
50849e56509SDag-Erling Smørgrav		($errors{$_} || $PAMERR{$_}) .
50949e56509SDag-Erling Smørgrav		".\n";
51046acc370SDag-Erling Smørgrav	}
51146acc370SDag-Erling Smørgrav	$mdoc .= ".El\n";
512ce77a8d6SDag-Erling Smørgrav    } elsif ($$func{type} eq "int") {
51346acc370SDag-Erling Smørgrav	$mdoc .= ".Sh RETURN VALUES
51446acc370SDag-Erling SmørgravThe
515ce77a8d6SDag-Erling Smørgrav.Fn $$func{name}
5162f3ed619SDag-Erling Smørgravfunction returns 0 on success and -1 on failure.
5172f3ed619SDag-Erling Smørgrav";
518ce77a8d6SDag-Erling Smørgrav    } elsif ($$func{type} =~ m/\*$/) {
5192f3ed619SDag-Erling Smørgrav	$mdoc .= ".Sh RETURN VALUES
5202f3ed619SDag-Erling SmørgravThe
521ce77a8d6SDag-Erling Smørgrav.Fn $$func{name}
52246acc370SDag-Erling Smørgravfunction returns
52346acc370SDag-Erling Smørgrav.Dv NULL
52446acc370SDag-Erling Smørgravon failure.
52546acc370SDag-Erling Smørgrav";
526ce77a8d6SDag-Erling Smørgrav    } elsif ($$func{type} ne "void") {
527ce77a8d6SDag-Erling Smørgrav	warn("$$func{name}(): no error specification\n");
52846acc370SDag-Erling Smørgrav    }
529ce77a8d6SDag-Erling Smørgrav    $mdoc .= ".Sh SEE ALSO\n" . genxref($$func{xref});
53046acc370SDag-Erling Smørgrav    $mdoc .= ".Sh STANDARDS\n";
531ce77a8d6SDag-Erling Smørgrav    if ($$func{openpam}) {
53246acc370SDag-Erling Smørgrav	$mdoc .= "The
533ce77a8d6SDag-Erling Smørgrav.Fn $$func{name}
53446acc370SDag-Erling Smørgravfunction is an OpenPAM extension.
53546acc370SDag-Erling Smørgrav";
53646acc370SDag-Erling Smørgrav    } else {
53746acc370SDag-Erling Smørgrav	$mdoc .= ".Rs
53846acc370SDag-Erling Smørgrav.%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
53946acc370SDag-Erling Smørgrav.%D \"June 1997\"
54046acc370SDag-Erling Smørgrav.Re
54146acc370SDag-Erling Smørgrav";
54246acc370SDag-Erling Smørgrav    }
54346acc370SDag-Erling Smørgrav    $mdoc .= ".Sh AUTHORS
54446acc370SDag-Erling SmørgravThe
545ce77a8d6SDag-Erling Smørgrav.Fn $$func{name}
5462f3ed619SDag-Erling Smørgravfunction and this manual page were\n";
547ce77a8d6SDag-Erling Smørgrav    $mdoc .= $AUTHORS{$$func{author} // 'THINKSEC_DARPA'} . "\n";
548ce77a8d6SDag-Erling Smørgrav    $fn = "$$func{name}.3";
5497f106882SDag-Erling Smørgrav    if (open(FILE, ">", $fn)) {
55046acc370SDag-Erling Smørgrav	print(FILE $mdoc);
55146acc370SDag-Erling Smørgrav	close(FILE);
552ac7e3b9dSDag-Erling Smørgrav    } else {
553ac7e3b9dSDag-Erling Smørgrav	warn("$fn: open(): $!\n");
554ac7e3b9dSDag-Erling Smørgrav    }
55546acc370SDag-Erling Smørgrav}
55646acc370SDag-Erling Smørgrav
557ee02aaa9SDag-Erling Smørgravsub readproto($) {
558ee02aaa9SDag-Erling Smørgrav    my $fn = shift;		# File name
55946acc370SDag-Erling Smørgrav
560ee02aaa9SDag-Erling Smørgrav    local *FILE;
561ee02aaa9SDag-Erling Smørgrav    my %func;
562ee02aaa9SDag-Erling Smørgrav
5637f106882SDag-Erling Smørgrav    open(FILE, "<", "$fn")
564ee02aaa9SDag-Erling Smørgrav	or die("$fn: open(): $!\n");
565ee02aaa9SDag-Erling Smørgrav    while (<FILE>) {
566f3b0ac34SDag-Erling Smørgrav	if (m/^\.Nm ((?:(?:open)?pam)_.*?)\s*$/) {
567ce77a8d6SDag-Erling Smørgrav	    $func{Nm} = $func{Nm} || $1;
568ee02aaa9SDag-Erling Smørgrav	} elsif (m/^\.Ft (\S.*?)\s*$/) {
569ce77a8d6SDag-Erling Smørgrav	    $func{Ft} = $func{Ft} || $1;
570ee02aaa9SDag-Erling Smørgrav	} elsif (m/^\.Fn (\S.*?)\s*$/) {
571ce77a8d6SDag-Erling Smørgrav	    $func{Fn} = $func{Fn} || $1;
572ee02aaa9SDag-Erling Smørgrav	}
573ee02aaa9SDag-Erling Smørgrav    }
574ee02aaa9SDag-Erling Smørgrav    close(FILE);
575ce77a8d6SDag-Erling Smørgrav    if ($func{Nm}) {
576ce77a8d6SDag-Erling Smørgrav	$FUNCTIONS{$func{Nm}} = \%func;
577ee02aaa9SDag-Erling Smørgrav    } else {
578ee02aaa9SDag-Erling Smørgrav	warn("No function found\n");
579ee02aaa9SDag-Erling Smørgrav    }
580ee02aaa9SDag-Erling Smørgrav}
581ee02aaa9SDag-Erling Smørgrav
582ee02aaa9SDag-Erling Smørgravsub gensummary($) {
583ee02aaa9SDag-Erling Smørgrav    my $page = shift;		# Which page to produce
584ee02aaa9SDag-Erling Smørgrav
585ee02aaa9SDag-Erling Smørgrav    local *FILE;
586ee02aaa9SDag-Erling Smørgrav    my $upage;
58746acc370SDag-Erling Smørgrav    my $func;
588ee02aaa9SDag-Erling Smørgrav    my %xref;
58946acc370SDag-Erling Smørgrav
5907f106882SDag-Erling Smørgrav    open(FILE, ">", "$page.3")
591ee02aaa9SDag-Erling Smørgrav	or die("$page.3: $!\n");
592ee02aaa9SDag-Erling Smørgrav
5937f106882SDag-Erling Smørgrav    $page =~ m/(\w+)$/;
5947f106882SDag-Erling Smørgrav    $upage = uc($1);
595ce77a8d6SDag-Erling Smørgrav    print FILE ".\\\" Generated by gendoc.pl
59646acc370SDag-Erling Smørgrav.Dd $TODAY
597ee02aaa9SDag-Erling Smørgrav.Dt $upage 3
59846acc370SDag-Erling Smørgrav.Os
59946acc370SDag-Erling Smørgrav.Sh NAME
60046acc370SDag-Erling Smørgrav";
60146acc370SDag-Erling Smørgrav    my @funcs = sort(keys(%FUNCTIONS));
60246acc370SDag-Erling Smørgrav    while ($func = shift(@funcs)) {
603ce77a8d6SDag-Erling Smørgrav	print FILE ".Nm $FUNCTIONS{$func}->{Nm}";
604ee02aaa9SDag-Erling Smørgrav	print FILE " ,"
605ee02aaa9SDag-Erling Smørgrav		if (@funcs);
606ee02aaa9SDag-Erling Smørgrav	print FILE "\n";
60746acc370SDag-Erling Smørgrav    }
608ee02aaa9SDag-Erling Smørgrav    print FILE ".Nd Pluggable Authentication Modules Library
60946acc370SDag-Erling Smørgrav.Sh LIBRARY
61046acc370SDag-Erling Smørgrav.Lb libpam
611ee02aaa9SDag-Erling Smørgrav.Sh SYNOPSIS\n";
612ee02aaa9SDag-Erling Smørgrav    if ($page eq 'pam') {
613ee02aaa9SDag-Erling Smørgrav	print FILE ".In security/pam_appl.h\n";
614ee02aaa9SDag-Erling Smørgrav    } else {
615ee02aaa9SDag-Erling Smørgrav	print FILE ".In security/openpam.h\n";
61646acc370SDag-Erling Smørgrav    }
617ee02aaa9SDag-Erling Smørgrav    foreach $func (sort(keys(%FUNCTIONS))) {
618ce77a8d6SDag-Erling Smørgrav	print FILE ".Ft $FUNCTIONS{$func}->{Ft}\n";
619ce77a8d6SDag-Erling Smørgrav	print FILE ".Fn $FUNCTIONS{$func}->{Fn}\n";
620ee02aaa9SDag-Erling Smørgrav    }
621ee02aaa9SDag-Erling Smørgrav    while (<STDIN>) {
622ee02aaa9SDag-Erling Smørgrav	if (m/^\.Xr (\S+)\s*(\d)\s*$/) {
623b33ab329SDag-Erling Smørgrav	    ++$xref{int($2)}->{$1};
624ee02aaa9SDag-Erling Smørgrav	}
625ee02aaa9SDag-Erling Smørgrav	print FILE $_;
626ee02aaa9SDag-Erling Smørgrav    }
627ee02aaa9SDag-Erling Smørgrav
628ee02aaa9SDag-Erling Smørgrav    if ($page eq 'pam') {
629ee02aaa9SDag-Erling Smørgrav	print FILE ".Sh RETURN VALUES
630ee02aaa9SDag-Erling SmørgravThe following return codes are defined by
631b33ab329SDag-Erling Smørgrav.In security/pam_constants.h :
63246acc370SDag-Erling Smørgrav.Bl -tag -width 18n
63346acc370SDag-Erling Smørgrav";
63446acc370SDag-Erling Smørgrav	foreach (sort(keys(%PAMERR))) {
635ee02aaa9SDag-Erling Smørgrav	    print FILE ".It Bq Er $_\n$PAMERR{$_}.\n";
63646acc370SDag-Erling Smørgrav	}
637ee02aaa9SDag-Erling Smørgrav	print FILE ".El\n";
638ee02aaa9SDag-Erling Smørgrav    }
639ee02aaa9SDag-Erling Smørgrav    print FILE ".Sh SEE ALSO
64046acc370SDag-Erling Smørgrav";
641b33ab329SDag-Erling Smørgrav    if ($page eq 'pam') {
642ce77a8d6SDag-Erling Smørgrav	++$xref{3}->{openpam};
643b33ab329SDag-Erling Smørgrav    }
644ee02aaa9SDag-Erling Smørgrav    foreach $func (keys(%FUNCTIONS)) {
645b33ab329SDag-Erling Smørgrav	++$xref{3}->{$func};
64646acc370SDag-Erling Smørgrav    }
647b33ab329SDag-Erling Smørgrav    print FILE genxref(\%xref);
648ee02aaa9SDag-Erling Smørgrav    print FILE ".Sh STANDARDS
64946acc370SDag-Erling Smørgrav.Rs
65046acc370SDag-Erling Smørgrav.%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
65146acc370SDag-Erling Smørgrav.%D \"June 1997\"
65246acc370SDag-Erling Smørgrav.Re
653f3b0ac34SDag-Erling Smørgrav";
654f3b0ac34SDag-Erling Smørgrav    print FILE ".Sh AUTHORS
655f3b0ac34SDag-Erling SmørgravThe OpenPAM library and this manual page were $AUTHORS{THINKSEC}
656ee02aaa9SDag-Erling Smørgrav";
657ee02aaa9SDag-Erling Smørgrav    close(FILE);
658ee02aaa9SDag-Erling Smørgrav}
659ee02aaa9SDag-Erling Smørgrav
660ee02aaa9SDag-Erling Smørgravsub usage() {
661ee02aaa9SDag-Erling Smørgrav
6627f106882SDag-Erling Smørgrav    print(STDERR "usage: gendoc [-op] source [...]\n");
663ee02aaa9SDag-Erling Smørgrav    exit(1);
66446acc370SDag-Erling Smørgrav}
66546acc370SDag-Erling Smørgrav
66646acc370SDag-Erling SmørgravMAIN:{
667ee02aaa9SDag-Erling Smørgrav    my %opts;
668ee02aaa9SDag-Erling Smørgrav
669ee02aaa9SDag-Erling Smørgrav    usage()
670ee02aaa9SDag-Erling Smørgrav	unless (@ARGV && getopts("op", \%opts));
67146acc370SDag-Erling Smørgrav    $TODAY = strftime("%B %e, %Y", localtime(time()));
67246acc370SDag-Erling Smørgrav    $TODAY =~ s,\s+, ,g;
673ce77a8d6SDag-Erling Smørgrav    if ($opts{o} || $opts{p}) {
67446acc370SDag-Erling Smørgrav	foreach my $fn (@ARGV) {
675ee02aaa9SDag-Erling Smørgrav	    readproto($fn);
67646acc370SDag-Erling Smørgrav	}
677ee02aaa9SDag-Erling Smørgrav	gensummary('openpam')
678ce77a8d6SDag-Erling Smørgrav	    if ($opts{o});
679ee02aaa9SDag-Erling Smørgrav	gensummary('pam')
680ce77a8d6SDag-Erling Smørgrav	    if ($opts{p});
681ee02aaa9SDag-Erling Smørgrav    } else {
682ee02aaa9SDag-Erling Smørgrav	foreach my $fn (@ARGV) {
683ee02aaa9SDag-Erling Smørgrav	    my $func = parse_source($fn);
684ee02aaa9SDag-Erling Smørgrav	    gendoc($func)
685ee02aaa9SDag-Erling Smørgrav		if (defined($func));
68646acc370SDag-Erling Smørgrav	}
687ee02aaa9SDag-Erling Smørgrav    }
688ee02aaa9SDag-Erling Smørgrav    exit(0);
68946acc370SDag-Erling Smørgrav}
690