/*
* noblank.c:
* a wrapper for applications and/or games that lack support
* for xscreensaver. deactivates every 60 seconds by default,
* tunable with the NOBLANK_INTERVAL env variable.
*
* Compiling:
* gcc noblank.c -o noblank
*
* Usage:
* noblank quake3 +disconnect +set fs_game arena
* noblank nwn
*
* Related:
* http://www.jwz.org/xscreensaver/faq.html#dvd
*
* Mike Hokenson
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
static int do_callback = 0;
static int do_exit = 0;
void sighandler(int sig)
{
switch (sig) {
case SIGALRM:
do_callback = 1;
break;
case SIGCHLD:
do_exit = 1;
break;
default:
break;
}
}
int main(int argc, char *argv[])
{
int interval = 60;
char *e;
pid_t pid;
if (argc < 2) {
fprintf(stderr, "Usage: %s command [ arg ... ]\n", argv[0]);
exit(1);
}
if ((e = getenv("NOBLANK_INTERVAL")) && *e) {
int n = atoi(e);
if (n > 0)
interval = n;
}
argv++;
argc--;
pid = fork();
switch (pid) {
case 0: /* child */
if (execvp(*argv, argv) == -1) {
fprintf(stderr, "Failed to execute '%s': %s\n", *argv, strerror(errno));
usleep(25000); /* long enough for sighandler to be installed below */
_exit(1);
}
_exit(0);
case -1: /* error */
fprintf(stderr, "Failed to create new process: %s\n", strerror(errno));
exit(1);
default: /* parent */
break;
}
signal(SIGALRM, sighandler);
signal(SIGCHLD, sighandler);
alarm(interval);
while (1) {
struct timeval tv;
if (do_exit)
break;
if (do_callback) {
signal(SIGCHLD, SIG_IGN);
system("xscreensaver-command -deactivate > /dev/null 2>&1");
signal(SIGCHLD, sighandler);
do_callback = 0;
alarm(interval);
if (kill(pid, 0)) /* check if the process has exited */
break;
}
tv.tv_sec = 0;
tv.tv_usec = 25000;
select(0, 0, NULL, NULL, &tv);
}
alarm(0);
wait(NULL);
exit(0);
}