logo

cmd-timer

run command at a specific interval git clone https://anongit.hacktivis.me/git/cmd-timer.git
commit: c93bd81010be5bde922ad54271f53d04549b6ec1
parent 378169e980db0bf73bd4e258c686622150be6383
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Wed, 18 Jun 2025 16:07:01 +0200

exits when child process returns non-zero

Diffstat:

Mtimer.c63++++++++++++++++++++++++++++++++++++++++++++++-----------------
1 file changed, 46 insertions(+), 17 deletions(-)

diff --git a/timer.c b/timer.c @@ -5,14 +5,15 @@ #include "strtodur.h" #include <errno.h> -#include <limits.h> // UINT_MAX -#include <signal.h> // sigaction -#include <spawn.h> // posix_spawnp -#include <stdio.h> // fprintf, fputs -#include <stdlib.h> // exit -#include <string.h> // strerror -#include <time.h> // timer_create -#include <unistd.h> // sleep +#include <limits.h> // UINT_MAX +#include <signal.h> // sigaction +#include <spawn.h> // posix_spawnp +#include <stdio.h> // fprintf, fputs +#include <stdlib.h> // exit +#include <string.h> // strerror +#include <sys/wait.h> // waitpid +#include <time.h> // timer_create +#include <unistd.h> // sleep extern char **environ; static char **args; @@ -33,6 +34,17 @@ sig_timer(int sig) } static void +sig_chld(int sig) +{ + int chld_stat = 0; + waitpid((pid_t)-1, &chld_stat, WNOHANG); + + if(!WIFEXITED(chld_stat)) return; + + if(WEXITSTATUS(chld_stat) != 0) exit(WEXITSTATUS(chld_stat)); +} + +static void bad_usage() { fputs("Usage: timer <interval> <command> [arguments...]\n", stderr); @@ -67,21 +79,25 @@ main(int argc, char *argv[]) argc--; argv++; - struct sigaction sa; - sa.sa_handler = &sig_timer; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; + struct sigaction sa_alrm; + sa_alrm.sa_handler = &sig_timer; + sigemptyset(&sa_alrm.sa_mask); + sa_alrm.sa_flags = SA_RESTART; - if(sigaction(SIGALRM, &sa, NULL) != 0) + if(sigaction(SIGALRM, &sa_alrm, NULL) != 0) { fprintf(stderr, "timer: error: Failed registering signal handler: %s\n", strerror(errno)); return 1; } - errno = 0; - if(signal(SIGCHLD, SIG_IGN) == SIG_ERR) + struct sigaction sa_chld; + sa_chld.sa_handler = &sig_chld; + sigemptyset(&sa_chld.sa_mask); + sa_chld.sa_flags = SA_RESTART; + + if(sigaction(SIGCHLD, &sa_chld, NULL) != 0) { - fprintf(stderr, "timer: error: Failed setting to ignore SIGCHLD: %s\n", strerror(errno)); + fprintf(stderr, "timer: error: Failed registering signal handler: %s\n", strerror(errno)); return 1; } @@ -109,7 +125,20 @@ main(int argc, char *argv[]) args = argv; - while(sigsuspend(&sa.sa_mask)) + sigset_t sigmask; + sigfillset(&sigmask); + if(sigdelset(&sigmask, SIGALRM) != 0) + { + fprintf(stderr, "timer: error: Failed adding SIGALARM to new sigmask: %s\n", strerror(errno)); + return 1; + } + if(sigdelset(&sigmask, SIGCHLD) != 0) + { + fprintf(stderr, "timer: error: Failed adding SIGCHLD to new sigmask: %s\n", strerror(errno)); + return 1; + } + + while(sigsuspend(&sigmask)) ; return 0;