5 * (c) 1999 Mark Wooding
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Pause.
12 * Pause is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later ersion.
17 * Pause is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with Pause; if not, write to the Free Software Foundation,
24 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 /*----- Header files ------------------------------------------------------*/
36 #include <sys/types.h>
41 #include <mLib/mdwopt.h>
42 #include <mLib/quis.h>
43 #include <mLib/report.h>
46 /*----- Static variables --------------------------------------------------*/
48 static struct termios ts_old, ts;
50 /*----- Main code ---------------------------------------------------------*/
54 * Arguments: @int s@ = signal number
58 * Use: Handles various fatal signals by resetting the terminal state
59 * and re-emitting the signal.
62 static void sig(int s)
64 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts_old);
69 /* --- @suspend@ --- *
71 * Arguments: @int s@ = signal number
75 * Use: Handles a job control signal, as recommended in APUE. It
76 * resets the terminal state, resets the signal disposition,
77 * unblocks the signal and re-emits it (so that the shell
78 * shows the right message). When that call returns, the
79 * signal handler is reattached, and the terminal state is set
83 static void suspend(int s)
87 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts_old);
91 sigprocmask(SIG_UNBLOCK, &ss, 0);
94 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts);
97 /* --- Traditional GNUey help options --- */
99 static void usage(FILE *fp)
101 pquis(fp, "Usage: $ [time]\n");
104 static void version(FILE *fp)
106 pquis(fp, "$ version " VERSION "\n");
109 static void help(FILE *fp)
115 Pauses until a key is pressed or an optional time-limit expires. The\n\
116 time is given as a floating point number with an option suffix of `s',\n\
117 `m', `h' or `d' (for `seconds', `minutes', `hours' or `days'\n\
120 Options available:\n\
122 -h, --help Show this help message.\n\
123 -v, --version Show program's version number.\n\
124 -u, --usage Show terse usage summary.\n\
130 * Arguments: @int argc@ = number of command line arguments
131 * @char *argv[]@ = vector of command line arguments
133 * Returns: Nonzero if it failed, zero if everything went well.
135 * Use: Souped-up version of `sleep'.
138 int main(int argc, char *argv[])
150 /* --- Library initialization --- */
154 /* --- Parse command line options --- */
157 static struct option opt[] = {
158 { "help", 0, 0, 'h' },
159 { "version", 0, 0, 'v' },
160 { "usage", 0, 0, 'u' },
163 int i = mdwopt(argc, argv, "hvu", opt, 0, 0, 0);
182 /* --- Parse a timer spec --- */
184 if (!(f & f_bogus) && optind < argc) {
185 const char *p =argv[optind++];
187 double t = strtod(p, &q);
192 case 's': if (q[1] != 0)
197 die(1, "bad time specification `%s'", p);
198 gettimeofday(&when, 0);
199 TV_ADDL(&when, &when, t, (t - floor(t)) * MILLION);
203 /* --- Report a syntax error --- */
212 /* --- Set up terminal for single keypresses --- */
214 if (tcgetattr(STDIN_FILENO, &ts_old) == 0) {
215 static struct { int sig; void (*func)(int); } sigs[] = {
219 { SIGTSTP, suspend },
224 /* --- Set up the new terminal attributes --- */
227 ts.c_lflag &= ~(ECHO | ICANON | TOSTOP);
229 /* --- Set up signal handlers to reset attributes --- */
231 for (i = 0; sigs[i].sig; i++) {
233 sigaction(sigs[i].sig, 0, &sa);
234 if (sa.sa_handler != SIG_IGN)
235 signal(sigs[i].sig, sigs[i].func);
237 signal(SIGTTIN, suspend);
239 /* --- Commit the terminal attribute changes --- */
241 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts);
245 /* --- Main loop --- */
250 struct timeval tv, *ptv;
252 /* --- Wait for a keypress --- */
256 FD_SET(STDIN_FILENO, &fd);
257 maxfd = STDIN_FILENO + 1;
264 /* --- Wait for the timer to expire --- */
267 gettimeofday(&tv, 0);
268 TV_SUB(&tv, &when, &tv);
273 /* --- See what interesting things have happened --- */
275 if (select(maxfd, pfd, 0, 0, ptv) < 0) {
276 if (errno == EINTR || errno == EAGAIN)
278 die(1, "error in select: %s", strerror(errno));
281 /* --- Check the timer --- */
284 gettimeofday(&tv, 0);
285 if (TV_CMP(&tv, >=, &when))
289 /* --- Check the key state --- */
291 if (f & f_key && FD_ISSET(STDIN_FILENO, &fd))
295 /* --- See what gives --- */
298 tcsetattr(STDIN_FILENO, TCSAFLUSH, &ts_old);
302 /*----- That's all, folks -------------------------------------------------*/