/* * 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); }