gendoc.pl revision 115619
1233294Sstas#!/usr/bin/perl -w 2178825Sdfr#- 3178825Sdfr# Copyright (c) 2002-2003 Networks Associates Technology, Inc. 4178825Sdfr# All rights reserved. 5233294Sstas# 6233294Sstas# This software was developed for the FreeBSD Project by ThinkSec AS and 7178825Sdfr# Network Associates Laboratories, the Security Research Division of 8178825Sdfr# Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 9178825Sdfr# ("CBOSS"), as part of the DARPA CHATS research program. 10178825Sdfr# 11178825Sdfr# Redistribution and use in source and binary forms, with or without 12178825Sdfr# modification, are permitted provided that the following conditions 13178825Sdfr# are met: 14178825Sdfr# 1. Redistributions of source code must retain the above copyright 15178825Sdfr# notice, this list of conditions and the following disclaimer. 16178825Sdfr# 2. Redistributions in binary form must reproduce the above copyright 17178825Sdfr# notice, this list of conditions and the following disclaimer in the 18233294Sstas# documentation and/or other materials provided with the distribution. 19178825Sdfr# 3. The name of the author may not be used to endorse or promote 20233294Sstas# products derived from this software without specific prior written 21178825Sdfr# permission. 22233294Sstas# 23178825Sdfr# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 24178825Sdfr# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25178825Sdfr# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26233294Sstas# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 27178825Sdfr# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28233294Sstas# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29178825Sdfr# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30178825Sdfr# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31178825Sdfr# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32178825Sdfr# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33178825Sdfr# SUCH DAMAGE. 34178825Sdfr# 35178825Sdfr# $P4: //depot/projects/openpam/misc/gendoc.pl#25 $ 36178825Sdfr# 37178825Sdfr 38178825Sdfruse strict; 39178825Sdfruse Fcntl; 40178825Sdfruse Getopt::Std; 41178825Sdfruse POSIX qw(strftime); 42178825Sdfruse vars qw($COPYRIGHT $TODAY %FUNCTIONS %PAMERR); 43178825Sdfr 44178825Sdfr$COPYRIGHT = ".\\\"- 45178825Sdfr.\\\" Copyright (c) 2001-2003 Networks Associates Technology, Inc. 46178825Sdfr.\\\" All rights reserved. 47178825Sdfr.\\\" 48178825Sdfr.\\\" This software was developed for the FreeBSD Project by ThinkSec AS and 49178825Sdfr.\\\" Network Associates Laboratories, the Security Research Division of 50233294Sstas.\\\" Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 51178825Sdfr.\\\" (\"CBOSS\"), as part of the DARPA CHATS research program. 52178825Sdfr.\\\" 53178825Sdfr.\\\" Redistribution and use in source and binary forms, with or without 54178825Sdfr.\\\" modification, are permitted provided that the following conditions 55178825Sdfr.\\\" are met: 56178825Sdfr.\\\" 1. Redistributions of source code must retain the above copyright 57178825Sdfr.\\\" notice, this list of conditions and the following disclaimer. 58178825Sdfr.\\\" 2. Redistributions in binary form must reproduce the above copyright 59178825Sdfr.\\\" notice, this list of conditions and the following disclaimer in the 60178825Sdfr.\\\" documentation and/or other materials provided with the distribution. 61178825Sdfr.\\\" 3. The name of the author may not be used to endorse or promote 62178825Sdfr.\\\" products derived from this software without specific prior written 63178825Sdfr.\\\" permission. 64178825Sdfr.\\\" 65233294Sstas.\\\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 66178825Sdfr.\\\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 67178825Sdfr.\\\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 68178825Sdfr.\\\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 69178825Sdfr.\\\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 70178825Sdfr.\\\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 71178825Sdfr.\\\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 72178825Sdfr.\\\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 73178825Sdfr.\\\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 74178825Sdfr.\\\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 75178825Sdfr.\\\" SUCH DAMAGE. 76178825Sdfr.\\\" 77178825Sdfr.\\\" \$" . "P4" . "\$ 78178825Sdfr.\\\""; 79233294Sstas 80233294Sstas%PAMERR = ( 81233294Sstas PAM_SUCCESS => "Success", 82233294Sstas PAM_OPEN_ERR => "Failed to load module", 83233294Sstas PAM_SYMBOL_ERR => "Invalid symbol", 84233294Sstas PAM_SERVICE_ERR => "Error in service module", 85178825Sdfr PAM_SYSTEM_ERR => "System error", 86178825Sdfr PAM_BUF_ERR => "Memory buffer error", 87178825Sdfr PAM_CONV_ERR => "Conversation failure", 88178825Sdfr PAM_PERM_DENIED => "Permission denied", 89178825Sdfr PAM_MAXTRIES => "Maximum number of tries exceeded", 90178825Sdfr PAM_AUTH_ERR => "Authentication error", 91178825Sdfr PAM_NEW_AUTHTOK_REQD => "New authentication token required", 92233294Sstas PAM_CRED_INSUFFICIENT => "Insufficient credentials", 93178825Sdfr PAM_AUTHINFO_UNAVAIL => "Authentication information is unavailable", 94178825Sdfr PAM_USER_UNKNOWN => "Unknown user", 95178825Sdfr PAM_CRED_UNAVAIL => "Failed to retrieve user credentials", 96178825Sdfr PAM_CRED_EXPIRED => "User credentials have expired", 97178825Sdfr PAM_CRED_ERR => "Failed to set user credentials", 98233294Sstas PAM_ACCT_EXPIRED => "User accound has expired", 99178825Sdfr PAM_AUTHTOK_EXPIRED => "Password has expired", 100178825Sdfr PAM_SESSION_ERR => "Session failure", 101178825Sdfr PAM_AUTHTOK_ERR => "Authentication token failure", 102178825Sdfr PAM_AUTHTOK_RECOVERY_ERR => "Failed to recover old authentication token", 103233294Sstas PAM_AUTHTOK_LOCK_BUSY => "Authentication token lock busy", 104233294Sstas PAM_AUTHTOK_DISABLE_AGING => "Authentication token aging disabled", 105178825Sdfr PAM_NO_MODULE_DATA => "Module data not found", 106178825Sdfr PAM_IGNORE => "Ignore this module", 107178825Sdfr PAM_ABORT => "General failure", 108178825Sdfr PAM_TRY_AGAIN => "Try again", 109233294Sstas PAM_MODULE_UNKNOWN => "Unknown module type", 110233294Sstas PAM_DOMAIN_UNKNOWN => "Unknown authentication domain", 111233294Sstas); 112233294Sstas 113178825Sdfrsub parse_source($) { 114233294Sstas my $fn = shift; 115233294Sstas 116233294Sstas local *FILE; 117178825Sdfr my $source; 118178825Sdfr my $func; 119178825Sdfr my $descr; 120178825Sdfr my $type; 121178825Sdfr my $args; 122178825Sdfr my $argnames; 123178825Sdfr my $man; 124178825Sdfr my $inlist; 125178825Sdfr my $inliteral; 126178825Sdfr my %xref; 127178825Sdfr my @errors; 128233294Sstas 129233294Sstas if ($fn !~ m,\.c$,) { 130233294Sstas warn("$fn: not C source, ignoring\n"); 131233294Sstas return undef; 132233294Sstas } 133233294Sstas 134233294Sstas sysopen(FILE, $fn, O_RDONLY) 135233294Sstas or die("$fn: open(): $!\n"); 136233294Sstas $source = join('', <FILE>); 137233294Sstas close(FILE); 138233294Sstas 139233294Sstas return undef 140233294Sstas if ($source =~ m/^ \* NOPARSE\s*$/m); 141233294Sstas 142233294Sstas $func = $fn; 143233294Sstas $func =~ s,^(?:.*/)?([^/]+)\.c$,$1,; 144233294Sstas if ($source !~ m,\n \* ([\S ]+)\n \*/\n\n([\S ]+)\n$func\((.*?)\)\n\{,s) { 145233294Sstas warn("$fn: can't find $func\n"); 146233294Sstas return undef; 147233294Sstas } 148233294Sstas ($descr, $type, $args) = ($1, $2, $3); 149178825Sdfr $descr =~ s,^([A-Z][a-z]),lc($1),e; 150178825Sdfr $descr =~ s,[\.\s]*$,,; 151178825Sdfr while ($args =~ s/^((?:[^\(]|\([^\)]*\))*),\s*/$1\" \"/g) { 152178825Sdfr # nothing 153178825Sdfr } 154178825Sdfr $args =~ s/,\s+/, /gs; 155178825Sdfr $args = "\"$args\""; 156178825Sdfr 157178825Sdfr %xref = ( 158233294Sstas "pam 3" => 1 159233294Sstas ); 160178825Sdfr 161178825Sdfr if ($type eq "int") { 162178825Sdfr foreach (split("\n", $source)) { 163178825Sdfr next unless (m/^ \*\s+(!?PAM_[A-Z_]+|=[a-z_]+)\s*$/); 164178825Sdfr push(@errors, $1); 165233294Sstas } 166233294Sstas $xref{"pam_strerror 3"} = 1; 167178825Sdfr } 168178825Sdfr 169178825Sdfr $argnames = $args; 170233294Sstas $argnames =~ s/\"[^\"]+\*?\b(\w+)\"/\"$1\"/g; 171178825Sdfr $argnames =~ s/([\|\[\]\(\)\.\*\+\?])/\\$1/g; 172178825Sdfr $argnames =~ s/\" \"/|/g; 173178825Sdfr $argnames =~ s/^\"(.*)\"$/($1)/; 174178825Sdfr $inliteral = $inlist = 0; 175178825Sdfr foreach (split("\n", $source)) { 176233294Sstas s/\s*$//; 177178825Sdfr if (!defined($man)) { 178178825Sdfr if (m/^\/\*\*$/) { 179233294Sstas $man = ""; 180178825Sdfr } 181178825Sdfr next; 182178825Sdfr } 183178825Sdfr last if (m/^ \*\/$/); 184233294Sstas s/^ \* ?//; 185233294Sstas s/\\(.)/$1/gs; 186233294Sstas if (m/^$/) { 187178825Sdfr if ($man ne "" && $man !~ m/\.Pp\n$/s) { 188178825Sdfr if ($inliteral) { 189178825Sdfr $man .= "\0\n"; 190178825Sdfr } elsif ($inlist) { 191178825Sdfr $man .= ".El\n.Pp\n"; 192233294Sstas $inlist = 0; 193178825Sdfr } else { 194178825Sdfr $man .= ".Pp\n"; 195178825Sdfr } 196178825Sdfr } 197178825Sdfr next; 198178825Sdfr } 199233294Sstas if (m/^>(\w+)(?:\s+(\d))?$/) { 200233294Sstas ++$xref{$2 ? "$1 $2" : "$1 3"}; 201178825Sdfr next; 202178825Sdfr } 203233294Sstas if (s/^\s+(=?\w+):\s*/.It $1/) { 204178825Sdfr if ($inliteral) { 205178825Sdfr $man .= ".Ed\n"; 206178825Sdfr $inliteral = 0; 207178825Sdfr } 208178825Sdfr if (!$inlist) { 209233294Sstas $man =~ s/\.Pp\n$//s; 210178825Sdfr $man .= ".Bl -tag -width 18n\n"; 211178825Sdfr $inlist = 1; 212178825Sdfr } 213178825Sdfr s/^\.It =([A-Z][A-Z_]+)$/.It Dv $1/gs; 214178825Sdfr $man .= "$_\n"; 215178825Sdfr next; 216178825Sdfr } elsif ($inlist && m/^\S/) { 217178825Sdfr $man .= ".El\n.Pp\n"; 218178825Sdfr $inlist = 0; 219178825Sdfr } elsif ($inliteral && m/^\S/) { 220178825Sdfr $man .= ".Ed\n"; 221178825Sdfr $inliteral = 0; 222178825Sdfr } elsif ($inliteral) { 223178825Sdfr $man .= "$_\n"; 224178825Sdfr next; 225178825Sdfr } elsif ($inlist) { 226178825Sdfr s/^\s+//; 227178825Sdfr } elsif (m/^\s+/) { 228178825Sdfr $man .= ".Bd -literal\n"; 229178825Sdfr $inliteral = 1; 230178825Sdfr $man .= "$_\n"; 231178825Sdfr next; 232178825Sdfr } 233233294Sstas s/\s*=$func\b\s*/\n.Nm\n/gs; 234178825Sdfr s/\s*=$argnames\b\s*/\n.Va $1\n/gs; 235178825Sdfr s/\s*=(struct \w+(?: \*)?)\b\s*/\n.Vt $1\n/gs; 236233294Sstas s/\s*:([a-z_]+)\b\s*/\n.Va $1\n/gs; 237178825Sdfr s/\s*;([a-z_]+)\b\s*/\n.Dv $1\n/gs; 238178825Sdfr while (s/\s*=([a-z_]+)\b\s*/\n.Xr $1 3\n/s) { 239178825Sdfr ++$xref{"$1 3"}; 240178825Sdfr } 241178825Sdfr s/\s*\"(?=\w)/\n.Do\n/gs; 242178825Sdfr s/\"(?!\w)\s*/\n.Dc\n/gs; 243178825Sdfr s/\s*=([A-Z][A-Z_]+)\b\s*(?![\.,:;])/\n.Dv $1\n/gs; 244178825Sdfr s/\s*=([A-Z][A-Z_]+)\b([\.,:;]+)\s*/\n.Dv $1 $2\n/gs; 245178825Sdfr s/\s*{([A-Z][a-z] .*?)}\s*/\n.$1\n/gs; 246178825Sdfr $man .= "$_\n"; 247178825Sdfr } 248178825Sdfr if (defined($man)) { 249178825Sdfr if ($inlist) { 250178825Sdfr $man .= ".El\n"; 251178825Sdfr } 252178825Sdfr if ($inliteral) { 253178825Sdfr $man .= ".Ed\n"; 254233294Sstas } 255233294Sstas $man =~ s/(\n\.[A-Z][a-z] [\w ]+)\n([\.,:;-]\S*)\s*/$1 $2\n/gs; 256178825Sdfr $man =~ s/\s*$/\n/gm; 257178825Sdfr $man =~ s/\n+/\n/gs; 258178825Sdfr $man =~ s/\0//gs; 259178825Sdfr $man =~ s/\n\n\./\n\./gs; 260178825Sdfr chomp($man); 261178825Sdfr } else { 262178825Sdfr $man = "No description available."; 263178825Sdfr } 264178825Sdfr 265178825Sdfr $FUNCTIONS{$func} = { 266178825Sdfr 'source' => $fn, 267178825Sdfr 'name' => $func, 268178825Sdfr 'descr' => $descr, 269178825Sdfr 'type' => $type, 270178825Sdfr 'args' => $args, 271233294Sstas 'man' => $man, 272178825Sdfr 'xref' => \%xref, 273178825Sdfr 'errors' => \@errors, 274233294Sstas }; 275178825Sdfr if ($source =~ m/^ \* NODOC\s*$/m) { 276178825Sdfr $FUNCTIONS{$func}->{'nodoc'} = 1; 277178825Sdfr } 278178825Sdfr if ($source !~ m/^ \* XSSO \d/m) { 279233294Sstas $FUNCTIONS{$func}->{'openpam'} = 1; 280178825Sdfr } 281233294Sstas expand_errors($FUNCTIONS{$func}); 282233294Sstas return $FUNCTIONS{$func}; 283233294Sstas} 284178825Sdfr 285233294Sstassub expand_errors($); 286178825Sdfrsub expand_errors($) { 287233294Sstas my $func = shift; # Ref to function hash 288233294Sstas 289178825Sdfr my %errors; 290178825Sdfr my $ref; 291178825Sdfr my $fn; 292178825Sdfr 293178825Sdfr if (defined($func->{'recursed'})) { 294233294Sstas warn("$func->{'name'}(): loop in error spec\n"); 295178825Sdfr return qw(); 296178825Sdfr } 297233294Sstas $func->{'recursed'} = 1; 298233294Sstas 299233294Sstas foreach (@{$func->{'errors'}}) { 300233294Sstas if (m/^(PAM_[A-Z_]+)$/) { 301178825Sdfr if (!defined($PAMERR{$1})) { 302233294Sstas warn("$func->{'name'}(): unrecognized error: $1\n"); 303178825Sdfr next; 304178825Sdfr } 305233294Sstas $errors{$1} = 1; 306233294Sstas } elsif (m/^!(PAM_[A-Z_]+)$/) { 307178825Sdfr # treat negations separately 308178825Sdfr } elsif (m/^=([a-z_]+)$/) { 309178825Sdfr $ref = $1; 310178825Sdfr if (!defined($FUNCTIONS{$ref})) { 311178825Sdfr $fn = $func->{'source'}; 312178825Sdfr $fn =~ s/$func->{'name'}/$ref/; 313178825Sdfr parse_source($fn); 314178825Sdfr } 315178825Sdfr if (!defined($FUNCTIONS{$ref})) { 316178825Sdfr warn("$func->{'name'}(): reference to unknown $ref()\n"); 317178825Sdfr next; 318178825Sdfr } 319178825Sdfr foreach (@{$FUNCTIONS{$ref}->{'errors'}}) { 320178825Sdfr $errors{$_} = 1; 321178825Sdfr } 322178825Sdfr } else { 323178825Sdfr warn("$func->{'name'}(): invalid error specification: $_\n"); 324233294Sstas } 325178825Sdfr } 326233294Sstas foreach (@{$func->{'errors'}}) { 327233294Sstas if (m/^!(PAM_[A-Z_]+)$/) { 328178825Sdfr delete($errors{$1}); 329233294Sstas } 330178825Sdfr } 331178825Sdfr delete($func->{'recursed'}); 332178825Sdfr $func->{'errors'} = [ sort(keys(%errors)) ]; 333178825Sdfr} 334178825Sdfr 335178825Sdfrsub gendoc($) { 336178825Sdfr my $func = shift; # Ref to function hash 337178825Sdfr 338178825Sdfr local *FILE; 339178825Sdfr my $mdoc; 340178825Sdfr my $fn; 341178825Sdfr 342178825Sdfr return if defined($func->{'nodoc'}); 343178825Sdfr 344178825Sdfr $mdoc = "$COPYRIGHT 345178825Sdfr.Dd $TODAY 346178825Sdfr.Dt " . uc($func->{'name'}) . " 3 347178825Sdfr.Os 348178825Sdfr.Sh NAME 349178825Sdfr.Nm $func->{'name'} 350178825Sdfr.Nd $func->{'descr'} 351178825Sdfr.Sh LIBRARY 352178825Sdfr.Lb libpam 353178825Sdfr.Sh SYNOPSIS 354178825Sdfr.In sys/types.h 355178825Sdfr.In security/pam_appl.h 356178825Sdfr"; 357178825Sdfr if ($func->{'name'} =~ m/_sm_/) { 358178825Sdfr $mdoc .= ".In security/pam_modules.h\n" 359178825Sdfr } 360178825Sdfr if ($func->{'name'} =~ m/openpam/) { 361178825Sdfr $mdoc .= ".In security/openpam.h\n" 362178825Sdfr } 363178825Sdfr $mdoc .= ".Ft $func->{'type'} 364178825Sdfr.Fn $func->{'name'} $func->{'args'} 365178825Sdfr.Sh DESCRIPTION 366178825Sdfr$func->{'man'} 367178825Sdfr"; 368178825Sdfr if ($func->{'type'} eq "int") { 369178825Sdfr $mdoc .= ".Sh RETURN VALUES 370233294SstasThe 371178825Sdfr.Nm 372178825Sdfrfunction returns one of the following values: 373233294Sstas.Bl -tag -width 18n 374178825Sdfr"; 375178825Sdfr my @errors = @{$func->{'errors'}}; 376233294Sstas warn("$func->{'name'}(): no error specification\n") 377233294Sstas unless(@errors); 378233294Sstas foreach (@errors) { 379233294Sstas $mdoc .= ".It Bq Er $_\n$PAMERR{$_}.\n"; 380178825Sdfr } 381178825Sdfr $mdoc .= ".El\n"; 382178825Sdfr } else { 383178825Sdfr if ($func->{'type'} =~ m/\*$/) { 384233294Sstas $mdoc .= ".Sh RETURN VALUES 385178825SdfrThe 386178825Sdfr.Nm 387178825Sdfrfunction returns 388178825Sdfr.Dv NULL 389178825Sdfron failure. 390178825Sdfr"; 391233294Sstas } 392178825Sdfr } 393178825Sdfr $mdoc .= ".Sh SEE ALSO\n"; 394178825Sdfr my @xref = sort(keys(%{$func->{'xref'}})); 395178825Sdfr while (@xref) { 396178825Sdfr $mdoc .= ".Xr " . shift(@xref) . (@xref ? " ,\n" : "\n"); 397178825Sdfr } 398233294Sstas $mdoc .= ".Sh STANDARDS\n"; 399178825Sdfr if ($func->{'openpam'}) { 400178825Sdfr $mdoc .= "The 401178825Sdfr.Nm 402178825Sdfrfunction is an OpenPAM extension. 403178825Sdfr"; 404178825Sdfr } else { 405178825Sdfr $mdoc .= ".Rs 406178825Sdfr.%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\" 407178825Sdfr.%D \"June 1997\" 408178825Sdfr.Re 409178825Sdfr"; 410178825Sdfr } 411233294Sstas $mdoc .= ".Sh AUTHORS 412178825SdfrThe 413178825Sdfr.Nm 414178825Sdfrfunction and this manual page were developed for the FreeBSD Project 415233294Sstasby ThinkSec AS and Network Associates Laboratories, the Security 416178825SdfrResearch Division of Network Associates, Inc. under DARPA/SPAWAR 417178825Sdfrcontract N66001-01-C-8035 418178825Sdfr.Pq Dq CBOSS , 419178825Sdfras part of the DARPA CHATS research program. 420178825Sdfr"; 421178825Sdfr 422178825Sdfr $fn = "$func->{'name'}.3"; 423178825Sdfr if (sysopen(FILE, $fn, O_RDWR|O_CREAT|O_TRUNC)) { 424233294Sstas print(FILE $mdoc); 425233294Sstas close(FILE); 426178825Sdfr } else { 427178825Sdfr warn("$fn: open(): $!\n"); 428178825Sdfr } 429178825Sdfr} 430233294Sstas 431178825Sdfrsub readproto($) { 432178825Sdfr my $fn = shift; # File name 433178825Sdfr 434233294Sstas local *FILE; 435178825Sdfr my %func; 436178825Sdfr 437178825Sdfr sysopen(FILE, $fn, O_RDONLY) 438178825Sdfr or die("$fn: open(): $!\n"); 439233294Sstas while (<FILE>) { 440233294Sstas if (m/^\.Nm ((?:open)?pam_.*?)\s*$/) { 441178825Sdfr $func{'Nm'} = $func{'Nm'} || $1; 442178825Sdfr } elsif (m/^\.Ft (\S.*?)\s*$/) { 443178825Sdfr $func{'Ft'} = $func{'Ft'} || $1; 444233294Sstas } elsif (m/^\.Fn (\S.*?)\s*$/) { 445233294Sstas $func{'Fn'} = $func{'Fn'} || $1; 446233294Sstas } 447178825Sdfr } 448178825Sdfr close(FILE); 449178825Sdfr if ($func{'Nm'}) { 450178825Sdfr $FUNCTIONS{$func{'Nm'}} = \%func; 451178825Sdfr } else { 452178825Sdfr warn("No function found\n"); 453178825Sdfr } 454178825Sdfr} 455178825Sdfr 456178825Sdfrsub gensummary($) { 457178825Sdfr my $page = shift; # Which page to produce 458178825Sdfr 459178825Sdfr local *FILE; 460178825Sdfr my $upage; 461178825Sdfr my $func; 462178825Sdfr my %xref; 463178825Sdfr 464233294Sstas sysopen(FILE, "$page.3", O_RDWR|O_CREAT|O_TRUNC) 465178825Sdfr or die("$page.3: $!\n"); 466178825Sdfr 467178825Sdfr $upage = uc($page); 468233294Sstas print FILE "$COPYRIGHT 469233294Sstas.Dd $TODAY 470233294Sstas.Dt $upage 3 471233294Sstas.Os 472233294Sstas.Sh NAME 473233294Sstas"; 474233294Sstas my @funcs = sort(keys(%FUNCTIONS)); 475233294Sstas while ($func = shift(@funcs)) { 476233294Sstas print FILE ".Nm $FUNCTIONS{$func}->{'Nm'}"; 477233294Sstas print FILE " ," 478233294Sstas if (@funcs); 479233294Sstas print FILE "\n"; 480233294Sstas } 481233294Sstas print FILE ".Nd Pluggable Authentication Modules Library 482233294Sstas.Sh LIBRARY 483233294Sstas.Lb libpam 484233294Sstas.Sh SYNOPSIS\n"; 485233294Sstas if ($page eq 'pam') { 486233294Sstas print FILE ".In security/pam_appl.h\n"; 487233294Sstas } else { 488233294Sstas print FILE ".In security/openpam.h\n"; 489178825Sdfr } 490178825Sdfr foreach $func (sort(keys(%FUNCTIONS))) { 491178825Sdfr print FILE ".Ft $FUNCTIONS{$func}->{'Ft'}\n"; 492233294Sstas print FILE ".Fn $FUNCTIONS{$func}->{'Fn'}\n"; 493233294Sstas } 494233294Sstas while (<STDIN>) { 495233294Sstas if (m/^\.Xr (\S+)\s*(\d)\s*$/) { 496233294Sstas $xref{$1} = $2; 497233294Sstas } 498233294Sstas print FILE $_; 499178825Sdfr } 500178825Sdfr 501233294Sstas if ($page eq 'pam') { 502233294Sstas print FILE ".Sh RETURN VALUES 503233294SstasThe following return codes are defined by 504233294Sstas.Aq Pa security/pam_constants.h : 505233294Sstas.Bl -tag -width 18n 506233294Sstas"; 507233294Sstas foreach (sort(keys(%PAMERR))) { 508178825Sdfr print FILE ".It Bq Er $_\n$PAMERR{$_}.\n"; 509178825Sdfr } 510178825Sdfr print FILE ".El\n"; 511178825Sdfr } 512178825Sdfr print FILE ".Sh SEE ALSO 513178825Sdfr"; 514178825Sdfr print FILE ".Xr openpam 3\n" 515178825Sdfr if ($page eq 'pam'); 516178825Sdfr foreach $func (keys(%FUNCTIONS)) { 517178825Sdfr $xref{$func} = 3; 518233294Sstas } 519233294Sstas my @refs = sort(keys(%xref)); 520233294Sstas while ($_ = shift(@refs)) { 521233294Sstas print FILE ".Xr $_ $xref{$_}"; 522233294Sstas print FILE " ," 523233294Sstas if (@refs); 524233294Sstas print FILE "\n"; 525233294Sstas } 526233294Sstas print FILE ".Sh STANDARDS 527233294Sstas.Rs 528233294Sstas.%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\" 529233294Sstas.%D \"June 1997\" 530233294Sstas.Re 531233294Sstas.Sh AUTHORS 532178825SdfrThe OpenPAM library and this manual page were developed for the 533233294SstasFreeBSD Project by ThinkSec AS and Network Associates Laboratories, 534233294Sstasthe Security Research Division of Network Associates, Inc. under 535233294SstasDARPA/SPAWAR contract N66001-01-C-8035 536233294Sstas.Pq Dq CBOSS , 537233294Sstasas part of the DARPA CHATS research program. 538178825Sdfr"; 539178825Sdfr close(FILE); 540233294Sstas} 541233294Sstas 542233294Sstassub usage() { 543233294Sstas 544233294Sstas print(STDERR "usage: gendoc [-s] source [...]\n"); 545178825Sdfr exit(1); 546178825Sdfr} 547233294Sstas 548233294SstasMAIN:{ 549233294Sstas my %opts; 550233294Sstas 551233294Sstas usage() 552178825Sdfr unless (@ARGV && getopts("op", \%opts)); 553178825Sdfr $TODAY = strftime("%B %e, %Y", localtime(time())); 554178825Sdfr $TODAY =~ s,\s+, ,g; 555178825Sdfr if ($opts{'o'} || $opts{'p'}) { 556178825Sdfr foreach my $fn (@ARGV) { 557178825Sdfr readproto($fn); 558233294Sstas } 559178825Sdfr gensummary('openpam') 560178825Sdfr if ($opts{'o'}); 561233294Sstas gensummary('pam') 562233294Sstas if ($opts{'p'}); 563233294Sstas } else { 564233294Sstas foreach my $fn (@ARGV) { 565233294Sstas my $func = parse_source($fn); 566233294Sstas gendoc($func) 567233294Sstas if (defined($func)); 568233294Sstas } 569233294Sstas } 570233294Sstas exit(0); 571233294Sstas} 572233294Sstas