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
