coder . cl » perl http://coder.cl web developer & system programmer Sat, 03 Nov 2012 12:37:47 +0000 en hourly 1 http://wordpress.org/?v=3.4.2 function prototypes and references in perl http://coder.cl/2010/08/function-prototypes-and-references-in-perl/ http://coder.cl/2010/08/function-prototypes-and-references-in-perl/#comments Fri, 20 Aug 2010 23:33:49 +0000 Daniel Molina Wegener http://coder.cl/?p=870 Some people is considering Perl as a non-friendly language, but in my opinion is a powerful language, not only for its capacity to do text-processing, it also has a lot of modules and extensions which makes it a language of choice for a wide variety of applications. I prefer to code Perl using strict and function prototypes, so it looks more clean and elegant. Also it supports lambdas for some tasks. Let’s take look on prototypes and references. You will find interesting topics reading perlsub(1) and perlref(1).

On the Perl language, prototypes usually are absent, since are not required. you just create a function — anonymous or not — by writing subs:

sub hello_world {
    return "hello world";
}

The principle of perl subs, is that you call them with an unique argument and that argument is a list, so that’s why calling functions in perl do not require the form function(arg1, arg2, arg3). For example you can call the hello_world function with four different forms:

print hello_world;        # the mos common form
print &hello_world;       # code reference style
print hello_world();      # the c derived form without arguments
print &hello_world();     # code reference style form without arguments

Like many languages, Perl provides for user-defined subroutines. These may be located anywhere in the main program, loaded in from other files via the do, require, or use keywords, or generated on the fly using eval or anonymous subroutines. You can even call a function indirectly using a variable containing its name or a CODE reference.

The last two ones are just indicating that the argument list is empty. Have you tried to pass an array or list as argument?

sub hello_who {
    my ($who) = @_;
    print "hello ${who}n";
}
my @nekos = ('neko', 'core', 'test');
hello_who 'neko';
hello_who @nekos;
hello_who (@nekos);

The code above will just print "hello neko" three times, since the argument handling is just requesting the first argument, and it’s equivalent to call my $who = shift;. So, to pass an array or list as argument, you need to pass its reference — which is handled internally as scalar type in perl:

sub hello_who_iterator($) {
    my ($who) = @_;
    foreach my $i (@{$who}) {
        print "hello ${i}n";
    }
}
my @nekos = ('neko', 'core', 'test');
hello_who_iterator @nekos;
hello_who_iterator @nekos, "hola";

The prototyped function above will allow you to handle one argument as reference and ignore the remaining argument, if any. The same happens to hashes, so you can pass three references without problems:

sub hello_world_three($$$) {
    my ($a, $h, $s) = @_;
    my @hello_l;
    foreach my $i (@{$a}) {
        if ($h->{$i}) {
            push @hello_l, "Hello ".$s.' '.$i.' '.$h->{$i};
        }
    }
    return join("n", @hello_l)."n";
}
my %saludos = ('Juan' => 'el "Gato"',
               'Pedro' => 'el "Epidemia"',
               'Diego' => 'el "Conejo"',);
my @saludar_a = ('Juan', 'Pedro');
print hello_world_three(@saludar_a, %saludos, 'Mr.');

But what happens if I pass directly those three arguments, without using their references? The example above will print the following text:

Hello Mr. Juan el "Gato"
Hello Mr. Pedro el "Epidemia"

If we replace the code to catch directly those arguments, and not their references, we will not get the same result and the function will not do anything…

sub hello_world_three {
    my (@a, %h, $s) = @_;
    my @hello_l;
    foreach my $i (@a) {
        if ($h{$i}) {
            push @hello_l, "Hello ".$s.' '.$i.' '.$h{$i};
        }
    }
    return join("n", @hello_l)."n";
}
my %saludos = ('Juan' => 'el "Gato"',
               'Pedro' => 'el "Epidemia"',
               'Diego' => 'el "Conejo"',);
my @saludar_a = ('Juan', 'Pedro');
print hello_world_three(@saludar_a, %saludos, 'Mr.');

The example above applies the shift function to the first argument, so the function just receives the @saludar_a argument, so %h and $s arguments will be empty. If you want to pass an array or a hash to a function, you must do it by passing their reference.

Any arguments passed in show up in the array @_. Therefore, if you called a function with two arguments, those would be stored in $_[0] and $_[1]. The array @_ is a local array, but its elements are aliases for the actual scalar parameters. In particular, if an element $_[0] is updated, the corresponding argument is updated (or an error occurs if it is not updatable). If an argument is an array or hash element which did not exist when the function was called, that element is created only when (and if) it is modified or a reference to it is taken. (Some earlier versions of Perl created the element whether or not the element was assigned to.) Assigning to the whole array @_ removes that aliasing, and does not update any arguments.


