#include #include #include #include #include #include int parse(char *s) { int cur=0,tot=0; int pos; char c; for (pos=0; c=s[pos],c!=0; pos++) { if ('0'<=c && c<='9') { cur*=10; cur+=c-'0'; } else { switch(c) { case 'h': cur *= 60; case 'm': cur *= 60; case 's': break; default: return -1; } tot+=cur; cur=0; } } return tot+cur; } void disp(int secs) { int rem; int h = secs/3600; rem= secs%3600; int m = rem/60; int s = rem%60; if (h>0) printf("%02dh",h); if (h>0||m>0) printf("%02dm",m); printf("%02ds",s); fflush(stdout); } int main(int argc, char **argv) { if (argc != 2) { fprintf(stderr, "usage: %s TIMESPEC\n", argv[0]); exit(1); } int secs = parse(argv[1]); if (secs==0) return 0; if (secs<0) { fprintf(stderr, "%s: invalid timespec %s\n", argv[0], argv[1]); exit(1); } struct termios orig_term, new_term; tcgetattr(0, &orig_term); memcpy(&new_term, &orig_term, sizeof(struct termios)); cfmakeraw(&new_term); tcsetattr(0, TCSADRAIN, &new_term); int paused = 0; struct pollfd pf = { .fd = 0, .events = POLLIN, }; while (secs>0) { if (paused) printf("[paused] "); disp(secs); int rc = poll(&pf, 1, paused ? -1 : 1000); if (rc == 0 && !paused) secs--; printf("\033[2K\033[G"); if (pf.revents & POLLIN) { char c; read(0,&c,1); switch(c){ case 'q': case 3: // ctrl-C goto end; case '+': secs+=10; break; case '=': secs++; break; case '_': secs -= 10; if (secs <= 0) secs=10; break; case '-': secs--; if (secs <= 0) secs=1; break; case ' ': paused = !paused; break; } } } end: tcsetattr(0, TCSADRAIN, &orig_term); return 0; }