diff --git a/main.c b/main.c index bf08424..408034b 100644 --- a/main.c +++ b/main.c @@ -45,6 +45,7 @@ static const char *valid_mode[] = {"block", "delay", NULL}; static volatile sig_atomic_t running = 1; static volatile sig_atomic_t cleanup_requested = 0; static int quiet = 0; +static int daemonize = 0; static void handle_sig(int sig) { (void)sig; @@ -347,7 +348,7 @@ static void usage(FILE *f, const char *prog) { fprintf(f, "Usage: %s -n [-n ...] " "[--what=WHAT] [--mode=MODE]\n" - " [--who=WHO] [--why=WHY] [--poll=SECONDS] [-q]\n" + " [--who=WHO] [--why=WHY] [--poll=SECONDS] [-d] [-q]\n" "\n" "Options:\n" " -n, --name PATTERN Process command-line substring to watch " @@ -365,6 +366,7 @@ static void usage(FILE *f, const char *prog) { "system idle...)\n" " --poll SECONDS Poll interval in seconds (%.1f-%.1f, " "default: %.1f)\n" + " -d, --daemon Run as daemon (fork to background)\n" " -q, --quiet Suppress informational output\n" " -h, --help Show this help\n" " -v, --version Show version\n", @@ -394,6 +396,63 @@ static void *safe_realloc(void *ptr, size_t new_size) { return new_ptr; } +// Daemonize the process +static int do_daemonize(void) { + pid_t pid = fork(); + if (pid < 0) { + fprintf(stderr, "fork failed: %s\n", strerror(errno)); + return -1; + } + + if (pid > 0) { + // Parent exits + exit(EXIT_OK); + } + + // Child continues + if (setsid() < 0) { + fprintf(stderr, "setsid failed: %s\n", strerror(errno)); + return -1; + } + + // Ignore SIGHUP + signal(SIGHUP, SIG_IGN); + + // Fork again to ensure we're not a session leader + pid = fork(); + if (pid < 0) { + fprintf(stderr, "second fork failed: %s\n", strerror(errno)); + return -1; + } + + if (pid > 0) { + // First child exits + exit(EXIT_OK); + } + + // Change to root directory + if (chdir("/") < 0) { + fprintf(stderr, "chdir failed: %s\n", strerror(errno)); + return -1; + } + + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + + int fd = open("/dev/null", O_RDWR); + if (fd >= 0) { + dup2(fd, STDIN_FILENO); + dup2(fd, STDOUT_FILENO); + dup2(fd, STDERR_FILENO); + if (fd > STDERR_FILENO) { + close(fd); + } + } + + return 0; +} + int main(int argc, char **argv) { double poll = DEFAULT_POLL_INTERVAL; const char *what = "idle"; @@ -497,6 +556,9 @@ int main(int argc, char **argv) { } else if (strcmp(argv[i], "--quiet") == 0 || strcmp(argv[i], "-q") == 0) { quiet = 1; + } else if (strcmp(argv[i], "--daemon") == 0 || strcmp(argv[i], "-d") == 0) { + daemonize = 1; + } else if (argv[i][0] == '-' && argv[i][1] == 'n' && argv[i][2] != '\0') { // Support "-npattern" form if (npats >= MAX_PATTERNS) { @@ -550,6 +612,15 @@ int main(int argc, char **argv) { strerror(errno)); } + // Daemonize before initializing inhibitor (must happen before D-Bus + // connection) + if (daemonize) { + if (do_daemonize() < 0) { + free(patterns); + return EXIT_INIT; + } + } + struct Inhibitor inh; if (inhibitor_init(&inh, what, who, why, mode) < 0) { free(patterns);