Here's how you can do it with
Inline under linux (the only OS I tested). You need the appropriate perms to the console so YMMV (also, most error checking removed for brevity sake).
(original Inline code)
#!/usr/bin/perl
use Inline C;
use strict;
toggle_lights();
__END__
__C__
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/kd.h>
#define ERROR -1
void toggle_lights() {
int fd;
int i = 0;
long int orig = 0;
if ((fd = open("/dev/console", O_NOCTTY)) == ERROR) {
perror("cannot open console");
exit(ERROR);
}
ioctl(fd, KDGETLED, &orig);
i |= LED_NUM;
ioctl(fd, KDSETLED, i);
sleep( 2 );
i = 0;
i |= LED_CAP;
ioctl(fd, KDSETLED, i);
sleep( 2 );
i = 0;
i |= LED_SCR;
ioctl(fd, KDSETLED, i);
sleep( 2 );
ioctl(fd, KDSETLED, orig);
}
-derby
Update: Whoa! I forgot that ioctl is normally available under
pure perl. I hade to steal the KD_* and LED_* constants from the include file but
it works fine.
(buggy pure perl code)
#!/usr/bin/perl
require "sys/ioctl.ph";
open( FH, "/dev/console" ) ||
die "cannot open console";
$KDSETLED = 0x4B32;
$KDGETLED = 0x4B31;
$LED_SCR = 0x01;
$LED_NUM = 0x02;
$LED_CAP = 0x04;
ioctl(FH, $KDGETLED, $orig);
$i = 0;
$i |= $LED_NUM;
ioctl(FH, $KDSETLED, $i);
sleep( 2 );
$i = 0;
$i |= $LED_CAP;
ioctl(FH, $KDSETLED, $i);
sleep( 2 );
$i = 0;
$i |= $LED_SCR;
ioctl(FH, $KDSETLED, $i);
sleep( 2 );
ioctl(FH, $KDSETLED, $orig);
Update (again): Noticed a small bug in the above perl code when
resetting the lights back to original. Here it is again:
#!/usr/bin/perl
require "sys/ioctl.ph";
open( FH, "/dev/console" ) ||
die "cannot open console";
$KDSETLED = 0x4B32;
$KDGETLED = 0x4B31;
$LED_NUM = 0x02;
$LED_CAP = 0x04;
$LED_SCR = 0x01;
ioctl(FH, $KDGETLED, $orig);
@ary = unpack("ccccs",$orig);
foreach $state ( $LED_NUM, $LED_CAP, $LED_SCR, $ary[0] ) {
$i = 0;
$i |= $state;
ioctl(FH, $KDSETLED, $i);
sleep( 2 );
}