7 * (c) 1999 Mark Wooding
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Pause.
14 * Pause is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later ersion.
19 * Pause is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with Pause; if not, write to the Free Software Foundation,
26 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29 /*----- Header files ------------------------------------------------------*/
38 #include <sys/types.h>
43 #include <mLib/mdwopt.h>
44 #include <mLib/quis.h>
45 #include <mLib/report.h>
48 /*----- Static variables --------------------------------------------------*/
50 static struct termios ts_old, ts;
52 /*----- Main code ---------------------------------------------------------*/
56 * Arguments: @int s@ = signal number
60 * Use: Handles various fatal signals by resetting the terminal state
61 * and re-emitting the signal.
64 static void sig(int s)
66 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts_old);
71 /* --- @suspend@ --- *
73 * Arguments: @int s@ = signal number
77 * Use: Handles a job control signal, as recommended in APUE. It
78 * resets the terminal state, resets the signal disposition,
79 * unblocks the signal and re-emits it (so that the shell
80 * shows the right message). When that call returns, the
81 * signal handler is reattached, and the terminal state is set
85 static void suspend(int s)
89 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts_old);
93 sigprocmask(SIG_UNBLOCK, &ss, 0);
96 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts);
99 /* --- Traditional GNUey help options --- */
101 static void usage(FILE *fp)
103 pquis(fp, "Usage: $ [time]\n");
106 static void version(FILE *fp)
108 pquis(fp, "$ version " VERSION "\n");
111 static void help(FILE *fp)
117 Pauses until a key is pressed or an optional time-limit expires. The\n\
118 time is given as a floating point number with an option suffix of `s',\n\
119 `m', `h' or `d' (for `seconds', `minutes', `hours' or `days'\n\
122 Options available:\n\
124 -h, --help Show this help message.\n\
125 -v, --version Show program's version number.\n\
126 -u, --usage Show terse usage summary.\n\
132 * Arguments: @int argc@ = number of command line arguments
133 * @char *argv[]@ = vector of command line arguments
135 * Returns: Nonzero if it failed, zero if everything went well.
137 * Use: Souped-up version of `sleep'.
140 int main(int argc, char *argv[])
152 /* --- Library initialization --- */
156 /* --- Parse command line options --- */
159 static struct option opt[] = {
160 { "help", 0, 0, 'h' },
161 { "version", 0, 0, 'v' },
162 { "usage", 0, 0, 'u' },
165 int i = mdwopt(argc, argv, "hvu", opt, 0, 0, 0);
184 /* --- Parse a timer spec --- */
186 if (!(f & f_bogus) && optind < argc) {
187 const char *p =argv[optind++];
189 double t = strtod(p, &q);
194 case 's': if (q[1] != 0)
199 die(1, "bad time specification `%s'", p);
200 gettimeofday(&when, 0);
201 TV_ADDL(&when, &when, t, (t - floor(t)) * MILLION);
205 /* --- Report a syntax error --- */
214 /* --- Set up terminal for single keypresses --- */
216 if (tcgetattr(STDIN_FILENO, &ts_old) == 0) {
217 static struct { int sig; void (*func)(int); } sigs[] = {
221 { SIGTSTP, suspend },
226 /* --- Set up the new terminal attributes --- */
229 ts.c_lflag &= ~(ECHO | ICANON | TOSTOP);
231 /* --- Set up signal handlers to reset attributes --- */
233 for (i = 0; sigs[i].sig; i++) {
235 sigaction(sigs[i].sig, 0, &sa);
236 if (sa.sa_handler != SIG_IGN)
237 signal(sigs[i].sig, sigs[i].func);
239 signal(SIGTTIN, suspend);
241 /* --- Commit the terminal attribute changes --- */
243 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts);
247 /* --- Main loop --- */
252 struct timeval tv, *ptv;
254 /* --- Wait for a keypress --- */
258 FD_SET(STDIN_FILENO, &fd);
259 maxfd = STDIN_FILENO + 1;
266 /* --- Wait for the timer to expire --- */
269 gettimeofday(&tv, 0);
270 TV_SUB(&tv, &when, &tv);
275 /* --- See what interesting things have happened --- */
277 if (select(maxfd, pfd, 0, 0, ptv) < 0) {
278 if (errno == EINTR || errno == EAGAIN)
280 die(1, "error in select: %s", strerror(errno));
283 /* --- Check the timer --- */
286 gettimeofday(&tv, 0);
287 if (TV_CMP(&tv, >=, &when))
291 /* --- Check the key state --- */
293 if (f & f_key && FD_ISSET(STDIN_FILENO, &fd))
297 /* --- See what gives --- */
300 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts_old);
304 /*----- That's all, folks -------------------------------------------------*/