ticktack.c (1670B)
1 /* 2 * Copyright (C) Raymond Cole <rc@wolog.xyz> 3 * 4 * Licensed under the GNU General Public License; either version 3 of 5 * the License, or (at your option) any later version. See the LICENSE 6 * file for details. 7 */ 8 #define _POSIX_C_SOURCE 200112L 9 #include <errno.h> 10 #include <signal.h> 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <string.h> 14 #include <time.h> 15 #include <unistd.h> 16 #include <sys/wait.h> 17 18 #include "util.h" 19 20 enum { TTS = 1, TTM = 2 }; 21 22 static volatile sig_atomic_t tt, sentterm; 23 static struct timespec request, now; 24 25 static void 26 updatereq(int t) 27 { 28 if (t & TTS) 29 request.tv_sec = now.tv_sec + 1; 30 else if (t & TTM) 31 request.tv_sec = now.tv_sec - now.tv_sec % 60 + 60; 32 } 33 34 int 35 main(int argc, char **argv) 36 { 37 time_t osec; 38 int c; 39 40 progname = argv[0]; 41 while ((c = getopt(argc, argv, "smh")) != -1) { 42 switch (c) { 43 case 's': tt |= TTS; break; 44 case 'm': tt |= TTM; break; 45 default: exit(1); 46 } 47 } 48 if (optind < argc) { 49 fputs("Too many arguments\n", stderr); 50 exit(1); 51 } 52 if (!tt) 53 for (;;) 54 pause(); 55 if (clock_gettime(CLOCK_REALTIME, &now) == -1) 56 die("clock_gettime:"); 57 updatereq(tt); 58 osec = now.tv_sec; 59 for (;;) { 60 c = '\0'; 61 if ((tt & TTM) && now.tv_sec - now.tv_sec % 60 > osec) { 62 c = 'm'; 63 updatereq(tt); 64 } else if ((tt & TTS) && now.tv_sec > osec) { 65 c = 's'; 66 updatereq(TTS); 67 } 68 if (c && write(1, (char []){ c, '\n' }, 2) < 0) 69 die("write:"); 70 osec = now.tv_sec; 71 switch (clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &request, NULL)) { 72 case 0: 73 case EINTR: 74 break; 75 default: 76 die("clock_nanosleep:"); 77 } 78 if (clock_gettime(CLOCK_REALTIME, &now) == -1) 79 die("clock_gettime:"); 80 } 81 return 0; 82 }