#include "prjlibs-include/standards.h" #include #include #include #include #include #include "skalibs/include/stddjb.h" #include "prjlibs-include/constants.h" #include "runwhen.h" char const* PROG="delayrun"; static void alarm_handler(int sig) { (void)sig; } static struct sigaction action; static char const var_delay[]="$DELAY"; int main(int argc, char** argv) { sigset_t alarmset; sigset_t blockset; unsigned long delay=0; char const* x; /* set up sigset containing SIGALRM */ if (sigemptyset(&alarmset)!=0) strerr_die5sys(100, PROG, err_unable, err_empty, err_sigset, ": "); if (sigaddset(&alarmset, SIGALRM)!=0) strerr_die5sys(100, PROG, err_unable, err_addto, err_sigset, ": "); /* block SIGALRM ASAP */ if (sigprocmask(SIG_BLOCK, &alarmset, &blockset)!=0) strerr_die4sys(100, PROG, err_unable, err_sigmask, ": "); /* initialize SIGALRM action, for catching or ignoring later */ if (sigemptyset(&action.sa_mask)!=0) strerr_die5sys(100, PROG, err_unable, err_empty, err_sigset, ": "); action.sa_flags=0; /* scan delay time */ x=env_get(var_delay+1); if (x!=null) { unsigned int const len=scan_ulong(x, &delay); if (len==0 || x[len]!='\0') strerr_die4x(111, PROG, ": ", var_delay, err_malformed); if (delay>LONG_MAX) strerr_die5x(100, PROG, ": ", var_delay, err_oflow, "long"); } if (x==null || delay!=0) { /* do we need to sleep? */ { /* schedule SIGALRM */ struct itimerval timer; timer.it_interval.tv_sec=0; timer.it_interval.tv_usec=0; timer.it_value.tv_sec=delay; timer.it_value.tv_usec=0; if (setitimer(ITIMER_REAL, &timer, null)!=0) strerr_die4sys(100, PROG, err_unable, err_timer, ": "); } /* catch SIGALRM */ action.sa_handler=alarm_handler; if (sigaction(SIGALRM, &action, null)!=0) strerr_die4sys(100, PROG, err_unable, err_sigact, ": "); /* sleep */ if (sigdelset(&blockset, SIGALRM)!=0) strerr_die5sys(100, PROG, err_unable, err_delfrom, err_sigset, ": "); if (sigsuspend(&blockset)!=0 && errno!=EINTR) strerr_die4sys(100, PROG, err_unable, err_suspend, ": "); } /* ignore and unblock SIGALRM */ action.sa_handler=SIG_IGN; if (sigaction(SIGALRM, &action, null)!=0) strerr_die4sys(100, PROG, err_unable, err_sigact, ": "); if (sigprocmask(SIG_UNBLOCK, &alarmset, null)!=0) strerr_die4sys(100, PROG, err_unable, err_sigmask, ": "); if (argc<2) _exit(0); ++argv; pathexec_run(argv[0], (char const**)argv, (char const**)environ); strerr_die5sys(errstat, PROG, err_unable, err_exec, argv[0], ": "); }