Skip to content

Instantly share code, notes, and snippets.

@ghedo
Last active July 5, 2020 10:21
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save ghedo/4118543 to your computer and use it in GitHub Desktop.
Save ghedo/4118543 to your computer and use it in GitHub Desktop.
Execute a command after some time of inactivity
/*
* Execute a command after some time of inactivity
*
* Compile:
* $ cc -o sleepd sleepd.c
*
* Usage:
* $ ./sleepd -t 600 -c "slock"
*
* NOTE: to run this as a normal (non-root) user you may need to change
* /dev/input/event* devices permissions, e.g. using udev:
*
* KERNEL=="event*", NAME="input/%k", MODE="644", GROUP="input"
*
* then create the group "input" and add your user to it. Be aware that this
* may have security implications, particularly on shared boxes.
*
* Copyright (C) 2012 Alessandro Ghedini <alessandro@ghedini.me>
* --------------------------------------------------------------
* "THE BEER-WARE LICENSE" (Revision 42):
* Alessandro Ghedini wrote this file. As long as you retain this
* notice you can do whatever you want with this stuff. If we
* meet some day, and you think this stuff is worth it, you can
* buy me a beer in return.
* --------------------------------------------------------------
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <getopt.h>
#include <unistd.h>
#include <sys/select.h>
#include <sys/types.h>
fd_set ev;
int devs[128];
void init_ev() {
int i = 0;
FD_ZERO(&ev);
do {
int fd;
char dev_name[128];
snprintf(dev_name, 127, "/dev/input/event%d", i++);
fd = open(dev_name, O_RDONLY);
if (fd < 0) break;
devs[i] = fd;
FD_SET(fd, &ev);
} while (1);
}
void clean_ev() {
int i;
for (i = 0; i < 128; i++)
close(devs[i]);
}
void usage(char *name) {
fprintf(stderr, "Usage: %s -t <timeout> -c <command>\n", name);
exit(-1);
}
int main(int argc, char *argv[]) {
char *cmd = NULL;
int opt, timeout = 0, enabled = 1;
struct timeval tv;
while ((opt = getopt(argc, argv, "c:t:")) != -1) {
switch (opt) {
case 'c':
cmd = strdup(optarg);
break;
case 't':
timeout = atoi(optarg);
break;
default:
usage(argv[0]);
}
}
if ((timeout == 0) || (cmd == NULL))
usage(argv[0]);
while (1) {
int rc;
init_ev();
tv.tv_sec = timeout;
tv.tv_usec = 0;
rc = select(FD_SETSIZE, &ev, NULL, NULL, &tv);
switch (rc) {
case -1: {
perror("sleepd");
return -1;
}
case 0: {
if (enabled) {
enabled = 0;
system(cmd);
}
break;
}
default: {
enabled = 1;
break;
}
}
clean_ev();
}
return 0;
}
@clort81
Copy link

clort81 commented Jul 5, 2020

I was looking for how to do exactly this. Muchas Gracias!

[EDIT] using xterm and putting sleepd into background, it starts after delay, regardless of term activity.

I want to only trigger my program if I am idle on keyboard > X seconds.

./sleepd -t 6 -c "./oldthugs"&

Any ideas how to do this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment