#include "prjlibs-include/standards.h"
#include <sys/time.h>
#include <unistd.h>
#include <errno.h>
#include <limits.h>
#include <signal.h>
#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], ": ");
}
syntax highlighted by Code2HTML, v. 0.9.1