references

  • perlsub(1)
  • perlref(1)

© Daniel Molina Wegener for coder . cl, 2010. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2010/08/function-prototypes-and-references-in-perl/feed/ 0
configuring snmptrapd http://coder.cl/2010/07/configuring-snmptrapd/ http://coder.cl/2010/07/configuring-snmptrapd/#comments Fri, 16 Jul 2010 23:28:27 +0000 Daniel Molina Wegener http://coder.cl/?p=703 snmptrapd(8) is a SNMP trap daemon, in other words, it captures SNMP notifications from the network and similar devices. In this post I will try to explain how to configure this daemon to allow a network server to process SNMP traps using both, embeded perl handlers for snmptrapd(8) and plain standard input — or stdin — handlers.

daemon configuration

The daemon is quite easy to configure, you must setup the snmptrapd.conf(5snmp) file. For this configuration, you must read your desired configuration options, such as logging and execution. For example if we have a community called inetsnmp, we can configure the file to allow traps from that community and also configure a trap handler written in perl.


# configure inetsnmp community to allow logging,
# execution of handlers and network traffic.
authCommunity   log,execute,net         inetsnmp

# perl embeded handler.
perl do "/usr/share/snmp/handler/trapdembed.pl"

This configuration is not enough, the snmptrapd(8) daemon uses hosts.allow(5) facility, so we need to add the proper rule in that file:


snmptrapd : 192.168.100.0/255.255.255.0 : allow
snmptrapd : 10.10.10.0/255.255.255.0 : allow

the embeded perl handler

#!/usr/bin/perl -w
#

# strict perl is better
use strict;
use FileHandle;
use Data::Dumper;
use NetSNMP::TrapReceiver;

# we create a sample/demo log file...
my $log = FileHandle->new("/var/log/snmptrapsample.log", "a+") ||
    die "Failed to open log file";

# how we process an SNMP variable
sub process_var {
    my ($var) = @_;
    my %res;
    my $name = "$var->[0]";
    my ($vt, $vv) = split /: /, "$var->[1]";
    $res{'oid'} = $name;
    $res{'type'} = $vt;
    $res{'value'} = $vv;
    return %res;
}

# our default receiver
sub default_receiver {
    my ($pdu, $ivars) = @_;
    my %vars;
    $log->print(Dumper($pdu));
    foreach my $k (@{$_[1]}) {
        $vars{$k->[0]} = process_var($k);
    }
    $log->print(Dumper(%vars));
    $log->flush;
}

# every OIDs pass through the default_receiver
NetSNMP::TrapReceiver::register("all", &default_receiver) ||
    die "Failed to laod Sample Trap Receivern";

# status message...
print STDERR "Loaded Sample Trap Receivern";

This perl(1) handler will allow you basically to create a handler which is capable to process SNMP notifications creating two main variables on the handler itself $pdu which is the reference to the %pdu hash and %vars hash. Both hashes contains the proper data to process the request as you want:


%pdu = {
    'notificationtype' => 'TRAP',
    'receivedfrom' => 'UDP: [10.10.10.1]:53951->[192.168.100.5]',
    'version' => 1,
    'errorstatus' => 0,
    'messageid' => 0,
    'community' => 'public',
    'transactionid' => 1,
    'errorindex' => 0,
    'requestid' => 1012897136
};


%vars = {
    'IF-MIB::ifDescr' => {
        'value' => 'eth0',
        'type' => 'STRING',
        'oid' => 'IF-MIB::ifDescr'
    },
    'IF-MIB::ifAdminStatus.1' => {
        'value' => '1',
        'type' => 'INTEGER',
        'oid' => 'IF-MIB::ifAdminStatus.1'
    },
    'DISMAN-EVENT-MIB::sysUpTimeInstance' => {
        'value' => '(0) 0:00:00.00',
        'type' => 'Timeticks',
        'oid' => 'DISMAN-EVENT-MIB::sysUpTimeInstance'
    },
    'IF-MIB::ifIndex.1' => {
        'value' => '1',
        'type' => 'INTEGER',
        'oid' => 'IF-MIB::ifIndex.1'
    },
    'SNMPv2-MIB::snmpTrapOID.0' => {
        'value' => 'IF-MIB::linkUp',
        'type' => 'OID',
        'oid' => 'SNMPv2-MIB::snmpTrapOID.0'
    },
    'IF-MIB::ifOperStatus.1' => {
        'value' => '1',
        'type' => 'INTEGER',
        'oid' => 'IF-MIB::ifOperStatus.1'
    }
};

Where each OID or variable, can be treated by using the NetSNMP::OID package. Fora stdin handler, if you don’t know about perl(1), the difference is made on the snmptrapd.conf(5snmp) file, instead of configuring a global perl script which itself registers which OIDs will handle, you need to configure a global trap handler or each handler for each OID that you want to handle:


# configure inetsnmp community to allow logging,
# execution of handlers and network traffic.
authCommunity   log,execute,net         inetsnmp

traphandle     default           /usr/share/snmp/handler/defaultstding.py   default
traphandle     IF-MIB::linkUp    /usr/share/snmp/handler/ifuphandler.py     up

This will make your script or application to receive the OID data from stdin as follows:

router
UDP: [10.10.10.1]:37745->[192.168.100.5]
DISMAN-EVENT-MIB::sysUpTimeInstance 0:0:00:00.00
SNMPv2-MIB::snmpTrapOID.0 IF-MIB::linkUp
IF-MIB::ifIndex.1 1
IF-MIB::ifAdminStatus.1 up
IF-MIB::ifOperStatus.1 up
IF-MIB::ifDescr eth0

And also will require that you will enable in some manner the processing of that data as plain text.

Good luck configuring SNMP traps :)


© Daniel Molina Wegener for coder . cl, 2010. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2010/07/configuring-snmptrapd/feed/ 0
the wrong way to run… http://coder.cl/2008/06/the-wrong-way-to-run/ http://coder.cl/2008/06/the-wrong-way-to-run/#comments Thu, 26 Jun 2008 03:05:24 +0000 Daniel Molina Wegener http://coder.cl/?p=39

Today was another development nightmare day, everything seems to be cloaked in wrong events. Me under pressure and Winbloat — call it Micro$oft Windows — fails everywhere I need it working.

WTF!

In the company where I work we use some tools to validate the source that is given to the clients and coding IDEs to work around languages such as Java and .RETARD — call it .NET if you want — including Eclipse and Visual Studio. Also, there are some proprietary validation tools to use with proprietary structured text file formats out of known standards.

Events related to eclipse were things like loosing library references — jar files — and slow project compiling tasks and non-writable files after file locking actions given by the operating system — do you know I work with Micro$oft Wintendo? — and then a reboot is the only solution — I know the unlocker program, but I don’t have it installed and also I prefer a solution given from the product manufacturer. Well, the project is huge, a lot of lines of code and classes to compile and really can’t imagine a .RETARD project with similar to this, I think that is possible to get a half day compiling a .RETARD project with all those lines of code.

Looking at the proprietary validation tool, from the Yoyodine company, I get "everything is working" messages. Since I know a little about Perl and I’ve prototyped some of my work under Perl — such as acl-user-tools, a small C language project to manage users around a web hosting environment — and, just for fun, some Irssi scripts, such as Irssi Exp. I use terminal based IRC clients, since while I’m working under FreeBSD-CURRENT I need lightweight software.

Here the point turns black. Since Micro$soft Wintendo has an association registry between the file extensions and the script interpreter, I was completely wrong about calling scripts directly from the command line without giving the path to the interpreter under the non-user-friendly Wintendo Command Interpreter known as cmd.exe.


C:somewhereinthedisk > yoyodine-validator.pl < file-to-validate.txt
There isn't problems in the given file

Everything is OK and I’ve sent the software parts to the company client. The response was clear "have you validated the software?". Nothing working in the Wintendo Non-Operating System, and I get this response, since I have lunched in 20 minutes to get software validated and working at time for two weeks and two days, I was hating the non-operating system for a while with the fixed idea of kicking off my workstation.

Looking at the file association registry, the way by I was running the yoyodine-validator.pl isn’t wrong for someone who knows about scripting languages such as Perl. Under *NIX operating systems — call it *BSD or Linux — scripting languages runs using magic strings and file permissions. The magic string isn’t so different from the form "#!/path/to/interpreter" at the beginning of the script and the file permissions are execution permissions to the user that is running the script. Micro$oft Wintendo have a different way to make a script runnable.

WTF!

I have associated the perl extension and the running statement is:

WTF!

Since a perl script can have many arguments, the first thing wrong in the calling statement is number of arguments, passing just the first argument — anyone knows if the cmd.exe command line interpreter is well documented anywhere? — and the rest of the argument aren’t present in the calling statement.

If you remember the script was called using I/O redirection, inherited from *NIX systems, and these arguments aren’t passed directly to the interpreter, instead are handled by command interpreter. Since the registry calls the native Wintendo shell — known as Wintendo Explorer — it ignores the input redirection given from the command line. The result, is an input stream completely loosed. Then I think "wintendo command line shell cmd.exe and windows shell explorer.exe aren’t integrated" since you can not pass an input stream from the command line to the program launched from the Wintendo shell. Another non-documented and buggy behavior of this non-operating system.

