From 9c5904d27fd0f942718e37700c2ae3ef939fcdfc Mon Sep 17 00:00:00 2001 From: Iain Patterson Date: Wed, 18 Jul 2012 08:46:17 +0100 Subject: [PATCH] Fix ktmux_helper for tmux 1.8 with run_shell -b. --- opt/bin/ktmux_helper | 123 +++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 109 insertions(+), 14 deletions(-) diff --git a/opt/bin/ktmux_helper b/opt/bin/ktmux_helper index e2b58a5..fb12672 100755 --- a/opt/bin/ktmux_helper +++ b/opt/bin/ktmux_helper @@ -2,11 +2,14 @@ # # ktmux_helper: Run krenew in the background for tmux. # Usage: ktmux_helper [options] -# Options: -I Specify path to kinit. -# -L Specify path to klist. -# -R Specify path to krenew. -# -T Specify path to tmux. -# Notes: Doesn't handle multiple sessions properly. +# Options: -I Specify path to kinit. +# -L Specify path to klist. +# -R Specify path to krenew. +# -T Specify path to tmux. +# -p Specify tmux PID. +# -s Specify tmux session number. +# Notes: The -p and -s flags are only used to identify instances when +# viewed in ps output. # use FindBin; @@ -15,20 +18,38 @@ use POSIX ":sys_wait_h"; 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"; @@ -64,21 +85,95 @@ LOOP: while (&ping_tmux) { 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 () { + 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; } @@ -91,11 +186,11 @@ sub get_tmux_helper { s/[^\d]//g; next if $_ == $$; $pid = $_; - last; + return $pid if &check_tmux_session($pid); } close IN; } - return $pid; + return undef; } sub ping_tmux { -- 2.7.4