From b645dc5a4118feabd37d95fabbc6aaa803e3c45f Mon Sep 17 00:00:00 2001 From: joey Date: Thu, 23 Mar 2006 07:37:16 +0000 Subject: [PATCH] Getopt::Long is a huge, heavy perl module. So why use it? This {gross,amazing} hack makes all wrapped uses of ikiwiki forgo any option parsing at all. Options come in preparses via an env var from the wrapper. As a bonus, Wrapper.pm no longer needs to be updated when command line options are added to the program. Load time is sped up by around 10%. ikiwikiwrap --params is no longer supported by this change. You will need to rebuild your wrappers to take advantage of it. --- IkiWiki/Wrapper.pm | 48 ++++++++++------------------- doc/usage.mdwn | 4 +-- doc/wrapperparamstrick.mdwn | 20 ------------ ikiwiki | 61 +++++++++++++++++++++---------------- 4 files changed, 52 insertions(+), 81 deletions(-) delete mode 100644 doc/wrapperparamstrick.mdwn diff --git a/IkiWiki/Wrapper.pm b/IkiWiki/Wrapper.pm index 8e513c1f6..62d284eb6 100644 --- a/IkiWiki/Wrapper.pm +++ b/IkiWiki/Wrapper.pm @@ -2,11 +2,12 @@ use warnings; use strict; +use Cwd q{abs_path}; +use Data::Dumper; package IkiWiki; sub gen_wrapper () { #{{{ - eval q{use Cwd 'abs_path'}; $config{srcdir}=abs_path($config{srcdir}); $config{destdir}=abs_path($config{destdir}); my $this=abs_path($0); @@ -17,26 +18,8 @@ sub gen_wrapper () { #{{{ if ($config{setup}) { error("cannot create a wrapper that uses a setup file"); } - - my @params=($config{srcdir}, $config{destdir}, - "--wikiname=$config{wikiname}", - "--templatedir=$config{templatedir}"); - push @params, "--verbose" if $config{verbose}; - push @params, "--rebuild" if $config{rebuild}; - push @params, "--nosvn" if !$config{svn}; - push @params, "--cgi" if $config{cgi}; - push @params, "--url=$config{url}" if length $config{url}; - push @params, "--cgiurl=$config{cgiurl}" if length $config{cgiurl}; - push @params, "--historyurl=$config{historyurl}" if length $config{historyurl}; - push @params, "--diffurl=$config{diffurl}" if length $config{diffurl}; - push @params, "--anonok" if $config{anonok}; - push @params, "--adminuser=$_" foreach @{$config{adminuser}}; - my $params=join(" ", @params); - my $call=''; - foreach my $p ($this, $this, @params) { - $call.=qq{"$p", }; - } - $call.="NULL"; + my $wrapper=possibly_foolish_untaint($config{wrapper}); + delete $config{wrapper}; my @envsave; push @envsave, qw{REMOTE_ADDR QUERY_STRING REQUEST_METHOD REQUEST_URI @@ -50,6 +33,11 @@ sub gen_wrapper () { #{{{ EOF } + $Data::Dumper::Indent=0; + my $configstring=Data::Dumper->Dump([\%config], ['*config']); + $configstring=~s/\\/\\\\/g; + $configstring=~s/"/\\"/g; + open(OUT, ">ikiwiki-wrap.c") || error("failed to write ikiwiki-wrap.c: $!");; print OUT <<"EOF"; /* A wrapper for ikiwiki, can be safely made suid. */ @@ -64,33 +52,29 @@ extern char **environ; int main (int argc, char **argv) { /* Sanitize environment. */ char *s; - char *newenviron[$#envsave+3]; + char *newenviron[$#envsave+4]; int i=0; $envsave newenviron[i++]="HOME=$ENV{HOME}"; + newenviron[i++]="WRAPPED_OPTIONS=$configstring"; newenviron[i]=NULL; environ=newenviron; - if (argc == 2 && strcmp(argv[1], "--params") == 0) { - printf("$params\\n"); - exit(0); - } - - execl($call); + execl("$this", "$this", NULL); perror("failed to run $this"); exit(1); } EOF close OUT; - if (system("gcc", "ikiwiki-wrap.c", "-o", possibly_foolish_untaint($config{wrapper})) != 0) { + if (system("gcc", "ikiwiki-wrap.c", "-o", $wrapper) != 0) { error("failed to compile ikiwiki-wrap.c"); } unlink("ikiwiki-wrap.c"); if (defined $config{wrappermode} && - ! chmod(oct($config{wrappermode}), possibly_foolish_untaint($config{wrapper}))) { - error("chmod $config{wrapper}: $!"); + ! chmod(oct($config{wrappermode}), $wrapper)) { + error("chmod $wrapper: $!"); } - print "successfully generated $config{wrapper}\n"; + print "successfully generated $wrapper\n"; } #}}} 1 diff --git a/doc/usage.mdwn b/doc/usage.mdwn index 83866c1a8..b9744438b 100644 --- a/doc/usage.mdwn +++ b/doc/usage.mdwn @@ -44,9 +44,7 @@ flags such as --verbose can be negated with --no-verbose. The wrapper is designed to be safely made suid and be run by untrusted users, as a [[Subversion]] [[post-commit]] hook, or as a [[CGI]]. - Note that the generated wrapper will ignore all command line parameters - except for --params, which will make it print out the parameters it would - run ikiwiki with. + Note that the generated wrapper will ignore all command line parameters. * --wrappermode mode diff --git a/doc/wrapperparamstrick.mdwn b/doc/wrapperparamstrick.mdwn deleted file mode 100644 index d55629a79..000000000 --- a/doc/wrapperparamstrick.mdwn +++ /dev/null @@ -1,20 +0,0 @@ -ikiwiki --wrapper can be used to generate a wrapper -program that runs ikiwiki with the specified parameters. This is used for -[[post-commit]] hooks, [[CGI]], etc, both for convenience and because these -things often need suid wrapper scripts to make ikiwiki run as the right -user. - -The generated wrapper is a binary program. What if you want to regenerate -it with different parameters, or just run ikiwiki like it would but with -some parameter changed? To easily accomomplish this, the wrappers all -support being run with --params, which causes them to print out the -parameters they run ikiwiki with. - -You can use this trick to regenerate a wrapper, adding or changing a -parameter: - - ikiwiki $(./ikiwiki-wrap --params) --wikiname="newname" --wrapper - -Or just to run ikiwiki like the wrapper would, and add a parameter: - - ikiwiki $(./ikiwiki-wrap --params) --rebuild diff --git a/ikiwiki b/ikiwiki index cdc5c8ca4..b59aa8c8f 100755 --- a/ikiwiki +++ b/ikiwiki @@ -10,7 +10,6 @@ use strict; use Memoize; use File::Spec; use HTML::Template; -use Getopt::Long; use vars qw{%config %links %oldlinks %oldpagemtime %renderedfiles %pagesources}; @@ -39,31 +38,41 @@ our %config=( #{{{ adminuser => undef, ); #}}} -GetOptions( #{{{ - "setup|s=s" => \$config{setup}, - "wikiname=s" => \$config{wikiname}, - "verbose|v!" => \$config{verbose}, - "rebuild!" => \$config{rebuild}, - "wrapper:s" => sub { $config{wrapper}=$_[1] ? $_[1] : "ikiwiki-wrap" }, - "wrappermode=i" => \$config{wrappermode}, - "svn!" => \$config{svn}, - "anonok!" => \$config{anonok}, - "cgi!" => \$config{cgi}, - "url=s" => \$config{url}, - "cgiurl=s" => \$config{cgiurl}, - "historyurl=s" => \$config{historyurl}, - "diffurl=s" => \$config{diffurl}, - "exclude=s@" => sub { - $config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/; - }, - "adminuser=s@" => sub { push @{$config{adminuser}}, $_[1] }, - "templatedir=s" => sub { $config{templatedir}=possibly_foolish_untaint($_[1]) }, -) || usage(); - -if (! $config{setup}) { - usage() unless @ARGV == 2; - $config{srcdir} = possibly_foolish_untaint(shift); - $config{destdir} = possibly_foolish_untaint(shift); +# option parsing #{{{ +if (! exists $ENV{WRAPPED_OPTIONS}) { + eval q{use Getopt::Long}; + GetOptions( + "setup|s=s" => \$config{setup}, + "wikiname=s" => \$config{wikiname}, + "verbose|v!" => \$config{verbose}, + "rebuild!" => \$config{rebuild}, + "wrapper:s" => sub { $config{wrapper}=$_[1] ? $_[1] : "ikiwiki-wrap" }, + "wrappermode=i" => \$config{wrappermode}, + "svn!" => \$config{svn}, + "anonok!" => \$config{anonok}, + "cgi!" => \$config{cgi}, + "url=s" => \$config{url}, + "cgiurl=s" => \$config{cgiurl}, + "historyurl=s" => \$config{historyurl}, + "diffurl=s" => \$config{diffurl}, + "exclude=s@" => sub { + $config{wiki_file_prune_regexp}=qr/$config{wiki_file_prune_regexp}|$_[1]/; + }, + "adminuser=s@" => sub { push @{$config{adminuser}}, $_[1] }, + "templatedir=s" => sub { $config{templatedir}=possibly_foolish_untaint($_[1]) }, + ) || usage(); + + if (! $config{setup}) { + usage() unless @ARGV == 2; + $config{srcdir} = possibly_foolish_untaint(shift); + $config{destdir} = possibly_foolish_untaint(shift); + checkoptions(); + } +} +else { + # wrapper passes a full config structure in the environment + # variable + eval possibly_foolish_untaint($ENV{WRAPPED_OPTIONS}); checkoptions(); } #}}} -- 2.26.2