File Coverage

blib/lib/App/Sys/Info.pm
Criterion Covered Total %
statement 203 251 80.8
branch 34 88 38.6
condition 12 38 31.5
subroutine 36 38 94.7
pod 3 3 100.0
total 288 418 68.9


line stmt bran cond sub pod time code
1             package App::Sys::Info;
2 1     1   17074 use strict;
  1         2  
  1         39  
3 1     1   4 use warnings;
  1         2  
  1         42  
4              
5             our $VERSION = '0.24';
6              
7 1     1   5 use constant CP_UTF8 => 65_001;
  1         4  
  1         73  
8 1     1   4 use constant LAST_ELEMENT => -1;
  1         1  
  1         80  
9              
10 1     1   6 use Carp qw( croak );
  1         1  
  1         65  
11 1     1   457 use Format::Human::Bytes;
  1         426  
  1         26  
12 1     1   486 use POSIX qw( locale_h );
  1         5302  
  1         6  
13 1     1   1530 use Text::Table qw();
  1         17054  
  1         29  
14 1     1   729 use Time::Elapsed qw( elapsed );
  1         4447  
  1         5  
15 1     1   578 use Sys::Info qw();
  1         12856  
  1         25  
16 1     1   8 use Sys::Info::Constants qw( NEW_PERL OSID );
  1         1  
  1         61  
