#include #include #include #include #include #include #include #include #define BLOCK_SIZE 512 #define STRNCMP(s, cs) strncmp(s, cs, strlen(cs)) int execute_shell_script() { char *home = getenv("HOME"); if (!home) { fprintf(stderr, "No home environment variable."); return 1; } char script_path[4096]; snprintf(script_path, sizeof(script_path) - 1, "%s/.xmonad/configure-displays", home); int f = fork(); if (f == 0) { // child process. execl(script_path, script_path, "change", NULL); perror("Exec failed"); exit(1); } else { if (f == -1) { perror("Forking failed"); return 1; } else { waitpid(f, NULL, 0); } } return 0; } int main() { struct udev *udev; struct udev_device *dev; struct udev_monitor *mon; int fd; udev = udev_new(); if (!udev) { fprintf(stderr, "Cannot create new udev context\n"); return 1; } mon = udev_monitor_new_from_netlink(udev, "udev"); udev_monitor_filter_add_match_subsystem_devtype(mon, "drm", NULL); udev_monitor_enable_receiving(mon); fd = udev_monitor_get_fd(mon); int found_event = 0; while (1) { fd_set fds; struct timeval to = {0}; if (found_event) { to.tv_usec = 100000; } int ret; FD_ZERO(&fds); FD_SET(fd, &fds); ret = select(fd + 1, &fds, NULL, NULL, found_event ? &to : NULL); if (ret > 0 && FD_ISSET(fd, &fds)) { dev = udev_monitor_receive_device(mon); if (dev) { if (STRNCMP(udev_device_get_action(dev), "change") == 0) { printf("I: Change detected.\n"); found_event = 1; // Still need to clean up some trailing detected changes. } } } else if (ret == 0 && found_event) { printf("Executing shell script hook.\n"); if (execute_shell_script()) { fprintf(stderr, "Unable to execute shell script."); }; found_event = 0; } } }