3 #include <fcntl.h> /* FASYNC */
4 #ifdef USG /* FASYNC for SysV */
7 #include <sys/time.h> /* itimer */
8 #include <sys/types.h> /* time_t */
11 extern char *sys_errlist
[], *malloc();
15 #define FS 1 /* field seperator for input */
22 int slot
; /* The next open place in the events array */
23 int mevent
= 0; /* 1+ the highest event number */
24 char *pname
; /* programme name for error messages */
26 /* Accepts a string of two fields seperated by a ';'
27 * First field is string for getdate, saying when to wake-up.
28 * Second field is a token to identify the request.
35 extern time_t getdate();
36 extern char *strcpy();
39 static struct event e
;
41 for(p
= str
; *p
&& *p
!= FS
; p
++);
43 (void)fprintf(stderr
, "%s: bad input format: %s", pname
, str
);
44 return((struct event
*)NULL
);
48 if ((e
.reply_at
= get_date(str
, NULL
)) - time(&now
) < 0) {
49 (void)fprintf(stderr
, "%s: bad time spec: %s%c%s", pname
, str
, FS
, p
);
50 return((struct event
*)NULL
);
53 if ((e
.token
= malloc((unsigned)strlen(p
) + 1)) == NULL
) {
54 (void)fprintf(stderr
, "%s: malloc %s: %s%c%s",
55 pname
, sys_errlist
[errno
], str
, FS
, p
);
56 return((struct event
*)NULL
);
58 (void)strcpy(e
.token
,p
);
68 register int i
, newmax
= 0;
69 /* I prefer using the interval timer rather than alarm(); the latter
70 could be substituted if portability requires it. */
71 struct itimerval itimer
;
73 now
= time((time_t *)NULL
);
75 itimer
.it_interval
.tv_sec
= itimer
.it_interval
.tv_usec
= 0;
76 itimer
.it_value
.tv_usec
= 0;
77 itimer
.it_value
.tv_sec
= -1;
79 for(i
=0; i
< mevent
; i
++) {
80 while (events
[i
] && events
[i
]->reply_at
<= now
) {
81 (void)fputs(events
[i
]->token
, stdout
);
82 free(events
[i
]->token
);
83 free((char *)events
[i
]);
89 if ((tdiff
= events
[i
]->reply_at
- now
) < (time_t)itimer
.it_value
.tv_sec
90 || itimer
.it_value
.tv_sec
< 0)
92 itimer
.it_value
.tv_sec
= (long)tdiff
;
94 /* Keep slot as the lowest unused events element */
95 if (i
< slot
) slot
= i
;
98 /* if the array is full to mevent, slot should be the next available spot */
99 if (slot
> (mevent
= newmax
)) slot
= mevent
;
100 /* If there's no more events, SIGIO should be next wake-up */
101 if (mevent
) (void)setitimer(ITIMER_REAL
, &itimer
, (struct itimerval
*)NULL
);
108 extern char *fgets();
112 /* in principle the itimer should be disabled on entry to this function,
113 but it really doesn't make any important difference if it isn't */
115 if (fgets(buf
, sizeof(buf
), stdin
) == NULL
) exit(0);
117 if (slot
== MAXEVENTS
)
118 (void)fprintf(stderr
, "%s: too many events: %s", pname
, buf
);
121 if ((events
[slot
] = (struct event
*)malloc((sizeof(struct event
))))
123 (void)fprintf(stderr
,"%s: malloc %s: %s", pname
, sys_errlist
[errno
],buf
);
126 if ((ep
= schedule(buf
)) == NULL
)
127 free((char *)events
[slot
]), events
[slot
] = 0;
130 memcpy((char *)events
[slot
],(char *)ep
,sizeof(struct event
));
131 if (slot
== mevent
) mevent
++;
135 /* timing, timing. Who knows what this interrupted, or if it said "now"? */
146 for (pname
= argv
[0] + strlen(argv
[0]); *pname
!= '/' && pname
!= argv
[0];
148 if (*pname
== '/') pname
++;
150 (void)signal(SIGIO
, getevent
);
151 (void)signal(SIGALRM
, notify
);
152 (void)fcntl(0, F_SETFL
, FASYNC
);