Fix PAGER.
[profile.git] / opt / bin / ktmux_helper
1 #!/usr/bin/perl
2 #
3 # ktmux_helper: Run krenew in the background for tmux.
4 # Notes: Doesn't handle multiple sessions properly.
5 #
6
7 use FindBin;
8 use POSIX ":sys_wait_h";
9
10 my $PROG = $FindBin::Script;
11
12 # Ensure tmux is our parent and find its PID.
13 my $tmux_pid = &get_tmux_pid;
14 unless ($tmux_pid) {
15   print STDERR "$PROG: Not a child of tmux!\n";
16   exit 100;
17 }
18
19 # Ensure there isn't already a helper running for this tmux.
20 my $tmux_helper = &get_tmux_helper;
21 exit 0 if $tmux_helper;
22 $tmux_helper = $$;
23
24 my $exitasap = 0;
25 my $pid = 0;
26 our $have_valid_credentials = undef;
27
28 $SIG{INT} = \&cleanup;
29 $SIG{QUIT} = \&cleanup;
30 $SIG{TERM} = \&cleanup;
31 $SIG{USR1} = \&want_credentials;
32 $SIG{USR2} = \&got_credentials;
33
34 LOOP: while (&ping_tmux) {
35   $pid = fork;
36   die "$PROG: Can't fork: $!\n" unless defined $pid;
37
38   if ($pid) {
39     while (&ping_tmux) {
40       my $exited = waitpid $pid, WNOHANG;
41       goto LOOP if $exited == $pid || $exited < 0;
42       sleep 1;
43     }
44
45     # tmux is dead so kill krenew.
46     kill QUIT, $pid;
47     waitpid $pid, 0;
48     exit 0;
49   }
50   else {
51     kill USR2, $tmux_helper unless &check_credentials;
52     exec "krenew", "-K", "60";
53     print "$PROG: Can't run krenew: $!\n";
54     exit 111;
55   }
56 }
57
58 sub get_tmux_pid {
59   my $pid = getppid;
60   my $cmd = `/bin/ps -o args= -p $pid`;
61   return $pid if $cmd =~ /\btmux\b/;
62   return undef;
63 }
64
65 sub get_tmux_helper {
66   my $pid = undef;
67   if (open IN, "pgrep -x -P $tmux_pid $PROG | ") {
68     while (<IN>) {
69       chomp;
70       s/[^\d]//g;
71       next if $_ == $$;
72       $pid = $_;
73       last;
74     }
75     close IN;
76   }
77   return $pid;
78 }
79
80 sub ping_tmux {
81   return kill 0, $tmux_pid;
82 }
83
84 # Try to check existing Kerberos credentials.
85 sub check_credentials {
86   system "klist", "-s";
87   return 1 if $? < 0;
88   return 0 unless $?;
89   kill USR1, $tmux_helper;
90   return 111;
91 }
92
93 # We were signalled by our child which noticed that our credentials expired.
94 sub want_credentials {
95   # Do we already know?
96   return if defined $have_valid_credentials && $have_valid_credentials == 0;
97   $SIG{USR1} = IGNORE;
98   $have_valid_credentials = 0;
99   system "tmux", "new-window", "exec kinit";
100 }
101
102 # We were signalled by our child which noticed that our credentials are valid.
103 sub got_credentials {
104   $have_valid_credentials = 1;
105   $SIG{USR1} = \&want_credentials;
106 }
107
108 sub cleanup {
109   unless ($exitasap) {
110     $exitasap = 1;
111     kill $pid;
112     waitpid $pid, WNOHANG;
113     exit 0;
114   }
115 }