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 -------------------------------------------------*/