Handle hostnames with upper-case letters
[webmin.git] / fastrpc.cgi
index 3bfb9ef..c00cb39 100755 (executable)
@@ -4,7 +4,8 @@
 # client. From then on, direct TCP connections can be made to this port
 # to send requests and get replies.
 
-do './web-lib.pl';
+BEGIN { push(@INC, ".."); };
+use WebminCore;
 use POSIX;
 use Socket;
 $force_lang = $default_lang;
@@ -54,14 +55,21 @@ untie(*STDOUT);
 # Accept the TCP connection
 $acptaddr = accept(SOCK, MAIN);
 die "accept failed!" if (!$acptaddr);
-select(SOCK); $| = 1;
+$oldsel = select(SOCK);
+$| = 1;
+select($oldsel);
 
+$rcount = 0;
 while(1) {
-       # Wait for the request
+       # Wait for the request. Wait longer if this isn't the first one
        local $rmask;
        vec($rmask, fileno(SOCK), 1) = 1;
-       local $sel = select($rmask, undef, undef, 60);
-       last if ($sel <= 0);
+       local $sel = select($rmask, undef, undef, $rcount ? 360 : 60);
+       if ($sel <= 0) {
+               print STDERR "fastrpc: session timed out\n"
+                       if ($gconfig{'rpcdebug'});
+               last;
+               }
 
        local $line = <SOCK>;
        last if (!$line);
@@ -89,7 +97,8 @@ while(1) {
                print STDERR "fastrpc: check $arg->{'module'}\n" if ($gconfig{'rpcdebug'});
                $rawrv = &serialise_variable(
                        { 'status' => 1,
-                         'rv' => &foreign_check($arg->{'module'}) } );
+                         'rv' => &foreign_check($arg->{'module'}, undef, undef,
+                                                $arg->{'api'}) } );
                }
        elsif ($arg->{'action'} eq 'config') {
                # Get the config for some module
@@ -207,17 +216,36 @@ while(1) {
        elsif ($arg->{'action'} eq 'require') {
                # require a library
                print STDERR "fastrpc: require $arg->{'module'}/$arg->{'file'}\n" if ($gconfig{'rpcdebug'});
-               &foreign_require($arg->{'module'},
-                                $arg->{'file'});
-               $rawrv = &serialise_variable( { 'status' => 1 });
+               eval {
+                       &foreign_require($arg->{'module'},
+                                        $arg->{'file'});
+                       };
+               if ($@) {
+                       print STDERR "fastrpc: require error $@\n" if ($gconfig{'rpcdebug'});
+                       $rawrv = &serialise_variable( { 'status' => 0,
+                                                       'rv' => $@ });
+                       }
+               else {
+                       print STDERR "fastrpc: require done\n" if ($gconfig{'rpcdebug'});
+                       $rawrv = &serialise_variable( { 'status' => 1 });
+                       }
                }
        elsif ($arg->{'action'} eq 'call') {
                # execute a function
                print STDERR "fastrpc: call $arg->{'module'}::$arg->{'func'}(",join(",", @{$arg->{'args'}}),")\n" if ($gconfig{'rpcdebug'});
-               local @rv = &foreign_call($arg->{'module'},
-                                   $arg->{'func'},
-                                   @{$arg->{'args'}});
-               if (@rv == 1) {
+               local @rv;
+               eval {
+                       local $main::error_must_die = 1;
+                       @rv = &foreign_call($arg->{'module'},
+                                           $arg->{'func'},
+                                           @{$arg->{'args'}});
+                       };
+               if ($@) {
+                       print STDERR "fastrpc: call error $@\n" if ($gconfig{'rpcdebug'});
+                       $rawrv = &serialise_variable(
+                               { 'status' => 0, 'rv' => $@ } );
+                       }
+               elsif (@rv == 1) {
                        $rawrv = &serialise_variable(
                                { 'status' => 1, 'rv' => $rv[0] } );
                        }
@@ -232,15 +260,23 @@ while(1) {
                print STDERR "fastrpc: eval $arg->{'module'} $arg->{'code'}\n" if ($gconfig{'rpcdebug'});
                local $rv;
                if ($arg->{'module'}) {
-                       $rv = eval "package $arg->{'module'};\n".
+                       local $pkg = $arg->{'module'};
+                       $pkg =~ s/[^A-Za-z0-9]/_/g;
+                       $rv = eval "package $pkg;\n".
                                   $arg->{'code'}."\n";
                        }
                else {
                        $rv = eval $arg->{'code'};
                        }
                print STDERR "fastrpc: eval $arg->{'module'} $arg->{'code'} done = $rv error = $@\n" if ($gconfig{'rpcdebug'});
-               $rawrv = &serialise_variable(
-                       { 'status' => 1, 'rv' => $rv } );
+               if ($@) {
+                       $rawrv = &serialise_variable(
+                               { 'status' => 0, 'rv' => $@ } );
+                       }
+               else {
+                       $rawrv = &serialise_variable(
+                               { 'status' => 1, 'rv' => $rv } );
+                       }
                }
        elsif ($arg->{'action'} eq 'quit') {
                print STDERR "fastrpc: quit\n" if ($gconfig{'rpcdebug'});
@@ -255,6 +291,7 @@ while(1) {
        print SOCK length($rawrv),"\n";
        print SOCK $rawrv;
        last if ($arg->{'action'} eq 'quit');
+       $rcount++;
        }
 
 # allocate_socket(handle, &port)