File Coverage

blib/lib/Shell/Guess.pm
Criterion Covered Total %
statement 74 101 73.2
branch 62 110 56.3
condition 3 9 33.3
subroutine 33 34 97.0
pod 29 29 100.0
total 201 283 71.0


line stmt bran cond sub pod time code
1             package Shell::Guess;
2              
3 16     16   827780 use strict;
  16         38  
  16         450  
4 16     16   80 use warnings;
  16         30  
  16         394  
5 16     16   73 use File::Spec;
  16         31  
  16         17367  
6              
7             # TODO: see where we can use P9Y::ProcessTable
8              
9             # ABSTRACT: Make an educated guess about the shell in use
10             our $VERSION = '0.07'; # VERSION
11              
12              
13             sub _win32_getppid
14             {
15 0     0   0 require Win32::Getppid;
16 0         0 Win32::Getppid::getppid();
17             }
18              
19             sub running_shell
20             {
21 1 50   1 1 74 if($^O eq 'MSWin32')
22             {
23 0         0 my $shell_name = eval {
24 0         0 require Win32::Process::List;
25 0         0 my $parent_pid = _win32_getppid();
26 0         0 Win32::Process::List->new->{processes}->[0]->{$parent_pid}
27             };
28 0 0       0 if(defined $shell_name)
29             {
30 0 0       0 if($shell_name =~ /cmd\.exe$/)
    0          
    0          
31 0         0 { return __PACKAGE__->cmd_shell }
32             elsif($shell_name =~ /powershell\.exe$/)
33 0         0 { return __PACKAGE__->power_shell }
34             elsif($shell_name =~ /command\.com$/)
35 0         0 { return __PACKAGE__->command_shell }
36             }
37             }
38              
39 1 50       4 if($^O eq 'MSWin32')
40             {
41 0 0       0 if($ENV{ComSpec} =~ /cmd\.exe$/)
42 0         0 { return __PACKAGE__->cmd_shell }
43             else
44 0         0 { return __PACKAGE__->command_shell }
45             }
46              
47 1 50       3 return __PACKAGE__->dcl_shell if $^O eq 'VMS';
48 1 50       4 return __PACKAGE__->command_shell if $^O eq 'dos';
49              
50             my $shell = eval {
51             open(my $fh, '<', File::Spec->catfile('', 'proc', getppid, 'cmdline')) || die;
52             my $command_line = <$fh>;
53             die unless defined $command_line; # don't spew warnings if read failed
54             close $fh;
55             $command_line =~ s/\0.*$//;
56             _unixy_shells($command_line);
57             }
58            
59 1   33     2 || eval {
60             require Unix::Process;
61             my $method = $^O eq 'solaris' ? 'comm' : 'command';
62             my($command) = map { s/\s+.*$//; $_ } Unix::Process->$method(getppid);
63             _unixy_shells($command);
64             };
65            
66 1 50       8 $shell || __PACKAGE__->login_shell;
67             }
68              
69              
70             sub login_shell
71             {
72 2     2 1 73 shift; # class ignored
73 2         3 my $shell;
74              
75 2 50       9 if($^O eq 'MSWin32')
76             {
77 0 0       0 if(Win32::IsWin95())
78 0         0 { return __PACKAGE__->command_shell }
79             else
80 0         0 { return __PACKAGE__->cmd_shell }
81             }
82              
83 2 50       6 return __PACKAGE__->dcl_shell if $^O eq 'VMS';
84 2 50       6 return __PACKAGE__->command_shell if $^O eq 'dos';
85              
86 2   33     21 my $username = shift || $ENV{USER} || $ENV{USERNAME} || $ENV{LOGNAME};
87              
88 2 50       6 if($^O eq 'darwin')
89             {
90 0         0 my $command = `dscl . -read /Users/$username UserShell`;
91 0         0 $shell = _unixy_shells($command);
92 0 0       0 return $shell if defined $shell;
93             }
94              
95 2         4 eval {
96 2         980 my $pw_shell = (getpwnam($username))[-1];
97 2         14 $shell = _unixy_shells($pw_shell);
98 2 50 33     30 $shell = _unixy_shells(readlink $pw_shell) if !defined($shell) && -l $pw_shell;
99             };
100              
101 2 50       13 $shell = __PACKAGE__->bourne_shell unless defined $shell;
102              
103 2         13 return $shell;
104             }
105              
106              
107 1     1 1 82 sub bash_shell { bless { bash => 1, bourne => 1, unix => 1, name => 'bash', default_location => '/bin/bash' }, __PACKAGE__ }
108              
109              
110 3     3 1 86 sub bourne_shell { bless { bourne => 1, unix => 1, name => 'bourne', default_location => '/bin/sh' }, __PACKAGE__ }
111              
112              
113 1     1 1 91 sub c_shell { bless { c => 1, unix => 1, name => 'c', default_location => '/bin/csh' }, __PACKAGE__ }
114              
115              
116 1     1 1 75 sub cmd_shell { bless { cmd => 1, win32 => 1, name => 'cmd', default_location => 'C:\\Windows\\system32\\cmd.exe' }, __PACKAGE__ }
117              
118              
119 1     1 1 74 sub command_shell { bless { command => 1, win32 => 1, name => 'command', default_location => 'C:\\Windows\\system32\\command.com' }, __PACKAGE__ }
120              
121              
122 1     1 1 77 sub dcl_shell { bless { dcl => 1, vms => 1, name => 'dcl' }, __PACKAGE__ }
123              
124              
125 1     1 1 77 sub fish_shell { bless { fish => 1, unix => 1, name => 'fish' }, __PACKAGE__ }
126              
127              
128 1     1 1 72 sub korn_shell { bless { korn => 1, bourne => 1, unix => 1, name => 'korn', default_location => '/bin/ksh' }, __PACKAGE__ }
129              
130              
131 1     1 1 78 sub power_shell { bless { power => 1, win32 => 1, name => 'power' }, __PACKAGE__ }
132              
133              
134 1     1 1 98 sub tc_shell { bless { c => 1, tc => 1, unix => 1, name => 'tc', default_location => '/bin/tcsh' }, __PACKAGE__ }
135              
136              
137 1     1 1 105 sub z_shell { bless { z => 1, bourne => 1, unix => 1, name => 'z', default_location => '/bin/zsh' }, __PACKAGE__ }
138              
139              
140             foreach my $type (qw( cmd command dcl bash fish korn c win32 unix vms bourne tc power z ))
141             {
142 11 50   11 1 60 eval qq{
  11 100   11 1 90  
  11 50   11 1 63  
  11 100   11 1 92  
  11 50   11 1 58  
  11 100   11 1 90  
  11 50   11 1 6098  
  11 100   11 1 156  
  11 50   11 1 60  
  11 100   11 1 99  
  11 50   13 1 59  
  11 100   11 1 89  
  11 50   13 1 56  
  11 100   11 1 111  
  11 50       58  
  11 100       94  
  11 50       60  
  11 100       88  
  11 50       62  
  11 100       93  
  13 50       103  
  13 100       93  
  11 50       62  
  11 100       209  
  13 50       1429  
  13 100       153  
  11 50       71  
  11 100       88  
143             sub is_$type
144             {
145             my \$self = ref \$_[0] ? shift : __PACKAGE__->running_shell;
146             \$self->{$type} || 0;
147             }
148             };
149             die $@ if $@;
150             }
151              
152              
153             sub name
154             {
155 4 50   4 1 504 my $self = ref $_[0] ? shift : __PACKAGE__->running_shell;
156 4         14 $self->{name};
157             }
158              
159              
160             sub default_location
161             {
162 9 50   9 1 39 my $self = ref $_[0] ? shift : __PACKAGE__->running_shell;
163 9         40 $self->{default_location};
164             }
165              
166             sub _unixy_shells
167             {
168 3     3   7 my $shell = shift;
169 3 50       154 if($shell =~ /tcsh$/)
    50          
    50          
    50          
    50          
    50          
    50          
170 0         0 { return __PACKAGE__->tc_shell }
171             elsif($shell =~ /csh$/)
172 0         0 { return __PACKAGE__->c_shell }
173             elsif($shell =~ /ksh$/)
174 0         0 { return __PACKAGE__->korn_shell }
175             elsif($shell =~ /bash$/)
176 0         0 { return __PACKAGE__->bash_shell }
177             elsif($shell =~ /zsh$/)
178 0         0 { return __PACKAGE__->z_shell }
179             elsif($shell =~ /fish$/)
180 0         0 { return __PACKAGE__->fish_shell }
181             elsif($shell =~ /sh$/)
182 0         0 { return __PACKAGE__->bourne_shell }
183             else
184 3         17 { return; }
185             }
186              
187             1;
188              
189             __END__