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   1086960 use strict;
  16         168  
  16         500  
4 16     16   85 use warnings;
  16         86  
  16         426  
5 16     16   81 use File::Spec;
  16         35  
  16         23226  
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.09'; # 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 87 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       4 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     2 || 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       13 $shell || __PACKAGE__->login_shell;
76             }
77              
78              
79             sub login_shell
80             {
81 2     2 1 87 shift; # class ignored
82 2         23 my $shell;
83              
84 2 50       12 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       7 return __PACKAGE__->dcl_shell if $^O eq 'VMS';
93 2 50       7 return __PACKAGE__->command_shell if $^O eq 'dos';
94              
95 2   33     25 my $username = shift || $ENV{USER} || $ENV{USERNAME} || $ENV{LOGNAME};
96              
97 2 50       7 unless(defined $username)
98             {
99 2         4 $username = eval { getpwuid $< };
  2         1299  
100             }
101              
102 2 50       17 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         4 eval {
110 2         224 my $pw_shell = (getpwnam($username))[-1];
111 2         12 $shell = _unixy_shells($pw_shell);
112 2 50 33     12 $shell = _unixy_shells(readlink $pw_shell) if !defined($shell) && -l $pw_shell;
113             };
114              
115 2 50       9 $shell = __PACKAGE__->bourne_shell unless defined $shell;
116              
117 2         12 return $shell;
118             }
119              
120              
121 3     3 1 118 sub bash_shell { bless { bash => 1, bourne => 1, unix => 1, name => 'bash', default_location => '/bin/bash' }, __PACKAGE__ }
122              
123              
124 1     1 1 103 sub bourne_shell { bless { bourne => 1, unix => 1, name => 'bourne', default_location => '/bin/sh' }, __PACKAGE__ }
125              
126              
127 1     1 1 102 sub c_shell { bless { c => 1, unix => 1, name => 'c', default_location => '/bin/csh' }, __PACKAGE__ }
128              
129              
130 1     1 1 98 sub cmd_shell { bless { cmd => 1, win32 => 1, name => 'cmd', default_location => 'C:\\Windows\\system32\\cmd.exe' }, __PACKAGE__ }
131              
132              
133 1     1 1 97 sub command_shell { bless { command => 1, win32 => 1, name => 'command', default_location => 'C:\\Windows\\system32\\command.com' }, __PACKAGE__ }
134              
135              
136 1     1 1 100 sub dcl_shell { bless { dcl => 1, vms => 1, name => 'dcl' }, __PACKAGE__ }
137              
138              
139 1     1 1 88 sub fish_shell { bless { fish => 1, unix => 1, name => 'fish' }, __PACKAGE__ }
140              
141              
142 1     1 1 99 sub korn_shell { bless { korn => 1, bourne => 1, unix => 1, name => 'korn', default_location => '/bin/ksh' }, __PACKAGE__ }
143              
144              
145 1     1 1 97 sub power_shell { bless { power => 1, win32 => 1, name => 'power' }, __PACKAGE__ }
146              
147              
148 1     1 1 99 sub tc_shell { bless { c => 1, tc => 1, unix => 1, name => 'tc', default_location => '/bin/tcsh' }, __PACKAGE__ }
149              
150              
151 1     1 1 93 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 72 eval qq{
  11 100   11 1 96  
  11 50   11 1 66  
  11 100   11 1 89  
  11 50   11 1 61  
  11 100   11 1 98  
  11 50   11 1 7510  
  11 100   11 1 148  
  11 50   11 1 64  
  11 100   11 1 102  
  11 50   13 1 68  
  11 100   11 1 149  
  11 50   13 1 65  
  11 100   11 1 243  
  11 50       61  
  11 100       94  
  11 50       71  
  11 100       93  
  11 50       73  
  11 100       95  
  13 50       112  
  13 100       114  
  11 50       65  
  11 100       96  
  13 50       1273  
  13 100       119  
  11 50       65  
  11 100       94  
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 774 my $self = ref $_[0] ? shift : __PACKAGE__->running_shell;
170 4         16 $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         42 $self->{default_location};
178             }
179              
180             sub _unixy_shells
181             {
182 4     4   11 my $shell = shift;
183 4 50       39 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         9 { 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         17 { return; }
201             }
202              
203             1;
204              
205             __END__