summaryrefslogtreecommitdiff
path: root/reference/C/CONTRIB/OR_USING_C/e.1.c
blob: 09f4a742ac90c4134adfb285e105b9a62af6746e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <sys/time.h>
#include <signal.h>

#define setvec(vec, a) \
            vec.sv_handler = a; \
            vec.sv_mask = vec.sv_flags = 0

static int ringring;

nap(n)
unsigned n;
{
    void napx();
    int omask;
    struct sigvec vec, ovec;
    struct itimerval itv, oitv;
    register struct itimerval *itp = &itv;

    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(sigmask(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 will restart.
             * And, anyway, sleep never did more than this before.
             */
            oitv.it_value.tv_sec = 1;
            oitv.it_value.tv_usec = 0;
        }
    }
    setvec(vec, napx);
    ringring = 0;
    sigvec(SIGALRM, &vec, &ovec);
    setitimer(ITIMER_REAL, itp, (struct itimerval *)0);
    while (!ringring)
        sigpause(omask &~ sigmask(SIGALRM));
    sigvec(SIGALRM, &ovec, (struct sigvec *)0);
    setitimer(ITIMER_REAL, &oitv, (struct itimerval *)0);
    sigsetmask(omask);
}

static void
napx()
{
    ringring = 1;
}