2 * Copyright (c) 1980 Regents of the University of California.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35 * 1999-02-22 Arkadiusz MiĆkiewicz <misiek@pld.ORG.PL>
36 * - added Native Language Support
38 * 2000-07-30 Per Andreas Buer <per@linpro.no> - added "q"-option
40 * 2014-05-30 Csaba Kos <csaba.kos@gmail.com>
41 * - fixed a rare deadlock after child termination
50 #include <sys/ioctl.h>
63 #include <sys/signalfd.h>
67 #include "closestream.h"
72 #include "monotonic.h"
73 #include "timeutils.h"
77 static UL_DEBUG_DEFINE_MASK(script
);
78 UL_DEBUG_DEFINE_MASKNAMES(script
) = UL_DEBUG_EMPTY_MASKNAMES
;
80 #define SCRIPT_DEBUG_INIT (1 << 1)
81 #define SCRIPT_DEBUG_POLL (1 << 2)
82 #define SCRIPT_DEBUG_SIGNAL (1 << 3)
83 #define SCRIPT_DEBUG_IO (1 << 4)
84 #define SCRIPT_DEBUG_MISC (1 << 5)
85 #define SCRIPT_DEBUG_ALL 0xFFFF
87 #define DBG(m, x) __UL_DBG(script, SCRIPT_DEBUG_, m, x)
88 #define ON_DBG(m, x) __UL_DBG_CALL(script, SCRIPT_DEBUG_, m, x)
90 #if defined(HAVE_LIBUTIL) && defined(HAVE_PTY_H)
94 #ifdef HAVE_LIBUTEMPTER
95 # include <utempter.h>
98 #define DEFAULT_TYPESCRIPT_FILENAME "typescript"
100 struct script_control
{
101 char *shell
; /* shell to be executed */
102 char *command
; /* command to be executed */
103 char *fname
; /* output file path */
104 FILE *typescriptfp
; /* output file pointer */
105 char *tname
; /* timing file path */
106 FILE *timingfp
; /* timing file pointer */
107 struct timeval oldtime
; /* previous write or command start time */
108 int master
; /* pseudoterminal master file descriptor */
109 int slave
; /* pseudoterminal slave file descriptor */
110 int poll_timeout
; /* poll() timeout, used in end of execution */
111 pid_t child
; /* child pid */
112 int childstatus
; /* child process exit value */
113 struct termios attrs
; /* slave terminal runtime attributes */
114 struct winsize win
; /* terminal window size */
115 #if !HAVE_LIBUTIL || !HAVE_PTY_H
116 char *line
; /* terminal line */
119 append
:1, /* append output */
120 rc_wanted
:1, /* return child exit value */
121 flush
:1, /* flush after each write */
122 quiet
:1, /* suppress most output */
123 timing
:1, /* include timing file */
124 force
:1, /* write output to links */
125 isterm
:1, /* is child process running as terminal */
126 die
:1; /* terminate program */
128 sigset_t sigset
; /* catch SIGCHLD and SIGWINCH with signalfd() */
129 sigset_t sigorg
; /* original signal mask */
130 int sigfd
; /* file descriptor for signalfd() */
133 static void script_init_debug(void)
135 __UL_INIT_DEBUG(script
, SCRIPT_DEBUG_
, 0, SCRIPT_DEBUG
);
139 * For tests we want to be able to control time output
142 static inline time_t script_time(time_t *t
)
144 const char *str
= getenv("SCRIPT_TEST_SECOND_SINCE_EPOCH");
147 if (!str
|| sscanf(str
, "%"SCNi64
, &sec
) != 1)
153 #else /* !TEST_SCRIPT */
154 # define script_time(x) time(x)
157 static void __attribute__((__noreturn__
)) usage(void)
160 fputs(USAGE_HEADER
, out
);
161 fprintf(out
, _(" %s [options] [file]\n"), program_invocation_short_name
);
163 fputs(USAGE_SEPARATOR
, out
);
164 fputs(_("Make a typescript of a terminal session.\n"), out
);
166 fputs(USAGE_OPTIONS
, out
);
167 fputs(_(" -a, --append append the output\n"
168 " -c, --command <command> run command rather than interactive shell\n"
169 " -e, --return return exit code of the child process\n"
170 " -f, --flush run flush after each write\n"
171 " --force use output file even when it is a link\n"
172 " -q, --quiet be quiet\n"
173 " -t, --timing[=<file>] output timing data to stderr (or to FILE)\n"
175 print_usage_help_options(25);
177 fprintf(out
, USAGE_MAN_TAIL("script(1)"));
181 static void die_if_link(const struct script_control
*ctl
)
187 if (lstat(ctl
->fname
, &s
) == 0 && (S_ISLNK(s
.st_mode
) || s
.st_nlink
> 1))
189 _("output file `%s' is a link\n"
190 "Use --force if you really want to use it.\n"
191 "Program not started."), ctl
->fname
);
194 static void restore_tty(struct script_control
*ctl
, int mode
)
202 tcsetattr(STDIN_FILENO
, mode
, &rtt
);
205 static void enable_rawmode_tty(struct script_control
*ctl
)
214 rtt
.c_lflag
&= ~ECHO
;
215 tcsetattr(STDIN_FILENO
, TCSANOW
, &rtt
);
218 static void __attribute__((__noreturn__
)) done(struct script_control
*ctl
)
220 DBG(MISC
, ul_debug("done!"));
222 restore_tty(ctl
, TCSADRAIN
);
224 if (!ctl
->quiet
&& ctl
->typescriptfp
)
225 printf(_("Script done, file is %s\n"), ctl
->fname
);
226 #ifdef HAVE_LIBUTEMPTER
227 if (ctl
->master
>= 0)
228 utempter_remove_record(ctl
->master
);
230 kill(ctl
->child
, SIGTERM
); /* make sure we don't create orphans */
232 if (ctl
->timingfp
&& close_stream(ctl
->timingfp
) != 0)
233 err(EXIT_FAILURE
, "write failed: %s", ctl
->tname
);
234 if (ctl
->typescriptfp
&& close_stream(ctl
->typescriptfp
) != 0)
235 err(EXIT_FAILURE
, "write failed: %s", ctl
->fname
);
237 if (ctl
->rc_wanted
) {
238 if (WIFSIGNALED(ctl
->childstatus
))
239 exit(WTERMSIG(ctl
->childstatus
) + 0x80);
241 exit(WEXITSTATUS(ctl
->childstatus
));
246 static void __attribute__((__noreturn__
)) fail(struct script_control
*ctl
)
248 DBG(MISC
, ul_debug("fail!"));
253 static void wait_for_child(struct script_control
*ctl
, int wait
)
257 int options
= wait
? 0 : WNOHANG
;
259 DBG(MISC
, ul_debug("waiting for child"));
261 while ((pid
= wait3(&status
, options
, NULL
)) > 0)
262 if (pid
== ctl
->child
)
263 ctl
->childstatus
= status
;
266 static void write_output(struct script_control
*ctl
, char *obuf
,
269 DBG(IO
, ul_debug(" writing output"));
271 if (ctl
->timing
&& ctl
->timingfp
) {
272 struct timeval now
, delta
;
274 DBG(IO
, ul_debug(" writing timing info"));
276 gettime_monotonic(&now
);
277 timersub(&now
, &ctl
->oldtime
, &delta
);
278 fprintf(ctl
->timingfp
, "%ld.%06ld %zd\n",
279 (long)delta
.tv_sec
, (long)delta
.tv_usec
, bytes
);
281 fflush(ctl
->timingfp
);
285 DBG(IO
, ul_debug(" writing to script file"));
287 if (fwrite_all(obuf
, 1, bytes
, ctl
->typescriptfp
)) {
288 warn(_("cannot write script file"));
292 fflush(ctl
->typescriptfp
);
294 DBG(IO
, ul_debug(" writing to output"));
296 if (write_all(STDOUT_FILENO
, obuf
, bytes
)) {
297 DBG(IO
, ul_debug(" writing output *failed*"));
298 warn(_("write failed"));
302 DBG(IO
, ul_debug(" writing output *done*"));
305 static int write_to_shell(struct script_control
*ctl
,
306 char *buf
, size_t bufsz
)
308 return write_all(ctl
->master
, buf
, bufsz
);
312 * The script(1) is usually faster than shell, so it's a good idea to wait until
313 * the previous message has been already read by shell from slave before we
314 * write to master. This is necessary especially for EOF situation when we can
315 * send EOF to master before shell is fully initialized, to workaround this
316 * problem we wait until slave is empty. For example:
318 * echo "date" | script
320 * Unfortunately, the child (usually shell) can ignore stdin at all, so we
321 * don't wait forever to avoid dead locks...
323 * Note that script is primarily designed for interactive sessions as it
324 * maintains master+slave tty stuff within the session. Use pipe to write to
325 * script(1) and assume non-interactive (tee-like) behavior is NOT well
328 static void write_eof_to_shell(struct script_control
*ctl
)
330 unsigned int tries
= 0;
331 struct pollfd fds
[] = {
332 { .fd
= ctl
->slave
, .events
= POLLIN
}
336 DBG(IO
, ul_debug(" waiting for empty slave"));
337 while (poll(fds
, 1, 10) == 1 && tries
< 8) {
338 DBG(IO
, ul_debug(" slave is not empty"));
343 DBG(IO
, ul_debug(" slave is empty now"));
345 DBG(IO
, ul_debug(" sending EOF to master"));
346 write_to_shell(ctl
, &c
, sizeof(char));
349 static void handle_io(struct script_control
*ctl
, int fd
, int *eof
)
354 DBG(IO
, ul_debug("%d FD active", fd
));
357 /* read from active FD */
358 bytes
= read(fd
, buf
, sizeof(buf
));
360 if (errno
== EAGAIN
|| errno
== EINTR
)
370 /* from stdin (user) to command */
371 if (fd
== STDIN_FILENO
) {
372 DBG(IO
, ul_debug(" stdin --> master %zd bytes", bytes
));
374 if (write_to_shell(ctl
, buf
, bytes
)) {
375 warn(_("write failed"));
378 /* without sync write_output() will write both input &
379 * shell output that looks like double echoing */
380 fdatasync(ctl
->master
);
382 /* from command (master) to stdout */
383 } else if (fd
== ctl
->master
) {
384 DBG(IO
, ul_debug(" master --> stdout %zd bytes", bytes
));
385 write_output(ctl
, buf
, bytes
);
389 static void handle_signal(struct script_control
*ctl
, int fd
)
391 struct signalfd_siginfo info
;
394 DBG(SIGNAL
, ul_debug("signal FD %d active", fd
));
396 bytes
= read(fd
, &info
, sizeof(info
));
397 if (bytes
!= sizeof(info
)) {
398 if (bytes
< 0 && (errno
== EAGAIN
|| errno
== EINTR
))
403 switch (info
.ssi_signo
) {
405 DBG(SIGNAL
, ul_debug(" get signal SIGCHLD"));
406 wait_for_child(ctl
, 0);
407 ctl
->poll_timeout
= 10;
410 DBG(SIGNAL
, ul_debug(" get signal SIGWINCH"));
412 ioctl(STDIN_FILENO
, TIOCGWINSZ
, (char *)&ctl
->win
);
413 ioctl(ctl
->slave
, TIOCSWINSZ
, (char *)&ctl
->win
);
421 DBG(SIGNAL
, ul_debug(" get signal SIG{TERM,INT,QUIT}"));
422 fprintf(stderr
, _("\nSession terminated.\n"));
423 /* Child termination is going to generate SIGCHILD (see above) */
424 kill(ctl
->child
, SIGTERM
);
431 static void do_io(struct script_control
*ctl
)
433 int ret
, ignore_stdin
= 0, eof
= 0;
434 time_t tvec
= script_time((time_t *)NULL
);
439 POLLFD_STDIN
/* optional; keep it last, see ignore_stdin */
442 struct pollfd pfd
[] = {
443 [POLLFD_SIGNAL
] = { .fd
= ctl
->sigfd
, .events
= POLLIN
| POLLERR
| POLLHUP
},
444 [POLLFD_MASTER
] = { .fd
= ctl
->master
, .events
= POLLIN
| POLLERR
| POLLHUP
},
445 [POLLFD_STDIN
] = { .fd
= STDIN_FILENO
, .events
= POLLIN
| POLLERR
| POLLHUP
}
449 if ((ctl
->typescriptfp
=
450 fopen(ctl
->fname
, ctl
->append
? "a" UL_CLOEXECSTR
: "w" UL_CLOEXECSTR
)) == NULL
) {
452 restore_tty(ctl
, TCSANOW
);
453 warn(_("cannot open %s"), ctl
->fname
);
457 const char *tname
= ctl
->tname
? ctl
->tname
: "/dev/stderr";
459 if (!(ctl
->timingfp
= fopen(tname
, "w" UL_CLOEXECSTR
))) {
460 restore_tty(ctl
, TCSANOW
);
461 warn(_("cannot open %s"), tname
);
467 if (ctl
->typescriptfp
) {
468 strtime_iso(&tvec
, ISO_8601_DATE
| ISO_8601_TIME
|
469 ISO_8601_TIMEZONE
| ISO_8601_SPACE
,
471 fprintf(ctl
->typescriptfp
, _("Script started on %s\n"), buf
);
473 gettime_monotonic(&ctl
->oldtime
);
479 DBG(POLL
, ul_debug("calling poll()"));
481 /* wait for input or signal */
482 ret
= poll(pfd
, ARRAY_SIZE(pfd
) - ignore_stdin
, ctl
->poll_timeout
);
484 DBG(POLL
, ul_debug("poll() rc=%d", ret
));
489 warn(_("poll failed"));
493 DBG(POLL
, ul_debug("setting die=1"));
498 for (i
= 0; i
< ARRAY_SIZE(pfd
) - ignore_stdin
; i
++) {
499 if (pfd
[i
].revents
== 0)
502 DBG(POLL
, ul_debug(" active pfd[%s].fd=%d %s %s %s",
503 i
== POLLFD_STDIN
? "stdin" :
504 i
== POLLFD_MASTER
? "master" :
505 i
== POLLFD_SIGNAL
? "signal" : "???",
507 pfd
[i
].revents
& POLLIN
? "POLLIN" : "",
508 pfd
[i
].revents
& POLLHUP
? "POLLHUP" : "",
509 pfd
[i
].revents
& POLLERR
? "POLLERR" : ""));
514 if (pfd
[i
].revents
& POLLIN
)
515 handle_io(ctl
, pfd
[i
].fd
, &eof
);
516 /* EOF maybe detected by two ways:
517 * A) poll() return POLLHUP event after close()
518 * B) read() returns 0 (no data) */
519 if ((pfd
[i
].revents
& POLLHUP
) || eof
) {
520 DBG(POLL
, ul_debug(" ignore FD"));
522 /* according to man poll() set FD to -1 can't be used to ignore
523 * STDIN, so let's remove the FD from pool at all */
524 if (i
== POLLFD_STDIN
) {
526 write_eof_to_shell(ctl
);
527 DBG(POLL
, ul_debug(" ignore STDIN"));
532 handle_signal(ctl
, pfd
[i
].fd
);
538 DBG(POLL
, ul_debug("poll() done"));
541 wait_for_child(ctl
, 1);
543 if (ctl
->typescriptfp
) {
544 tvec
= script_time((time_t *)NULL
);
545 strtime_iso(&tvec
, ISO_8601_DATE
| ISO_8601_TIME
|
546 ISO_8601_TIMEZONE
| ISO_8601_SPACE
,
548 fprintf(ctl
->typescriptfp
, _("\nScript done on %s\n"), buf
);
553 static void getslave(struct script_control
*ctl
)
556 ctl
->line
[strlen("/dev/")] = 't';
557 ctl
->slave
= open(ctl
->line
, O_RDWR
| O_CLOEXEC
);
558 if (ctl
->slave
< 0) {
559 warn(_("cannot open %s"), ctl
->line
);
563 tcsetattr(ctl
->slave
, TCSANOW
, &ctl
->attrs
);
564 ioctl(ctl
->slave
, TIOCSWINSZ
, (char *)&ctl
->win
);
568 ioctl(ctl
->slave
, TIOCSCTTY
, 0);
571 /* don't use DBG() stuff here otherwise it will be in the typescript file */
572 static void __attribute__((__noreturn__
)) do_shell(struct script_control
*ctl
)
578 /* close things irrelevant for this process */
582 dup2(ctl
->slave
, STDIN_FILENO
);
583 dup2(ctl
->slave
, STDOUT_FILENO
);
584 dup2(ctl
->slave
, STDERR_FILENO
);
589 shname
= strrchr(ctl
->shell
, '/');
595 sigprocmask(SIG_SETMASK
, &ctl
->sigorg
, NULL
);
598 * When invoked from within /etc/csh.login, script spawns a csh shell
599 * that spawns programs that cannot be killed with a SIGTERM. This is
600 * because csh has a documented behavior wherein it disables all
601 * signals when processing the /etc/csh.* files.
603 * Let's restore the default behavior.
605 signal(SIGTERM
, SIG_DFL
);
607 if (access(ctl
->shell
, X_OK
) == 0) {
609 execl(ctl
->shell
, shname
, "-c", ctl
->command
, NULL
);
611 execl(ctl
->shell
, shname
, "-i", NULL
);
614 execlp(shname
, "-c", ctl
->command
, NULL
);
616 execlp(shname
, "-i", NULL
);
618 warn(_("failed to execute %s"), ctl
->shell
);
623 static void getmaster(struct script_control
*ctl
)
625 #if defined(HAVE_LIBUTIL) && defined(HAVE_PTY_H)
628 ctl
->isterm
= isatty(STDIN_FILENO
);
631 if (tcgetattr(STDIN_FILENO
, &ctl
->attrs
) != 0)
632 err(EXIT_FAILURE
, _("failed to get terminal attributes"));
633 ioctl(STDIN_FILENO
, TIOCGWINSZ
, (char *)&ctl
->win
);
634 rc
= openpty(&ctl
->master
, &ctl
->slave
, NULL
, &ctl
->attrs
, &ctl
->win
);
636 rc
= openpty(&ctl
->master
, &ctl
->slave
, NULL
, NULL
, NULL
);
639 warn(_("openpty failed"));
643 char *pty
, *bank
, *cp
;
645 ctl
->isterm
= isatty(STDIN_FILENO
);
647 pty
= &ctl
->line
[strlen("/dev/ptyp")];
648 for (bank
= "pqrs"; *bank
; bank
++) {
649 ctl
->line
[strlen("/dev/pty")] = *bank
;
651 if (access(ctl
->line
, F_OK
) != 0)
653 for (cp
= "0123456789abcdef"; *cp
; cp
++) {
655 ctl
->master
= open(ctl
->line
, O_RDWR
| O_CLOEXEC
);
656 if (ctl
->master
>= 0) {
657 char *tp
= &ctl
->line
[strlen("/dev/")];
660 /* verify slave side is usable */
662 ok
= access(ctl
->line
, R_OK
| W_OK
) == 0;
666 tcgetattr(STDIN_FILENO
, &ctl
->attrs
);
667 ioctl(STDIN_FILENO
, TIOCGWINSZ
, (char *)&ctl
->win
);
677 warn(_("out of pty's"));
679 #endif /* not HAVE_LIBUTIL */
681 DBG(IO
, ul_debug("master fd: %d", ctl
->master
));
684 int main(int argc
, char **argv
)
686 struct script_control ctl
= {
687 #if !HAVE_LIBUTIL || !HAVE_PTY_H
688 .line
= "/dev/ptyXX",
696 enum { FORCE_OPTION
= CHAR_MAX
+ 1 };
698 static const struct option longopts
[] = {
699 {"append", no_argument
, NULL
, 'a'},
700 {"command", required_argument
, NULL
, 'c'},
701 {"return", no_argument
, NULL
, 'e'},
702 {"flush", no_argument
, NULL
, 'f'},
703 {"force", no_argument
, NULL
, FORCE_OPTION
,},
704 {"quiet", no_argument
, NULL
, 'q'},
705 {"timing", optional_argument
, NULL
, 't'},
706 {"version", no_argument
, NULL
, 'V'},
707 {"help", no_argument
, NULL
, 'h'},
711 setlocale(LC_ALL
, "");
713 * script -t prints time delays as floating point numbers. The example
714 * program (scriptreplay) that we provide to handle this timing output
715 * is a perl script, and does not handle numbers in locale format (not
716 * even when "use locale;" is added). So, since these numbers are not
717 * for human consumption, it seems easiest to set LC_NUMERIC here.
719 setlocale(LC_NUMERIC
, "C");
720 bindtextdomain(PACKAGE
, LOCALEDIR
);
722 atexit(close_stdout
);
726 while ((ch
= getopt_long(argc
, argv
, "ac:efqt::Vh", longopts
, NULL
)) != -1)
732 ctl
.command
= optarg
;
752 printf(UTIL_LINUX_VERSION
);
759 errtryhelp(EXIT_FAILURE
);
767 ctl
.fname
= DEFAULT_TYPESCRIPT_FILENAME
;
771 ctl
.shell
= getenv("SHELL");
772 if (ctl
.shell
== NULL
)
773 ctl
.shell
= _PATH_BSHELL
;
777 printf(_("Script started, file is %s\n"), ctl
.fname
);
778 enable_rawmode_tty(&ctl
);
780 #ifdef HAVE_LIBUTEMPTER
781 utempter_add_record(ctl
.master
, NULL
);
783 /* setup signal handler */
784 sigemptyset(&ctl
.sigset
);
785 sigaddset(&ctl
.sigset
, SIGCHLD
);
786 sigaddset(&ctl
.sigset
, SIGWINCH
);
787 sigaddset(&ctl
.sigset
, SIGTERM
);
788 sigaddset(&ctl
.sigset
, SIGINT
);
789 sigaddset(&ctl
.sigset
, SIGQUIT
);
791 /* block signals used for signalfd() to prevent the signals being
792 * handled according to their default dispositions */
793 sigprocmask(SIG_BLOCK
, &ctl
.sigset
, &ctl
.sigorg
);
795 if ((ctl
.sigfd
= signalfd(-1, &ctl
.sigset
, SFD_CLOEXEC
)) < 0)
796 err(EXIT_FAILURE
, _("cannot set signal handler"));
798 DBG(SIGNAL
, ul_debug("signal fd=%d", ctl
.sigfd
));
805 warn(_("fork failed"));
811 default: /* parent */
816 /* should not happen, all used functions are non-return */