#include <sys/time.h>
#include <signal.h>

#define mask(s) (1<<((s)-1))
#define setvec(vec, a) \
        vec.sv_handler = a; vec.sv_mask = vec.sv_onstack = 0

static int ringring;


nap(n)
	unsigned n;
/*
** Sleep for 'n' Hz (60ths of a second).
** (Be aware that the Sun II timer has a granularity of about 20 milliseconds.)
*/
{
        int napx(), omask;
        struct itimerval itv, oitv;
        register struct itimerval *itp = &itv;
        struct sigvec vec, ovec;

        if (n == 0)
                return;
        timerclear(&itp->it_interval);
        timerclear(&itp->it_value);
        if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
                return;
        setvec(ovec, SIG_DFL);
        omask = sigblock(mask(SIGALRM));
        itp->it_value.tv_sec = n/60;
	itp->it_value.tv_usec = (n%60)*1000000/60;
        if (timerisset(&oitv.it_value)) {
		if (oitv.it_value.tv_sec >= itp->it_value.tv_sec)
		{
		    if (oitv.it_value.tv_sec == itp->it_value.tv_sec &&
		    	oitv.it_value.tv_usec > itp->it_value.tv_usec)
			    oitv.it_value.tv_usec -= itp->it_value.tv_usec;
                        oitv.it_value.tv_sec -= itp->it_value.tv_sec;
		}
                else {
                        itp->it_value = oitv.it_value;
                        /*
                         * This is a hack, but we must have time to
                         * return from the setitimer after the alarm
                         * or else it'll be restarted.  And, anyway,
                         * sleep never did anything more than this before.
                         */
                        oitv.it_value.tv_sec = 1;
                        oitv.it_value.tv_usec = 0;
                }
        }
        setvec(vec, napx);
        ringring = 0;
        (void) sigvec(SIGALRM, &vec, &ovec);
        (void) setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
        while (!ringring)
                sigpause(omask &~ mask(SIGALRM));
        (void) sigvec(SIGALRM, &ovec, (struct sigvec *)0);
        (void) setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
}

static napx() { ringring = 1; }
