aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src
diff options
context:
space:
mode:
authorJim Blandy1992-08-19 03:54:46 +0000
committerJim Blandy1992-08-19 03:54:46 +0000
commitfbfed6f05fdf5bf363ca5691aefde4d573ce8203 (patch)
tree726c22e6a55cb3e760a25f6aa60580d76c8de253 /lib-src
parent4d4c4e027fe376759227a6fb6b31a88be6e36347 (diff)
downloademacs-fbfed6f05fdf5bf363ca5691aefde4d573ce8203.tar.gz
emacs-fbfed6f05fdf5bf363ca5691aefde4d573ce8203.zip
entered into RCS
Diffstat (limited to 'lib-src')
-rw-r--r--lib-src/b2m.c7
-rw-r--r--lib-src/timer.c334
2 files changed, 198 insertions, 143 deletions
diff --git a/lib-src/b2m.c b/lib-src/b2m.c
index 2aa79b8edc0..5ae81949aed 100644
--- a/lib-src/b2m.c
+++ b/lib-src/b2m.c
@@ -17,7 +17,14 @@
17 17
18#include <stdio.h> 18#include <stdio.h>
19#include <time.h> 19#include <time.h>
20
21#include "../src/config.h"
22
23#ifdef USG
24#include <string.h>
25#else
20#include <strings.h> 26#include <strings.h>
27#endif
21 28
22/* BSD's strings.h does not declare the type of strtok. */ 29/* BSD's strings.h does not declare the type of strtok. */
23extern char *strtok (); 30extern char *strtok ();
diff --git a/lib-src/timer.c b/lib-src/timer.c
index 2c1b9a729f6..a12295db014 100644
--- a/lib-src/timer.c
+++ b/lib-src/timer.c
@@ -1,17 +1,17 @@
1/* 1/* timer.c --- daemon to provide a tagged interval timer service
2 * timer.c --- daemon to provide a tagged interval timer service 2
3 * 3 This little daemon runs forever waiting for signals. SIGIO (or
4 * This little daemon runs forever waiting for signals. SIGIO (or SIGUSR1) 4 SIGUSR1) causes it to read an event spec from stdin; that is, a
5 * causes it to read an event spec from stdin; that is, a date followed by 5 date followed by colon followed by an event label. SIGALRM causes
6 * colon followed by an event label. SIGALRM causes it to check its queue 6 it to check its queue for events attached to the current second; if
7 * for events attached to the current second; if one is found, its label 7 one is found, its label is written to stdout. SIGTERM causes it to
8 * is written to stdout. SIGTERM causes it to terminate, printing a list 8 terminate, printing a list of pending events.
9 * of pending events. 9
10 * 10 This program is intended to be used with the lisp package called
11 * This program is intended to be used with the lisp package called timer.el. 11 timer.el. It was written anonymously in 1990. This version was
12 * It was written anonymously in 1990. This version was documented and 12 documented and rewritten for portability by esr@snark,thyrsus.com,
13 * rewritten for portability by esr@snark,thyrsus.com, Aug 7 1992. 13 Aug 7 1992. */
14 */ 14
15#include <stdio.h> 15#include <stdio.h>
16#include <signal.h> 16#include <signal.h>
17#include <fcntl.h> /* FASYNC */ 17#include <fcntl.h> /* FASYNC */
@@ -24,10 +24,8 @@
24#endif 24#endif
25 25
26extern int errno; 26extern int errno;
27extern char *sys_errlist[], *malloc(); 27extern char *sys_errlist[], *malloc ();
28extern time_t time(); 28extern time_t time ();
29
30#define MAXEVENTS 256
31 29
32/* 30/*
33 * The field separator for input. This character shouldn't be legal in a date, 31 * The field separator for input. This character shouldn't be legal in a date,
@@ -37,185 +35,235 @@ extern time_t time();
37#define FS '@' 35#define FS '@'
38 36
39struct event 37struct event
40{ 38 {
41 char *token; 39 char *token;
42 time_t reply_at; 40 time_t reply_at;
43} 41 };
44events[MAXEVENTS]; 42int events_size; /* How many slots have we allocated? */
43int num_events; /* How many are actually scheduled? */
44struct event *events; /* events[0 .. num_events-1] are the
45 valid events. */
45 46
46char *pname; /* programme name for error messages */ 47char *pname; /* programme name for error messages */
47 48
48/* Accepts a string of two fields seperated by FS. 49/* Accepts a string of two fields seperated by FS.
49 * First field is string for getdate, saying when to wake-up. 50 First field is string for getdate, saying when to wake-up.
50 * Second field is a token to identify the request. 51 Second field is a token to identify the request. */
51 */ 52void
52void schedule(str) 53schedule (str)
53 char *str; 54 char *str;
54{ 55{
55 extern time_t getdate(); 56 extern time_t getdate ();
56 extern char *strcpy(); 57 extern char *strcpy ();
57 time_t now; 58 time_t now;
58 register char *p; 59 register char *p;
59 static struct event *ep; 60 static struct event *ep;
60 61
61#ifdef DEBUG 62 /* check entry format */
62 (void) fprintf(stderr, "Timer sees: %s", str); 63 for (p = str; *p && *p != FS; p++)
63#endif /* DEBUG */ 64 continue;
64 65 if (!*p)
65 /* check entry format */
66 for(p = str; *p && *p != FS; p++)
67 continue;
68 if (!*p)
69 { 66 {
70 (void)fprintf(stderr, "%s: bad input format: %s", pname, str); 67 fprintf (stderr, "%s: bad input format: %s", pname, str);
71 return; 68 return;
72 } 69 }
73 *p++ = 0; 70 *p++ = 0;
74 71
75 /* allocate an event slot */ 72 /* allocate an event slot */
76 for(ep = events; ep < events + MAXEVENTS; ep++) 73 ep = events + num_events;
77 if (ep->token == (char *)NULL) 74
78 break; 75 /* If the event array is full, stretch it. After stretching, we know
79 if (ep == events + MAXEVENTS) 76 that ep will be pointing to an available event spot. */
80 (void) fprintf(stderr, "%s: too many events: %s", pname, str); 77 if (ep == events + events_size)
81
82 /* don't allow users to schedule events in past time */
83 else if ((ep->reply_at = get_date(str, NULL)) - time(&now) < 0)
84 (void)fprintf(stderr, "%s: bad time spec: %s%c%s", pname, str, FS, p);
85
86 /* save the event description */
87 else if ((ep->token = malloc((unsigned)strlen(p) + 1)) == NULL)
88 (void)fprintf(stderr, "%s: malloc %s: %s%c%s",
89 pname, sys_errlist[errno], str, FS, p);
90 else
91 { 78 {
92 (void)strcpy(ep->token, p); 79 int old_size = events_size;
93 80
94#ifdef DEBUG 81 events_size *= 2;
95 (void) fprintf(stderr, 82 events = ((struct event *)
96 "New event: %ld: %s", ep->reply_at, ep->token); 83 realloc (events, events_size * sizeof (struct event)));
97#endif /* DEBUG */ 84 if (! events)
85 {
86 fprintf (stderr, "%s: virtual memory exhausted.\n", pname);
87
88 /* Should timer exit now? Well, we've still got other
89 events in the queue, and more memory might become
90 available in the future, so we'll just toss this event.
91 This will screw up whoever scheduled the event, but
92 maybe someone else will survive. */
93 return;
94 }
95
96 while (old_size < events_size)
97 events[old_size++].token = NULL;
98 }
99
100 /* Don't allow users to schedule events in past time. */
101 ep->reply_at = get_date (str, NULL);
102 if (ep->reply_at - time (&now) < 0)
103 {
104 fprintf (stderr, "%s: bad time spec: %s%c%s", pname, str, FS, p);
105 return;
106 }
107
108 /* save the event description */
109 ep->token = (char *) malloc ((unsigned) strlen (p) + 1);
110 if (! ep->token)
111 {
112 fprintf (stderr, "%s: malloc %s: %s%c%s",
113 pname, sys_errlist[errno], str, FS, p);
114 return;
98 } 115 }
116
117 strcpy (ep->token, p);
118 num_events++;
99} 119}
100 120
101void 121void
102notify() 122notify ()
103{ 123{
104 time_t now, tdiff, waitfor = -1; 124 time_t now, tdiff, waitfor;
105 register struct event *ep; 125 register struct event *ep;
126
127 now = time ((time_t *) NULL);
106 128
107 now = time((time_t *)NULL); 129 for (ep = events; ep < events + num_events; ep++)
130 /* Are any events ready to fire? */
131 if (ep->reply_at <= now)
132 {
133 fputs (ep->token, stdout);
134 free (ep->token);
108 135
109 for(ep = events; ep < events + MAXEVENTS; ep++) 136 /* We now have a hole in the event array; fill it with the last
110 if (ep->token) 137 event. */
138 ep->token = events[num_events].token;
139 ep->reply_at = events[num_events].reply_at;
140 num_events--;
141
142 /* We ought to scan this event again. */
143 ep--;
144 }
145 else
146 {
147 /* next timeout should be the soonest of any remaining */
148 if ((tdiff = ep->reply_at - now) < waitfor || waitfor < 0)
149 waitfor = (long)tdiff;
150 }
151
152 /* If there are no more events, we needn't bother setting an alarm. */
153 if (num_events > 0)
154 alarm (waitfor);
155}
156
157void
158getevent ()
159{
160 int i;
161 char *buf;
162 int buf_size;
163
164 /* In principle the itimer should be disabled on entry to this
165 function, but it really doesn't make any important difference
166 if it isn't. */
167
168 buf_size = 80;
169 buf = (char *) malloc (buf_size);
170
171 /* Read a line from standard input, expanding buf if it is too short
172 to hold the line. */
173 for (i = 0; ; i++)
174 {
175 int c;
176
177 if (i >= buf_size)
111 { 178 {
112 /* any events ready to fire? */ 179 buf_size *= 2;
113 if (ep->reply_at <= now) 180 buf = (char *) realloc (buf, buf_size);
114 { 181
115#ifdef DEBUG 182 /* If we're out of memory, toss this event. */
116 (void) fprintf(stderr, 183 do
117 "Event %d firing: %ld @ %s",
118 (ep - events), ep->reply_at, ep->token);
119#endif /* DEBUG */
120 (void)fputs(ep->token, stdout);
121 free(ep->token);
122 ep->token = (char *)NULL;
123 }
124 else
125 { 184 {
126#ifdef DEBUG 185 c = getchar ();
127 (void) fprintf(stderr,
128 "Event %d still waiting: %ld @ %s",
129 (ep - events), ep->reply_at, ep->token);
130#endif /* DEBUG */
131
132 /* next timeout should be the soonest of any remaining */
133 if ((tdiff = ep->reply_at - now) < waitfor || waitfor < 0)
134 waitfor = (long)tdiff;
135 } 186 }
187 while (c != '\n' && c != EOF);
188
189 return;
136 } 190 }
137 191
138 /* If there's no more events, SIGIO should be next wake-up */ 192 c = getchar ();
139 if (waitfor != -1)
140 {
141#ifdef DEBUG
142 (void) fprintf(stderr,
143 "Setting %d-second alarm\n", waitfor);
144#endif /* DEBUG */
145 (void)alarm(waitfor);
146 }
147}
148 193
149void 194 if (c == EOF)
150getevent() 195 exit (0);
151{
152 extern char *fgets();
153 struct event *ep;
154 char buf[BUFSIZ];
155 196
156 /* in principle the itimer should be disabled on entry to this function, 197 if (c == '\n')
157 but it really doesn't make any important difference if it isn't */ 198 {
199 buf[i] = '\0';
200 break;
201 }
158 202
159 if (fgets(buf, sizeof(buf), stdin) == NULL) 203 buf[i] = c;
160 exit(0); 204 }
161 205
162 /* register the event */ 206 /* Register the event. */
163 schedule(buf); 207 schedule (buf);
208 free (buf);
164 209
165 /* Who knows what this interrupted, or if it said "now"? */ 210 /* Who knows what this interrupted, or if it said "now"? */
166 notify(); 211 notify ();
167} 212}
168 213
169void 214void
170sigcatch(sig) 215sigcatch (sig)
216 int sig;
171/* dispatch on incoming signal, then restore it */ 217/* dispatch on incoming signal, then restore it */
172{ 218{
173 struct event *ep; 219 struct event *ep;
174 220
175 switch(sig) 221 switch (sig)
176 { 222 {
177 case SIGALRM: 223 case SIGALRM:
178#ifdef DEBUG 224 notify ();
179 (void) fprintf(stderr, "Alarm signal received\n"); 225 break;
180#endif /* DEBUG */
181 notify();
182 break;
183 case SIGIO: 226 case SIGIO:
184 getevent(); 227 getevent ();
185 break; 228 break;
186 case SIGTERM: 229 case SIGTERM:
187 (void) fprintf(stderr, "Events still queued:\n"); 230 fprintf (stderr, "Events still queued:\n");
188 for (ep = events; ep < events + MAXEVENTS; ep++) 231 for (ep = events; ep < events + num_events; ep++)
189 if (ep->token) 232 fprintf (stderr, "%d = %ld @ %s",
190 (void) fprintf(stderr, "%d = %ld @ %s", 233 ep - events, ep->reply_at, ep->token);
191 ep - events, ep->reply_at, ep->token); 234 exit (0);
192 exit(0); 235 break;
193 break;
194 } 236 }
195 237
196 /* required on older UNIXes; harmless on newer ones */ 238 /* required on older UNIXes; harmless on newer ones */
197 (void) signal(sig, sigcatch); 239 signal (sig, sigcatch);
198} 240}
199 241
200/*ARGSUSED*/ 242/*ARGSUSED*/
201int 243int
202main(argc, argv) 244main (argc, argv)
203 int argc; 245 int argc;
204 char **argv; 246 char **argv;
205{ 247{
206 for (pname = argv[0] + strlen(argv[0]); *pname != '/' && pname != argv[0]; 248 for (pname = argv[0] + strlen (argv[0]);
249 *pname != '/' && pname != argv[0];
207 pname--); 250 pname--);
208 if (*pname == '/') pname++; 251 if (*pname == '/')
252 pname++;
253
254 events_size = 16;
255 events = ((struct event *) malloc (events_size * sizeof (*events)));
256 num_events = 0;
209 257
210 (void)signal(SIGIO, sigcatch); 258 signal (SIGIO, sigcatch);
211 (void)signal(SIGALRM, sigcatch); 259 signal (SIGALRM, sigcatch);
212 (void)signal(SIGTERM, sigcatch); 260 signal (SIGTERM, sigcatch);
213 261
214#ifndef USG 262#ifndef USG
215 (void)fcntl(0, F_SETFL, FASYNC); 263 fcntl (0, F_SETFL, FASYNC);
216#endif /* USG */ 264#endif /* USG */
217 265
218 while (1) pause(); 266 while (1) pause ();
219} 267}
220 268
221/* timer.c ends here */ 269/* timer.c ends here */