mirror of
https://github.com/openssl/openssl.git
synced 2026-10-28 08:25:12 +08:00
Reviewed-by: Daniel Kubec <kubec@openssl.foundation> Reviewed-by: Eugene Syromiatnikov <esyr@openssl.org> Merge-date: Wed Sep 9 13:12:46 2026 Release: yes
180 lines
4.9 KiB
Perl
Executable File
180 lines
4.9 KiB
Perl
Executable File
#! /usr/bin/env perl
|
|
# Copyright 2020-2026 The OpenSSL Project Authors. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License 2.0 (the "License"). You may not use
|
|
# this file except in compliance with the License. You can obtain a copy
|
|
# in the file LICENSE in the source distribution or at
|
|
# https://www.openssl.org/source/license.html
|
|
|
|
use strict;
|
|
use warnings;
|
|
|
|
use lib ".";
|
|
use Getopt::Std;
|
|
use File::Basename;
|
|
use Pod::Html;
|
|
use File::Spec::Functions qw(:DEFAULT rel2abs);
|
|
|
|
# With -i, convert the one named pod, which is what the per-page rules and
|
|
# the other build systems do. Without it, convert every pod named on the
|
|
# command line, deriving each output from the pod's own path. Pod::Html is
|
|
# expensive to compile and OpenSSL has over nine hundred pages, so loading
|
|
# it once and dividing the pages between a few forked workers is far
|
|
# cheaper than starting this program once per page.
|
|
|
|
# Options.
|
|
our ($opt_i); # -i INFILE, one page; without it, pods are read from @ARGV
|
|
our ($opt_o); # -o OUTFILE with -i, otherwise the directory to write into
|
|
our ($opt_t); # -t TITLE, only with -i
|
|
our ($opt_r); # -r PODROOT
|
|
our ($opt_j); # -j JOBS, only without -i
|
|
|
|
getopts('i:o:t:r:j:');
|
|
die "-o flag missing" unless $opt_o;
|
|
die "-r flag missing" unless $opt_r;
|
|
|
|
# We originally used realpath() here, but the Windows implementation appears
|
|
# to require that the directory or file exist to be able to process the input,
|
|
# so we use rel2abs() instead, which only processes the string without
|
|
# looking further.
|
|
my $podroot = rel2abs($opt_r) or die "Can't convert to real path: $!";
|
|
|
|
sub cpu_count
|
|
{
|
|
my $cpus = $ENV{"NUMBER_OF_PROCESSORS"}; # Windows sets this.
|
|
|
|
if (!defined($cpus) && $^O =~ /linux/) {
|
|
my $tmp = qx(nproc 2>/dev/null);
|
|
|
|
$cpus = $tmp if $? == 0 && $tmp > 0;
|
|
}
|
|
if (!defined($cpus) && -r "/proc/cpuinfo") {
|
|
my $tmp = qx(grep -c ^processor /proc/cpuinfo 2>/dev/null);
|
|
|
|
$cpus = $tmp if $? == 0 && $tmp > 0;
|
|
}
|
|
if (!defined($cpus)) {
|
|
my $tmp = qx(sysctl -n hw.ncpu 2>/dev/null); # BSDs, macOS
|
|
|
|
$cpus = $tmp if $? == 0 && $tmp > 0;
|
|
}
|
|
|
|
return defined($cpus) && $cpus > 0 ? int($cpus) : 1;
|
|
}
|
|
|
|
# Turn one pod into one HTML page.
|
|
sub format_page
|
|
{
|
|
my ($pod, $out, $title) = @_;
|
|
|
|
$pod = rel2abs($pod) or die "Can't convert to real path: $!";
|
|
$out = rel2abs($out) or die "Can't convert to real path: $!";
|
|
|
|
unlink $out;
|
|
|
|
pod2html "--infile=$pod",
|
|
"--outfile=$out",
|
|
"--title=$title",
|
|
"--podroot=$podroot",
|
|
"--podpath=man1:man3:man5:man7",
|
|
"--htmldir=..";
|
|
|
|
# Read in contents.
|
|
open my $fh, "<", $out
|
|
or die "Can't read $out, $!";
|
|
my $contents = do { local $/ = undef; <$fh> };
|
|
close $fh;
|
|
unlink $out;
|
|
|
|
$contents =~
|
|
s|href="http://man\.he\.net/(man\d/[^"]+)(?:\.html)?"|href="../$1.html"|g;
|
|
open $fh, ">", $out
|
|
or die "Can't write $out, $!";
|
|
print $fh $contents;
|
|
close $fh;
|
|
|
|
chmod 0444, $out
|
|
or die "Can't set the mode of $out, $!\n";
|
|
}
|
|
|
|
# One named page: the output file and title are given.
|
|
if (defined $opt_i) {
|
|
die "-t flag missing" unless $opt_t;
|
|
format_page($opt_i, $opt_o, $opt_t);
|
|
exit 0;
|
|
}
|
|
|
|
# Otherwise every pod named on the command line, with $opt_o the directory
|
|
# holding the man1..man7 subdirectories: doc/man3/BIO_s_mem.pod becomes
|
|
# $opt_o/man3/BIO_s_mem.html, titled BIO_s_mem.
|
|
sub page_of
|
|
{
|
|
my $pod = shift;
|
|
my $name = basename($pod, ".pod");
|
|
my ($section) = basename(dirname($pod)) =~ m|^man(\d)$|;
|
|
|
|
die "Can't tell the section of $pod from its directory\n"
|
|
unless defined $section;
|
|
|
|
return ("$opt_o/man$section/$name.html", $name);
|
|
}
|
|
|
|
my @pods = @ARGV;
|
|
|
|
exit 0 unless @pods;
|
|
|
|
# Only ask how many processors there are when the answer can matter; the
|
|
# count is found by running a command.
|
|
my $jobs = @pods > 1
|
|
? (defined $opt_j && $opt_j > 0 ? int($opt_j) : cpu_count())
|
|
: 1;
|
|
|
|
$jobs = scalar @pods if $jobs > @pods;
|
|
|
|
sub format_pods
|
|
{
|
|
foreach my $pod (@_) {
|
|
my ($out, $title) = page_of($pod);
|
|
|
|
# The page is current when it is newer than the pod it comes from.
|
|
next if -e $out && -M $out < -M $pod;
|
|
|
|
format_page($pod, $out, $title);
|
|
}
|
|
}
|
|
|
|
if ($jobs <= 1) {
|
|
format_pods(@pods);
|
|
exit 0;
|
|
}
|
|
|
|
my @pids;
|
|
|
|
foreach my $worker (0 .. $jobs - 1) {
|
|
my $pid = fork();
|
|
|
|
die "Can't fork, $!\n" unless defined $pid;
|
|
if (!$pid) {
|
|
# Deal every $jobs'th page to this worker. The pages differ a lot
|
|
# in size, and dealing them out interleaves the large ones instead
|
|
# of handing one worker a contiguous run of them.
|
|
my @mine;
|
|
|
|
for (my $i = $worker; $i <= $#pods; $i += $jobs) {
|
|
push @mine, $pods[$i];
|
|
}
|
|
format_pods(@mine);
|
|
exit 0;
|
|
}
|
|
push @pids, $pid;
|
|
}
|
|
|
|
my $failed = 0;
|
|
|
|
foreach my $pid (@pids) {
|
|
waitpid($pid, 0);
|
|
$failed = 1 if $?;
|
|
}
|
|
|
|
die "Failed to convert the manual pages to HTML\n" if $failed;
|