The solution to work with similar tasks is calling the programs directly from the command line, overriding the cmd.exe pass-through-the-real-shell explorer.exe calling statements. Then we can’t emulate the *NIX magic strings and file permissions to get a script working as a native command. Somewhere I’ve seen a magic string to work with script interpreters, but "where is documented?" and "does the system comes with the proper documentation to work on these kind of tasks?".


C:pathtoanywhere > C:pathtoperl.exe yoyodine-script.pl < to-validate.txt

A single line of code changes the behavior of a script program completely. If you ask me, Micro$oft Wintendo is thinked to work with games, word processors and spreadsheets. Wasn’t thinked as *NIX as we see in "Program design in the UNIX© environment" and do not have in any manner a consideration on integration between streams connectivity. If you want to integrate any component of the non-operating system, you must write an Active X object or write similar things — a high-cost implementation for a small task — then I think that Micro$oft Wintendo isn’t an harmoniously developed operating system.

The possible reason about this behavior it’s that cmd.exe is using the ShellExecute system call, instead of using a proper way to handle I/O redirection or piping functions. If I’m true, you can’t expect the right behavior on scripts if your trying to run them under cmd.exe by using registry associations on the scripts files. Then, you must research about possible magic strings in batch commands and use the script under these terms. Meanwhile isn’t a well documented way to use language interpreters under windows, you will not be able to run scripts directly…


© Daniel Molina Wegener for coder . cl, 2008. | Permalink | No comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2008/06/the-wrong-way-to-run/feed/ 0
fighting spam in kontact (under FreeBSD) http://coder.cl/2008/04/fighting-spam-in-kontact-under-freebsd/ http://coder.cl/2008/04/fighting-spam-in-kontact-under-freebsd/#comments Tue, 22 Apr 2008 04:00:08 +0000 Daniel Molina Wegener http://coder.cl/?p=19

Hi!, I’m a KDE user and receiving some spam like any concurrent Internet user. Sometimes I was looking at Kontact menus and wow!, the Tools have a two interesting entries: Anti-Spam Wizard and Anti-Virus Wizard.

Well, the Anti-Virus Wizard seems to have no sense, but can be useful while you are forwarding mail and the Anti-Spam Wizard rocks. Here you have the steps to use Anti-Spam tools under Kontact.

First, install some Anti-Spam filters known to Kontact.


# portinstall -PP bogofilter-qdbm
# portinstall -PP p5-Mail-SpamAssassin

Then, restart Kontact (not the entire operating system like Micro$oft Winbloat) and launch the Anti-Spam Wizard and select Bogofilter and SpamAssassin X.X (Perl) (select the daemon SpamAssassin X.X (Daemon) if you share your computer with more people and you have it running. By default both, Bogofilter and SpamAssassin have the learning rules options activated.

Now, I have three anti-spam layers, the filters on my mail providers and the filters running on my workstation with a 101% of the spam filtered, since these filters blocks some spamming domains.

Try them, and have fun :D


© Daniel Molina Wegener for coder . cl, 2008. | Permalink | One comment | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2008/04/fighting-spam-in-kontact-under-freebsd/feed/ 1
procinfo-0.2 (win32 process information, updated) http://coder.cl/2007/10/procinfo-01-win32-process-information/ http://coder.cl/2007/10/procinfo-01-win32-process-information/#comments Sat, 27 Oct 2007 20:28:41 +0000 Daniel Molina Wegener http://coder.cl/?p=8 Hello, I’ve made a small program in C, using the Win32 API and PCRE (Perl Compatible Regular Expressions) library. It works as a CLI application, this means that you must use it from the windows console, also known as cmd.exe.

The sources are licenced under GPL, and also is available a binary distribution, optimized for pentium processor. The complete project is constructed under Code::Blocks, a small C/C++ IDE.

Follow the next links to download:

MD5 (procinfo-bin-0.2.tgz) = 0f841029e583fb084bd79eb7cc31d0d4
MD5 (procinfo-0.2.tgz) = b5d99e7c938bd99b1cb6c9ddcc067981

Feel free to send comments, requests and patches… have fun with the tool…

I’ve noticed that M$ Windows Vista does not handle directories with a “.bin” extension and the system takes it as a “binary” file… I’ve renamed the “binary” tarball to “-bin” xD, thanks for testing…


© Daniel Molina Wegener for coder . cl, 2007. | Permalink | 5 comments | Add to del.icio.us
Post tags:

Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported (CC BY-NC-SA 3.0)

]]>
http://coder.cl/2007/10/procinfo-01-win32-process-information/feed/ 5