*** empty log message ***
[emacs.git] / lib-src / timer.c
blobd7084bfcdc4c9c87d3577f65d40ef374ddcb7c2a
1 #include <stdio.h>
2 #include <signal.h>
3 #include <fcntl.h> /* FASYNC */
4 #ifdef USG /* FASYNC for SysV */
5 #include <sys/file.h>
6 #endif
7 #include <sys/time.h> /* itimer */
8 #include <sys/types.h> /* time_t */
10 extern int errno;
11 extern char *sys_errlist[], *malloc();
12 extern time_t time();
14 #define MAXEVENTS 256
15 #define FS 1 /* field seperator for input */
17 struct event {
18 char *token;
19 time_t reply_at;
20 } *events[MAXEVENTS];
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.
30 struct event *
31 schedule(str)
32 char *str;
35 extern time_t getdate();
36 extern char *strcpy();
37 time_t now;
38 register char *p;
39 static struct event e;
41 for(p = str; *p && *p != FS; p++);
42 if (!*p) {
43 (void)fprintf(stderr, "%s: bad input format: %s", pname, str);
44 return((struct event *)NULL);
46 *p++ = 0;
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);
60 return(&e);
63 void
64 notify()
67 time_t now, tdiff;
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);
74 slot = mevent;
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]);
84 events[i] = 0;
87 if (events[i]) {
88 newmax = i+1;
89 if ((tdiff = events[i]->reply_at - now) < (time_t)itimer.it_value.tv_sec
90 || itimer.it_value.tv_sec < 0)
91 /* next timeout */
92 itimer.it_value.tv_sec = (long)tdiff;
93 } else {
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);
104 void
105 getevent()
108 extern char *fgets();
109 struct event *ep;
110 char buf[256];
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);
120 else {
121 if ((events[slot] = (struct event *)malloc((sizeof(struct event))))
122 == NULL)
123 (void)fprintf(stderr,"%s: malloc %s: %s", pname, sys_errlist[errno],buf);
125 else {
126 if ((ep = schedule(buf)) == NULL)
127 free((char *)events[slot]), events[slot] = 0;
129 else {
130 memcpy((char *)events[slot],(char *)ep,sizeof(struct event));
131 if (slot == mevent) mevent++;
132 } /* schedule */
133 } /* malloc */
134 } /* limit events */
135 /* timing, timing. Who knows what this interrupted, or if it said "now"? */
136 notify();
139 /*ARGSUSED*/
141 main(argc, argv)
142 int argc;
143 char **argv;
146 for (pname = argv[0] + strlen(argv[0]); *pname != '/' && pname != argv[0];
147 pname--);
148 if (*pname == '/') pname++;
150 (void)signal(SIGIO, getevent);
151 (void)signal(SIGALRM, notify);
152 (void)fcntl(0, F_SETFL, FASYNC);
154 while (1) pause();