Detect and Display of operating system using Perl - perl

I want to display my computer's operating system using Perl. I thought the following would do
#!/usr/bin/perl
use strict;
use warnings;
my $os = $^O;
print "$os\n";
But the output I got is
linux
I want the output to be displayed as
Windows XP
How to do this? Please help. Thanks in advance.

Use the uname() function that the POSIX module provides for you.

All Perl distributions come with the Config module. This module is a bit rickety because it imports the hash %Config, but it's an easy way to get access to all sorts of Perl configuration information.
use Config; # This exports a %Config hash
print "My OS is $Config{osname}\n";
print "My OS version is $Config{osvers}\n";
print "My Architecture Family is $Config{archname}\n";
#
# Print out all of the keys, and see which one looks like one
# you can use. "ld" is actually a rather nice value
#
for my $key (sort keys %Config) {
no warnings qw(uninitialized); # Some elements have undef values
print qq($key: "$Config{$key}"\n);
}

Are you perhaps looking for
use CGI qw( );
use HTTP::BrowserDetect qw( );
my $cgi = CGI->new();
print $cgi->header('text/plain');
my $bd = HTTP::BrowserDetect->new($cgi->user_agent());
print $bd->os_string(), "\n";

Related

Issues with getopts in perl

I'm using Getopt::Std to process my command line args. My command line args are strings. I have issuewithgetopts()`, as it works only for single character based opts.
As seen below "srcdir" "targetdir" options are mandatory and script should error out if any one of them is missing. "block" is NOT a mandatory option.
I don't see %options has is being set with the code below, and all my options{key} are NULL. Had I replaced "srcdir=>s" and "targetdir=>t" then the below piece of code works. It doesn't work with "-srcdir" "-targetdir" options.
What's the best way to address the issue I have?
Use mode:
perl test.pl -srcdir foo1 -targetdir hello1
#!/usr/bin/perl -w
use strict;
use Getopt::Std;
# declare the perl command line flags/opt we want to allow
my %options=();
my $optstring = 'srcdir:targetdir:block';
getopts( "$optstring", %options);
# test for the existence of the opt on the command line.
print "-srcdir $options{srcdir}\n" if defined $options{srcdir};
print "-targetdir $options{targetdir}\n" if defined $options{targetdir};
print "-blocks $options{block}\n" if defined $options{block};
# other things found on the command line
print "loop:\n" if ($#ARGV > 0);
foreach (#ARGV)
{
print "$_\n";
}
You really want to use Getopt::Long to handle words like srcdir:
use warnings;
use strict;
use Data::Dumper;
use Getopt::Long;
$Data::Dumper::Sortkeys=1;
my %options;
GetOptions(\%options, qw(srcdir=s targetdir=s block));
print Dumper(\%options);
print Dumper(\#ARGV);
The reason your hash was empty was that you need to pass a reference to a hash, as shown in Getopt::Std:
getopts( "$optstring", \%options);
Also, since Std only handles single letters, it would interpret srcdir as 6 separate options: s, r, etc.

Input parameter for perl CGI script

I need some insight on my Perl CGI script.
First of all all this is running under webmin so i'm doing a custom module.
I'm calling a CGI Perl script passing 2 parameter from another Perl CGI. The link I'm calling is in the following format:
http://IP:8080/foobar/alat.cgi?sysinfo=xxxxxxx&SR=yyyyyyyy
The alat.cgi script look like this
#!/usr/bin/perl
use CGI qw(:standard);
ReadParse();
$q = new CGI;
my $dir = $in->param('SR');
my $s = $in->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s"<br>";
The only output I get printed is the value of $dir and $s seems to be empty.
What am I doing wrong?
As #Сухой27 said, add use strict;, but also use warnings; to the top of your script, right below the shebang (#!/usr/bin/perl) line. Those will tell you about syntax errors and other stuff where Perl is doing something other than you might intend.
With CGI (which is btw not part of the Perl core in the latest 5.22 release any more) and the object oriented approach you are tyring to take, you don't need to use ReadParse(). That is an abomination left in from Perl 4's cgilib.pl times.
I don't know what your ui_print_header function does. I'm guessing it outputs a bunch of HTML. Are you sure you defined it?
With fixing all your syntax errors and using modern syntax, your program would look like this. I'll break down what is happening for you.
#!/usr/bin/perl
use strict;
use warnings;
use CGI;
my $q = CGI->new;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
# you need to declare this to use it below
my %text = ( edit_title => 'foo' );
# we declare this sub further down
ui_print_header(undef, $text{'edit_title'} . $dir, q{});
print $dir . '<br />';
print $s . '<br />';
sub ui_print_header {
my ( $foo, $title, $dir, $bar ) = #_;
# do stuff here...
}
Let's look at some of the things I did here.
Saying new CGI as the CGI docs suggest is fine, but since we are using the OOP way you can use the more common CGI->new. It's the same thing really, but it's consistent with the rest of the OOP Perl world and it's more clear that you are calling the new method on the CGI package.
If you have $q, keep using it. There is no $in.
Declare all your variables with my.
Declare %text so you can use $text{'edit_title'} later. Probably you imported that, or ommitted it from the code you showed us.
Declare ui_print_header(). See above.
q{} is the same as '', but it's clearer that it's an empty string.
thank you everyone for the very quick answer, and as I was suspecting I just had some silly mistake.
Adding here the corrected code that now works
#!/usr/bin/perl
# Run alat on selected sysinfo and allow display of output
#use strict;
use diagnostics;
require 'recoverpoint-lib.pl';
use CGI qw(:standard);
ReadParse();
my $q = new CGI;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s."<br>";
Just to clarify for some of previous answer, this is a custom module of webmin so variable $text is imported and function ui_print_header is a webmin defined one, it basically print the page header in HTML
As you enable strict and warnings you can easily know the errors.Also you should check Apache error logs, I think the script should be like this:
#!/usr/bin/perl
use CGI qw(:standard);
use strict;
use warnings;
ReadParse();
my $q = new CGI;
my $dir = $q->param('SR');
my $s = $q->param('sysinfo');
ui_print_header(undef, $text{'edit_title'}.$dir, "");
print $dir."<br>";
print $s."<br>";

How to use a module in Perl

Guys im really confused on how to use a module i just installed in Perl.
I installed a Corelist module in Perl. And i want to display all the modules that came with Perl 5.006. But there is a hint in doing this by using this code which i dont understand:
my %modules = %{ $Module::CoreList::version{5.006} };
But when i did this
#! usr/bin/perl
use warnings;
use strict;
my %modules = %{$Module::CoreList::version{5.006}};
print %modules;
it gives this error: Module::CoreList::version used only once . I also tried putting
use Module::CoreList; still no luck
The name of the module is 'Module::CoreList'. You should put the following line into your programme:
use Module::CoreList;
Also note the capital L. Perl is case sensitive.
If you simply want to print the hash, just add Data::Dumper module along with strict and warnings, then
print Dumper(\%modules);
Updated: try something like
use warnings;
use strict;
use Module::CoreList;
use Data::Dumper;
my %module = %{ $Module::CoreList::version{5.006} };
print Dumper (\%module);

How to use Term::ReadLine to retrieve command history?

I've the following script, which is almost the same of the sample in synopsis paragraph in documentation.
use strict;
use warnings;
use Term::ReadLine;
my $term = Term::ReadLine->new('My shell');
print $term, "\n";
my $prompt = "-> ";
while ( defined ($_ = $term->readline($prompt)) ) {
print $_, "\n";
$term->addhistory($_);
}
It executes with no error, but unfortunately, even if I click the Up Arrow, I only get ^[[A and no history. What am I missing?
The print $term statement prints Term::ReadLine::Stub=ARRAY(0x223d2b8).
Since we are here, I noticed it prints the prompt underlined... but I can't find in the docs anything which could prevent it. Is there any way to avoid it?
To answer the main question, you probably don't have a good Term::ReadLine library installed. you will want either 'perl-Term-ReadLine-Perl' or 'perl-Term-ReadLine-Gnu'. These are the fedora package names, but i'm sure that the ubuntu/debian names would be similar. I believe you could also get them from CPAN, but I haven't tested that. If you haven't installed the package, perl loads a dummy module that has almost no features. for this reason history was not part of it.
The underline is part of what readline calls ornaments. if you want to turn them off completely, add $term->ornaments(0); somewhere apropriate.
my rewrite of your script is as follows
#!/usr/bin/perl
use strict;
use warnings;
use Term::ReadLine; # make sure you have the gnu or perl implementation of readline isntalled
# eg: Term::ReadLine::Gnu or Term::ReadLine::Perl
my $term = Term::ReadLine->new('My shell');
my $prompt = "-> ";
$term->ornaments(0); # disable ornaments.
while ( defined ($_ = $term->readline($prompt)) ) {
print $_, "\n";
$term->addhistory($_);
}

Is there a way to encapsulate the common Perl functions into their own scripts?

I am maintaining several Perl scripts that all have similar code blocks for different functions. Each time a code block is updated, I have to go through each script and manually make the change.
Is there a way to encapsulate the common functions into their own scripts and call them?
Put the common functionality in a module. See perldoc perlmod for details.
There are other ways, but they all have severe issues. Modules are the way to go, and they don't have to be very complicated. Here is a basic template:
package Mod;
use strict;
use warnings;
use Exporter 'import';
#list of functions/package variables to automatically export
our #EXPORT = qw(
always_exported
);
#list of functions/package variables to export on request
our #EXPORT_OK = qw(
exported_on_request
also_exported_on_request
);
sub always_exported { print "Hi\n" }
sub exported_on_request { print "Hello\n" }
sub also_exported_on_request { print "hello world\n" }
1; #this 1; is required, see perldoc perlmod for details
Create a directory like /home/user/perllib. Put that code in a file named Mod.pm in that directory. You can use the module like this:
#!/usr/bin/perl
use strict;
use warnings;
#this line tells Perl where your custom modules are
use lib '/home/user/perllib';
use Mod qw/exported_on_request/;
always_exported();
exported_on_request();
Of course, you can name the file anything you want. It is good form to name the package the same as file. If you want to have :: in the name of the package (like File::Find) you will need to create subdirectories in /home/user/perllib. Each :: is equivalent to a /, so My::Neat::Module would go in the file /home/user/perllib/My/Neat/Module.pm. You can read more about modules in perldoc perlmod and more about Exporter in perldoc Exporter
About a third of Intermediate Perl is devoted to just this topic.
Using a module is the most robust way, and learning how to use modules would be helpful.
Less efficient is the do function. Extract your code to a separate file, say "mysub.pl", and
do 'mysub.pl';
This will read and then eval the contents of the file.
You can use the
require "some_lib_file.pl";
where you would put all your common functions and call them from other scripts which would contain the line above.
For example:
146$ cat tools.pl
# this is a common function we are going to call from other scripts
sub util()
{
my $v = shift;
return "$v\n";
}
1; # note this 1; the 'required' script needs to end with a true value
147$ cat test.pl
#!/bin/perl5.8 -w
require 'tools.pl';
print "starting $0\n";
print util("asdfasfdas");
exit(0);
148$ cat test2.pl
#!/bin/perl5.8 -w
require "tools.pl";
print "starting $0\n";
print util(1);
exit(0);
Then executing test.pl and test2.pl will yield the following results:
149$ test.pl
starting test.pl
asdfasfdas
150$ test2.pl
starting test2.pl
1