Code

Make sure a newline is passed to the socket
[gosa.git] / trunk / gosa-si / gosa-si-client
index 481ea3e1e5b42c4bd5af358fd31e0263afe3dd90..36b55f5227841a6d15fdf7e28e6d11ecb409ea24 100755 (executable)
@@ -76,6 +76,8 @@ our $client_force_hostname;
 our $server_key;
 our $opts_dnslookup;
 
+our $FIFO_FD = undef;
+
 # default variables
 our $REGISTERED = 0;
 our $REGISTRATION_IN_PROGRESS = 0;
@@ -221,15 +223,34 @@ sub check_pid {
     }
 }
 
+sub clean_shutdown
+{
+    unlink($pid_file) if (-w $pid_file);
+    unlink($gosa_si_client_fifo) if (-S $gosa_si_client_fifo);
+}
 
-sub sig_int_handler {
+sub sig_int_or_term_handler
+{
     my ($signal) = @_;
-       
-    daemon_log("shutting down gosa-si-client", 1);
-    system("kill `ps -C gosa-si-client -o pid=`");
+    daemon_log("Got SIG${signal} - shutting down gosa-si-client", 1);
+    clean_shutdown();
+    POE::Kernel->signal('client_session', 'KILL');
+    POE::Kernel->signal('gosa-si-client', 'KILL');
+    return 1;
 }
-$SIG{INT} = \&sig_int_handler;
 
+sub sig_warn_handler
+{
+    my @loc = caller(0);
+    daemon_log( "SIGWARN line " . $loc[2] . ": " . $_[0], 1 );
+    return 1;
+}
+       
+$SIG{'INT'} = \&sig_int_or_term_handler;
+$SIG{'TERM'} = \&sig_int_or_term_handler;
+$SIG{'__WARN__'} = \&sig_warn_handler;
+$SIG{'USR1'} = 'IGNORE';
+$SIG{'USR2'} = 'IGNORE';
 
 #===  FUNCTION  ================================================================
 #         NAME:  logging
@@ -468,6 +489,7 @@ sub send_msg_to_target {
         if ($REGISTERED == 1) {
             $REGISTERED = 0;        # if server is not available, cause reregistering
             daemon_log("INFO: cause reregistering at gosa-si-server", 5); 
+            sleep(2);
             $global_kernel->post('client_session', 'register_at_gosa_si_server');
 
         }
@@ -567,6 +589,7 @@ sub register_at_gosa_si_server {
             # append shifted gosa-si-server at the end of @servers, so looking for servers never stop if
             # a registration never occured
             my $server = shift(@servers);
+            &main::daemon_log("INFO: Trying to register with server $server", 3);
             push(@servers, $server);
             ($server_ip = $server) =~ s/:.*$//;
             $server_address = $server;
@@ -619,8 +642,6 @@ sub register_at_gosa_si_server {
 
                        # if delivery of registration msg succeed
                        if(defined($res) and $res eq "0") {
-                       # reset try_to_register
-                               $REGISTRATION_TRIES = 0;
 
                        # Set fixed client address and mac address
                                $client_ip= &get_local_ip_for_remote_ip(sprintf("%s", $server =~ /^([0-9\.]*?):.*$/));
@@ -630,17 +651,18 @@ sub register_at_gosa_si_server {
                 last;
 
                        # delivery of registration msg failed   
-                       } else {
-                       # wait 1 sec until trying to register again
-                               sleep(1);
-                               next;
+                       } elsif($REGISTRATION_TRIES > scalar(@servers)) {
+                               last;
                        }
 
     } # end of while
        # one circle through all servers finished and no registration succeed
-       if ( $REGISTRATION_TRIES >= (scalar(@servers)) )  {
+       if ( $REGISTRATION_TRIES > (scalar(@servers)) )  {
+                       $REGISTRATION_TRIES = 0;
                        &write_to_file("gosa-si-no-server-available", $fai_logpath);
-                       $kernel->delay_set('register_at_gosa_si_server', $delay_set_time);
+                       daemon_log("WARNING: Could not register with any of the servers, waiting $delay_set_time seconds",3);
+                       sleep($delay_set_time);
+                       $kernel->post('client_session', 'register_at_gosa_si_server');
        
        # delivery of registraion msg succeed, waiting for server response
        } else {
@@ -663,6 +685,9 @@ sub check_key_and_xml_validity {
     my $msg_hash;
     eval{
         $msg = &decrypt_msg($crypted_msg, $module_key);
+        if ($msg  !~ /^<xml>/i ) {
+            die 'could not decrypt message';
+        }
         &main::daemon_log("decrypted_msg: \n$msg", 9);
 
         $msg_hash = $xml->XMLin($msg, ForceArray=>1);
@@ -796,8 +821,19 @@ sub trigger_logged_in_users_report {
                        @logged_in_user_list = split(/\s/, $result);
                }
                
-        system("echo 'CURRENTLY_LOGGED_IN ".join(" ", @logged_in_user_list)."' > /var/run/gosa-si-client.socket"); 
-        $kernel->delay_set('trigger_logged_in_users_report', $trigger_logged_in_users_report_delay);
+       $FIFO_FD = undef
+           if (! defined $FIFO_FD && ! defined open($FIFO_FD, '>', $gosa_si_client_fifo));
+       if (! defined $FIFO_FD) {
+           daemon_log("ERROR: unable to open fifo for writing: $!", 1);
+           $kernel->delay_set('trigger_logged_in_users_report', 30);
+       }
+       else {
+           print($FIFO_FD 'CURRENTLY_LOGGED_IN ' . join(" ", @logged_in_user_list)."\n");
+           close($FIFO_FD);
+           my $userlist = join(" ", @logged_in_user_list);
+           daemon_log("DEBUG: Sent logged in user list to server: $userlist", 5);
+           $kernel->delay_set('trigger_logged_in_users_report', $trigger_logged_in_users_report_delay);
+       }
     } else {
         # try it in 10 sec again
         $kernel->delay_set('trigger_logged_in_users_report', 10);
@@ -855,9 +891,8 @@ sub trigger_seen_messages {
             my $send_error = &send_msg_to_target($confirm_msg, $server_address, $server_key);
 
             # Delete file
-            if (not $send_error) {
-                system("rm $goto_dir/$goto_file");
-            }
+            unlink("$goto_dir/$goto_file")
+                if (! $send_error);
         }
     }
 
@@ -970,21 +1005,11 @@ sub save_fai_log {
 }
 
 
-sub sig_handler {
-       my ($kernel, $signal) = @_[KERNEL, ARG0] ;
-       daemon_log("0 INFO got signal '$signal'", 1); 
-       $kernel->sig_handled();
-       return;
-}
-
-
 sub _start {
     my ($kernel, $heap) = @_[KERNEL, HEAP];
     $kernel->alias_set('client_session');
     $global_kernel = $kernel;       # this is used to throw events at each point of the skript
  
-    $kernel->sig(USR1 => "sig_handler");
-
     # force a registration at a gosa-si-server
     $kernel->yield('register_at_gosa_si_server');
     
@@ -1008,6 +1033,17 @@ sub _start {
 }
 
 
+sub _stop {
+    my ($kernel, $session, $heap) = @_[KERNEL, SESSION, HEAP];
+    delete $heap->{'services'};
+    delete $heap->{'watchers'};
+    $kernel->alias_remove($heap->{alias});
+    $kernel->alarm_remove_all();
+    $kernel->post($heap->{child_session}, '_stop');
+    close( $FIFO_FD ) if( defined $FIFO_FD );
+}
+
+
 sub _default {
     daemon_log("ERROR: can not handle incoming msg with header '$_[ARG0]'", 1);
     return;
@@ -1019,12 +1055,18 @@ sub server_input {
     my $remote_ip = $heap->{'remote_ip'},
     my $error = 0;
     my $answer;
+    my $msg;
+    my $msg_hash;    
     
 
-    daemon_log("INFO: Incoming msg from '$remote_ip'", 5);
+    daemon_log("INFO: Incoming msg from '$remote_ip', server_ip: $server_ip", 5);
     daemon_log("DEBUG: Incoming msg:\n$input\n", 9);
 
-    my ($msg, $msg_hash) = &check_key_and_xml_validity($input, $server_key);
+    if (not "$remote_ip" eq "$server_ip" and "$server_ip" ne "127.0.0.1") {
+        daemon_log("INFO: Incoming msg not from server ($server_ip), ignoring", 5);
+        $error++;
+    } else {
+        ($msg, $msg_hash) = &check_key_and_xml_validity($input, $server_key);
     if( (!$msg) || (!$msg_hash) ) {
         daemon_log("WARNING: Deciphering of incoming msg failed", 3);
         if($server_address =~ /$remote_ip/) {
@@ -1046,12 +1088,13 @@ sub server_input {
                 }
                 $FAILED_CRYPTO++;
                                $REGISTERED = 0;
+                               sleep(2);
                                $kernel->post('client_session', 'register_at_gosa_si_server');
                        }
         }
         $error++;
     }
-
+    }
 
     ######################
     # process incoming msg
@@ -1089,6 +1132,10 @@ sub server_input {
                 # set registered flag to true to stop sending further registered msgs
                 $REGISTERED = 1;
                 $REGISTRATION_IN_PROGRESS = 0;
+                               if( $server_ip eq "127.0.0.1") {
+                                       $server_ip = $remote_ip;
+                                       daemon_log("INFO: Registered at localhost, setting server_ip to $server_ip",3);
+                               }
             } 
             else {
                 $answer =~ /<header>(\S+)<\/header>/;
@@ -1209,33 +1256,6 @@ GetOptions("h|help" => \&usage,
 &read_configfile($cfg_file, %cfg_defaults);
 &check_pid;
 
-# forward error messages to logfile
-if ( ! $foreground ) {
-  open( STDIN,  '+>/dev/null' );
-  open( STDOUT, '+>&STDIN'    );
-  open( STDERR, '+>&STDIN'    );
-}
-
-# Just fork, if we are not in foreground mode
-if( ! $foreground ) { 
-    chdir '/'                 or die "Can't chdir to /: $!";
-    $pid = fork;
-    setsid                    or die "Can't start a new session: $!";
-    umask 0;
-} else { 
-    $pid = $$; 
-}
-
-# Do something useful - put our PID into the pid_file
-if( 0 != $pid ) {
-    open( LOCK_FILE, ">$pid_file" );
-    print LOCK_FILE "$pid\n";
-    close( LOCK_FILE );
-    if( !$foreground ) { 
-        exit( 0 ) 
-    };
-}
-
 # parse head url and revision from svn
 my $client_status_hash = { 'developmental'=>'revision', 'stable'=>'release'};
 $client_version =~ /^\$HeadURL: (\S+) \$:\$Rev: (\d+) \$$/;
@@ -1264,6 +1284,52 @@ daemon_log("INFO: ".$client_status_hash->{$client_status}.": $client_revision",
 # delete old DBsqlite lock files
 system('rm -f /tmp/gosa_si_lock*gosa-si-client*');
 
+# (re-)create FIFO
+if (-e $gosa_si_client_fifo) {
+    daemon_log("INFO: $gosa_si_client_fifo exists - deleting", 5);
+    if (1 != unlink($gosa_si_client_fifo)) {
+        daemon_log("ERROR: unable to delete '$gosa_si_client_fifo': $!", 1);
+        exit( 1 );
+    }
+}
+if (! defined POSIX::mkfifo($gosa_si_client_fifo, "0600")) {
+    daemon_log("ERROR: failed creating fifo: $!", 1);
+    exit( 1 );
+}
+
+# Just fork, if we are not in foreground mode
+if( ! $foreground ) {
+    if (! chdir('/')) {
+        daemon_log("ERROR: Can't chdir to /: $!");
+        exit( 1 );
+    }
+    umask( 0 );
+    $pid = fork;
+} else { 
+    $pid = $$; 
+}
+
+if( 0 != $pid ) {
+    # Parent: put our PID into the $pid_file
+    open( LOCK_FILE, ">$pid_file" );
+    print LOCK_FILE "$pid\n";
+    close( LOCK_FILE );
+    if( !$foreground ) {
+        exit( 0 );
+    }
+}
+else {
+    # Child
+    open( STDIN,  '+>/dev/null' );
+    open( STDOUT, '+>&STDIN'    );
+    open( STDERR, '+>&STDIN'    );
+    if (! POSIX::setsid()) {
+        deamon_log("ERROR: Can't start a new session: $!", 1);
+        exit( 1 );
+    }
+    $poe_kernel->has_forked() if ($poe_kernel->can('has_forked'));
+}
+
 # detect ip and mac address and complete host address
 $client_address = $client_ip.":".$client_port;
 my $network_interface= &get_interface_for_ip($client_ip);
@@ -1308,15 +1374,11 @@ $default_server_key = $server_key;
 # Find servers from config and DNS
 &find_servers;
 
-# open fifo for non-gosa-si-client-msgs to gosa-si-server
-POSIX::mkfifo("$gosa_si_client_fifo", "0600");
-
-
 POE::Session->create(
        inline_states => {
                _start => \&_start, 
+        _stop => \&_stop,
         _default => \&_default,
-        sig_handler => \&sig_handler,
         register_at_gosa_si_server => \&register_at_gosa_si_server,
 
         # trigger periodical tasks