Mercurial > emacs
comparison lib-src/=timer.c @ 45:a55a3ac41924
Initial revision
author | root <root> |
---|---|
date | Sat, 20 Jan 1990 04:04:04 +0000 |
parents | |
children | 1aa96958b728 |
comparison
equal
deleted
inserted
replaced
44:a25bf36b0410 | 45:a55a3ac41924 |
---|---|
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 */ | |
9 | |
10 extern int errno; | |
11 extern char *sys_errlist[], *malloc(); | |
12 extern time_t time(); | |
13 | |
14 #define MAXEVENTS 256 | |
15 #define FS 1 /* field seperator for input */ | |
16 | |
17 struct event { | |
18 char *token; | |
19 time_t reply_at; | |
20 } *events[MAXEVENTS]; | |
21 | |
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 */ | |
25 | |
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. | |
29 */ | |
30 struct event * | |
31 schedule(str) | |
32 char *str; | |
33 | |
34 { | |
35 extern time_t getdate(); | |
36 extern char *strcpy(); | |
37 time_t now; | |
38 register char *p; | |
39 static struct event e; | |
40 | |
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); | |
45 } | |
46 *p++ = 0; | |
47 | |
48 if ((e.reply_at = getdate(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); | |
51 } | |
52 | |
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); | |
57 } | |
58 (void)strcpy(e.token,p); | |
59 | |
60 return(&e); | |
61 } | |
62 | |
63 void | |
64 notify() | |
65 | |
66 { | |
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; | |
72 | |
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; | |
78 | |
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; | |
85 } | |
86 | |
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; | |
96 } | |
97 } | |
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); | |
102 } | |
103 | |
104 void | |
105 getevent() | |
106 | |
107 { | |
108 extern char *memcpy(), *fgets(); | |
109 struct event *ep; | |
110 char buf[256]; | |
111 | |
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 */ | |
114 | |
115 if (fgets(buf, sizeof(buf), stdin) == NULL) exit(0); | |
116 | |
117 if (slot == MAXEVENTS) | |
118 (void)fprintf(stderr, "%s: too many events: %s", pname, buf); | |
119 | |
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); | |
124 | |
125 else { | |
126 if ((ep = schedule(buf)) == NULL) | |
127 free((char *)events[slot]), events[slot] = 0; | |
128 | |
129 else { | |
130 (void)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(); | |
137 } | |
138 | |
139 /*ARGSUSED*/ | |
140 int | |
141 main(argc, argv) | |
142 int argc; | |
143 char **argv; | |
144 | |
145 { | |
146 for (pname = argv[0] + strlen(argv[0]); *pname != '/' && pname != argv[0]; | |
147 pname--); | |
148 if (*pname == '/') pname++; | |
149 | |
150 (void)signal(SIGIO, getevent); | |
151 (void)signal(SIGALRM, notify); | |
152 (void)fcntl(0, F_SETFL, FASYNC); | |
153 | |
154 while (1) pause(); | |
155 } |