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   1266696 use strict;
  16         138  
  16         358  
4 16     16   63 use warnings;
  16         22  
  16         301  
5 16     16   56 use File::Spec;
  16         20  
  16         18224  
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.08'; # 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 97 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       3 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       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       11 $shell || __PACKAGE__->login_shell;
76             }
77              
78              
79             sub login_shell
80             {
81 2     2 1 83 shift; # class ignored
82 2         12 my $shell;
83              
84 2 50       8 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       5 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       7 if($^O eq 'darwin')
98             {
99 0         0 my $command = `dscl . -read /Users/$username UserShell`;
100 0         0 $shell = _unixy_shells($command);
101 0 0       0 return $shell if defined $shell;
102             }
103              
104 2         4 eval {
105 2         1183 my $pw_shell = (getpwnam($username))[-1];
106 2         13 $shell = _unixy_shells($pw_shell);
107 2 50 33     42 $shell = _unixy_shells(readlink $pw_shell) if !defined($shell) && -l $pw_shell;
108             };
109              
110 2 50       11 $shell = __PACKAGE__->bourne_shell unless defined $shell;
111              
112 2         18 return $shell;
113             }
114              
115              
116 1     1 1 92 sub bash_shell { bless { bash => 1, bourne => 1, unix => 1, name => 'bash', default_location => '/bin/bash' }, __PACKAGE__ }
117              
118              
119 3     3 1 98 sub bourne_shell { bless { bourne => 1, unix => 1, name => 'bourne', default_location => '/bin/sh' }, __PACKAGE__ }
120              
121              
122 1     1 1 89 sub c_shell { bless { c => 1, unix => 1, name => 'c', default_location => '/bin/csh' }, __PACKAGE__ }
123              
124              
125 1     1 1 92 sub cmd_shell { bless { cmd => 1, win32 => 1, name => 'cmd', default_location => 'C:\\Windows\\system32\\cmd.exe' }, __PACKAGE__ }
126              
127              
128 1     1 1 102 sub command_shell { bless { command => 1, win32 => 1, name => 'command', default_location => 'C:\\Windows\\system32\\command.com' }, __PACKAGE__ }
129              
130              
131 1     1 1 84 sub dcl_shell { bless { dcl => 1, vms => 1, name => 'dcl' }, __PACKAGE__ }
132              
133              
134 1     1 1 100 sub fish_shell { bless { fish => 1, unix => 1, name => 'fish' }, __PACKAGE__ }
135              
136              
137 1     1 1 88 sub korn_shell { bless { korn => 1, bourne => 1, unix => 1, name => 'korn', default_location => '/bin/ksh' }, __PACKAGE__ }
138              
139              
140 1     1 1 88 sub power_shell { bless { power => 1, win32 => 1, name => 'power' }, __PACKAGE__ }
141              
142              
143 1     1 1 111 sub tc_shell { bless { c => 1, tc => 1, unix => 1, name => 'tc', default_location => '/bin/tcsh' }, __PACKAGE__ }
144              
145              
146 1     1 1 96 sub z_shell { bless { z => 1, bourne => 1, unix => 1, name => 'z', default_location => '/bin/zsh' }, __PACKAGE__ }
147              
148              
149             foreach my $type (qw( cmd command dcl bash fish korn c win32 unix vms bourne tc power z ))
150             {
151 11 50   11 1 45 eval qq{
  11 100   11 1 73  
  11 50   11 1 43  
  11 100   11 1 67  
  11 50   11 1 44  
  11 100   11 1 71  
  11 50   11 1 5972  
  11 100   11 1 102  
  11 50   11 1 46  
  11 100   11 1 76  
  11 50   13 1 44  
  11 100   11 1 95  
  11 50   13 1 43  
  11 100   11 1 160  
  11 50       46  
  11 100       71  
  11 50       47  
  11 100       72  
  11 50       44  
  11 100       77  
  13 50       84  
  13 100       73  
  11 50       44  
  11 100       69  
  13 50       1050  
  13 100       88  
  11 50       45  
  11 100       70  
152             sub is_$type
153             {
154             my \$self = ref \$_[0] ? shift : __PACKAGE__->running_shell;
155             \$self->{$type} || 0;
156             }
157             };
158             die $@ if $@;
159             }
160              
161              
162             sub name
163             {
164 4 50   4 1 495 my $self = ref $_[0] ? shift : __PACKAGE__->running_shell;
165 4         11 $self->{name};
166             }
167              
168              
169             sub default_location
170             {
171 9 50   9 1 40 my $self = ref $_[0] ? shift : __PACKAGE__->running_shell;
172 9         30 $self->{default_location};
173             }
174              
175             sub _unixy_shells
176             {
177 4     4   8 my $shell = shift;
178 4 50       182 if($shell =~ /tcsh$/)
    50          
    50          
    50          
    50          
    50          
    50          
179 0         0 { return __PACKAGE__->tc_shell }
180             elsif($shell =~ /csh$/)
181 0         0 { return __PACKAGE__->c_shell }
182             elsif($shell =~ /ksh$/)
183 0         0 { return __PACKAGE__->korn_shell }
184             elsif($shell =~ /bash$/)
185 0         0 { return __PACKAGE__->bash_shell }
186             elsif($shell =~ /zsh$/)
187 0         0 { return __PACKAGE__->z_shell }
188             elsif($shell =~ /fish$/)
189 0         0 { return __PACKAGE__->fish_shell }
190             elsif($shell =~ /sh$/)
191 0         0 { return __PACKAGE__->bourne_shell }
192             else
193 4         24 { return; }
194             }
195              
196             1;
197              
198             __END__