diff --git a/scripts/zmcontrol.pl.in b/scripts/zmcontrol.pl.in index b0388bcf3..f83bc82d4 100644 --- a/scripts/zmcontrol.pl.in +++ b/scripts/zmcontrol.pl.in @@ -30,7 +30,7 @@ use autouse 'Pod::Usage'=>qw(pod2usage); use POSIX qw/strftime EPIPE/; use Socket; #use Data::Dumper; -use Module::Load::Conditional qw{can_load};; +use Module::Load::Conditional qw{can_load}; use constant MAX_CONNECT_DELAY => 15; use constant MAX_COMMAND_WAIT => 1800; @@ -43,7 +43,7 @@ delete @ENV{qw(IFS CDPATH ENV BASH_ENV)}; logInit(); -my $arg_string = join( " ", @ARGV ); +my $arg_string = join(' ', @ARGV); my $id; my %options; @@ -64,22 +64,46 @@ GetOptions( ) or pod2usage(-exitstatus => -1); if ( !$id ) { - print( STDERR "Please give a valid monitor id\n" ); + print(STDERR "Please give a valid monitor id\n"); pod2usage(-exitstatus => -1); } ( $id ) = $id =~ /^(\w+)$/; -Debug("zmcontrol: arg string: $arg_string"); my $sock_file = $Config{ZM_PATH_SOCKS}.'/zmcontrol-'.$id.'.sock'; +Debug("zmcontrol: arg string: $arg_string sock file $sock_file"); -socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) - or Fatal("Can't open socket: $!"); +socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!"); my $saddr = sockaddr_un($sock_file); -my $server_up = connect(CLIENT, $saddr); -if ( !$server_up ) { + +if ( $options{command} ) { + # Have a command, so we are the client, connect to the server and send it. + + my $tries = 10; + my $server_up; + while ( $tries and ! ( $server_up = connect(CLIENT, $saddr) ) ) { + Debug("Failed to connect to $server_up at $sock_file"); + runCommand("zmdc.pl start zmcontrol.pl --id=$id"); + sleep 1; + $tries -= 1; + } + if ( $server_up ) { + # The server is there, connect to it + #print( "Writing commands\n" ); + CLIENT->autoflush(); + + if ( $options{command} ) { + my $message = jsonEncode(\%options); + print(CLIENT $message); + } + shutdown(CLIENT, 1); + } else { + Error("Unable to connect to zmcontrol server at $sock_file"); + } +} else { + # The server isn't there my $monitor = zmDbGetMonitorAndControl($id); if ( !$monitor ) { @@ -113,99 +137,72 @@ if ( !$server_up ) { Fatal("Can't load ZoneMinder::Control::$protocol\n$Module::Load::Conditional::ERROR"); } - if ( my $cpid = fork() ) { - logReinit(); + Info("Control server $id/$protocol starting at " + .strftime('%y/%m/%d %H:%M:%S', localtime()) + ); - # Parent process just sleep and fall through - socket(CLIENT, PF_UNIX, SOCK_STREAM, 0) - or die("Can't open socket: $!"); - my $attempts = 0; - while ( !connect(CLIENT, $saddr) ) { - $attempts++; - Fatal("Can't connect: $! after $attempts attempts to $sock_file") if $attempts > MAX_CONNECT_DELAY; - sleep(1); - } - } elsif ( defined($cpid) ) { - close(STDOUT); - close(STDERR); + $0 = $0." --id=$id"; - setpgrp(); + my $control = "ZoneMinder::Control::$protocol"->new($id); + my $control_key = $control->getKey(); + $control->loadMonitor(); - logReinit(); + $control->open(); - Info("Control server $id/$protocol starting at " - .strftime('%y/%m/%d %H:%M:%S', localtime()) - ); - - $0 = $0." --id $id"; - - my $control = "ZoneMinder::Control::$protocol"->new($id); - my $control_key = $control->getKey(); - $control->loadMonitor(); - - $control->open(); - - socket(SERVER, PF_UNIX, SOCK_STREAM, 0) - or Fatal("Can't open socket: $!"); - unlink($sock_file); - bind(SERVER, $saddr) or Fatal("Can't bind: $!"); - listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!"); - - my $rin = ''; - vec( $rin, fileno(SERVER), 1 ) = 1; - my $win = $rin; - my $ein = $win; - my $timeout = MAX_COMMAND_WAIT; - while( 1 ) { - my $nfound = select(my $rout = $rin, undef, undef, $timeout); - if ( $nfound > 0 ) { - if ( vec( $rout, fileno(SERVER), 1 ) ) { - my $paddr = accept(CLIENT, SERVER); - my $message = ; - - next if !$message; - - my $params = jsonDecode($message); - #Debug( Dumper( $params ) ); - - my $command = $params->{command}; - close( CLIENT ); - if ( $command eq 'quit' ) { - last; - } - $control->$command($params); - } else { - Fatal('Bogus descriptor'); - } - } elsif ( $nfound < 0 ) { - if ( $! == EPIPE ) { - Error("Can't select: $!"); - } else { - Fatal("Can't select: $!"); - } - } else { - #print( "Select timed out\n" ); - last; - } - } # end while forever - Info("Control server $id/$protocol exiting"); - unlink($sock_file); - $control->close(); - exit(0); - } else { - Fatal("Can't fork: $!"); + # If we have a command when starting up, then do it. + if ( $options{command} ) { + my $command = $options{command}; + $control->$command(\%options); } + + socket(SERVER, PF_UNIX, SOCK_STREAM, 0) or Fatal("Can't open socket: $!"); + unlink($sock_file); + bind(SERVER, $saddr) or Fatal("Can't bind: $!"); + listen(SERVER, SOMAXCONN) or Fatal("Can't listen: $!"); + + my $rin = ''; + vec( $rin, fileno(SERVER), 1 ) = 1; + my $win = $rin; + my $ein = $win; + my $timeout = MAX_COMMAND_WAIT; + while( 1 ) { + my $nfound = select(my $rout = $rin, undef, undef, $timeout); + if ( $nfound > 0 ) { + if ( vec( $rout, fileno(SERVER), 1 ) ) { + my $paddr = accept(CLIENT, SERVER); + my $message = ; + + next if !$message; + + my $params = jsonDecode($message); + #Debug( Dumper( $params ) ); + + my $command = $params->{command}; + close( CLIENT ); + if ( $command eq 'quit' ) { + last; + } + $control->$command($params); + } else { + Fatal('Bogus descriptor'); + } + } elsif ( $nfound < 0 ) { + if ( $! == EPIPE ) { + Error("Can't select: $!"); + } else { + Fatal("Can't select: $!"); + } + } else { + #print( "Select timed out\n" ); + last; + } + } # end while forever + Info("Control server $id/$protocol exiting"); + unlink($sock_file); + $control->close(); + exit(0); } # end if !server up -# The server is there, connect to it -#print( "Writing commands\n" ); -CLIENT->autoflush(); - -if ( $options{command} ) { - my $message = jsonEncode(\%options); - print(CLIENT $message); -} -shutdown(CLIENT, 1); exit(0);