#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="rw-wake";
static void alarm_handler(int sig) { (void)sig; }
int main(int argc, char** argv) {
struct itimerval timer;
struct sigaction action;
sigset_t alarmset;
sigset_t blockset;
int flag_sleep;
if (argc<2)
strerr_die3x(100, usage, PROG, " {stamp|-} program [arg...]");
/* 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, ": ");
/* figure out how long to sleep */
if (argv[1][0]=='-' && argv[1][1]=='\0') {
flag_sleep=1;
timer.it_value.tv_sec=0;
timer.it_value.tv_usec=0;
} else {
struct taia now, wake_time;
taia_now(&now);
rw_scan(&wake_time, argv[1]);
if (taia_less(&wake_time, &now)) flag_sleep=0;
else {
taia_sub(&wake_time, &wake_time, &now);
if (timeval_from_taia_relative(&timer.it_value, &wake_time)==0)
strerr_die4x(100, PROG, ": sleep time", err_oflow, "timeval");
flag_sleep=1;
}
}
/* 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;
if (flag_sleep) {
/* schedule SIGALRM */
timer.it_interval.tv_sec=0;
timer.it_interval.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, ": ");
argv+=2;
pathexec0_run((char const**)argv, (char const**)environ);
strerr_die5sys(errstat, PROG, err_unable, err_exec, argv[0], ": ");
}
syntax highlighted by Code2HTML, v. 0.9.1