File: | src/games/grdc/grdc.c |
Warning: | line 234, column 10 The left operand of '+' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: grdc.c,v 1.37 2022/09/27 03:01:42 deraadt Exp $ */ | |||
2 | /* | |||
3 | * | |||
4 | * Copyright 2002 Amos Shapir. Public domain. | |||
5 | * | |||
6 | * Grand digital clock for curses compatible terminals | |||
7 | * Usage: grdc [-s] [n] -- run for n seconds (default infinity) | |||
8 | * Flags: -s: scroll | |||
9 | * | |||
10 | * modified 10-18-89 for curses (jrl) | |||
11 | * 10-18-89 added signal handling | |||
12 | */ | |||
13 | ||||
14 | #include <sys/ioctl.h> | |||
15 | ||||
16 | #include <curses.h> | |||
17 | #include <err.h> | |||
18 | #include <limits.h> | |||
19 | #include <poll.h> | |||
20 | #include <signal.h> | |||
21 | #include <stdio.h> | |||
22 | #include <stdlib.h> | |||
23 | #include <string.h> | |||
24 | #include <time.h> | |||
25 | #include <unistd.h> | |||
26 | ||||
27 | #define XLENGTH58 58 | |||
28 | #define YDEPTH7 7 | |||
29 | ||||
30 | struct timespec now; | |||
31 | struct tm *tm; | |||
32 | ||||
33 | short disp[11] = { | |||
34 | 075557, 011111, 071747, 071717, 055711, | |||
35 | 074717, 074757, 071111, 075757, 075717, 002020 | |||
36 | }; | |||
37 | long old[6], next[6], new[6], mask; | |||
38 | ||||
39 | volatile sig_atomic_t sigalrmed = 0; | |||
40 | volatile sig_atomic_t sigtermed = 0; | |||
41 | volatile sig_atomic_t sigwinched = 0; | |||
42 | ||||
43 | int hascolor = 0; | |||
44 | ||||
45 | void getwinsize(int *, int *); | |||
46 | void set(int, int); | |||
47 | void standt(int); | |||
48 | void __dead__attribute__((__noreturn__)) usage(void); | |||
49 | ||||
50 | void | |||
51 | sigalrm(int signo) | |||
52 | { | |||
53 | sigalrmed = signo; | |||
54 | } | |||
55 | ||||
56 | void | |||
57 | sighndl(int signo) | |||
58 | { | |||
59 | sigtermed = signo; | |||
60 | } | |||
61 | ||||
62 | void | |||
63 | sigresize(int signo) | |||
64 | { | |||
65 | sigwinched = signo; | |||
66 | } | |||
67 | ||||
68 | int | |||
69 | main(int argc, char *argv[]) | |||
70 | { | |||
71 | long t, a; | |||
72 | int i, j, s, k, rv; | |||
73 | int scrol; | |||
74 | unsigned int n = 0; | |||
75 | struct timespec delay; | |||
76 | struct pollfd pfd; | |||
77 | const char *errstr; | |||
78 | long scroldelay = 50000000; | |||
79 | int xbase; | |||
80 | int ybase; | |||
| ||||
81 | int wintoosmall; | |||
82 | int tz_len = 0; | |||
83 | int h, m; | |||
84 | int prev_tm_gmtoff; | |||
85 | char *tz; | |||
86 | ||||
87 | tz = getenv("TZ"); | |||
88 | if (tz
| |||
89 | tz_len = strlen(tz); | |||
90 | ||||
91 | scrol = wintoosmall = 0; | |||
92 | while ((i = getopt(argc, argv, "sh")) != -1) { | |||
93 | switch (i) { | |||
94 | case 's': | |||
95 | scrol = 1; | |||
96 | break; | |||
97 | case 'h': | |||
98 | default: | |||
99 | usage(); | |||
100 | } | |||
101 | } | |||
102 | argv += optind; | |||
103 | argc -= optind; | |||
104 | ||||
105 | if (argc > 1) | |||
106 | usage(); | |||
107 | if (argc == 1) { | |||
108 | n = strtonum(*argv, 1, UINT_MAX0xffffffffU, &errstr); | |||
109 | if (errstr) { | |||
110 | warnx("number of seconds is %s", errstr); | |||
111 | usage(); | |||
112 | } | |||
113 | } | |||
114 | ||||
115 | initscr(); | |||
116 | ||||
117 | if (pledge("stdio tty", NULL((void *)0)) == -1) | |||
118 | err(1, "pledge"); | |||
119 | ||||
120 | signal(SIGINT2, sighndl); | |||
121 | signal(SIGTERM15, sighndl); | |||
122 | signal(SIGHUP1, sighndl); | |||
123 | signal(SIGWINCH28, sigresize); | |||
124 | signal(SIGCONT19, sigresize); /* for resizes during suspend */ | |||
125 | ||||
126 | pfd.fd = STDIN_FILENO0; | |||
127 | pfd.events = POLLIN0x0001; | |||
128 | ||||
129 | cbreak(); | |||
130 | noecho(); | |||
131 | ||||
132 | hascolor = has_colors(); | |||
133 | ||||
134 | if (hascolor) { | |||
135 | start_color(); | |||
136 | init_pair(1, COLOR_BLACK0, COLOR_RED1); | |||
137 | init_pair(2, COLOR_RED1, COLOR_BLACK0); | |||
138 | init_pair(3, COLOR_WHITE7, COLOR_BLACK0); | |||
139 | attrset(COLOR_PAIR(2))wattrset(stdscr,((((chtype)(((2))) << ((0) + 8)) & ( (chtype)((((1U) << 8) - 1U)) << ((0) + 8))))); | |||
140 | } | |||
141 | ||||
142 | curs_set(0); | |||
143 | sigwinched = 1; /* force initial sizing */ | |||
144 | prev_tm_gmtoff = 24 * 3600; /* force initial header printing */ | |||
145 | ||||
146 | clock_gettime(CLOCK_REALTIME0, &now); | |||
147 | if (n
| |||
148 | signal(SIGALRM14, sigalrm); | |||
149 | alarm(n); | |||
150 | } | |||
151 | do { | |||
152 | mask = 0; | |||
153 | tm = localtime(&now.tv_sec); | |||
154 | set(tm->tm_sec % 10, 0); | |||
155 | set(tm->tm_sec / 10, 4); | |||
156 | set(tm->tm_min % 10, 10); | |||
157 | set(tm->tm_min / 10, 14); | |||
158 | set(tm->tm_hour % 10, 20); | |||
159 | set(tm->tm_hour / 10, 24); | |||
160 | set(10, 7); | |||
161 | set(10, 17); | |||
162 | /* force repaint if window size changed or DST changed */ | |||
163 | if (sigwinched
| |||
164 | sigwinched = 0; | |||
165 | wintoosmall = 0; | |||
166 | prev_tm_gmtoff = tm->tm_gmtoff; | |||
167 | getwinsize(&i, &j); | |||
168 | if (i >= XLENGTH58 + 2) | |||
169 | xbase = (i - XLENGTH58) / 2; | |||
170 | else | |||
171 | wintoosmall = 1; | |||
172 | if (j >= YDEPTH7 + 2) | |||
173 | ybase = (j - YDEPTH7) / 2; | |||
174 | else | |||
175 | wintoosmall = 1; | |||
176 | resizeterm(j, i); | |||
177 | clear()wclear(stdscr); | |||
178 | refresh()wrefresh(stdscr); | |||
179 | if (hascolor && !wintoosmall) { | |||
180 | attrset(COLOR_PAIR(3))wattrset(stdscr,((((chtype)(((3))) << ((0) + 8)) & ( (chtype)((((1U) << 8) - 1U)) << ((0) + 8))))); | |||
181 | ||||
182 | mvaddch(ybase - 1, xbase - 1, ACS_ULCORNER)(wmove((stdscr),((ybase - 1)),((xbase - 1))) == (-1) ? (-1) : waddch((stdscr),(((acs_map[(unsigned char)(('l'))]))))); | |||
183 | hline(ACS_HLINE, XLENGTH)whline(stdscr, (acs_map[(unsigned char)(('q'))]), (58)); | |||
184 | mvaddch(ybase - 1, xbase + XLENGTH, ACS_URCORNER)(wmove((stdscr),((ybase - 1)),((xbase + 58))) == (-1) ? (-1) : waddch((stdscr),(((acs_map[(unsigned char)(('k'))]))))); | |||
185 | ||||
186 | mvaddch(ybase + YDEPTH, xbase - 1, ACS_LLCORNER)(wmove((stdscr),((ybase + 7)),((xbase - 1))) == (-1) ? (-1) : waddch((stdscr),(((acs_map[(unsigned char)(('m'))]))))); | |||
187 | hline(ACS_HLINE, XLENGTH)whline(stdscr, (acs_map[(unsigned char)(('q'))]), (58)); | |||
188 | mvaddch(ybase + YDEPTH, xbase + XLENGTH, ACS_LRCORNER)(wmove((stdscr),((ybase + 7)),((xbase + 58))) == (-1) ? (-1) : waddch((stdscr),(((acs_map[(unsigned char)(('j'))]))))); | |||
189 | ||||
190 | move(ybase, xbase - 1)wmove(stdscr,(ybase),(xbase - 1)); | |||
191 | vline(ACS_VLINE, YDEPTH)wvline(stdscr, (acs_map[(unsigned char)(('x'))]), (7)); | |||
192 | ||||
193 | move(ybase, xbase + XLENGTH)wmove(stdscr,(ybase),(xbase + 58)); | |||
194 | vline(ACS_VLINE, YDEPTH)wvline(stdscr, (acs_map[(unsigned char)(('x'))]), (7)); | |||
195 | ||||
196 | move(ybase - 1, xbase)wmove(stdscr,(ybase - 1),(xbase)); | |||
197 | ||||
198 | h = tm->tm_gmtoff / 3600; | |||
199 | m = abs((int)tm->tm_gmtoff % 3600 / 60); | |||
200 | ||||
201 | if (tz_len > 0 && tz_len <= XLENGTH58 - | |||
202 | strlen("[ () +0000 ]") - | |||
203 | strlen(tm->tm_zone)) | |||
204 | printw("[ %s (%s) %+2.2d%02d ]", tz, | |||
205 | tm->tm_zone, h, m); | |||
206 | else | |||
207 | printw("[ %s %+2.2d%02d ]", | |||
208 | tm->tm_zone, h, m); | |||
209 | ||||
210 | attrset(COLOR_PAIR(2))wattrset(stdscr,((((chtype)(((2))) << ((0) + 8)) & ( (chtype)((((1U) << 8) - 1U)) << ((0) + 8))))); | |||
211 | } | |||
212 | for (k = 0; k < 6; k++) | |||
213 | old[k] = 0; | |||
214 | } | |||
215 | if (wintoosmall
| |||
216 | move(0, 0)wmove(stdscr,(0),(0)); | |||
217 | printw("%02d:%02d:%02d", tm->tm_hour, tm->tm_min, | |||
218 | tm->tm_sec); | |||
219 | } else for (k = 0; k < 6; k++) { | |||
220 | if (scrol
| |||
221 | for(i = 0; i < 5; i++) | |||
222 | new[i] = (new[i] & ~mask) | (new[i + 1] & mask); | |||
223 | new[5] = (new[5] & ~mask) | (next[k] & mask); | |||
224 | } else | |||
225 | new[k] = (new[k] & ~mask) | (next[k] & mask); | |||
226 | next[k] = 0; | |||
227 | for (s = 1; s >= 0; s--) { | |||
228 | standt(s); | |||
229 | for (i = 0; i < 6; i++) { | |||
230 | if ((a = (new[i] ^ old[i]) & (s
| |||
231 | for (j = 0, t = 1 << 26; t; t >>= 1, j++) { | |||
232 | if (a & t) { | |||
233 | if (!(a & (t << 1))) { | |||
234 | move(ybase + i + 1, xbase + 2 * (j + 1))wmove(stdscr,(ybase + i + 1),(xbase + 2 * (j + 1))); | |||
| ||||
235 | } | |||
236 | addstr(" ")waddnstr(stdscr,(" "),-1); | |||
237 | } | |||
238 | } | |||
239 | } | |||
240 | if (!s) { | |||
241 | old[i] = new[i]; | |||
242 | } | |||
243 | } | |||
244 | if (!s) { | |||
245 | refresh()wrefresh(stdscr); | |||
246 | } | |||
247 | } | |||
248 | if (scrol && k <= 4) { | |||
249 | clock_gettime(CLOCK_REALTIME0, &now); | |||
250 | delay.tv_sec = 0; | |||
251 | delay.tv_nsec = 1000000000 - now.tv_nsec | |||
252 | - (4 - k) * scroldelay; | |||
253 | if (delay.tv_nsec <= scroldelay && | |||
254 | delay.tv_nsec > 0) | |||
255 | nanosleep(&delay, NULL((void *)0)); | |||
256 | } | |||
257 | } | |||
258 | move(6, 0)wmove(stdscr,(6),(0)); | |||
259 | refresh()wrefresh(stdscr); | |||
260 | clock_gettime(CLOCK_REALTIME0, &now); | |||
261 | delay.tv_sec = 0; | |||
262 | delay.tv_nsec = (1000000000 - now.tv_nsec); | |||
263 | /* want scrolling to END on the second */ | |||
264 | if (scrol && !wintoosmall) | |||
265 | delay.tv_nsec -= 5 * scroldelay; | |||
266 | rv = ppoll(&pfd, 1, &delay, NULL((void *)0)); | |||
267 | if (rv == 1) { | |||
268 | char q = 0; | |||
269 | read(STDIN_FILENO0, &q, 1); | |||
270 | if (q == 'q') | |||
271 | sigalrmed = 1; | |||
272 | } | |||
273 | now.tv_sec++; | |||
274 | ||||
275 | if (sigtermed) { | |||
276 | standend()(wattrset(stdscr,(1U - 1U))); | |||
277 | clear()wclear(stdscr); | |||
278 | refresh()wrefresh(stdscr); | |||
279 | endwin(); | |||
280 | exit(0); | |||
281 | } | |||
282 | } while (!sigalrmed); | |||
283 | standend()(wattrset(stdscr,(1U - 1U))); | |||
284 | clear()wclear(stdscr); | |||
285 | refresh()wrefresh(stdscr); | |||
286 | endwin(); | |||
287 | return 0; | |||
288 | } | |||
289 | ||||
290 | void | |||
291 | set(int t, int n) | |||
292 | { | |||
293 | int i, m; | |||
294 | ||||
295 | m = 7 << n; | |||
296 | for (i = 0; i < 5; i++) { | |||
297 | next[i] |= ((disp[t] >> (4 - i) * 3) & 07) << n; | |||
298 | mask |= (next[i] ^ old[i]) & m; | |||
299 | } | |||
300 | if (mask & m) | |||
301 | mask |= m; | |||
302 | } | |||
303 | ||||
304 | void | |||
305 | standt(int on) | |||
306 | { | |||
307 | if (on) { | |||
308 | if (hascolor) { | |||
309 | attron(COLOR_PAIR(1))wattr_on(stdscr, (attr_t)(((((chtype)(((1))) << ((0) + 8 )) & ((chtype)((((1U) << 8) - 1U)) << ((0) + 8 ))))), ((void *)0)); | |||
310 | } else { | |||
311 | attron(A_STANDOUT)wattr_on(stdscr, (attr_t)((((chtype)((1U)) << ((8) + 8) ))), ((void *)0)); | |||
312 | } | |||
313 | } else { | |||
314 | if (hascolor) { | |||
315 | attron(COLOR_PAIR(2))wattr_on(stdscr, (attr_t)(((((chtype)(((2))) << ((0) + 8 )) & ((chtype)((((1U) << 8) - 1U)) << ((0) + 8 ))))), ((void *)0)); | |||
316 | } else { | |||
317 | attroff(A_STANDOUT)wattr_off(stdscr, (attr_t)((((chtype)((1U)) << ((8) + 8 )))), ((void *)0)); | |||
318 | } | |||
319 | } | |||
320 | } | |||
321 | ||||
322 | void | |||
323 | getwinsize(int *wid, int *ht) | |||
324 | { | |||
325 | struct winsize size; | |||
326 | ||||
327 | if (ioctl(STDOUT_FILENO1, TIOCGWINSZ((unsigned long)0x40000000 | ((sizeof(struct winsize) & 0x1fff ) << 16) | ((('t')) << 8) | ((104))), &size) == -1) { | |||
328 | *wid = 80; /* Default */ | |||
329 | *ht = 24; | |||
330 | } else { | |||
331 | *wid = size.ws_col; | |||
332 | *ht = size.ws_row; | |||
333 | } | |||
334 | } | |||
335 | ||||
336 | void __dead__attribute__((__noreturn__)) | |||
337 | usage(void) | |||
338 | { | |||
339 | fprintf(stderr(&__sF[2]), "usage: %s [-s] [number]\n", getprogname()); | |||
340 | exit(1); | |||
341 | } |