File Coverage

blib/lib/Shell/Guess.pm
Criterion Covered Total %
statement 78 105 74.2
branch 65 114 57.0
condition 3 9 33.3
subroutine 33 34 97.0
pod 29 29 100.0
total 208 291 71.4


line stmt bran cond sub pod time code
1             package Shell::Guess;
2              
3 16     16   2338574 use strict;
  16         42  
  16         770  
4 16     16   214 use warnings;
  16         39  
  16         1215  
5 16     16   114 use File::Spec;
  16         38  
  16         35106  
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.10'; # 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 238679 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       5 return __PACKAGE__->dcl_shell if $^O eq 'VMS';
48 1 50       3 return __PACKAGE__->command_shell if $^O eq 'dos';
49              
50             my $shell = eval {
51             open(my $fh, '<', File::Spec->catfile('', 'proc', getppid, 'comm')) || 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             || eval {
60             open(my $fh, '<', File::Spec->catfile('', 'proc', getppid, 'cmdline')) || die;
61             my $command_line = <$fh>;
62             die unless defined $command_line; # don't spew warnings if read failed
63             close $fh;
64             $command_line =~ s/\0.*$//;
65             _unixy_shells($command_line);
66             }
67              
68 1   33     3 || eval {
69             require Unix::Process;
70             my $method = $^O eq 'solaris' ? 'comm' : 'command';
71             my($command) = map { s/\s+.*$//; $_ } Unix::Process->$method(getppid);
72             _unixy_shells($command);
73             };
74              
75 1 50       12 $shell || __PACKAGE__->login_shell;
76             }
77              
78              
79             sub login_shell
80             {
81 2     2 1 245747 shift; # class ignored
82 2         5 my $shell;
83              
84 2 50       13 if($^O eq 'MSWin32')
85             {
86 0 0       0 if(Win32::IsWin95())
87 0         0 { return __PACKAGE__->command_shell }
88             else
89 0         0 { return __PACKAGE__->cmd_shell }
90             }
91              
92 2 50       8 return __PACKAGE__->dcl_shell if $^O eq 'VMS';
93 2 50       8 return __PACKAGE__->command_shell if $^O eq 'dos';
94              
95 2   33     29 my $username = shift || $ENV{USER} || $ENV{USERNAME} || $ENV{LOGNAME};
96              
97 2 50       12 unless(defined $username)
98             {
99 2         7 $username = eval { getpwuid $< };
  2         647  
100             }
101              
102 2 50       20 if($^O eq 'darwin')
103             {
104 0         0 my $command = `dscl . -read /Users/$username UserShell`;
105 0         0 $shell = _unixy_shells($command);
106 0 0       0 return $shell if defined $shell;
107             }
108              
109 2         5 eval {
110 2         230 my $pw_shell = (getpwnam($username))[-1];
111 2         24 $shell = _unixy_shells($pw_shell);
112 2 50 33     11 $shell = _unixy_shells(readlink $pw_shell) if !defined($shell) && -l $pw_shell;
113             };
114              
115 2 50       7 $shell = __PACKAGE__->bourne_shell unless defined $shell;
116              
117 2         17 return $shell;
118             }
119              
120              
121 3     3 1 290899 sub bash_shell { bless { bash => 1, bourne => 1, unix => 1, name => 'bash', default_location => '/bin/bash' }, __PACKAGE__ }
122              
123              
124 1     1 1 172283 sub bourne_shell { bless { bourne => 1, unix => 1, name => 'bourne', default_location => '/bin/sh' }, __PACKAGE__ }
125              
126              
127 1     1 1 260065 sub c_shell { bless { c => 1, unix => 1, name => 'c', default_location => '/bin/csh' }, __PACKAGE__ }
128              
129              
130 1     1 1 252681 sub cmd_shell { bless { cmd => 1, win32 => 1, name => 'cmd', default_location => 'C:\\Windows\\system32\\cmd.exe' }, __PACKAGE__ }
131              
132              
133 1     1 1 229300 sub command_shell { bless { command => 1, win32 => 1, name => 'command', default_location => 'C:\\Windows\\system32\\command.com' }, __PACKAGE__ }
134              
135              
136 1     1 1 255397 sub dcl_shell { bless { dcl => 1, vms => 1, name => 'dcl' }, __PACKAGE__ }
137              
138              
139 1     1 1 206991 sub fish_shell { bless { fish => 1, unix => 1, name => 'fish' }, __PACKAGE__ }
140              
141              
142 1     1 1 247734 sub korn_shell { bless { korn => 1, bourne => 1, unix => 1, name => 'korn', default_location => '/bin/ksh' }, __PACKAGE__ }
143              
144              
145 1     1 1 206463 sub power_shell { bless { power => 1, win32 => 1, name => 'power' }, __PACKAGE__ }
146              
147              
148 1     1 1 209266 sub tc_shell { bless { c => 1, tc => 1, unix => 1, name => 'tc', default_location => '/bin/tcsh' }, __PACKAGE__ }
149              
150              
151 1     1 1 308126 sub z_shell { bless { z => 1, bourne => 1, unix => 1, name => 'z', default_location => '/bin/zsh' }, __PACKAGE__ }
152              
153              
154             foreach my $type (qw( cmd command dcl bash fish korn c win32 unix vms bourne tc power z ))
155             {
156 11 50   11 1 59 eval qq{
  11 100   11 1 102  
  11 50   11 1 66  
  11 100   11 1 100  
  11 50   11 1 63  
  11 100   11 1 105  
  11 50   11 1 10712  
  11 100   11 1 155  
  11 50   11 1 58  
  11 100   11 1 155  
  11 50   13 1 57  
  11 100   11 1 105  
  11 50   13 1 60  
  11 100   11 1 103  
  11 50       61  
  11 100       105  
  11 50       63  
  11 100       118  
  11 50       61  
  11 100       111  
  13 50       125  
  13 100       100  
  11 50       56  
  11 100       101  
  13 50       2280  
  13 100       124  
  11 50       65  
  11 100       100  
157             sub is_$type
158             {
159             my \$self = ref \$_[0] ? shift : __PACKAGE__->running_shell;
160             \$self->{$type} || 0;
161             }
162             };
163             die $@ if $@;
164             }
165              
166              
167             sub name
168             {
169 4 50   4 1 1267 my $self = ref $_[0] ? shift : __PACKAGE__->running_shell;
170 4         20 $self->{name};
171             }
172              
173              
174             sub default_location
175             {
176 9 50   9 1 42 my $self = ref $_[0] ? shift : __PACKAGE__->running_shell;
177 9         119 $self->{default_location};
178             }
179              
180             sub _unixy_shells
181             {
182 4     4   13 my $shell = shift;
183 4 50       49 if($shell =~ /tcsh$/)
    50          
    50          
    100          
    50          
    50          
    50          
    50          
184 0         0 { return __PACKAGE__->tc_shell }
185             elsif($shell =~ /csh$/)
186 0         0 { return __PACKAGE__->c_shell }
187             elsif($shell =~ /ksh$/)
188 0         0 { return __PACKAGE__->korn_shell }
189             elsif($shell =~ /bash$/)
190 2         12 { return __PACKAGE__->bash_shell }
191             elsif($shell =~ /zsh$/)
192 0         0 { return __PACKAGE__->z_shell }
193             elsif($shell =~ /fish$/)
194 0         0 { return __PACKAGE__->fish_shell }
195             elsif($shell =~ /pwsh$/)
196 0         0 { return __PACKAGE__->power_shell }
197             elsif($shell =~ /sh$/)
198 0         0 { return __PACKAGE__->bourne_shell }
199             else
200 2         19 { return; }
201             }
202              
203             1;
204              
205             __END__