tls: in AES-GCM decoding, avoid memmove
[oweals/busybox.git] / util-linux / script.c
index ba90b065dcd3dcc250b9677bb82a43e3badc7e01..aac77c3ba78dcba9740bcc31fb0de9402cd5e20a 100644 (file)
@@ -6,11 +6,43 @@
  *
  * Based on code from util-linux v 2.12r
  * Copyright (c) 1980
- *     The Regents of the University of California.  All rights reserved.
+ * The Regents of the University of California.  All rights reserved.
  *
- * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
+ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
  */
+//config:config SCRIPT
+//config:      bool "script (8 kb)"
+//config:      default y
+//config:      help
+//config:      The script makes typescript of terminal session.
+
+//applet:IF_SCRIPT(APPLET(script, BB_DIR_USR_BIN, BB_SUID_DROP))
+
+//kbuild:lib-$(CONFIG_SCRIPT) += script.o
+
+//usage:#define script_trivial_usage
+//usage:       "[-afq] [-t[FILE]] [-c PROG] [OUTFILE]"
+//usage:#define script_full_usage "\n\n"
+//usage:       "Default OUTFILE is 'typescript'"
+//usage:     "\n"
+//usage:     "\n       -a      Append output"
+//usage:     "\n       -c PROG Run PROG, not shell"
+/* Accepted but has no effect (we never buffer output) */
+/*//usage:     "\n     -f      Flush output after each write"*/
+//usage:     "\n       -q      Quiet"
+//usage:     "\n       -t[FILE] Send timing to stderr or FILE"
+
+//util-linux-2.28:
+//-e: return exit code of the child
+
+//FYI (reported as bbox bug #2749):
+// > script -q -c 'echo -e -n "1\n2\n3\n"' /dev/null </dev/null >123.txt
+// > The output file on full-blown ubuntu system contains 6 bytes.
+// > Output on Busybox system (arm-linux) contains extra '\r' byte in each line.
+//however, in my test, "script" from util-linux-2.28 seems to also add '\r' bytes.
+
 #include "libbb.h"
+#include "common_bufsiz.h"
 
 int script_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int script_main(int argc UNUSED_PARAM, char **argv)
@@ -24,6 +56,8 @@ int script_main(int argc UNUSED_PARAM, char **argv)
        char pty_line[GETPTY_BUFSIZE];
        struct termios tt, rtt;
        struct winsize win;
+       FILE *timing_fp;
+       const char *str_t = NULL;
        const char *fname = "typescript";
        const char *shell;
        char shell_opt[] = "-i";
@@ -37,19 +71,19 @@ int script_main(int argc UNUSED_PARAM, char **argv)
        };
 
 #if ENABLE_LONG_OPTS
-       static const char getopt_longopts[] ALIGN1 =
+       static const char script_longopts[] ALIGN1 =
                "append\0"  No_argument       "a"
                "command\0" Required_argument "c"
                "flush\0"   No_argument       "f"
                "quiet\0"   No_argument       "q"
-               IF_SCRIPTREPLAY("timing\0" No_argument "t")
+               "timing\0"  Optional_argument "t"
                ;
-
-       applet_long_options = getopt_longopts;
 #endif
 
-       opt_complementary = "?1"; /* max one arg */
-       opt = getopt32(argv, "ac:fq" IF_SCRIPTREPLAY("t") , &shell_arg);
+       opt = getopt32long(argv, "^" "ac:fqt::" "\0" "?1"/* max one arg */,
+                               script_longopts,
+                               &shell_arg, &str_t
+       );
        //argc -= optind;
        argv += optind;
        if (argv[0]) {
@@ -65,11 +99,19 @@ int script_main(int argc UNUSED_PARAM, char **argv)
        if (!(opt & OPT_q)) {
                printf("Script started, file is %s\n", fname);
        }
-       shell = getenv("SHELL");
-       if (shell == NULL) {
-               shell = DEFAULT_SHELL;
+       timing_fp = stderr;
+       if (str_t) {
+               timing_fp = xfopen_for_write(str_t);
        }
 
+       shell = get_shell_name();
+
+       /* Some people run "script ... 0>&-".
+        * Our code assumes that STDIN_FILENO != pty.
+        * Ensure STDIN_FILENO is not closed:
+        */
+       bb_sanitize_stdio();
+
        pty = xgetpty(pty_line);
 
        /* get current stdin's tty params */
@@ -92,12 +134,14 @@ int script_main(int argc UNUSED_PARAM, char **argv)
 
        if (child_pid) {
                /* parent */
-#define buf bb_common_bufsiz1
                struct pollfd pfd[2];
                int outfd, count, loop;
-               double oldtime = ENABLE_SCRIPTREPLAY ? time(NULL) : 0;
+               double oldtime = time(NULL);
                smallint fd_count = 2;
 
+#define buf bb_common_bufsiz1
+               setup_common_bufsiz();
+
                outfd = xopen(fname, mode);
                pfd[0].fd = pty;
                pfd[0].events = POLLIN;
@@ -118,30 +162,31 @@ int script_main(int argc UNUSED_PARAM, char **argv)
                        }
                        if (pfd[0].revents) {
                                errno = 0;
-                               count = safe_read(pty, buf, sizeof(buf));
+                               count = safe_read(pty, buf, COMMON_BUFSIZE);
                                if (count <= 0 && errno != EAGAIN) {
                                        /* err/eof from pty: exit */
                                        goto restore;
                                }
                                if (count > 0) {
-                                       if (ENABLE_SCRIPTREPLAY && (opt & OPT_t)) {
+                                       if (opt & OPT_t) {
                                                struct timeval tv;
                                                double newtime;
 
                                                gettimeofday(&tv, NULL);
                                                newtime = tv.tv_sec + (double) tv.tv_usec / 1000000;
-                                               fprintf(stderr, "%f %u\n", newtime - oldtime, count);
+                                               fprintf(timing_fp, "%f %u\n", newtime - oldtime, count);
                                                oldtime = newtime;
                                        }
                                        full_write(STDOUT_FILENO, buf, count);
                                        full_write(outfd, buf, count);
-                                       if (opt & OPT_f) {
-                                               fsync(outfd);
-                                       }
+                                       // If we'd be using (buffered) FILE i/o, we'd need this:
+                                       //if (opt & OPT_f) {
+                                       //      fflush(outfd);
+                                       //}
                                }
                        }
                        if (pfd[1].revents) {
-                               count = safe_read(STDIN_FILENO, buf, sizeof(buf));
+                               count = safe_read(STDIN_FILENO, buf, COMMON_BUFSIZE);
                                if (count <= 0) {
                                        /* err/eof from stdin: don't read stdin anymore */
                                        pfd[1].revents = 0;
@@ -160,7 +205,7 @@ int script_main(int argc UNUSED_PARAM, char **argv)
                 * (util-linux's script doesn't do this. buggy :) */
                loop = 999;
                /* pty is in O_NONBLOCK mode, we exit as soon as buffer is empty */
-               while (--loop && (count = safe_read(pty, buf, sizeof(buf))) > 0) {
+               while (--loop && (count = safe_read(pty, buf, COMMON_BUFSIZE)) > 0) {
                        full_write(STDOUT_FILENO, buf, count);
                        full_write(outfd, buf, count);
                }