jabberd.in.patch   [plain text]


--- /tmp/jabberd-2.2.14/tools/jabberd.in	2011-05-31 15:11:37.000000000 -0700
+++ ./jabberd2/tools/jabberd.in	2011-07-28 19:41:15.000000000 -0700
@@ -19,18 +19,20 @@ use IPC::Open3;
 use IO::Select;
 use POSIX;
 use POSIX qw(setsid);
-
+use File::Copy 'mv';
 
 #-----------------------------------------------------------------------------
 # Define some initial variables and default them as needed.
 #-----------------------------------------------------------------------------
 my $Bin = "@bindir@";
+my $LibExec = "@libexecdir@";
 my $VERSION = "@VERSION@";
 my $config_dir = "@sysconfdir@";
 my $config = $config_dir."/jabberd.cfg";
 $config = "internal" unless (-e $config);
 my $debug = 0;
 my $daemon = 0;
+my $g_kill_signal = "";
 my $select = IO::Select->new();
 my ($exe) = ($0 =~ /([^\/]+)$/);
 my %jobs;
@@ -103,7 +105,12 @@ else
         next if /^\#/;
         next if /^\s*$/;
         my ($job,$config) = /^\s*(\S+)\s*(\S*)\s*$/;
-        push(@programs,[$job,$config]);
+        # Assume that all the commands are in the same directory
+        # as the jabberd script. The current configuration file
+        # format does not allow specification of pathnames for commands.
+        #my $cmd = "$Bin/$job";
+        my $cmd = $jobs{$job}->{cmd};
+        push(@programs,[$job,$config,$cmd]);
     }
     close(CFG);
 }
@@ -116,6 +123,29 @@ if ($debug)
 }
 
 #-----------------------------------------------------------------------------
