3 # Copyright (c) 2002-2003 Networks Associates Technology, Inc.
4 # Copyright (c) 2004-2007 Dag-Erling Smørgrav
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.
12 # Redistribution and use in source and binary forms, with or without
13 # modification, are permitted provided that the following conditions
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
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
36 # $Id: gendoc.pl,v 1.5 2008/01/27 01:23:01 christos Exp $
43 use POSIX
qw(locale_h strftime);
44 use vars
qw($COPYRIGHT $TODAY %FUNCTIONS %PAMERR);
47 .\\\" Copyright (c) 2001-2003 Networks Associates Technology, Inc.
48 .\\\" Copyright (c) 2004-2007 Dag-Erling Smørgrav
49 .\\\" All rights reserved.
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.
56 .\\\" Redistribution and use in source and binary forms, with or without
57 .\\\" modification, are permitted provided that the following conditions
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
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
80 .\\\" \$" . "P4" . "\$
84 PAM_SUCCESS => "Success",
85 PAM_OPEN_ERR => "Failed to load module",
86 PAM_SYMBOL_ERR => "Invalid symbol",
87 PAM_SERVICE_ERR => "Error in service module",
88 PAM_SYSTEM_ERR => "System error",
89 PAM_BUF_ERR => "Memory buffer error",
90 PAM_CONV_ERR => "Conversation failure",
91 PAM_PERM_DENIED => "Permission denied",
92 PAM_MAXTRIES => "Maximum number of tries exceeded",
93 PAM_AUTH_ERR => "Authentication error",
94 PAM_NEW_AUTHTOK_REQD => "New authentication token required",
95 PAM_CRED_INSUFFICIENT => "Insufficient credentials",
96 PAM_AUTHINFO_UNAVAIL => "Authentication information is unavailable",
97 PAM_USER_UNKNOWN => "Unknown user",
98 PAM_CRED_UNAVAIL => "Failed to retrieve user credentials",
99 PAM_CRED_EXPIRED => "User credentials have expired",
100 PAM_CRED_ERR => "Failed to set user credentials",
101 PAM_ACCT_EXPIRED => "User account has expired",
102 PAM_AUTHTOK_EXPIRED => "Password has expired",
103 PAM_SESSION_ERR => "Session failure",
104 PAM_AUTHTOK_ERR => "Authentication token failure",
105 PAM_AUTHTOK_RECOVERY_ERR => "Failed to recover old authentication token",
106 PAM_AUTHTOK_LOCK_BUSY => "Authentication token lock busy",
107 PAM_AUTHTOK_DISABLE_AGING => "Authentication token aging disabled",
108 PAM_NO_MODULE_DATA => "Module data not found",
109 PAM_IGNORE => "Ignore this module",
110 PAM_ABORT => "General failure",
111 PAM_TRY_AGAIN => "Try again",
112 PAM_MODULE_UNKNOWN => "Unknown module type",
113 PAM_DOMAIN_UNKNOWN => "Unknown authentication domain",
116 sub parse_source($) {
132 if ($fn !~ m,\.c$,) {
133 warn("$fn: not C source, ignoring\n");
137 sysopen(FILE, $fn, O_RDONLY)
138 or die("$fn: open(): $!\n");
139 $source = join('', <FILE>);
143 if ($source =~ m/^ \* NOPARSE\s*$/m);
146 $func =~ s,^(?:.*/)?([^/]+)\.c$,$1,;
147 if ($source !~ m,\n \* ([\S ]+)\n \*/\n\n([\S ]+)\n$func\((.*?)\)\n\{,s) {
148 warn("$fn: can't find $func\n");
151 ($descr, $type, $args) = ($1, $2, $3);
152 $descr =~ s,^([A-Z][a-z]),lc($1),e;
153 $descr =~ s,[\.\s]*$,,;
154 while ($args =~ s/^((?:[^\(]|\([^\)]*\))*),\s*/$1\" \"/g) {
157 $args =~ s/,\s+/, /gs;
164 if ($type eq "int") {
165 foreach (split("\n", $source)) {
166 next unless (m/^ \*\s+(!?PAM_[A-Z_]+|=[a-z_]+)\s*$/);
169 ++$xref{3}->{'pam_strerror'};
173 # extract names of regular arguments
174 $argnames =~ s/\"[^\"]+\*?\b(\w+)\"/\"$1\"/g;
175 # extract names of function pointer arguments
176 $argnames =~ s/\"([\w\s\*]+)\(\*?(\w+)\)\([^\)]+\)\"/\"$2\"/g;
177 # escape metacharacters (there shouldn't be any, but...)
178 $argnames =~ s/([\|\[\]\(\)\.\*\+\?])/\\$1/g;
179 # separate argument names with |
180 $argnames =~ s/\" \"/|/g;
181 # and surround with ()
182 $argnames =~ s/^\"(.*)\"$/($1)/;
183 # $argnames is now a regexp that matches argument names
184 $inliteral = $inlist = 0;
185 foreach (split("\n", $source)) {
187 if (!defined($man)) {
193 last if (m/^ \*\/$/);
197 if ($man ne "" && $man !~ m/\.Pp\n$/s) {
201 $man .= ".El\n.Pp\n";
209 if (m/^>(\w+)(\s+\d)?$/) {
210 my ($page, $sect) = ($1, $2 ? int($2) : 3);
211 ++$xref{$sect}->{$page};
214 if (s/^\s+(=?\w+):\s*/.It $1/) {
220 $man =~ s/\.Pp\n$//s;
221 $man .= ".Bl -tag -width 18n\n";
224 s/^\.It =([A-Z][A-Z_]+)$/.It Dv $1/gs;
227 } elsif ($inlist && m/^\S/) {
228 $man .= ".El\n.Pp\n";
230 } elsif ($inliteral && m/^\S/) {
233 } elsif ($inliteral) {
239 $man .= ".Bd -literal\n";
244 s/\s*=$func\b\s*/\n.Nm\n/gs;
245 s/\s*=$argnames\b\s*/\n.Fa $1\n/gs;
246 s/\s*=(struct \w+(?: \*)?)\b\s*/\n.Vt $1\n/gs;
247 s/\s*:([a-z_]+)\b\s*/\n.Va $1\n/gs;
248 s/\s*;([a-z_]+)\b\s*/\n.Dv $1\n/gs;
249 s/\s*=cleanup\s*/\n.Ar cleanup\n/gs;
250 while (s/\s*=([a-z_]+)\b\s*/\n.Xr $1 3\n/s) {
253 s/\s*\"(?=\w)/\n.Do\n/gs;
254 s/\"(?!\w)\s*/\n.Dc\n/gs;
255 s/\s*=([A-Z][A-Z_]+)\b\s*(?![\.,:;])/\n.Dv $1\n/gs;
256 s/\s*=([A-Z][A-Z_]+)\b([\.,:;]+)\s*/\n.Dv $1 $2\n/gs;
257 s/\s*{([A-Z][a-z] .*?)}\s*/\n.$1\n/gs;
267 $man =~ s/(\n\.[A-Z][a-z] [\w ]+)\n([\.,:;-]\S*)\s*/$1 $2\n/gs;
268 $man =~ s/\s*$/\n/gm;
271 $man =~ s/\n\n\./\n\./gs;
274 $man = "No description available.";
277 $FUNCTIONS{$func} = {
285 'errors' => \@errors,
287 if ($source =~ m/^ \* NODOC\s*$/m) {
288 $FUNCTIONS{$func}->{'nodoc'} = 1;
290 if ($source !~ m/^ \* XSSO \d/m) {
291 $FUNCTIONS{$func}->{'openpam'} = 1;
293 expand_errors($FUNCTIONS{$func});
294 return $FUNCTIONS{$func};
297 sub expand_errors($);
298 sub expand_errors($) {
299 my $func = shift; # Ref to function hash
305 if (defined($func->{'recursed'})) {
306 warn("$func->{'name'}(): loop in error spec\n");
309 $func->{'recursed'} = 1;
311 foreach (@
{$func->{'errors'}}) {
312 if (m/^(PAM_[A-Z_]+)$/) {
313 if (!defined($PAMERR{$1})) {
314 warn("$func->{'name'}(): unrecognized error: $1\n");
318 } elsif (m/^!(PAM_[A-Z_]+)$/) {
319 # treat negations separately
320 } elsif (m/^=([a-z_]+)$/) {
322 if (!defined($FUNCTIONS{$ref})) {
323 $fn = $func->{'source'};
324 $fn =~ s/$func->{'name'}/$ref/;
327 if (!defined($FUNCTIONS{$ref})) {
328 warn("$func->{'name'}(): reference to unknown $ref()\n");
331 foreach (@
{$FUNCTIONS{$ref}->{'errors'}}) {
335 warn("$func->{'name'}(): invalid error specification: $_\n");
338 foreach (@
{$func->{'errors'}}) {
339 if (m/^!(PAM_[A-Z_]+)$/) {
343 delete($func->{'recursed'});
344 $func->{'errors'} = [ sort(keys(%errors)) ];
347 sub dictionary_order
($$) {
350 $a =~ s/[^[:alpha:]]//g;
351 $b =~ s/[^[:alpha:]]//g;
356 my $xref = shift; # References
360 foreach my $sect (sort(keys(%{$xref}))) {
361 foreach my $page (sort(dictionary_order
keys(%{$xref->{$sect}}))) {
362 push(@refs, "$page $sect");
365 while ($_ = shift(@refs)) {
367 (@refs ?
" ,\n" : "\n");
373 my $func = shift; # Ref to function hash
379 return if defined($func->{'nodoc'});
386 .Dt " . uc($func->{'name'}) . " 3
395 .In security/pam_appl.h
397 if ($func->{'name'} =~ m/_sm_/) {
398 $mdoc .= ".In security/pam_modules.h\n"
400 if ($func->{'name'} =~ m/openpam/) {
401 $mdoc .= ".In security/openpam.h\n"
403 $mdoc .= ".Ft \"$func->{'type'}\"
404 .Fn $func->{'name'} $func->{'args'}
408 if ($func->{'type'} eq "int") {
409 $mdoc .= ".Sh RETURN VALUES
412 function returns one of the following values:
415 my @errors = @
{$func->{'errors'}};
416 warn("$func->{'name'}(): no error specification\n")
419 $mdoc .= ".It Bq Er $_\n$PAMERR{$_}.\n";
423 if ($func->{'type'} =~ m/\*$/) {
424 $mdoc .= ".Sh RETURN VALUES
433 $mdoc .= ".Sh SEE ALSO\n" . genxref
($func->{'xref'});
434 $mdoc .= ".Sh STANDARDS\n";
435 if ($func->{'openpam'}) {
438 function is an OpenPAM extension.
442 .%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
447 $mdoc .= ".Sh AUTHORS
450 function and this manual page were developed for the
452 Project by ThinkSec AS and Network Associates Laboratories, the
453 Security Research Division of Network Associates, Inc.\\& under
454 DARPA/SPAWAR contract N66001-01-C-8035
456 as part of the DARPA CHATS research program.
459 $fn = "$func->{'name'}.3";
460 if (sysopen(FILE
, $fn, O_RDWR
|O_CREAT
|O_TRUNC
)) {
464 warn("$fn: open(): $!\n");
469 my $fn = shift; # File name
474 sysopen(FILE
, $fn, O_RDONLY
)
475 or die("$fn: open(): $!\n");
477 if (m/^\.Nm ((?:open)?pam_.*?)\s*$/) {
478 $func{'Nm'} = $func{'Nm'} || $1;
479 } elsif (m/^\.Ft (\S.*?)\s*$/) {
480 $func{'Ft'} = $func{'Ft'} || $1;
481 } elsif (m/^\.Fn (\S.*?)\s*$/) {
482 $func{'Fn'} = $func{'Fn'} || $1;
487 $FUNCTIONS{$func{'Nm'}} = \
%func;
489 warn("No function found\n");
494 my $page = shift; # Which page to produce
501 sysopen(FILE
, "$page.3", O_RDWR
|O_CREAT
|O_TRUNC
)
502 or die("$page.3: $!\n");
505 print FILE
"$COPYRIGHT
511 my @funcs = sort(keys(%FUNCTIONS));
512 while ($func = shift(@funcs)) {
513 print FILE
".Nm $FUNCTIONS{$func}->{'Nm'}";
518 print FILE
".Nd Pluggable Authentication Modules Library
522 if ($page eq 'pam') {
523 print FILE
".In security/pam_appl.h\n";
525 print FILE
".In security/openpam.h\n";
527 foreach $func (sort(keys(%FUNCTIONS))) {
528 print FILE
".Ft $FUNCTIONS{$func}->{'Ft'}\n";
529 print FILE
".Fn $FUNCTIONS{$func}->{'Fn'}\n";
532 if (m/^\.Xr (\S+)\s*(\d)\s*$/) {
533 ++$xref{int($2)}->{$1};
538 if ($page eq 'pam') {
539 print FILE
".Sh RETURN VALUES
540 The following return codes are defined by
541 .In security/pam_constants.h :
544 foreach (sort(keys(%PAMERR))) {
545 print FILE
".It Bq Er $_\n$PAMERR{$_}.\n";
549 print FILE
".Sh SEE ALSO
551 if ($page eq 'pam') {
552 ++$xref{3}->{'openpam'};
554 foreach $func (keys(%FUNCTIONS)) {
557 print FILE genxref
(\
%xref);
558 print FILE
".Sh STANDARDS
560 .%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
564 The OpenPAM library and this manual page were developed for the
566 Project by ThinkSec AS and Network Associates Laboratories, the
567 Security Research Division of Network Associates, Inc.\\& under
568 DARPA/SPAWAR contract N66001-01-C-8035
570 as part of the DARPA CHATS research program.
577 print(STDERR
"usage: gendoc [-s] source [...]\n");
585 unless (@ARGV && getopts
("op", \
%opts));
586 setlocale
(LC_ALL
, "en_US.ISO8859-1");
587 $TODAY = strftime
("%B %e, %Y", localtime(time()));
589 if ($opts{'o'} || $opts{'p'}) {
590 foreach my $fn (@ARGV) {
593 gensummary
('openpam')
598 foreach my $fn (@ARGV) {
599 my $func = parse_source
($fn);