1*4724848cSchristos#! /usr/bin/env perl 2*4724848cSchristos# Copyright 2016-2018 The OpenSSL Project Authors. All Rights Reserved. 3*4724848cSchristos# 4*4724848cSchristos# Licensed under the OpenSSL license (the "License"). You may not use 5*4724848cSchristos# this file except in compliance with the License. You can obtain a copy 6*4724848cSchristos# in the file LICENSE in the source distribution or at 7*4724848cSchristos# https://www.openssl.org/source/license.html 8*4724848cSchristos 9*4724848cSchristosuse strict; 10*4724848cSchristosuse warnings; 11*4724848cSchristos 12*4724848cSchristosuse File::Spec::Functions; 13*4724848cSchristosuse File::Basename; 14*4724848cSchristosuse File::Copy; 15*4724848cSchristosuse File::Path; 16*4724848cSchristosuse FindBin; 17*4724848cSchristosuse lib "$FindBin::Bin/perl"; 18*4724848cSchristosuse OpenSSL::Glob; 19*4724848cSchristosuse Getopt::Long; 20*4724848cSchristosuse Pod::Usage; 21*4724848cSchristos 22*4724848cSchristosuse lib '.'; 23*4724848cSchristosuse configdata; 24*4724848cSchristos 25*4724848cSchristos# We know we are in the 'util' directory and that our perl modules are 26*4724848cSchristos# in util/perl 27*4724848cSchristosuse lib catdir(dirname($0), "perl"); 28*4724848cSchristosuse OpenSSL::Util::Pod; 29*4724848cSchristos 30*4724848cSchristosmy %options = (); 31*4724848cSchristosGetOptions(\%options, 32*4724848cSchristos 'sourcedir=s', # Source directory 33*4724848cSchristos 'section=i@', # Subdirectories to look through, 34*4724848cSchristos # with associated section numbers 35*4724848cSchristos 'destdir=s', # Destination directory 36*4724848cSchristos #'in=s@', # Explicit files to process (ignores sourcedir) 37*4724848cSchristos 'type=s', # The result type, 'man' or 'html' 38*4724848cSchristos 'suffix:s', # Suffix to add to the extension. 39*4724848cSchristos # Only used with type=man 40*4724848cSchristos 'remove', # To remove files rather than writing them 41*4724848cSchristos 'dry-run|n', # Only output file names on STDOUT 42*4724848cSchristos 'debug|D+', 43*4724848cSchristos ); 44*4724848cSchristos 45*4724848cSchristosunless ($options{section}) { 46*4724848cSchristos $options{section} = [ 1, 3, 5, 7 ]; 47*4724848cSchristos} 48*4724848cSchristosunless ($options{sourcedir}) { 49*4724848cSchristos $options{sourcedir} = catdir($config{sourcedir}, "doc"); 50*4724848cSchristos} 51*4724848cSchristospod2usage(1) unless ( defined $options{section} 52*4724848cSchristos && defined $options{sourcedir} 53*4724848cSchristos && defined $options{destdir} 54*4724848cSchristos && defined $options{type} 55*4724848cSchristos && ($options{type} eq 'man' 56*4724848cSchristos || $options{type} eq 'html') ); 57*4724848cSchristospod2usage(1) if ( $options{type} eq 'html' 58*4724848cSchristos && defined $options{suffix} ); 59*4724848cSchristos 60*4724848cSchristosif ($options{debug}) { 61*4724848cSchristos print STDERR "DEBUG: options:\n"; 62*4724848cSchristos print STDERR "DEBUG: --sourcedir = $options{sourcedir}\n" 63*4724848cSchristos if defined $options{sourcedir}; 64*4724848cSchristos print STDERR "DEBUG: --destdir = $options{destdir}\n" 65*4724848cSchristos if defined $options{destdir}; 66*4724848cSchristos print STDERR "DEBUG: --type = $options{type}\n" 67*4724848cSchristos if defined $options{type}; 68*4724848cSchristos print STDERR "DEBUG: --suffix = $options{suffix}\n" 69*4724848cSchristos if defined $options{suffix}; 70*4724848cSchristos foreach (sort @{$options{section}}) { 71*4724848cSchristos print STDERR "DEBUG: --section = $_\n"; 72*4724848cSchristos } 73*4724848cSchristos print STDERR "DEBUG: --remove = $options{remove}\n" 74*4724848cSchristos if defined $options{remove}; 75*4724848cSchristos print STDERR "DEBUG: --debug = $options{debug}\n" 76*4724848cSchristos if defined $options{debug}; 77*4724848cSchristos print STDERR "DEBUG: --dry-run = $options{\"dry-run\"}\n" 78*4724848cSchristos if defined $options{"dry-run"}; 79*4724848cSchristos} 80*4724848cSchristos 81*4724848cSchristosmy $symlink_exists = eval { symlink("",""); 1 }; 82*4724848cSchristos 83*4724848cSchristosforeach my $section (sort @{$options{section}}) { 84*4724848cSchristos my $subdir = "man$section"; 85*4724848cSchristos my $podsourcedir = catfile($options{sourcedir}, $subdir); 86*4724848cSchristos my $podglob = catfile($podsourcedir, "*.pod"); 87*4724848cSchristos 88*4724848cSchristos foreach my $podfile (glob $podglob) { 89*4724848cSchristos my $podname = basename($podfile, ".pod"); 90*4724848cSchristos my $podpath = catfile($podfile); 91*4724848cSchristos my %podinfo = extract_pod_info($podpath, 92*4724848cSchristos { debug => $options{debug}, 93*4724848cSchristos section => $section }); 94*4724848cSchristos my @podfiles = grep { $_ ne $podname } @{$podinfo{names}}; 95*4724848cSchristos 96*4724848cSchristos my $updir = updir(); 97*4724848cSchristos my $name = uc $podname; 98*4724848cSchristos my $suffix = { man => ".$podinfo{section}".($options{suffix} // ""), 99*4724848cSchristos html => ".html" } -> {$options{type}}; 100*4724848cSchristos my $generate = { man => "pod2man --name=$name --section=$podinfo{section} --center=OpenSSL --release=$config{version} \"$podpath\"", 101*4724848cSchristos html => "pod2html \"--podroot=$options{sourcedir}\" --htmldir=$updir --podpath=man1:man3:man5:man7 \"--infile=$podpath\" \"--title=$podname\" --quiet" 102*4724848cSchristos } -> {$options{type}}; 103*4724848cSchristos my $output_dir = catdir($options{destdir}, "man$podinfo{section}"); 104*4724848cSchristos my $output_file = $podname . $suffix; 105*4724848cSchristos my $output_path = catfile($output_dir, $output_file); 106*4724848cSchristos 107*4724848cSchristos if (! $options{remove}) { 108*4724848cSchristos my @output; 109*4724848cSchristos print STDERR "DEBUG: Processing, using \"$generate\"\n" 110*4724848cSchristos if $options{debug}; 111*4724848cSchristos unless ($options{"dry-run"}) { 112*4724848cSchristos @output = `$generate`; 113*4724848cSchristos map { s|href="http://man\.he\.net/(man\d/[^"]+)(?:\.html)?"|href="../$1.html"|g; } @output 114*4724848cSchristos if $options{type} eq "html"; 115*4724848cSchristos if ($options{type} eq "man") { 116*4724848cSchristos # Because some *roff parsers are more strict than others, 117*4724848cSchristos # multiple lines in the NAME section must be merged into 118*4724848cSchristos # one. 119*4724848cSchristos my $in_name = 0; 120*4724848cSchristos my $name_line = ""; 121*4724848cSchristos my @newoutput = (); 122*4724848cSchristos foreach (@output) { 123*4724848cSchristos if ($in_name) { 124*4724848cSchristos if (/^\.SH "/) { 125*4724848cSchristos $in_name = 0; 126*4724848cSchristos push @newoutput, $name_line."\n"; 127*4724848cSchristos } else { 128*4724848cSchristos chomp (my $x = $_); 129*4724848cSchristos $name_line .= " " if $name_line; 130*4724848cSchristos $name_line .= $x; 131*4724848cSchristos next; 132*4724848cSchristos } 133*4724848cSchristos } 134*4724848cSchristos if (/^\.SH +"NAME" *$/) { 135*4724848cSchristos $in_name = 1; 136*4724848cSchristos } 137*4724848cSchristos push @newoutput, $_; 138*4724848cSchristos } 139*4724848cSchristos @output = @newoutput; 140*4724848cSchristos } 141*4724848cSchristos } 142*4724848cSchristos print STDERR "DEBUG: Done processing\n" if $options{debug}; 143*4724848cSchristos 144*4724848cSchristos if (! -d $output_dir) { 145*4724848cSchristos print STDERR "DEBUG: Creating directory $output_dir\n" if $options{debug}; 146*4724848cSchristos unless ($options{"dry-run"}) { 147*4724848cSchristos mkpath $output_dir 148*4724848cSchristos or die "Trying to create directory $output_dir: $!\n"; 149*4724848cSchristos } 150*4724848cSchristos } 151*4724848cSchristos print STDERR "DEBUG: Writing $output_path\n" if $options{debug}; 152*4724848cSchristos unless ($options{"dry-run"}) { 153*4724848cSchristos open my $output_fh, '>', $output_path 154*4724848cSchristos or die "Trying to write to $output_path: $!\n"; 155*4724848cSchristos foreach (@output) { 156*4724848cSchristos print $output_fh $_; 157*4724848cSchristos } 158*4724848cSchristos close $output_fh; 159*4724848cSchristos } 160*4724848cSchristos print STDERR "DEBUG: Done writing $output_path\n" if $options{debug}; 161*4724848cSchristos } else { 162*4724848cSchristos print STDERR "DEBUG: Removing $output_path\n" if $options{debug}; 163*4724848cSchristos unless ($options{"dry-run"}) { 164*4724848cSchristos while (unlink $output_path) {} 165*4724848cSchristos } 166*4724848cSchristos } 167*4724848cSchristos print "$output_path\n"; 168*4724848cSchristos 169*4724848cSchristos foreach (@podfiles) { 170*4724848cSchristos my $link_file = $_ . $suffix; 171*4724848cSchristos my $link_path = catfile($output_dir, $link_file); 172*4724848cSchristos if (! $options{remove}) { 173*4724848cSchristos if ($symlink_exists) { 174*4724848cSchristos print STDERR "DEBUG: Linking $link_path -> $output_file\n" 175*4724848cSchristos if $options{debug}; 176*4724848cSchristos unless ($options{"dry-run"}) { 177*4724848cSchristos symlink $output_file, $link_path; 178*4724848cSchristos } 179*4724848cSchristos } else { 180*4724848cSchristos print STDERR "DEBUG: Copying $output_path to link_path\n" 181*4724848cSchristos if $options{debug}; 182*4724848cSchristos unless ($options{"dry-run"}) { 183*4724848cSchristos copy $output_path, $link_path; 184*4724848cSchristos } 185*4724848cSchristos } 186*4724848cSchristos } else { 187*4724848cSchristos print STDERR "DEBUG: Removing $link_path\n" if $options{debug}; 188*4724848cSchristos unless ($options{"dry-run"}) { 189*4724848cSchristos while (unlink $link_path) {} 190*4724848cSchristos } 191*4724848cSchristos } 192*4724848cSchristos print "$link_path -> $output_path\n"; 193*4724848cSchristos } 194*4724848cSchristos } 195*4724848cSchristos} 196*4724848cSchristos 197*4724848cSchristos__END__ 198*4724848cSchristos 199*4724848cSchristos=pod 200*4724848cSchristos 201*4724848cSchristos=head1 NAME 202*4724848cSchristos 203*4724848cSchristosprocess_docs.pl - A script to process OpenSSL docs 204*4724848cSchristos 205*4724848cSchristos=head1 SYNOPSIS 206*4724848cSchristos 207*4724848cSchristosB<process_docs.pl> 208*4724848cSchristos[B<--sourcedir>=I<dir>] 209*4724848cSchristosB<--destdir>=I<dir> 210*4724848cSchristosB<--type>=B<man>|B<html> 211*4724848cSchristos[B<--suffix>=I<suffix>] 212*4724848cSchristos[B<--remove>] 213*4724848cSchristos[B<--dry-run>|B<-n>] 214*4724848cSchristos[B<--debug>|B<-D>] 215*4724848cSchristos 216*4724848cSchristos=head1 DESCRIPTION 217*4724848cSchristos 218*4724848cSchristosThis script looks for .pod files in the subdirectories 'apps', 'crypto' 219*4724848cSchristosand 'ssl' under the given source directory. 220*4724848cSchristos 221*4724848cSchristosThe OpenSSL configuration data file F<configdata.pm> I<must> reside in 222*4724848cSchristosthe current directory, I<or> perl must have the directory it resides in 223*4724848cSchristosin its inclusion array. For the latter variant, a call like this would 224*4724848cSchristoswork: 225*4724848cSchristos 226*4724848cSchristos perl -I../foo util/process_docs.pl {options ...} 227*4724848cSchristos 228*4724848cSchristos=head1 OPTIONS 229*4724848cSchristos 230*4724848cSchristos=over 4 231*4724848cSchristos 232*4724848cSchristos=item B<--sourcedir>=I<dir> 233*4724848cSchristos 234*4724848cSchristosTop directory where the source files are found. 235*4724848cSchristos 236*4724848cSchristos=item B<--destdir>=I<dir> 237*4724848cSchristos 238*4724848cSchristosTop directory where the resulting files should end up 239*4724848cSchristos 240*4724848cSchristos=item B<--type>=B<man>|B<html> 241*4724848cSchristos 242*4724848cSchristosType of output to produce. Currently supported are man pages and HTML files. 243*4724848cSchristos 244*4724848cSchristos=item B<--suffix>=I<suffix> 245*4724848cSchristos 246*4724848cSchristosA suffix added to the extension. Only valid with B<--type>=B<man> 247*4724848cSchristos 248*4724848cSchristos=item B<--remove> 249*4724848cSchristos 250*4724848cSchristosInstead of writing the files, remove them. 251*4724848cSchristos 252*4724848cSchristos=item B<--dry-run>|B<-n> 253*4724848cSchristos 254*4724848cSchristosDo not perform any file writing, directory creation or file removal. 255*4724848cSchristos 256*4724848cSchristos=item B<--debug>|B<-D> 257*4724848cSchristos 258*4724848cSchristosPrint extra debugging output. 259*4724848cSchristos 260*4724848cSchristos=back 261*4724848cSchristos 262*4724848cSchristos=head1 COPYRIGHT 263*4724848cSchristos 264*4724848cSchristosCopyright 2013-2018 The OpenSSL Project Authors. All Rights Reserved. 265*4724848cSchristos 266*4724848cSchristosLicensed under the OpenSSL license (the "License"). You may not use 267*4724848cSchristosthis file except in compliance with the License. You can obtain a copy 268*4724848cSchristosin the file LICENSE in the source distribution or at 269*4724848cSchristoshttps://www.openssl.org/source/license.html 270*4724848cSchristos 271*4724848cSchristos=cut 272