#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="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], ": "); }