#
# ktmux_helper: Run krenew in the background for tmux.
# Usage: ktmux_helper [options]
-# Options: -I <path> Specify path to kinit.
-# -L <path> Specify path to klist.
-# -R <path> Specify path to krenew.
-# -T <path> Specify path to tmux.
-# Notes: Doesn't handle multiple sessions properly.
+# Options: -I <path> Specify path to kinit.
+# -L <path> Specify path to klist.
+# -R <path> Specify path to krenew.
+# -T <path> Specify path to tmux.
+# -p <pid> Specify tmux PID.
+# -s <session> Specify tmux session number.
+# Notes: The -p and -s flags are only used to identify instances when
+# viewed in ps output.
#
use FindBin;
my $PROG = $FindBin::Script;
-# Ensure tmux is our parent and find its PID.
-our $tmux_pid = &get_tmux_pid;
+# Remember args for re-exec.
+my @execargs;
+foreach my $arg (@ARGV) {
+ push @execargs, $arg;
+}
+
+my %opts;
+getopts('I:L:R:T:p:s:', \%opts);
+
+# Ensure tmux is our parent and find its PID if not already known.
+our $tmux_pid = &get_tmux_pid($opts{'p'});
unless ($tmux_pid) {
print STDERR "$PROG: Not a child of tmux!\n";
exit 100;
}
+# Find session if possible.
+our $tmux_session = &get_tmux_session($opts{'s'});
+
+# Fix the environment.
+$ENV{TMUX} =~ s/,\d+,-?\d+$/,$tmux_pid,$tmux_session/;
+
# Ensure there isn't already a helper running for this tmux.
my $tmux_helper = &get_tmux_helper;
exit 0 if $tmux_helper;
$tmux_helper = $$;
-my %opts;
-getopts('I:L:R:T:', \%opts);
+# Re-exec ourselves purely so the session and PID are set in the environment.
+my @args;
+push @args, "-p", $tmux_pid unless defined $opts{'p'};
+push @args, "-s", $tmux_session unless defined $opts{'s'};
+exec $0, @args, @execargs if @args;
my $kinit = $opts{'I'} || "kinit";
my $klist = $opts{'L'} || "klist";
else {
exit 1 if &check_credentials;
exec $krenew, "-K", "60";
- print "$PROG: Can't run krenew: $!\n";
+ print STDERR "$PROG: Can't run krenew: $!\n";
exit 111;
}
}
sub get_tmux_pid {
- my $pid = getppid;
+ # Set from command line?
+ my $pid = shift;
+
+ # Set from environment?
+ unless ($pid) {
+ if ($ENV{TMUX} =~ /,(\d+),[^,]+$/) {
+ $pid = $1;
+ }
+ }
+
+ my $ppid = getppid;
+
+ if ($pid) {
+ # Check it really is our parent.
+ if ($pid == $ppid) {
+ # Check that it's still running.
+ return $pid if kill -0, $pid;
+ }
+ }
+
+ return undef;
+
+ # Everything below probably can't happen so should be removed.
my $cmd = `/bin/ps -o args= -p $pid`;
return $pid if $cmd =~ /\btmux\b/;
return undef;
}
+sub get_tmux_session {
+ # Set from command line?
+ my $session = shift;
+
+ # Set from environment?
+ unless ($session) {
+ # The session identifier will be -1 if we were launched from run-shell
+ # because a run-shell command doesn't count as being part of a session.
+ if ($ENV{TMUX} =~ /,(-?\d+)$/) {
+ $session = $1;
+ }
+ }
+
+ return $session;
+}
+
+# Check that a given process was launched from our session.
+sub check_tmux_session {
+ my $pid = shift;
+
+ return undef unless defined $tmux_session;
+
+ my $cmd;
+ if ($^O eq "linux") {
+ $cmd = "xargs -0 -n 1 < /proc/$pid/environ";
+ }
+ elsif ($^O eq "solaris") {
+ $cmd = "pargs -Fe $pid";
+ }
+ else {
+ # Don't know how to check on this OS.
+ return undef;
+ }
+
+ return undef unless (open IN, "$cmd | ");
+
+ while (<IN>) {
+ chomp;
+ next unless /TMUX=.+,(-?\d+)/;
+ # Abort if the running helper doesn't know what session it's for.
+ if ($1 eq $tmux_session || $1 eq "-1") {
+ close IN;
+ return 1;
+ }
+ }
+
+ close IN;
+ return 0;
+}
+
sub check_kinit_child {
foreach my $pid (`/bin/ps -o ppid= -C kinit`) {
- return 1 if $pid =~ /^\s*$tmux_pid\s*$/;
+ next unless $pid =~ /^\s*$tmux_pid\s*$/;
+ next if &check_tmux_session($pid);
+ return 1;
}
return 0;
}
s/[^\d]//g;
next if $_ == $$;
$pid = $_;
- last;
+ return $pid if &check_tmux_session($pid);
}
close IN;
}
- return $pid;
+ return undef;
}
sub ping_tmux {