sin: add daemon mode for forked processes

Signed-off-by: NotAShelf <raf@notashelf.dev>
Change-Id: Iefbc9a8ac320f6a8898dc4b00cdb08316a6a6964
This commit is contained in:
raf 2025-12-04 17:11:36 +03:00
commit 8ebde6a45c
Signed by: NotAShelf
GPG key ID: 29D95B64378DB4BF

73
main.c
View file

@ -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 <pattern> [-n <pattern> ...] "
"[--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);