1#!/usr/bin/perl -w 2#- 3# Copyright (c) 2002-2003 Networks Associates Technology, Inc. 4# Copyright (c) 2004-2011 Dag-Erling Smørgrav 5# All rights reserved. 6# 7# This software was developed for the FreeBSD Project by ThinkSec AS and 8# Network Associates Laboratories, the Security Research Division of 9# Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 10# ("CBOSS"), as part of the DARPA CHATS research program. 11# 12# Redistribution and use in source and binary forms, with or without 13# modification, are permitted provided that the following conditions 14# are met: 15# 1. Redistributions of source code must retain the above copyright 16# notice, this list of conditions and the following disclaimer. 17# 2. Redistributions in binary form must reproduce the above copyright 18# notice, this list of conditions and the following disclaimer in the 19# documentation and/or other materials provided with the distribution. 20# 3. The name of the author may not be used to endorse or promote 21# products derived from this software without specific prior written 22# permission. 23# 24# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 25# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 28# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34# SUCH DAMAGE. 35# 36# $Id: gendoc.pl 599 2012-04-14 15:06:41Z des $ 37# 38 39use strict; 40use locale; 41use Fcntl; 42use Getopt::Std; 43use POSIX qw(locale_h strftime); 44use vars qw($COPYRIGHT %AUTHORS $TODAY %FUNCTIONS %PAMERR); 45 46$COPYRIGHT = ".\\\"- 47.\\\" Copyright (c) 2001-2003 Networks Associates Technology, Inc. 48.\\\" Copyright (c) 2004-2011 Dag-Erling Smørgrav 49.\\\" All rights reserved. 50.\\\" 51.\\\" This software was developed for the FreeBSD Project by ThinkSec AS and 52.\\\" Network Associates Laboratories, the Security Research Division of 53.\\\" Network Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 54.\\\" (\"CBOSS\"), as part of the DARPA CHATS research program. 55.\\\" 56.\\\" Redistribution and use in source and binary forms, with or without 57.\\\" modification, are permitted provided that the following conditions 58.\\\" are met: 59.\\\" 1. Redistributions of source code must retain the above copyright 60.\\\" notice, this list of conditions and the following disclaimer. 61.\\\" 2. Redistributions in binary form must reproduce the above copyright 62.\\\" notice, this list of conditions and the following disclaimer in the 63.\\\" documentation and/or other materials provided with the distribution. 64.\\\" 3. The name of the author may not be used to endorse or promote 65.\\\" products derived from this software without specific prior written 66.\\\" permission. 67.\\\" 68.\\\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 69.\\\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 70.\\\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 71.\\\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 72.\\\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 73.\\\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 74.\\\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 75.\\\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 76.\\\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 77.\\\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 78.\\\" SUCH DAMAGE. 79.\\\" 80.\\\" \$" . "Id" . "\$ 81.\\\""; 82 83%AUTHORS = ( 84 THINKSEC => "developed for the 85.Fx 86Project by ThinkSec AS and Network Associates Laboratories, the 87Security Research Division of Network Associates, Inc.\\& under 88DARPA/SPAWAR contract N66001-01-C-8035 89.Pq Dq CBOSS , 90as part of the DARPA CHATS research program.", 91 DES => "developed by 92.An Dag-Erling Sm\\(/orgrav Aq des\@des.no .", 93); 94 95%PAMERR = ( 96 PAM_SUCCESS => "Success", 97 PAM_OPEN_ERR => "Failed to load module", 98 PAM_SYMBOL_ERR => "Invalid symbol", 99 PAM_SERVICE_ERR => "Error in service module", 100 PAM_SYSTEM_ERR => "System error", 101 PAM_BUF_ERR => "Memory buffer error", 102 PAM_CONV_ERR => "Conversation failure", 103 PAM_PERM_DENIED => "Permission denied", 104 PAM_MAXTRIES => "Maximum number of tries exceeded", 105 PAM_AUTH_ERR => "Authentication error", 106 PAM_NEW_AUTHTOK_REQD => "New authentication token required", 107 PAM_CRED_INSUFFICIENT => "Insufficient credentials", 108 PAM_AUTHINFO_UNAVAIL => "Authentication information is unavailable", 109 PAM_USER_UNKNOWN => "Unknown user", 110 PAM_CRED_UNAVAIL => "Failed to retrieve user credentials", 111 PAM_CRED_EXPIRED => "User credentials have expired", 112 PAM_CRED_ERR => "Failed to set user credentials", 113 PAM_ACCT_EXPIRED => "User account has expired", 114 PAM_AUTHTOK_EXPIRED => "Password has expired", 115 PAM_SESSION_ERR => "Session failure", 116 PAM_AUTHTOK_ERR => "Authentication token failure", 117 PAM_AUTHTOK_RECOVERY_ERR => "Failed to recover old authentication token", 118 PAM_AUTHTOK_LOCK_BUSY => "Authentication token lock busy", 119 PAM_AUTHTOK_DISABLE_AGING => "Authentication token aging disabled", 120 PAM_NO_MODULE_DATA => "Module data not found", 121 PAM_IGNORE => "Ignore this module", 122 PAM_ABORT => "General failure", 123 PAM_TRY_AGAIN => "Try again", 124 PAM_MODULE_UNKNOWN => "Unknown module type", 125 PAM_DOMAIN_UNKNOWN => "Unknown authentication domain", 126); 127 128sub parse_source($) { 129 my $fn = shift; 130 131 local *FILE; 132 my $source; 133 my $func; 134 my $descr; 135 my $type; 136 my $args; 137 my $argnames; 138 my $man; 139 my $inlist; 140 my $intaglist; 141 my $inliteral; 142 my $customrv; 143 my $deprecated; 144 my $experimental; 145 my %xref; 146 my @errors; 147 my $author; 148 149 if ($fn !~ m,\.c$,) { 150 warn("$fn: not C source, ignoring\n"); 151 return undef; 152 } 153 154 open(FILE, "<", "$fn") 155 or die("$fn: open(): $!\n"); 156 $source = join('', <FILE>); 157 close(FILE); 158 159 return undef 160 if ($source =~ m/^ \* NOPARSE\s*$/m); 161 162 $author = 'THINKSEC'; 163 if ($source =~ s/^ \* AUTHOR\s+(\w*)\s*$//m) { 164 $author = $1; 165 } 166 167 if ($source =~ s/^ \* DEPRECATED\s*(\w*)\s*$//m) { 168 $deprecated = $1 // 0; 169 } 170 171 if ($source =~ s/^ \* EXPERIMENTAL\s*$//m) { 172 $experimental = 1; 173 } 174 175 $func = $fn; 176 $func =~ s,^(?:.*/)?([^/]+)\.c$,$1,; 177 if ($source !~ m,\n \* ([\S ]+)\n \*/\n\n([\S ]+)\n$func\((.*?)\)\n\{,s) { 178 warn("$fn: can't find $func\n"); 179 return undef; 180 } 181 ($descr, $type, $args) = ($1, $2, $3); 182 $descr =~ s,^([A-Z][a-z]),lc($1),e; 183 $descr =~ s,[\.\s]*$,,; 184 while ($args =~ s/^((?:[^\(]|\([^\)]*\))*),\s*/$1\" \"/g) { 185 # nothing 186 } 187 $args =~ s/,\s+/, /gs; 188 $args = "\"$args\""; 189 190 %xref = ( 191 3 => { 'pam' => 1 }, 192 ); 193 194 if ($type eq "int") { 195 foreach (split("\n", $source)) { 196 next unless (m/^ \*\s+(!?PAM_[A-Z_]+|=[a-z_]+)\s*$/); 197 push(@errors, $1); 198 } 199 ++$xref{3}->{'pam_strerror'}; 200 } 201 202 $argnames = $args; 203 # extract names of regular arguments 204 $argnames =~ s/\"[^\"]+\*?\b(\w+)\"/\"$1\"/g; 205 # extract names of function pointer arguments 206 $argnames =~ s/\"([\w\s\*]+)\(\*?(\w+)\)\([^\)]+\)\"/\"$2\"/g; 207 # escape metacharacters (there shouldn't be any, but...) 208 $argnames =~ s/([\|\[\]\(\)\.\*\+\?])/\\$1/g; 209 # separate argument names with | 210 $argnames =~ s/\" \"/|/g; 211 # and surround with () 212 $argnames =~ s/^\"(.*)\"$/$1/; 213 # $argnames is now a regexp that matches argument names 214 $inliteral = $inlist = $intaglist = 0; 215 foreach (split("\n", $source)) { 216 s/\s*$//; 217 if (!defined($man)) { 218 if (m/^\/\*\*$/) { 219 $man = ""; 220 } 221 next; 222 } 223 last if (m/^ \*\/$/); 224 s/^ \* ?//; 225 s/\\(.)/$1/gs; 226 if (m/^$/) { 227 # paragraph separator 228 if ($inlist || $intaglist) { 229 # either a blank line between list items, or a blank 230 # line after the final list item. The latter case 231 # will be handled further down. 232 next; 233 } 234 if ($man =~ m/\n\.Sh [^\n]+\n$/s) { 235 # a blank line after a section header 236 next; 237 } 238 if ($man ne "" && $man !~ m/\.Pp\n$/s) { 239 if ($inliteral) { 240 $man .= "\0\n"; 241 } else { 242 $man .= ".Pp\n"; 243 } 244 } 245 next; 246 } 247 if (m/^>(\w+)(\s+\d)?$/) { 248 # "see also" cross-reference 249 my ($page, $sect) = ($1, $2 ? int($2) : 3); 250 ++$xref{$sect}->{$page}; 251 next; 252 } 253 if (s/^([A-Z][0-9A-Z -]+)$/.Sh $1/) { 254 if ($1 eq "RETURN VALUES") { 255 $customrv = $1; 256 } 257 $man =~ s/\n\.Pp$/\n/s; 258 $man .= "$_\n"; 259 next; 260 } 261 if (s/^\s+-\s+//) { 262 # item in bullet list 263 if ($inliteral) { 264 $man .= ".Ed\n"; 265 $inliteral = 0; 266 } 267 if ($intaglist) { 268 $man .= ".El\n.Pp\n"; 269 $intaglist = 0; 270 } 271 if (!$inlist) { 272 $man =~ s/\.Pp\n$//s; 273 $man .= ".Bl -bullet\n"; 274 $inlist = 1; 275 } 276 $man .= ".It\n"; 277 # fall through 278 } elsif (s/^\s+(\S+):\s*/.It $1/) { 279 # item in tag list 280 if ($inliteral) { 281 $man .= ".Ed\n"; 282 $inliteral = 0; 283 } 284 if ($inlist) { 285 $man .= ".El\n.Pp\n"; 286 $inlist = 0; 287 } 288 if (!$intaglist) { 289 $man =~ s/\.Pp\n$//s; 290 $man .= ".Bl -tag -width 18n\n"; 291 $intaglist = 1; 292 } 293 s/^\.It =([A-Z][A-Z_]+)$/.It Dv $1/gs; 294 $man .= "$_\n"; 295 next; 296 } elsif (($inlist || $intaglist) && m/^\S/) { 297 # regular text after list 298 $man .= ".El\n.Pp\n"; 299 $inlist = $intaglist = 0; 300 } elsif ($inliteral && m/^\S/) { 301 # regular text after literal section 302 $man .= ".Ed\n"; 303 $inliteral = 0; 304 } elsif ($inliteral) { 305 # additional text within literal section 306 $man .= "$_\n"; 307 next; 308 } elsif ($inlist || $intaglist) { 309 # additional text within list 310 s/^\s+//; 311 } elsif (m/^\s+/) { 312 # new literal section 313 $man .= ".Bd -literal\n"; 314 $inliteral = 1; 315 $man .= "$_\n"; 316 next; 317 } 318 s/\s*=($func)\b\s*/\n.Fn $1\n/gs; 319 s/\s*=($argnames)\b\s*/\n.Fa $1\n/gs; 320 s/\s*=(struct \w+(?: \*)?)\b\s*/\n.Vt $1\n/gs; 321 s/\s*:([a-z_]+)\b\s*/\n.Va $1\n/gs; 322 s/\s*;([a-z_]+)\b\s*/\n.Dv $1\n/gs; 323 s/\s*=!([a-z_]+)\b\s*/\n.Xr $1 3\n/gs; 324 while (s/\s*=([a-z_]+)\b\s*/\n.Xr $1 3\n/s) { 325 ++$xref{3}->{$1}; 326 } 327 s/\s*\"(?=\w)/\n.Do\n/gs; 328 s/\"(?!\w)\s*/\n.Dc\n/gs; 329 s/\s*=([A-Z][A-Z_]+)\b\s*(?![\.,:;])/\n.Dv $1\n/gs; 330 s/\s*=([A-Z][A-Z_]+)\b([\.,:;]+)\s*/\n.Dv $1 $2\n/gs; 331 s/\s*{([A-Z][a-z] .*?)}\s*/\n.$1\n/gs; 332 $man .= "$_\n"; 333 } 334 if (defined($man)) { 335 if ($inlist || $intaglist) { 336 $man .= ".El\n"; 337 $inlist = $intaglist = 0; 338 } 339 if ($inliteral) { 340 $man .= ".Ed\n"; 341 $inliteral = 0; 342 } 343 $man =~ s/\%/\\&\%/gs; 344 $man =~ s/(\n\.[A-Z][a-z] [\w ]+)\n([.,:;-])\s+/$1 $2\n/gs; 345 $man =~ s/\s*$/\n/gm; 346 $man =~ s/\n+/\n/gs; 347 $man =~ s/\0//gs; 348 $man =~ s/\n\n\./\n\./gs; 349 chomp($man); 350 } else { 351 $man = "No description available."; 352 } 353 354 $FUNCTIONS{$func} = { 355 'source' => $fn, 356 'name' => $func, 357 'descr' => $descr, 358 'type' => $type, 359 'args' => $args, 360 'man' => $man, 361 'xref' => \%xref, 362 'errors' => \@errors, 363 'author' => $author, 364 'customrv' => $customrv, 365 'deprecated' => $deprecated, 366 'experimental' => $experimental, 367 }; 368 if ($source =~ m/^ \* NODOC\s*$/m) { 369 $FUNCTIONS{$func}->{'nodoc'} = 1; 370 } 371 if ($source !~ m/^ \* XSSO \d/m) { 372 $FUNCTIONS{$func}->{'openpam'} = 1; 373 } 374 expand_errors($FUNCTIONS{$func}); 375 return $FUNCTIONS{$func}; 376} 377 378sub expand_errors($); 379sub expand_errors($) { 380 my $func = shift; # Ref to function hash 381 382 my %errors; 383 my $ref; 384 my $fn; 385 386 if (defined($func->{'recursed'})) { 387 warn("$func->{'name'}(): loop in error spec\n"); 388 return qw(); 389 } 390 $func->{'recursed'} = 1; 391 392 foreach (@{$func->{'errors'}}) { 393 if (m/^(PAM_[A-Z_]+)$/) { 394 if (!defined($PAMERR{$1})) { 395 warn("$func->{'name'}(): unrecognized error: $1\n"); 396 next; 397 } 398 $errors{$1} = 1; 399 } elsif (m/^!(PAM_[A-Z_]+)$/) { 400 # treat negations separately 401 } elsif (m/^=([a-z_]+)$/) { 402 $ref = $1; 403 if (!defined($FUNCTIONS{$ref})) { 404 $fn = $func->{'source'}; 405 $fn =~ s/$func->{'name'}/$ref/; 406 parse_source($fn); 407 } 408 if (!defined($FUNCTIONS{$ref})) { 409 warn("$func->{'name'}(): reference to unknown $ref()\n"); 410 next; 411 } 412 foreach (@{$FUNCTIONS{$ref}->{'errors'}}) { 413 $errors{$_} = 1; 414 } 415 } else { 416 warn("$func->{'name'}(): invalid error specification: $_\n"); 417 } 418 } 419 foreach (@{$func->{'errors'}}) { 420 if (m/^!(PAM_[A-Z_]+)$/) { 421 delete($errors{$1}); 422 } 423 } 424 delete($func->{'recursed'}); 425 $func->{'errors'} = [ sort(keys(%errors)) ]; 426} 427 428sub dictionary_order($$) { 429 my ($a, $b) = @_; 430 431 $a =~ s/[^[:alpha:]]//g; 432 $b =~ s/[^[:alpha:]]//g; 433 $a cmp $b; 434} 435 436sub genxref($) { 437 my $xref = shift; # References 438 439 my $mdoc = ''; 440 my @refs = (); 441 foreach my $sect (sort(keys(%{$xref}))) { 442 foreach my $page (sort(dictionary_order keys(%{$xref->{$sect}}))) { 443 push(@refs, "$page $sect"); 444 } 445 } 446 while ($_ = shift(@refs)) { 447 $mdoc .= ".Xr $_" . 448 (@refs ? " ,\n" : "\n"); 449 } 450 return $mdoc; 451} 452 453sub gendoc($) { 454 my $func = shift; # Ref to function hash 455 456 local *FILE; 457 my $mdoc; 458 my $fn; 459 460 return if defined($func->{'nodoc'}); 461 462 $mdoc = "$COPYRIGHT 463.Dd $TODAY 464.Dt " . uc($func->{'name'}) . " 3 465.Os 466.Sh NAME 467.Nm $func->{'name'} 468.Nd $func->{'descr'} 469.Sh LIBRARY 470.Lb libpam 471.Sh SYNOPSIS 472.In sys/types.h 473"; 474 if ($func->{'args'} =~ m/\bFILE \*\b/) { 475 $mdoc .= ".In stdio.h\n"; 476 } 477 $mdoc .= ".In security/pam_appl.h 478"; 479 if ($func->{'name'} =~ m/_sm_/) { 480 $mdoc .= ".In security/pam_modules.h\n"; 481 } 482 if ($func->{'name'} =~ m/openpam/) { 483 $mdoc .= ".In security/openpam.h\n"; 484 } 485 $mdoc .= ".Ft \"$func->{'type'}\" 486.Fn $func->{'name'} $func->{'args'} 487.Sh DESCRIPTION 488"; 489 if (defined($func->{'deprecated'})) { 490 $mdoc .= ".Bf Sy\n" . 491 "This function is deprecated and may be removed " . 492 "in a future release without further warning.\n"; 493 if ($func->{'deprecated'}) { 494 $mdoc .= "The\n.Fn $func->{'deprecated'}\nfunction " . 495 "may be used to achieve similar results.\n"; 496 } 497 $mdoc .= ".Ef\n.Pp\n"; 498 } 499 if ($func->{'experimental'}) { 500 $mdoc .= ".Bf Sy\n" . 501 "This function is experimental and may be modified or removed " . 502 "in a future release without further warning.\n"; 503 $mdoc .= ".Ef\n.Pp\n"; 504 } 505 $mdoc .= "$func->{'man'}\n"; 506 my @errors = @{$func->{'errors'}}; 507 if ($func->{'customrv'}) { 508 # leave it 509 } elsif ($func->{'type'} eq "int" && @errors) { 510 $mdoc .= ".Sh RETURN VALUES 511The 512.Fn $func->{'name'} 513function returns one of the following values: 514.Bl -tag -width 18n 515"; 516 foreach (@errors) { 517 $mdoc .= ".It Bq Er $_\n$PAMERR{$_}.\n"; 518 } 519 $mdoc .= ".El\n"; 520 } elsif ($func->{'type'} eq "int") { 521 $mdoc .= ".Sh RETURN VALUES 522The 523.Fn $func->{'name'} 524function returns 0 on success and -1 on failure. 525"; 526 } elsif ($func->{'type'} =~ m/\*$/) { 527 $mdoc .= ".Sh RETURN VALUES 528The 529.Fn $func->{'name'} 530function returns 531.Dv NULL 532on failure. 533"; 534 } elsif ($func->{'type'} ne "void") { 535 warn("$func->{'name'}(): no error specification\n"); 536 } 537 $mdoc .= ".Sh SEE ALSO\n" . genxref($func->{'xref'}); 538 $mdoc .= ".Sh STANDARDS\n"; 539 if ($func->{'openpam'}) { 540 $mdoc .= "The 541.Fn $func->{'name'} 542function is an OpenPAM extension. 543"; 544 } else { 545 $mdoc .= ".Rs 546.%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\" 547.%D \"June 1997\" 548.Re 549"; 550 } 551 $mdoc .= ".Sh AUTHORS 552The 553.Fn $func->{'name'} 554function and this manual page were\n"; 555 $mdoc .= $AUTHORS{$func->{'author'} // 'THINKSEC_DARPA'} . "\n"; 556 $fn = "$func->{'name'}.3"; 557 if (open(FILE, ">", $fn)) { 558 print(FILE $mdoc); 559 close(FILE); 560 } else { 561 warn("$fn: open(): $!\n"); 562 } 563} 564 565sub readproto($) { 566 my $fn = shift; # File name 567 568 local *FILE; 569 my %func; 570 571 open(FILE, "<", "$fn") 572 or die("$fn: open(): $!\n"); 573 while (<FILE>) { 574 if (m/^\.Nm ((?:open)?pam_.*?)\s*$/) { 575 $func{'Nm'} = $func{'Nm'} || $1; 576 } elsif (m/^\.Ft (\S.*?)\s*$/) { 577 $func{'Ft'} = $func{'Ft'} || $1; 578 } elsif (m/^\.Fn (\S.*?)\s*$/) { 579 $func{'Fn'} = $func{'Fn'} || $1; 580 } 581 } 582 close(FILE); 583 if ($func{'Nm'}) { 584 $FUNCTIONS{$func{'Nm'}} = \%func; 585 } else { 586 warn("No function found\n"); 587 } 588} 589 590sub gensummary($) { 591 my $page = shift; # Which page to produce 592 593 local *FILE; 594 my $upage; 595 my $func; 596 my %xref; 597 598 open(FILE, ">", "$page.3") 599 or die("$page.3: $!\n"); 600 601 $page =~ m/(\w+)$/; 602 $upage = uc($1); 603 print FILE "$COPYRIGHT 604.Dd $TODAY 605.Dt $upage 3 606.Os 607.Sh NAME 608"; 609 my @funcs = sort(keys(%FUNCTIONS)); 610 while ($func = shift(@funcs)) { 611 print FILE ".Nm $FUNCTIONS{$func}->{'Nm'}"; 612 print FILE " ," 613 if (@funcs); 614 print FILE "\n"; 615 } 616 print FILE ".Nd Pluggable Authentication Modules Library 617.Sh LIBRARY 618.Lb libpam 619.Sh SYNOPSIS\n"; 620 if ($page eq 'pam') { 621 print FILE ".In security/pam_appl.h\n"; 622 } else { 623 print FILE ".In security/openpam.h\n"; 624 } 625 foreach $func (sort(keys(%FUNCTIONS))) { 626 print FILE ".Ft $FUNCTIONS{$func}->{'Ft'}\n"; 627 print FILE ".Fn $FUNCTIONS{$func}->{'Fn'}\n"; 628 } 629 while (<STDIN>) { 630 if (m/^\.Xr (\S+)\s*(\d)\s*$/) { 631 ++$xref{int($2)}->{$1}; 632 } 633 print FILE $_; 634 } 635 636 if ($page eq 'pam') { 637 print FILE ".Sh RETURN VALUES 638The following return codes are defined by 639.In security/pam_constants.h : 640.Bl -tag -width 18n 641"; 642 foreach (sort(keys(%PAMERR))) { 643 print FILE ".It Bq Er $_\n$PAMERR{$_}.\n"; 644 } 645 print FILE ".El\n"; 646 } 647 print FILE ".Sh SEE ALSO 648"; 649 if ($page eq 'pam') { 650 ++$xref{3}->{'openpam'}; 651 } 652 foreach $func (keys(%FUNCTIONS)) { 653 ++$xref{3}->{$func}; 654 } 655 print FILE genxref(\%xref); 656 print FILE ".Sh STANDARDS 657.Rs 658.%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\" 659.%D \"June 1997\" 660.Re 661.Sh AUTHORS 662The OpenPAM library and this manual page were developed for the 663.Fx 664Project by ThinkSec AS and Network Associates Laboratories, the 665Security Research Division of Network Associates, Inc.\\& under 666DARPA/SPAWAR contract N66001-01-C-8035 667.Pq Dq CBOSS , 668as part of the DARPA CHATS research program. 669.Pp 670The OpenPAM library is maintained by 671.An Dag-Erling Sm\\(/orgrav Aq des\@des.no . 672"; 673 close(FILE); 674} 675 676sub usage() { 677 678 print(STDERR "usage: gendoc [-op] source [...]\n"); 679 exit(1); 680} 681 682MAIN:{ 683 my %opts; 684 685 usage() 686 unless (@ARGV && getopts("op", \%opts)); 687 setlocale(LC_ALL, "en_US.UTF-8"); 688 $TODAY = strftime("%B %e, %Y", localtime(time())); 689 $TODAY =~ s,\s+, ,g; 690 if ($opts{'o'} || $opts{'p'}) { 691 foreach my $fn (@ARGV) { 692 readproto($fn); 693 } 694 gensummary('openpam') 695 if ($opts{'o'}); 696 gensummary('pam') 697 if ($opts{'p'}); 698 } else { 699 foreach my $fn (@ARGV) { 700 my $func = parse_source($fn); 701 gendoc($func) 702 if (defined($func)); 703 } 704 } 705 exit(0); 706} 707