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 408 2007-12-21 11:36:24Z des $
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 while (s/\s*=([a-z_]+)\b\s*/\n.Xr $1 3\n/s) {
252 s/\s*\"(?=\w)/\n.Do\n/gs;
253 s/\"(?!\w)\s*/\n.Dc\n/gs;
254 s/\s*=([A-Z][A-Z_]+)\b\s*(?![\.,:;])/\n.Dv $1\n/gs;
255 s/\s*=([A-Z][A-Z_]+)\b([\.,:;]+)\s*/\n.Dv $1 $2\n/gs;
256 s/\s*{([A-Z][a-z] .*?)}\s*/\n.$1\n/gs;
266 $man =~ s/(\n\.[A-Z][a-z] [\w ]+)\n([\.,:;-]\S*)\s*/$1 $2\n/gs;
267 $man =~ s/\s*$/\n/gm;
270 $man =~ s/\n\n\./\n\./gs;
273 $man = "No description available.";
276 $FUNCTIONS{$func} = {
284 'errors' => \@errors,
286 if ($source =~ m/^ \* NODOC\s*$/m) {
287 $FUNCTIONS{$func}->{'nodoc'} = 1;
289 if ($source !~ m/^ \* XSSO \d/m) {
290 $FUNCTIONS{$func}->{'openpam'} = 1;
292 expand_errors($FUNCTIONS{$func});
293 return $FUNCTIONS{$func};
296 sub expand_errors($);
297 sub expand_errors($) {
298 my $func = shift; # Ref to function hash
304 if (defined($func->{'recursed'})) {
305 warn("$func->{'name'}(): loop in error spec\n");
308 $func->{'recursed'} = 1;
310 foreach (@{$func->{'errors'}}) {
311 if (m/^(PAM_[A-Z_]+)$/) {
312 if (!defined($PAMERR{$1})) {
313 warn("$func->{'name'}(): unrecognized error: $1\n");
317 } elsif (m/^!(PAM_[A-Z_]+)$/) {
318 # treat negations separately
319 } elsif (m/^=([a-z_]+)$/) {
321 if (!defined($FUNCTIONS{$ref})) {
322 $fn = $func->{'source'};
323 $fn =~ s/$func->{'name'}/$ref/;
326 if (!defined($FUNCTIONS{$ref})) {
327 warn("$func->{'name'}(): reference to unknown $ref()\n");
330 foreach (@{$FUNCTIONS{$ref}->{'errors'}}) {
334 warn("$func->{'name'}(): invalid error specification: $_\n");
337 foreach (@{$func->{'errors'}}) {
338 if (m/^!(PAM_[A-Z_]+)$/) {
342 delete($func->{'recursed'});
343 $func->{'errors'} = [ sort(keys(%errors)) ];
346 sub dictionary_order($$) {
349 $a =~ s/[^[:alpha:]]//g;
350 $b =~ s/[^[:alpha:]]//g;
355 my $xref = shift; # References
359 foreach my $sect (sort(keys(%{$xref}))) {
360 foreach my $page (sort(dictionary_order keys(%{$xref->{$sect}}))) {
361 push(@refs, "$page $sect");
364 while ($_ = shift(@refs)) {
366 (@refs ? " ,\n" : "\n");
372 my $func = shift; # Ref to function hash
378 return if defined($func->{'nodoc'});
382 .Dt " . uc($func->{'name'}) . " 3
391 .In security/pam_appl.h
393 if ($func->{'name'} =~ m/_sm_/) {
394 $mdoc .= ".In security/pam_modules.h\n"
396 if ($func->{'name'} =~ m/openpam/) {
397 $mdoc .= ".In security/openpam.h\n"
399 $mdoc .= ".Ft \"$func->{'type'}\"
400 .Fn $func->{'name'} $func->{'args'}
404 if ($func->{'type'} eq "int") {
405 $mdoc .= ".Sh RETURN VALUES
408 function returns one of the following values:
411 my @errors = @{$func->{'errors'}};
412 warn("$func->{'name'}(): no error specification\n")
415 $mdoc .= ".It Bq Er $_\n$PAMERR{$_}.\n";
419 if ($func->{'type'} =~ m/\*$/) {
420 $mdoc .= ".Sh RETURN VALUES
429 $mdoc .= ".Sh SEE ALSO\n" . genxref($func->{'xref'});
430 $mdoc .= ".Sh STANDARDS\n";
431 if ($func->{'openpam'}) {
434 function is an OpenPAM extension.
438 .%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
443 $mdoc .= ".Sh AUTHORS
446 function and this manual page were developed for the
448 Project by ThinkSec AS and Network Associates Laboratories, the
449 Security Research Division of Network Associates, Inc.\\& under
450 DARPA/SPAWAR contract N66001-01-C-8035
452 as part of the DARPA CHATS research program.
455 $fn = "$func->{'name'}.3";
456 if (sysopen(FILE, $fn, O_RDWR|O_CREAT|O_TRUNC)) {
460 warn("$fn: open(): $!\n");
465 my $fn = shift; # File name
470 sysopen(FILE, $fn, O_RDONLY)
471 or die("$fn: open(): $!\n");
473 if (m/^\.Nm ((?:open)?pam_.*?)\s*$/) {
474 $func{'Nm'} = $func{'Nm'} || $1;
475 } elsif (m/^\.Ft (\S.*?)\s*$/) {
476 $func{'Ft'} = $func{'Ft'} || $1;
477 } elsif (m/^\.Fn (\S.*?)\s*$/) {
478 $func{'Fn'} = $func{'Fn'} || $1;
483 $FUNCTIONS{$func{'Nm'}} = \%func;
485 warn("No function found\n");
490 my $page = shift; # Which page to produce
497 sysopen(FILE, "$page.3", O_RDWR|O_CREAT|O_TRUNC)
498 or die("$page.3: $!\n");
501 print FILE "$COPYRIGHT
507 my @funcs = sort(keys(%FUNCTIONS));
508 while ($func = shift(@funcs)) {
509 print FILE ".Nm $FUNCTIONS{$func}->{'Nm'}";
514 print FILE ".Nd Pluggable Authentication Modules Library
518 if ($page eq 'pam') {
519 print FILE ".In security/pam_appl.h\n";
521 print FILE ".In security/openpam.h\n";
523 foreach $func (sort(keys(%FUNCTIONS))) {
524 print FILE ".Ft $FUNCTIONS{$func}->{'Ft'}\n";
525 print FILE ".Fn $FUNCTIONS{$func}->{'Fn'}\n";
528 if (m/^\.Xr (\S+)\s*(\d)\s*$/) {
529 ++$xref{int($2)}->{$1};
534 if ($page eq 'pam') {
535 print FILE ".Sh RETURN VALUES
536 The following return codes are defined by
537 .In security/pam_constants.h :
540 foreach (sort(keys(%PAMERR))) {
541 print FILE ".It Bq Er $_\n$PAMERR{$_}.\n";
545 print FILE ".Sh SEE ALSO
547 if ($page eq 'pam') {
548 ++$xref{3}->{'openpam'};
550 foreach $func (keys(%FUNCTIONS)) {
553 print FILE genxref(\%xref);
554 print FILE ".Sh STANDARDS
556 .%T \"X/Open Single Sign-On Service (XSSO) - Pluggable Authentication Modules\"
560 The OpenPAM library and this manual page were developed for the
562 Project by ThinkSec AS and Network Associates Laboratories, the
563 Security Research Division of Network Associates, Inc.\\& under
564 DARPA/SPAWAR contract N66001-01-C-8035
566 as part of the DARPA CHATS research program.
573 print(STDERR "usage: gendoc [-s] source [...]\n");
581 unless (@ARGV && getopts("op", \%opts));
582 setlocale(LC_ALL, "en_US.ISO8859-1");
583 $TODAY = strftime("%B %e, %Y", localtime(time()));
585 if ($opts{'o'} || $opts{'p'}) {
586 foreach my $fn (@ARGV) {
589 gensummary('openpam')
594 foreach my $fn (@ARGV) {
595 my $func = parse_source($fn);