17              
18             my($NEED_CHCP, $OLDCP);
19              
20             BEGIN {
21 1     1   4 no strict qw( refs );
  1         1  
  1         51  
22 1     1   3 foreach my $id ( qw( info os cpu fhb meta NA ) ) {
23 6     25   12 *{ $id } = sub () { return shift->{$id} };
  6         2160  
  25         83  
24             }
25             }
26              
27             END {
28 1 50 33 1   2074 _chcp( $OLDCP ) if $NEED_CHCP && $OLDCP;
29             }
30              
31             sub _chcp {
32 0   0 0   0 my $enc = shift || croak 'No encoding specified';
33 0         0 system chcp => $enc, '2>nul', '1>nul';
34 0         0 return;
35             }
36              
37             sub new {
38 1     1 1 2 my $class = shift;
39 1         7 my $i = Sys::Info->new;
40 1         7 my $loc = do {
41 1         1 my $rv;
42             eval {
43 1         13 $rv = setlocale( LC_CTYPE );
44 1         4 1;
45 1 50       2 } or do {
46 0   0     0 my $error = $@ || 'Unknown error';
47 0         0 warn "Unable to collect the locale information: $error";
48 0         0 $rv = '';
49             };
50 1         3 $rv;
51             };
52 1         5 my $self = {
53             LOCALE => $loc,
54             NA => 'N/A',
55             info => $i,
56             os => $i->os,
57             cpu => $i->device('CPU'),
58             fhb => Format::Human::Bytes->new,
59             };
60 1         13694 $self->{meta} = { $self->{os}->meta };
61 1         34257 bless $self, $class;
62 1         4 return $self;
63             }
64              
65             sub run {
66 1     1 1 14 my $self = __PACKAGE__->new;
67 1   33     4 $NEED_CHCP = $self->os->is_winnt && $ENV{PROMPT};
68 1         7 my @probe = $self->probe;
69              
70 1         4 $self->_init_encoding;
71              
72 1         8 my $tb = Text::Table->new( q{}, q{} );
73 1         445 $tb->load( @probe );
74              
75 1 50       1256 print "\n", $tb or croak "Unable to orint to STDOUT: $!";
76 1         18737 return;
77             }
78              
79             sub probe {
80 1     1 1 2 my $self = shift;
81 1         1 my @rv = eval { $self->_probe(); };
  1         4  
82 1 50       3 croak "Error fetching information: $@" if $@;
83 1         5 return @rv;
84             }
85              
86             sub _init_encoding {
87 1     1   23 my $self = shift;
88 1 50       3 if ( $NEED_CHCP ) {
89             ## no critic (InputOutput::ProhibitBacktickOperators)
90 0         0 chomp($OLDCP = (split /:\s?/xms, qx(chcp))[LAST_ELEMENT]);
91             # try to change the command line encoding to unicode
92 0 0       0 _chcp( CP_UTF8 ) if $OLDCP;
93 0         0 if ( NEW_PERL ) {
94 0         0 my $eok = eval q{ binmode STDOUT, ':utf8'; 1; };
95             }
96             }
97 1         1 return;
98             }
99              
100             sub _probe {
101 1     1   2 my $self = shift;
102 1         3 my $meta = $self->meta;
103 1         4 my $NA = $self->NA;
104 1         4 my $i = $self->info;
105 1         3 my $os = $self->os;
106 1         3 my $pt = $os->product_type;
107 1         5 my $proc = $self->_processors;
108 1         10 my $tz = $os->tz;
109 1         115 my $driver = 'Sys::Info::Driver::' . OSID;
110 1         5 my @rv;
111              
112 1         18 push @rv,
113             [ 'Sys::Info Version' => Sys::Info->VERSION ],
114             [ sprintf( '%s Driver Version', OSID ) => $driver->VERSION ],
115             [ 'Perl Version' => $i->perl_long ],
116             [ 'Host Name' => $os->host_name ],
117             [ 'OS Name' => $self->_os_name ],
118             [ 'OS Version' => $self->_os_version ],
119             ;
120              
121 1         19 my $manu = $meta->{manufacturer};
122 1         2 my $bt = $meta->{build_type};
123              
124 1 50       4 push @rv, [ 'OS Manufacturer' => $manu ] if $manu;
125 1 50       2 push @rv, [ 'OS Configuration' => $pt ] if $pt;
126 1 50       2 push @rv, [ 'OS Build Type' => $bt ] if $bt;
127              
128 1         4 $self->_bitness( \@rv );
129 1         4 $self->_current_user( \@rv );
130 1         820 $self->_registered( \@rv, $meta );
131              
132 1         7 my $pid = $meta->{product_id};
133 1         9 my $tick = $os->tick_count;
134 1         159 my $st = $meta->{system_type};
135              
136 1 50       3 push @rv, [ 'Product ID' => $pid ] if $pid;
137              
138 1         4 $self->_install_date( \@rv );
139              
140 1 50       7 push @rv, [ 'System Up Time' => elapsed($tick) ] if $tick;
141              
142 1         1174 $self->_manufacturer( \@rv, $meta );
143              
144 1 50       9 push @rv, [ 'System Type' => $st ] if $st;
145 1 50       3 push @rv, [ 'Processor(s)' => $proc ] if $proc;
146              
147 1         3 $self->_proc_meta( \@rv );
148 1         3 $self->_bios_version( \@rv );
149 1         4 $self->_directories( \@rv, $meta );
150              
151 1         2 my $loc = $self->{LOCALE};
152              
153 1 50       4 push @rv, [ 'System Locale' => $loc ] if $loc;
154 1 50       4 push @rv, [ 'Input Locale' => $loc ] if $loc;
155 1 50       4 push @rv, [ 'Time Zone' => $tz ] if $tz;
156              
157 1         4 $self->_memory( \@rv, $meta );
158 1         3 $self->_vm( \@rv );
159              
160 1         18 my $domain = $os->domain_name;
161 1         110 my $logon = $os->logon_server;
162 1         5 my $ip = $os->ip;
163 1         5315 my $page = $meta->{page_file_path};
164              
165 1 50       6 push @rv, [ 'Page File Location(s)' => $page ] if $page;
166 1 50       5 push @rv, [ 'Domain' => $domain ] if $domain;
167 1 50       3 push @rv, [ 'Logon Server' => $logon ] if $logon;
168 1 50       3 push @rv, [ 'IP Address' => $ip ] if $ip;
169              
170 1         5 $self->_cdkey( \@rv );
171              
172 1         14 return @rv;
173             }
174              
175             sub _registered {
176 1     1   3 my($self, $rv, $meta) = @_;
177 1 50       3 return if ! $self->os->is_windows;
178 0         0 my $owner = $meta->{owner};
179 0         0 my $org = $meta->{organization};
180 0 0       0 push @{ $rv }, [ 'Registered Owner' => $owner ] if $owner;
  0         0  
181 0 0       0 push @{ $rv }, [ 'Registered Organization' => $org ] if $org;
  0         0  
182 0         0 return;
183             }
184              
185             sub _directories {
186 1     1   2 my($self, $rv, $meta) = @_;
187 1         2 my $win = $meta->{windows_dir};
188 1         2 my $sys = $meta->{system_dir};
189 1         1 my $boot = $meta->{boot_device};
190 1 50       3 push @{ $rv }, [ 'Windows Directory' => $win ] if $win;
  0         0  
191 1 50       3 push @{ $rv }, [ 'System Directory' => $sys ] if $sys;
  0         0  
192 1 50       2 push @{ $rv }, [ 'Boot Device' => $boot ] if $boot;
  0         0  
193 1         1 return;
194             }
195              
196             sub _manufacturer {
197 1     1   3 my($self, $rv, $meta) = @_;
198 1 50       5 return if ! $self->os->is_windows;
199 0         0 my $manu = $meta->{system_manufacturer};
200 0         0 my $model = $meta->{system_model};
201 0 0       0 push @{ $rv }, [ 'System Manufacturer' => $manu ] if $manu;
  0         0  
202 0 0       0 push @{ $rv }, [ 'System Model' => $model ] if $model;
  0         0  
203 0         0 return;
204             }
205              
206             sub _cdkey {
207 1     1   1 my($self, $rv) = @_;
208 1         4 my $os = $self->os;
209 1 50       3 return if ! $os->is_windows;
210              
211 0         0 my $cdkey = $os->cdkey;
212 0         0 my $okey = $self->_office_cdkey;
213 0 0       0 push @{ $rv }, [ 'Windows CD Key' => $cdkey ] if $cdkey;
  0         0  
214 0 0       0 push @{ $rv }, [ 'Microsoft Office CD Key' => $okey ] if $okey;
  0         0  
215 0         0 return;
216             }
217              
218             sub _current_user {
219 1     1   2 my($self, $rv_ref) = @_;
220 1         2 my $os = $self->os;
221 1   50     7 my $user = $os->login_name || return;
222 0         0 my $real = $os->login_name( real => 1 );
223              
224 0 0 0     0 return if ! $user || ! $real;
225              
226 0 0 0     0 my $display = $real && ($real ne $user) ? qq{$real ($user)} : $user;
227 0 0       0 $display .= $os->is_root ? q{ is an administrator} : q{};
228 0         0 push @{ $rv_ref }, [ 'Current User', $display ];
  0         0  
229              
230 0         0 return;
231             }
232              
233             sub _proc_meta {
234 1     1   2 my $self = shift;
235 1         2 my $data = shift;
236 1         2 my @cpu = $self->cpu->identify;
237 1   50     14 my $prop = $cpu[0] || {};
238 1         3 my $load = $self->cpu->load;
239 1         107 my $L1 = $prop->{L1_cache}{max_cache_size};
240 1         3 my $L2 = $prop->{L2_cache}{max_cache_size};
241 1         2 my $sock = $prop->{socket_designation};
242 1         1 my $id = $prop->{processor_id};
243 1         1 my @rv;
244              
245             my $check_lc = sub {
246 2   50 2   4 my $ref = shift || return;
247 2 100       2 return if ! ${ $ref };
  2         7  
248 1 50       1 ${ $ref } .= q{ KB} if ${ $ref } !~ m{\sKB\z}xms;
  0         0  
  1         7  
249 1         2 return;
250 1         4 };
251              
252 1         3 $check_lc->( \$L1 );
253 1         2 $check_lc->( \$L2 );
254              
255 1 50       4 push @rv, qq{Load : $load} if $load;
256 1 50       3 push @rv, qq{L1 Cache: $L1} if $L1;
257 1 50       3 push @rv, qq{L2 Cache: $L2} if $L2;
258 1 50       2 push @rv, qq{Package : $sock} if $sock;
259 1 50       5 push @rv, qq{ID : $id} if $id;
260              
261 1         1 my $buf = q{ } x 2**2;
262 1         3 push @{$data}, [ q{ }, $buf . $_ ] for @rv;
  2         6  
263 1         5 return;
264             }
265              
266             sub _processors {
267 1     1   2 my $self = shift;
268 1         2 my $cpu = $self->cpu;
269 1         17 my $name = scalar $cpu->identify;
270 1         2901 my $rv = sprintf '%s ~%sMHz', $name, $cpu->speed;
271 1         25 $rv =~ s{\s+}{ }xmsg;
272 1         3 return $rv;
273             }
274              
275             sub _memory {
276 1     1   1 my($self, $rv, $meta) = @_;
277 1         7 push @{ $rv },
  4         55  
278             map {
279 1         2 [ $_->[0], $self->_mb( $_->[1] ) ]
280             }
281             [ 'Total Physical Memory' => $meta->{physical_memory_total} ],
282             [ 'Available Physical Memory' => $meta->{physical_memory_available} ],
283             [ 'Virtual Memory: Max Size' => $meta->{page_file_total} ],
284             [ 'Virtual Memory: Available' => $meta->{page_file_available} ],
285             ;
286 1         14 return;
287             }
288              
289             sub _vm {
290 1     1   1 my($self, $rv_ref) = @_;
291 1   50     3 my $tot = $self->meta->{page_file_total} || return;
292 1   50     2 my $av = $self->meta->{page_file_available} || return;
293 1         2 push @{ $rv_ref },
  1         4  
294             [ 'Virtual Memory: In Use' => $self->_mb( $tot - $av ) ]
295             ;
296 1         12 return;
297             }
298              
299             sub _mb {
300 5     5   5 my $self = shift;
301 5   50     9 my $kb = shift || return $self->NA;
302 5         7 return $self->fhb->base2( $kb, 2 );
303             }
304              
305             sub _os_name {
306 1     1   48 my $self = shift;
307 1         2 return $self->os->name( long => 1, edition => 1 );
308             }
309              
310             sub _os_version {
311 1     1   19 my $self = shift;
312 1         3 my $os = $self->os;
313 1         7 return $os->version . q{.} . $os->build;
314             }
315              
316             sub _office_cdkey {
317 0     0   0 my $self = shift;
318 0         0 my @office = $self->os->cdkey( office => 1 );
319 0 0       0 return @office ? $office[0] : undef;
320             }
321              
322             sub _bitness {
323 1     1   2 my($self, $rv_ref) = @_;
324 1   50     2 my $cpu = $self->cpu->bitness || q{??};
325 1   50     39 my $os = $self->os->bitness || q{??};
326 1         14 push @{ $rv_ref }, [ 'Running on' => qq{${cpu}bit CPU & ${os}bit OS} ];
  1         4  
327 1         2 return;
328             }
329              
330             sub _install_date {
331 1     1   2 my($self, $rv_ref) = @_;
332 1   50     3 my $date = $self->meta->{install_date} || return;
333 1         1 push @{ $rv_ref }, [ 'Original Install Date' => scalar localtime $date ];
  1         21  
334 1         2 return;
335             }
336              
337             sub _bios_version {
338 1     1   2 my($self, $rv_ref) = @_;
339 1         1 local $@;
340 1         2 my $bv = eval { $self->info->device('bios')->version; };
  1         2  
341 1 50 33     422 return if $@ || ! $bv;
342 0           push @{ $rv_ref }, [ 'BIOS Version' => $bv ];
  0            
343 0           return;
344             }
345              
346             1;
347              
348             __END__