mirror of
https://github.com/freebsd/freebsd-src.git
synced 2024-11-26 20:12:44 +00:00
script: handle terminal resize on SIGWINCH
Add a -w flag to forward terminal resize events on to the child, which can be useful in some circumstances to avoid terminal corruption. Reviewed by: des Co-authored-by: Xavier Beaudouin <xavier.beaudouin@klarasystems.com> Sponsored by: Modirum MDPay Sponsored by: Klara, Inc. Differential Revision: https://reviews.freebsd.org/D44167
This commit is contained in:
parent
4459abe334
commit
8ceac8e13d
@ -33,7 +33,7 @@
|
||||
.Nd make typescript of terminal session
|
||||
.Sh SYNOPSIS
|
||||
.Nm
|
||||
.Op Fl aeFfkqr
|
||||
.Op Fl aeFfkqrw
|
||||
.Op Fl t Ar time
|
||||
.Op Ar file Op Ar command ...
|
||||
.Nm
|
||||
@ -131,6 +131,9 @@ characters, it indicates the default format:
|
||||
which is useful for both tools and humans to read, should be used.
|
||||
Note that time-stamps will only be output when different from the
|
||||
previous one.
|
||||
.It Fl w
|
||||
Forward terminal size changes on
|
||||
.Dv SIGWINCH .
|
||||
.El
|
||||
.Pp
|
||||
The script ends when the forked shell (or command) exits (a
|
||||
|
@ -77,6 +77,7 @@ static char *fmfname;
|
||||
static int fflg, qflg, ttyflg;
|
||||
static int usesleep, rawout, showexit;
|
||||
static TAILQ_HEAD(, buf_elm) obuf_list = TAILQ_HEAD_INITIALIZER(obuf_list);
|
||||
static volatile sig_atomic_t doresize;
|
||||
|
||||
static struct termios tt;
|
||||
|
||||
@ -94,31 +95,43 @@ static void record(FILE *, char *, size_t, int);
|
||||
static void consume(FILE *, off_t, char *, int);
|
||||
static void playback(FILE *) __dead2;
|
||||
static void usage(void) __dead2;
|
||||
static void resizeit(int);
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct termios rtt, stt;
|
||||
struct winsize win;
|
||||
struct timeval tv, *tvp;
|
||||
struct timespec tv, *tvp;
|
||||
time_t tvec, start;
|
||||
char obuf[BUFSIZ];
|
||||
char ibuf[BUFSIZ];
|
||||
sigset_t *pselmask, selmask;
|
||||
fd_set rfd, wfd;
|
||||
struct buf_elm *be;
|
||||
ssize_t cc;
|
||||
int aflg, Fflg, kflg, pflg, ch, k, n, fcm;
|
||||
int aflg, Fflg, kflg, pflg, wflg, ch, k, n, fcm;
|
||||
int flushtime, readstdin;
|
||||
int fm_fd, fm_log;
|
||||
|
||||
aflg = Fflg = kflg = pflg = 0;
|
||||
aflg = Fflg = kflg = pflg = wflg = 0;
|
||||
doresize = 0;
|
||||
usesleep = 1;
|
||||
rawout = 0;
|
||||
flushtime = 30;
|
||||
fm_fd = -1;
|
||||
showexit = 0;
|
||||
|
||||
while ((ch = getopt(argc, argv, "adeFfkpqrT:t:")) != -1)
|
||||
/*
|
||||
* For normal operation, we'll leave pselmask == NULL so that pselect(2)
|
||||
* leaves the signal mask alone. If -w is specified, we'll restore the
|
||||
* process signal mask upon entry with SIGWINCH unblocked so that we can
|
||||
* forward resize events properly.
|
||||
*/
|
||||
sigemptyset(&selmask);
|
||||
pselmask = NULL;
|
||||
|
||||
while ((ch = getopt(argc, argv, "adeFfkpqrT:t:w")) != -1)
|
||||
switch (ch) {
|
||||
case 'a':
|
||||
aflg = 1;
|
||||
@ -157,6 +170,9 @@ main(int argc, char *argv[])
|
||||
if (strchr(optarg, '%'))
|
||||
tstamp_fmt = optarg;
|
||||
break;
|
||||
case 'w':
|
||||
wflg = 1;
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
@ -260,6 +276,23 @@ main(int argc, char *argv[])
|
||||
}
|
||||
close(slave);
|
||||
|
||||
if (wflg) {
|
||||
struct sigaction sa = { .sa_handler = resizeit };
|
||||
sigset_t smask;
|
||||
|
||||
sigaction(SIGWINCH, &sa, NULL);
|
||||
|
||||
sigemptyset(&smask);
|
||||
sigaddset(&smask, SIGWINCH);
|
||||
|
||||
if (sigprocmask(SIG_BLOCK, &smask, &selmask) != 0)
|
||||
err(1, "Failed to block SIGWINCH");
|
||||
|
||||
/* Just in case SIGWINCH was blocked before we came in. */
|
||||
sigdelset(&selmask, SIGWINCH);
|
||||
pselmask = &selmask;
|
||||
}
|
||||
|
||||
start = tvec = time(0);
|
||||
readstdin = 1;
|
||||
for (;;) {
|
||||
@ -272,19 +305,26 @@ main(int argc, char *argv[])
|
||||
FD_SET(master, &wfd);
|
||||
if (!readstdin && ttyflg) {
|
||||
tv.tv_sec = 1;
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_nsec = 0;
|
||||
tvp = &tv;
|
||||
readstdin = 1;
|
||||
} else if (flushtime > 0) {
|
||||
tv.tv_sec = flushtime - (tvec - start);
|
||||
tv.tv_usec = 0;
|
||||
tv.tv_nsec = 0;
|
||||
tvp = &tv;
|
||||
} else {
|
||||
tvp = NULL;
|
||||
}
|
||||
n = select(master + 1, &rfd, &wfd, NULL, tvp);
|
||||
n = pselect(master + 1, &rfd, &wfd, NULL, tvp, pselmask);
|
||||
if (n < 0 && errno != EINTR)
|
||||
break;
|
||||
|
||||
if (doresize) {
|
||||
if (ioctl(STDIN_FILENO, TIOCGWINSZ, &win) != -1)
|
||||
ioctl(master, TIOCSWINSZ, &win);
|
||||
doresize = 0;
|
||||
}
|
||||
|
||||
if (n > 0 && FD_ISSET(STDIN_FILENO, &rfd)) {
|
||||
cc = read(STDIN_FILENO, ibuf, BUFSIZ);
|
||||
if (cc < 0)
|
||||
@ -359,7 +399,7 @@ static void
|
||||
usage(void)
|
||||
{
|
||||
(void)fprintf(stderr,
|
||||
"usage: script [-aeFfkpqr] [-t time] [file [command ...]]\n");
|
||||
"usage: script [-aeFfkpqrw] [-t time] [file [command ...]]\n");
|
||||
(void)fprintf(stderr,
|
||||
" script -p [-deq] [-T fmt] [file]\n");
|
||||
exit(1);
|
||||
@ -605,3 +645,9 @@ playback(FILE *fp)
|
||||
(void)fclose(fp);
|
||||
exit(0);
|
||||
}
|
||||
|
||||
static void
|
||||
resizeit(int signo __unused)
|
||||
{
|
||||
doresize = 1;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user