diff options
| author | Jim Blandy | 1992-08-19 03:54:46 +0000 |
|---|---|---|
| committer | Jim Blandy | 1992-08-19 03:54:46 +0000 |
| commit | fbfed6f05fdf5bf363ca5691aefde4d573ce8203 (patch) | |
| tree | 726c22e6a55cb3e760a25f6aa60580d76c8de253 /lib-src | |
| parent | 4d4c4e027fe376759227a6fb6b31a88be6e36347 (diff) | |
| download | emacs-fbfed6f05fdf5bf363ca5691aefde4d573ce8203.tar.gz emacs-fbfed6f05fdf5bf363ca5691aefde4d573ce8203.zip | |
entered into RCS
Diffstat (limited to 'lib-src')
| -rw-r--r-- | lib-src/b2m.c | 7 | ||||
| -rw-r--r-- | lib-src/timer.c | 334 |
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. */ |
| 23 | extern char *strtok (); | 30 | extern 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 | ||
| 26 | extern int errno; | 26 | extern int errno; |
| 27 | extern char *sys_errlist[], *malloc(); | 27 | extern char *sys_errlist[], *malloc (); |
| 28 | extern time_t time(); | 28 | extern 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 | ||
| 39 | struct event | 37 | struct event |
| 40 | { | 38 | { |
| 41 | char *token; | 39 | char *token; |
| 42 | time_t reply_at; | 40 | time_t reply_at; |
| 43 | } | 41 | }; |
| 44 | events[MAXEVENTS]; | 42 | int events_size; /* How many slots have we allocated? */ |
| 43 | int num_events; /* How many are actually scheduled? */ | ||
| 44 | struct event *events; /* events[0 .. num_events-1] are the | ||
| 45 | valid events. */ | ||
| 45 | 46 | ||
| 46 | char *pname; /* programme name for error messages */ | 47 | char *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 | */ | 52 | void |
| 52 | void schedule(str) | 53 | schedule (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 | ||
| 101 | void | 121 | void |
| 102 | notify() | 122 | notify () |
| 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 | |||
| 157 | void | ||
| 158 | getevent () | ||
| 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 | ||
| 149 | void | 194 | if (c == EOF) |
| 150 | getevent() | 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 | ||
| 169 | void | 214 | void |
| 170 | sigcatch(sig) | 215 | sigcatch (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*/ |
| 201 | int | 243 | int |
| 202 | main(argc, argv) | 244 | main (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 */ |