+# APPLE: Look for required actions due to software update installation and
+# perform any that have not been completed yet.
+#-----------------------------------------------------------------------------
+# 10.7.2
+my $s2s_ipv6_fix_done_path;
+my $s2s_cfg_path = "";
+foreach my $job_tmp (@programs) {
+    if ($job_tmp->[0] eq "s2s") {
+        $s2s_cfg_path = $job_tmp->[1];
+        last;
+    }
+}
+if ($s2s_cfg_path =~ /jabberd_notification/) {
+    $s2s_ipv6_fix_done_path = "/private/var/jabberd/.10.7.2.s2s_ipv6_fix_notification_server";
+} else {
+    $s2s_ipv6_fix_done_path = "/private/var/jabberd/.10.7.2.s2s_ipv6_fix";
+}
+
+if (! -e $s2s_ipv6_fix_done_path) {
+    &apple_update_s2s_ipv6_fix;
+}
+
+#-----------------------------------------------------------------------------
 # Launch all of the jobs.
 #-----------------------------------------------------------------------------
 if ($#programs == -1)
@@ -127,7 +157,7 @@ if ($#programs == -1)
 
 foreach my $job (@programs)
 {
-    &LaunchJob($job->[0],$job->[1]);
+    &LaunchJob($job->[0],$job->[1],$job->[2]);
 }
 
 unless (!$daemon || $debug)
@@ -151,6 +181,15 @@ unless (!$daemon || $debug)
 while (1)
 {
     my @ready = $select->can_read();
+    if ($g_kill_signal ne "") {
+        if (($g_kill_signal eq "INT") || ($g_kill_signal eq "TERM"))
+        {
+            &Shutdown($g_kill_signal);
+        } else {
+            &PassSignal($g_kill_signal);
+        }
+        $g_kill_signal = "";
+    }
     foreach my $fh (@ready)
     {
         my $line = <$fh>;
@@ -161,7 +200,7 @@ while (1)
         else
         {
             print "ERROR: $fhs{$fh}->{job} died.  Shutting down server.\n";
-            &Signal("TERM");
+            &Shutdown;
         }
     }
 }
@@ -177,18 +216,32 @@ sub LaunchJob
 {
     my $job = shift;
     my $config = shift;
+    my $cmd = shift;
 
-    my $cmd = $jobs{$job}->{cmd};
+    if (!defined($cmd) || $cmd eq "")
+    {
+        $cmd = $jobs{$job}->{cmd};
+        if ($cmd eq "") {
+            print "cmd is empty, cannot launch\n";
+            return;
+        }
+    }
 
     if (defined($config))
     {
         $cmd .= " -c ".$config;
     }
-    else
+    elsif (defined($jobs{$job}->{config}))
     {
         $cmd .= " -c ".$jobs{$job}->{config};
     }
-    $cmd .= " -D" if $debug;
+
+    if ($debug && $jobs{$job}->{prefix} ne "MUC") {
+        $cmd .= " -D";
+    }
+    if (defined($jobs{$job}->{args}) && ($jobs{$job}->{args} ne "")) {
+        $cmd .= " ".$jobs{$job}->{args};
+    }
     
     &debug("jabberd","stdout","LaunchJob: $job -> $cmd\n");
 
@@ -248,23 +301,41 @@ sub CloseJob
 ##############################################################################
 sub Signal
 {
-    my $sig = shift;
+    $g_kill_signal = shift;
+}
 
-    &debug("jabberd","stdout","Got a signal... pass it on.\n");
+sub PassSignal
+{
+    my $sig = shift;
+    if ((! defined($sig)) || ($sig eq "")) {
+        return;
+    }
         
     foreach my $job (keys(%jobs))
     {
         next unless exists($jobs{$job}->{launched});
+        &debug("jabberd","stdout","sending $sig to $jobs{$job}->{pid} : $job\n");
         kill $sig => $jobs{$job}->{pid};
     }
+}
 
-    if (($sig eq "INT") || ($sig eq "TERM"))
+sub Shutdown
     {
-        &debug("jabberd","stdout","It was a $sig.  Shut it all down!\n");
-        exit(0);
+    my $sig = shift;
+    if (! defined($sig)) {
+        $sig = "TERM";
     }
+
+    PassSignal($sig);
+
+    &debug("Shutting down.\n");
+    my $ret;
+    foreach my $job(keys(%jobs)) {
+        $ret = waitpid($jobs{$job}->{pid}, 0) if defined($jobs{$job}->{pid});
 }
 
+    exit(0);
+}
 
 ##############################################################################
 #
@@ -306,3 +377,169 @@ sub usage
     exit(0);
 }
 
+##############################################################################
+#
+# APPLE: action required for update to 10.7.2 (changes to fix broken IPv6 s2s)
+#
+##############################################################################
+sub apple_update_s2s_ipv6_fix
+{
+    &log_message("Attempting configuration file changes for Apple software update 10.7.2, fix for IPv6 s2s");
+
+    # Backup the original s2s.xml file
+    &log_message("Backing up $s2s_cfg_path to $s2s_cfg_path.software_update.10.7.2.bak");
+    qx( cp $s2s_cfg_path $s2s_cfg_path.software_update.10.7.2.bak );
+
+    # Use some simple pattern matching to replace the old <origin> preference with our new
+    # <origins> defaults, and update the corresponding comments.
+    if (! open(S2SCFG, "<$s2s_cfg_path")) {
+        &log_message("Failed to update s2s configuration for IPv6 origin support (cannot open file): $!");
+        return;
+    }
+    my @lines = <S2SCFG>;
+    close(S2SCFG);
+
+    my $inserted_new_comment = 0;
+    my $inserted_new_pref = 0;
+
+    # different changes are needed for iChat Server vs. Notification Server configs
+    if ($s2s_cfg_path =~ /jabberd_notification/) {
+        # Notification Server configuration
+        my $removed_fixme_comment = 0;
+        my $updated_local_ip = 0;
+        my $index = 0;
+        for (; $index <= $#lines; $index++) {
+            my $line = $lines[$index];
+            if ((! $removed_fixme_comment) && $line =~ /APPLE: FIXME: must use IPv4 as of 2\.2\.9/) {
+                $lines[$index] = "";
+                $removed_fixme_comment = 1;
+                &log_message("s2s configuration changes: removed obsolete comment 1");
+                if ($lines[$index+1] =~ /^(\s+)<!-- <ip>::<\/ip> -->$/) {
+                    $lines[++$index] = "";
+                    &log_message("s2s configuration changes: removed obsolete comment 2");
+                }
+                next;
+            }
+            elsif ((! $updated_local_ip) && $line =~ /^(\s+)<ip>0\.0\.0\.0<\/ip>$/) {
+                $lines[$index] = "    <ip>::<\/ip>\n";
+                $updated_local_ip = 1;
+                &log_message("s2s configuration changes: updated local ip address to ::");
+                next;
+            }
+            elsif ((! $inserted_new_comment) && $line =~ /If not set, the <ip> section address above is used\. -->/) {
+                $lines[$index] = "         If not set, the <ip> section address above is used.\n".
+                "         APPLE: specify multiple origin IP addrs to add support for both\n".
+                "         IPv4 and IPv6 connections. -->\n";
+                $inserted_new_comment = 1;
+                &log_message("s2s configuration changes: updated <origins> comment");
+                next;
+            }
+            elsif ((! $inserted_new_pref) && ($line =~             /^(\s+)<!--$/) &&
+                    ($lines[$index+1] =~ /^(\s+)<origin>1\.2\.3\.4<\/origin>$/)   &&
+                    ($lines[$index+2] =~ /^(\s+)-->$/)) {
+                $lines[$index] = "    <origins>\n".
+                "        <ip>::</ip>\n".
+                "        <ip>0.0.0.0</ip>\n".
+                "    </origins>\n";
+                $lines[++$index] = "";
+                $lines[++$index] = "";
+                $inserted_new_pref = 1;
+                &log_message("s2s configuration changes: updated s2s configuration for IPv6 origin support");
+                next;
+            }
+            elsif ((! $inserted_new_pref) && $line =~ /<origin>(.+)<\/origin>/) {
+                if ($1 ne "::" && $1 ne "0.0.0.0") {
+                    # They have customized the value, so use it instead of our defaults
+                    $lines[$index] = "    <origins>\n        <ip>$1</ip>\n    </origins>\n";
+                } else {
+                    $lines[$index] = "    <origins>\n".
+                    "        <ip>::</ip>\n".
+                    "        <ip>0.0.0.0</ip>\n".
+                    "    </origins>\n";
+                }
+                $inserted_new_pref = 1;
+                &log_message("s2s configuration changes: updated s2s configuration for IPv6 origin support, no changes made.");
+                next;
+            }
+        }
+
+    } else {
+        # iChat Server configuration
+        my $replaced_old_ip = 0;
+        foreach my $line (@lines) {
+            if ((! $replaced_old_ip) && $line =~ /^(\s+)<ip>0\.0\.0\.0<\/ip>$/) {
+                $line = "    <ip>::<\/ip>\n";
+                $replaced_old_ip = 1;
+                &log_message("s2s configuration changes: replaced IPv4 IP address with IPv6");
+                next;
+            }
+            elsif ((! $inserted_new_comment) && $line =~ /If not set, the <ip> section address above is used\. -->/) {
+                $line = "         If not set, the <ip> section address above is used.\n".
+                "         APPLE: specify multiple origin IP addrs to add support for both\n".
+                "         IPv4 and IPv6 connections. -->\n";
+                $inserted_new_comment = 1;
+                &log_message("s2s configuration changes: updated comment text");
+                next;
+            }
+            elsif ((! $inserted_new_pref) && $line =~ /<origin>(.+)<\/origin>/) {
+                if ($1 ne "::" && $1 ne "0.0.0.0") {
+                    # They have customized the value, so use it instead of our defaults
+                    $line = "    <origins>\n".
+                    "        <ip>$1</ip>\n".
+                    "    </origins>\n";
+                } else {
+                    $line = "    <origins>\n".
+                    "        <ip>::</ip>\n".
+                    "        <ip>0.0.0.0</ip>\n".
+                    "    </origins>\n";
+                }
+                $inserted_new_pref = 1;
+                &log_message("s2s configuration changes: replaced <origin> with new array, using original value");
+                next;
+            }
+        }
+    }
+    if (! $inserted_new_pref) {
+        # If we failed, its probably due to user-modified configuration files not matching, or
+        # the file is up-to-date (eg. a fresh 10.7.x install).
+        &log_message("Failed to update s2s configuration for IPv6 origin support");
+        qx( touch $s2s_ipv6_fix_done_path );  # Don't attempt again; this is a one-shot action.
+        return;
+    }
+
+    my $tmpname = qx{ mktemp /private/var/jabberd/tmp/s2s.xml.XXXXXXXXXXXXXXXXXXXXXXXX };
+    chomp($tmpname);
+
+    if (! open(S2SCFG, ">$tmpname")) {
+        &log_message("Error creating new configuration file: $!");
+        return;
+    }
+    print S2SCFG @lines;
+    close(S2SCFG);
+
+    if (! mv($tmpname, $s2s_cfg_path)) {
+        &log_message("Failed to move update file into place, restoring original");
+        qx( cp -f $s2s_cfg_path.software_update.10.7.2.bak $s2s_cfg_path );
+        qx( chown _jabber:wheel $s2s_cfg_path );
+        qx( chmod 0600 $s2s_cfg_path );
+        return;
+    }
+
+    qx( chown _jabber:wheel $s2s_cfg_path );
+    qx( chmod 0600 $s2s_cfg_path );
+    qx( touch $s2s_ipv6_fix_done_path );
+    &log_message("Completed Apple software update for 10.7.2, fix for IPv6 s2s");
+}
+
+sub log_message
+{
+    my $apple_su_log = "/private/var/jabberd/log/software_updates.log";
+    if (! open(LOGFILE, ">>$apple_su_log")) {
+        print "APPLE: cannot open $apple_su_log: $!";
+        return;
+    }
+    my $time = localtime();
+    print LOGFILE "$time: @_\n";
+    print "APPLE: @_\n" if $debug;
+    close(LOGFILE);
+}