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