#!/usr/bin/env perl # This script does the following: # 1. Clean up the screenenv directory. # 2. Update the environment if a -r or -R option is used. # 3. Unset SSH-related environment variables, as if a screen session # is started from a SSH connection, it may still be running after # the connection is closed and the variables would be incorrect. # 4. Execute screen on the unmodified arguments. use strict; my ($proc) = '$Id: escreen 91724 2016-09-01 12:12:59Z vinc17/cventin $' =~ /^.Id: (\S+) / or die; my $screenenv = $ENV{SCREENENV} || "$ENV{HOME}/.screenenv"; my %sessions; open SESSIONS, '-|', qw(env LC_ALL=C screen -list) or die "$proc: can't exec screen -list: $!\n"; while () { m,^\s*(\S+)\s+(?:\([-/: \d]+\)\s*)?\((Attached|Detached), or next; $sessions{$1} = $2 eq 'Detached' ? 1 : 0; } close SESSIONS; # Note: do not test the exit status as "screen -list" always returns # with a non-zero exit status! my $session; foreach my $i (0..$#ARGV) { $ARGV[$i] =~ /^-[dD]?[rR]+$/ or next; $session = $ARGV[$i+1]; defined $sessions{$session} and last; my @s = grep { ! defined $session || /(^|\.)\Q$session\E(\.|$)/ } keys %sessions; @s or undef $session, last; # No matches amongst existing session names. @s == 1 and $session = $s[0], last; # Single match, let's take it. # Several matches, let's see the detached sessions... my @d = grep { $sessions{$_} } @s; @d == 1 and $session = $d[0], last; # Single match, let's take it. undef $session; last; } if (-d $screenenv) { opendir SCREENENV, $screenenv or die "$proc: can't open directory '$screenenv': $!\n"; my @dir = readdir SCREENENV; closedir SCREENENV or die "$proc: can't close directory '$screenenv': $!\n"; unlink map "$screenenv/$_", grep { $_ ne '.' && $_ ne '..' && ! defined $sessions{$_} } @dir; } sub setvar ($;$) { my ($var,$rep) = @_; my $value = $ENV{$var}; defined $value or $value = $rep; #return (defined $value ? "$var=$value\nexport" : "unset")." $var\n\n"; # The variant below may not work with old non-POSIX shells, but # avoids warnings with zsh + the WARN_CREATE_GLOBAL option for # variables that were not exported yet. return (defined $value ? "export $var=$value" : "unset $var")."\n\n"; } if (defined $session) { -d $screenenv or mkdir $screenenv or die "$proc: can't create directory '$screenenv': $!\n"; chmod 0700, $screenenv; my $contents = setvar('DISPLAY'). setvar('XAUTHORITY',"$ENV{HOME}/.Xauthority"). setvar('XAPPLRESDIR'). setvar('XFILESEARCHPATH'). setvar('DBUS_SESSION_BUS_ADDRESS'); foreach (grep /^X11_/, keys %ENV) { $contents .= setvar($_); } $contents .= setvar('SCREEN_IN_SSH',1) if defined $ENV{SSH_CONNECTION}; $contents .= "# Written by $proc\n"; my $file = "$screenenv/$session"; open FILE, '>', $file or die "$proc: can't create file '$file': $!\n"; print FILE $contents or die "$proc: can't write to file '$file': $!\n"; close FILE or die "$proc: can't close file '$file': $!\n"; } delete $ENV{SSH_CLIENT}; delete $ENV{SSH_CONNECTION}; delete $ENV{SSH_TTY}; exec 'screen', @ARGV or die "$proc: can't exec screen: $!\n";