diff options
Diffstat (limited to 'util-linux/script.c')
-rw-r--r-- | util-linux/script.c | 54 |
1 files changed, 36 insertions, 18 deletions
diff --git a/util-linux/script.c b/util-linux/script.c index 9eebb51a4..aac77c3ba 100644 --- a/util-linux/script.c +++ b/util-linux/script.c | |||
@@ -21,15 +21,25 @@ | |||
21 | //kbuild:lib-$(CONFIG_SCRIPT) += script.o | 21 | //kbuild:lib-$(CONFIG_SCRIPT) += script.o |
22 | 22 | ||
23 | //usage:#define script_trivial_usage | 23 | //usage:#define script_trivial_usage |
24 | //usage: "[-afq" IF_SCRIPTREPLAY("t") "] [-c PROG] [OUTFILE]" | 24 | //usage: "[-afq] [-t[FILE]] [-c PROG] [OUTFILE]" |
25 | //usage:#define script_full_usage "\n\n" | 25 | //usage:#define script_full_usage "\n\n" |
26 | //usage: " -a Append output" | 26 | //usage: "Default OUTFILE is 'typescript'" |
27 | //usage: "\n" | ||
28 | //usage: "\n -a Append output" | ||
27 | //usage: "\n -c PROG Run PROG, not shell" | 29 | //usage: "\n -c PROG Run PROG, not shell" |
28 | //usage: "\n -f Flush output after each write" | 30 | /* Accepted but has no effect (we never buffer output) */ |
31 | /*//usage: "\n -f Flush output after each write"*/ | ||
29 | //usage: "\n -q Quiet" | 32 | //usage: "\n -q Quiet" |
30 | //usage: IF_SCRIPTREPLAY( | 33 | //usage: "\n -t[FILE] Send timing to stderr or FILE" |
31 | //usage: "\n -t Send timing to stderr" | 34 | |
32 | //usage: ) | 35 | //util-linux-2.28: |
36 | //-e: return exit code of the child | ||
37 | |||
38 | //FYI (reported as bbox bug #2749): | ||
39 | // > script -q -c 'echo -e -n "1\n2\n3\n"' /dev/null </dev/null >123.txt | ||
40 | // > The output file on full-blown ubuntu system contains 6 bytes. | ||
41 | // > Output on Busybox system (arm-linux) contains extra '\r' byte in each line. | ||
42 | //however, in my test, "script" from util-linux-2.28 seems to also add '\r' bytes. | ||
33 | 43 | ||
34 | #include "libbb.h" | 44 | #include "libbb.h" |
35 | #include "common_bufsiz.h" | 45 | #include "common_bufsiz.h" |
@@ -46,6 +56,8 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
46 | char pty_line[GETPTY_BUFSIZE]; | 56 | char pty_line[GETPTY_BUFSIZE]; |
47 | struct termios tt, rtt; | 57 | struct termios tt, rtt; |
48 | struct winsize win; | 58 | struct winsize win; |
59 | FILE *timing_fp; | ||
60 | const char *str_t = NULL; | ||
49 | const char *fname = "typescript"; | 61 | const char *fname = "typescript"; |
50 | const char *shell; | 62 | const char *shell; |
51 | char shell_opt[] = "-i"; | 63 | char shell_opt[] = "-i"; |
@@ -59,19 +71,19 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
59 | }; | 71 | }; |
60 | 72 | ||
61 | #if ENABLE_LONG_OPTS | 73 | #if ENABLE_LONG_OPTS |
62 | static const char getopt_longopts[] ALIGN1 = | 74 | static const char script_longopts[] ALIGN1 = |
63 | "append\0" No_argument "a" | 75 | "append\0" No_argument "a" |
64 | "command\0" Required_argument "c" | 76 | "command\0" Required_argument "c" |
65 | "flush\0" No_argument "f" | 77 | "flush\0" No_argument "f" |
66 | "quiet\0" No_argument "q" | 78 | "quiet\0" No_argument "q" |
67 | IF_SCRIPTREPLAY("timing\0" No_argument "t") | 79 | "timing\0" Optional_argument "t" |
68 | ; | 80 | ; |
69 | |||
70 | applet_long_options = getopt_longopts; | ||
71 | #endif | 81 | #endif |
72 | 82 | ||
73 | opt_complementary = "?1"; /* max one arg */ | 83 | opt = getopt32long(argv, "^" "ac:fqt::" "\0" "?1"/* max one arg */, |
74 | opt = getopt32(argv, "ac:fq" IF_SCRIPTREPLAY("t") , &shell_arg); | 84 | script_longopts, |
85 | &shell_arg, &str_t | ||
86 | ); | ||
75 | //argc -= optind; | 87 | //argc -= optind; |
76 | argv += optind; | 88 | argv += optind; |
77 | if (argv[0]) { | 89 | if (argv[0]) { |
@@ -87,6 +99,10 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
87 | if (!(opt & OPT_q)) { | 99 | if (!(opt & OPT_q)) { |
88 | printf("Script started, file is %s\n", fname); | 100 | printf("Script started, file is %s\n", fname); |
89 | } | 101 | } |
102 | timing_fp = stderr; | ||
103 | if (str_t) { | ||
104 | timing_fp = xfopen_for_write(str_t); | ||
105 | } | ||
90 | 106 | ||
91 | shell = get_shell_name(); | 107 | shell = get_shell_name(); |
92 | 108 | ||
@@ -120,8 +136,9 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
120 | /* parent */ | 136 | /* parent */ |
121 | struct pollfd pfd[2]; | 137 | struct pollfd pfd[2]; |
122 | int outfd, count, loop; | 138 | int outfd, count, loop; |
123 | double oldtime = ENABLE_SCRIPTREPLAY ? time(NULL) : 0; | 139 | double oldtime = time(NULL); |
124 | smallint fd_count = 2; | 140 | smallint fd_count = 2; |
141 | |||
125 | #define buf bb_common_bufsiz1 | 142 | #define buf bb_common_bufsiz1 |
126 | setup_common_bufsiz(); | 143 | setup_common_bufsiz(); |
127 | 144 | ||
@@ -151,20 +168,21 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
151 | goto restore; | 168 | goto restore; |
152 | } | 169 | } |
153 | if (count > 0) { | 170 | if (count > 0) { |
154 | if (ENABLE_SCRIPTREPLAY && (opt & OPT_t)) { | 171 | if (opt & OPT_t) { |
155 | struct timeval tv; | 172 | struct timeval tv; |
156 | double newtime; | 173 | double newtime; |
157 | 174 | ||
158 | gettimeofday(&tv, NULL); | 175 | gettimeofday(&tv, NULL); |
159 | newtime = tv.tv_sec + (double) tv.tv_usec / 1000000; | 176 | newtime = tv.tv_sec + (double) tv.tv_usec / 1000000; |
160 | fprintf(stderr, "%f %u\n", newtime - oldtime, count); | 177 | fprintf(timing_fp, "%f %u\n", newtime - oldtime, count); |
161 | oldtime = newtime; | 178 | oldtime = newtime; |
162 | } | 179 | } |
163 | full_write(STDOUT_FILENO, buf, count); | 180 | full_write(STDOUT_FILENO, buf, count); |
164 | full_write(outfd, buf, count); | 181 | full_write(outfd, buf, count); |
165 | if (opt & OPT_f) { | 182 | // If we'd be using (buffered) FILE i/o, we'd need this: |
166 | fsync(outfd); | 183 | //if (opt & OPT_f) { |
167 | } | 184 | // fflush(outfd); |
185 | //} | ||
168 | } | 186 | } |
169 | } | 187 | } |
170 | if (pfd[1].revents) { | 188 | if (pfd[1].revents) { |