ioctl FILEHANDLE, REQUEST, SCALAR
El primer argumento es el manejador de fichero, el segundo especifica que operación es la que se solicita y en el tercero es donde queda el resultado de la operación.
ioctl mediante perldoc.
ioctl mediante man
man ioctl_list
El siguiente ejemplo calcula el tamaño de la terminal usando
ioctl:
lhp@nereida:~/Lperl/src/cookbook/ch12$ cat -n winsz.pl
1 #!/usr/bin/perl
2 # winsz - find x and y for chars and pixels
3 use strict;
4 require 'sys/ioctl.ph';
5 die "no TIOCGWINSZ " unless defined &TIOCGWINSZ;
6 my $winsize;
7 open(TTY, "+</dev/tty") or die "No tty: $!";
8 unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {
9 die sprintf "$0: ioctl TIOCGWINSZ (%08x: $!)\n", &TIOCGWINSZ;
10 }
11 my ($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
12 print "(row,col) = ($row,$col)";
13 print " (xpixel,ypixel) = ($xpixel,$ypixel)" if $xpixel || $ypixel;
14 print "\n";
lhp@nereida:~/Lperl/src/cookbook/ch12$ winsz.pl
(row,col) = (26,90)
lhp@nereida:~/Lperl/src/cookbook/ch12$ stty size
26 90
Para entender el programa anterior tenga en cuenta que:
+< indica que el manejador se abre para lectura
y escritura, sin truncamiento.
ioctl con servicio
TIOCGWINSZ hace que en la variable $winsize quede
una estructura compactada describiendo el tamaño de la ventana.
unpack es usado en la línea 11 para
obtener los valores de los tamaños.
Los operadores pack y unpack permiten
compactar y descomprimir diferentes tipos. El operador
pack funciona de manera parecida
a sprintf: recibe una cadena de formato seguida
de la lista de valores a formatear. El operador unpack
realiza la operación inversa:
lhp@nereida:~/Lperl/src/cookbook/ch12$ perl -de 0 main::(-e:1): 0 DB<1> x unpack "CCC", "PP2" 0 80 1 80 2 50 DB<2> x pack "CCC", 80, 80, 50 # C = unsigned char 0 'PP2' DB<3> x pack "C3", 80, 80, 50 # C3 especificador de repetición 0 'PP2' DB<4> x pack "S2", 65281, 766 # S = 16-bit unsigned integer 0 "\cAÿp\cB" DB<5> x unpack "S2", "\cAÿp\cB" 0 65281 1 766 DB<6> x unpack "S4", "\cAÿp\cB" 0 65281 1 766
La misma ejecución del programa anterior
winsz.pl en una xterm da como resultado:
lhp@nereida:~/projects/perl/src/cookbook/ch12$ perl -d ./winsz.pl
Enter h or `h h' for help, or `man perldebug' for more help.
main::(./winsz.pl:4): require 'sys/ioctl.ph';
DB<1> !!echo $TERM
xterm
DB<2> l
4==> require 'sys/ioctl.ph';
5: die "no TIOCGWINSZ " unless defined &TIOCGWINSZ;
6: my $winsize;
7: open(TTY, "+</dev/tty") or die "No tty: $!";
8: unless (ioctl(TTY, &TIOCGWINSZ, $winsize='')) {
9: die sprintf "$0: ioctl TIOCGWINSZ (%08x: $!)\n", &TIOCGWINSZ;
10 }
11: my ($row, $col, $xpixel, $ypixel) = unpack('S4', $winsize);
12: print "(row,col) = ($row,$col)";
13: print " (xpixel,ypixel) = ($xpixel,$ypixel)" if $xpixel || $ypixel;
DB<2> b 5
DB<3> c
main::(./winsz.pl:5): die "no TIOCGWINSZ " unless defined &TIOCGWINSZ;
DB<3> x &TIOCGWINSZ
0 21523
DB<4> c
(row,col) = (52,166) (xpixel,ypixel) = (1017,687)
La forma normal de obtener en Perl el tamaño de la ventana es
usando el módulo Term::ReadKey:
lhp@nereida:~/Lperl/src/cookbook/ch12$ perl -de 0 DB<1> use Term::ReadKey DB<2> x GetTerminalSize() 0 80 # ancho en caracteres 1 24 # largo en caracteres 2 499 # ancho en pixels 3 316 # largo en pixels
Casiano Rodríguez León
