#!/usr/bin/perl BEGIN { @main::args = @ARGV ; } use strict ; use Getopt::Long ; use IO::Select ; use IO::Socket::UNIX ; use IO::Socket::INET ; use POSIX ; use Sys::Syslog ; $SIG{CHLD} = 'IGNORE' ; $SIG{PIPE} = 'IGNORE' ; my %opts = () ; GetOptions(\%opts, "d", # debug ) ; sub usage { print STDERR "Usage: $0 [-d]\n" ; exit(1) ; } $Utils::DEBUG = 1 if $opts{d} ; my $sockname = "/var/run/vservers/vproxy.sock" ; do_tool_mode($sockname) if (scalar(@ARGV)) ; # Open syslog init_slog('vproxy') ; slog('info', "$0 starting ($0 " . join(' ', @main::args) . ")") ; # Setup the Unix domain control socket if ((-e $sockname)&&(! unlink($sockname))){ scroak("Can't unlink '$sockname': $!\n") ; } my $control = new IO::Socket::UNIX( Local => $sockname, Type => SOCK_STREAM, Listen => 5, Timeout => 5, Reuse => 1 ) ; scroak("Can't create UNIX socket '$sockname': $!\n") unless defined($control) ; scroak("Can't chmod UNIX socket '$sockname': $!\n") unless chmod(0777, $sockname) ; if (! $opts{d}){ my $pid = fork() ; if (! defined($pid)){ scroak("Can't fork: $!") ; } elsif ($pid != 0){ exit(0) ; } POSIX::setsid() ; open(STDERR, ">/dev/null") or die("Error opening /dev/null: $!"); open(STDOUT, ">/dev/null") or die("Error opening /dev/null: $!"); open(STDIN, "can_read() ; foreach my $fh (@ready){ my $sock = $fh->accept() ; # Sometimes a signal can break the loop... next if !defined($sock) ; if ($fh eq $control){ my $cmd = <$sock> ; chomp($cmd) ; my ($verb, @args) = split(/\s+/, $cmd) ; slog('info', "Command received on control socket: $verb " . join(' ', @args)) ; my $vserver = $args[0] ; my $vserver_root = $args[1] ; if ($verb eq 'start'){ add_vserver($vserver, $vserver_root) ; } elsif ($verb eq 'stop'){ remove_vserver($vserver, $vserver_root) ; } elsif ($verb eq 'status'){ print $sock "OK: " . join(", ", keys %sockets) . "\n" ; } else { slog('warn', "Invalid command received on control socket: $verb " . join(' ', @args)) ; } next ; } # We got a message on the client socket. my $vinfo = undef ; foreach my $v (keys %sockets){ if ($sockets{$v}->{fh} eq $fh){ $vinfo = $sockets{$v} ; last ; } } my $pid = fork() ; if (! defined($pid)){ scroak("Can't fork: $!\n") ; } elsif ($pid == 0){ close($control) ; $SIG{CHLD} = 'DEFAULT' ; scroak("Unknown socket '$fh' ?!") unless $vinfo ; my $cmd = <$sock> ; chomp($cmd) ; slog('info', "Command received on vserver $vinfo->{vserver} socket ($vinfo->{path}): $cmd") ; scroak("Invalid command '$cmd' from vserver $vinfo->{vserver}") unless $cmd =~ /^\w+$/ ; my $script = "/etc/vservers/$vinfo->{vserver}.sh" ; debug("Script is $script") ; if ((-f $script)&&(-x $script)){ slog('info', "Executing $script '$cmd' '$vinfo->{vserver}' '$vinfo->{root}':") ; my $rc = open(SCRIPT, "$script '$cmd' '$vinfo->{vserver}' '$vinfo->{root}' 2>&1 |") ; while (