Você poderia fazer isso com um pouco de magia C (qualquer outra linguagem de programação que suporte as funções necessárias também será boa). O que você precisa fazer é:
- abra todos os dispositivos de evento
input
(tudo que corresponda a/dev/input/event[0-9]*
) - tem
select(2)
chamado nesses dispositivos, aguardando entrada, com um tempo limite apropriado (seu período ocioso)- no tempo limite: nada aconteceu: inicie seu programa
- se a entrada estiver pronta: algo aconteceu: mate seu programa, se estiver executando
-
read(2)
de entrada de todos os dispositivos, por isso, a próxima chamadaselect(2)
não retornará imediatamente
Um exemplo rápido em C ficaria assim:
#include <sys/select.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <glob.h>
#include <stdlib.h>
#include <stdio.h>
int
main(int argc, char *argv[])
{
int *fds, ret, i;
glob_t glob_result;
/* find all devices matching /dev/input/event[0-9]* */
ret = glob("/dev/input/event[0-9]*", GLOB_ERR|GLOB_NOSORT|GLOB_NOESCAPE, NULL, &glob_result);
if (ret)
err(EXIT_FAILURE, "glob");
/* allocate array for opened file descriptors */
fds = malloc(sizeof(*fds) * (glob_result.gl_pathc+1));
if (fds == NULL)
err(EXIT_FAILURE, "malloc");
/* open devices */
for (i = 0; i < glob_result.gl_pathc; i++) {
fds[i] = open(glob_result.gl_pathv[i], O_RDONLY|O_NONBLOCK);
if (fds[i] == -1)
err(EXIT_FAILURE, "open '%s'", glob_result.gl_pathv[i]);
}
fds[i] = -1; /* end of array */
for (;;) {
char buf[512];
struct timeval timeout;
fd_set readfds;
int nfds = -1;
FD_ZERO(&readfds);
/* select(2) might alter the fdset, thus freshly set it
on every iteration */
for (i = 0; fds[i] != -1; i++) {
FD_SET(fds[i], &readfds);
nfds = fds[i] >= nfds ? fds[i] + 1 : nfds;
/* read everything what's available on this fd */
while ((ret = read(fds[i], buf, sizeof(buf))) > 0)
continue; /* read away input */
if (ret == -1 && errno != EAGAIN)
err(EXIT_FAILURE, "read");
}
/* same for timeout, 5 seconds here */
timeout.tv_sec = 5; /* FIXME */
timeout.tv_usec = 0;
ret = select(nfds, &readfds, NULL, NULL, &timeout);
if (ret == -1)
err(EXIT_FAILURE, "select");
if (ret == 0)
printf("Timeout: start first script\n");
} else {
printf("No timeout: start second script\n");
}
}
return 0;
}
Este exemplo aguardaria a entrada indefinidamente. Se após 5 segundos nenhuma entrada for recebida, imprimirá "Tempo limite:…", se a entrada for recebida "Sem tempo limite:…"
Para ler mais (você deseja executar e eliminar processos, por exemplo), consulte fork(2)
, exec(2)
e kill(2)
, respectivamente. Como mencionado anteriormente, cada linguagem que permite executar select(2)
em arquivos seria suficiente, então você também pode fazer isso em Python, Ruby ou algo parecido.
Observação: Esse é apenas um exemplo, haveria outras coisas a serem atendidas. Por exemplo, isso imprime "Timeout" a cada 5 segundos, não apenas uma vez até que a entrada seja recebida, da mesma forma "Sem timeout" aparece em todos os movimentos da tecla / mouse .
Além disso, isso precisa ser executado como root
, pois os dispositivos de evento input
não são legíveis por ninguém por motivos óbvios.