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