diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-19 17:36:16 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2009-05-19 17:36:16 +0200 |
commit | 5e61115ea45c621867941e52e6ac016680415656 (patch) | |
tree | 7e92d0ee0720d907b4b35bfa510c3969c79eaaa8 /util-linux/script.c | |
parent | 5a49d284a6a9f6cf2076f23561f95aebdfd44592 (diff) | |
download | busybox-w32-5e61115ea45c621867941e52e6ac016680415656.tar.gz busybox-w32-5e61115ea45c621867941e52e6ac016680415656.tar.bz2 busybox-w32-5e61115ea45c621867941e52e6ac016680415656.zip |
scriptreplay: new applet. +423 bytes
Signed-off-by: Pascal Bellard <pascal.bellard@ads-lu.com>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'util-linux/script.c')
-rw-r--r-- | util-linux/script.c | 59 |
1 files changed, 39 insertions, 20 deletions
diff --git a/util-linux/script.c b/util-linux/script.c index a9f24b10e..d16a2914a 100644 --- a/util-linux/script.c +++ b/util-linux/script.c | |||
@@ -10,16 +10,8 @@ | |||
10 | * | 10 | * |
11 | * Licensed under GPLv2 or later, see file License in this tarball for details. | 11 | * Licensed under GPLv2 or later, see file License in this tarball for details. |
12 | */ | 12 | */ |
13 | |||
14 | #include "libbb.h" | 13 | #include "libbb.h" |
15 | 14 | ||
16 | static smallint fd_count = 2; | ||
17 | |||
18 | static void handle_sigchld(int sig UNUSED_PARAM) | ||
19 | { | ||
20 | fd_count = 0; | ||
21 | } | ||
22 | |||
23 | int script_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 15 | int script_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
24 | int script_main(int argc UNUSED_PARAM, char **argv) | 16 | int script_main(int argc UNUSED_PARAM, char **argv) |
25 | { | 17 | { |
@@ -36,6 +28,15 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
36 | const char *shell; | 28 | const char *shell; |
37 | char shell_opt[] = "-i"; | 29 | char shell_opt[] = "-i"; |
38 | char *shell_arg = NULL; | 30 | char *shell_arg = NULL; |
31 | enum { | ||
32 | OPT_a = (1 << 0), | ||
33 | OPT_c = (1 << 1), | ||
34 | OPT_f = (1 << 2), | ||
35 | OPT_q = (1 << 3), | ||
36 | #if ENABLE_SCRIPTREPLAY | ||
37 | OPT_t = (1 << 4), | ||
38 | #endif | ||
39 | }; | ||
39 | 40 | ||
40 | #if ENABLE_GETOPT_LONG | 41 | #if ENABLE_GETOPT_LONG |
41 | static const char getopt_longopts[] ALIGN1 = | 42 | static const char getopt_longopts[] ALIGN1 = |
@@ -43,25 +44,28 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
43 | "command\0" Required_argument "c" | 44 | "command\0" Required_argument "c" |
44 | "flush\0" No_argument "f" | 45 | "flush\0" No_argument "f" |
45 | "quiet\0" No_argument "q" | 46 | "quiet\0" No_argument "q" |
47 | # if ENABLE_SCRIPTREPLAY | ||
48 | "timing\0" No_argument "t" | ||
49 | # endif | ||
46 | ; | 50 | ; |
47 | 51 | ||
48 | applet_long_options = getopt_longopts; | 52 | applet_long_options = getopt_longopts; |
49 | #endif | 53 | #endif |
50 | opt_complementary = "?1"; /* max one arg */ | 54 | opt_complementary = "?1"; /* max one arg */ |
51 | opt = getopt32(argv, "ac:fq", &shell_arg); | 55 | opt = getopt32(argv, "ac:fq" IF_SCRIPTREPLAY("t") , &shell_arg); |
52 | //argc -= optind; | 56 | //argc -= optind; |
53 | argv += optind; | 57 | argv += optind; |
54 | if (argv[0]) { | 58 | if (argv[0]) { |
55 | fname = argv[0]; | 59 | fname = argv[0]; |
56 | } | 60 | } |
57 | mode = O_CREAT|O_TRUNC|O_WRONLY; | 61 | mode = O_CREAT|O_TRUNC|O_WRONLY; |
58 | if (opt & 1) { | 62 | if (opt & OPT_a) { |
59 | mode = O_CREAT|O_APPEND|O_WRONLY; | 63 | mode = O_CREAT|O_APPEND|O_WRONLY; |
60 | } | 64 | } |
61 | if (opt & 2) { | 65 | if (opt & OPT_c) { |
62 | shell_opt[1] = 'c'; | 66 | shell_opt[1] = 'c'; |
63 | } | 67 | } |
64 | if (!(opt & 8)) { /* not -q */ | 68 | if (!(opt & OPT_q)) { |
65 | printf("Script started, file is %s\n", fname); | 69 | printf("Script started, file is %s\n", fname); |
66 | } | 70 | } |
67 | shell = getenv("SHELL"); | 71 | shell = getenv("SHELL"); |
@@ -83,7 +87,7 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
83 | /* "script" from util-linux exits when child exits, | 87 | /* "script" from util-linux exits when child exits, |
84 | * we wouldn't wait for EOF from slave pty | 88 | * we wouldn't wait for EOF from slave pty |
85 | * (output may be produced by grandchildren of child) */ | 89 | * (output may be produced by grandchildren of child) */ |
86 | signal(SIGCHLD, handle_sigchld); | 90 | signal(SIGCHLD, record_signo); |
87 | 91 | ||
88 | /* TODO: SIGWINCH? pass window size changes down to slave? */ | 92 | /* TODO: SIGWINCH? pass window size changes down to slave? */ |
89 | 93 | ||
@@ -97,19 +101,23 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
97 | #define buf bb_common_bufsiz1 | 101 | #define buf bb_common_bufsiz1 |
98 | struct pollfd pfd[2]; | 102 | struct pollfd pfd[2]; |
99 | int outfd, count, loop; | 103 | int outfd, count, loop; |
104 | #if ENABLE_SCRIPTREPLAY | ||
105 | double oldtime = time(NULL); | ||
106 | #endif | ||
107 | smallint fd_count = 2; | ||
100 | 108 | ||
101 | outfd = xopen(fname, mode); | 109 | outfd = xopen(fname, mode); |
102 | pfd[0].fd = pty; | 110 | pfd[0].fd = pty; |
103 | pfd[0].events = POLLIN; | 111 | pfd[0].events = POLLIN; |
104 | pfd[1].fd = 0; | 112 | pfd[1].fd = STDIN_FILENO; |
105 | pfd[1].events = POLLIN; | 113 | pfd[1].events = POLLIN; |
106 | ndelay_on(pty); /* this descriptor is not shared, can do this */ | 114 | ndelay_on(pty); /* this descriptor is not shared, can do this */ |
107 | /* ndelay_on(0); - NO, stdin can be shared! Pity :( */ | 115 | /* ndelay_on(STDIN_FILENO); - NO, stdin can be shared! Pity :( */ |
108 | 116 | ||
109 | /* copy stdin to pty master input, | 117 | /* copy stdin to pty master input, |
110 | * copy pty master output to stdout and file */ | 118 | * copy pty master output to stdout and file */ |
111 | /* TODO: don't use full_write's, use proper write buffering */ | 119 | /* TODO: don't use full_write's, use proper write buffering */ |
112 | while (fd_count) { | 120 | while (fd_count && !bb_got_signal) { |
113 | /* not safe_poll! we want SIGCHLD to EINTR poll */ | 121 | /* not safe_poll! we want SIGCHLD to EINTR poll */ |
114 | if (poll(pfd, fd_count, -1) < 0 && errno != EINTR) { | 122 | if (poll(pfd, fd_count, -1) < 0 && errno != EINTR) { |
115 | /* If child exits too quickly, we may get EIO: | 123 | /* If child exits too quickly, we may get EIO: |
@@ -124,9 +132,20 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
124 | goto restore; | 132 | goto restore; |
125 | } | 133 | } |
126 | if (count > 0) { | 134 | if (count > 0) { |
135 | #if ENABLE_SCRIPTREPLAY | ||
136 | if (opt & OPT_t) { | ||
137 | struct timeval tv; | ||
138 | double newtime; | ||
139 | |||
140 | gettimeofday(&tv, NULL); | ||
141 | newtime = tv.tv_sec + (double) tv.tv_usec / 1000000; | ||
142 | fprintf(stderr, "%f %u\n", newtime - oldtime, count); | ||
143 | oldtime = newtime; | ||
144 | } | ||
145 | #endif | ||
127 | full_write(STDOUT_FILENO, buf, count); | 146 | full_write(STDOUT_FILENO, buf, count); |
128 | full_write(outfd, buf, count); | 147 | full_write(outfd, buf, count); |
129 | if (opt & 4) { /* -f */ | 148 | if (opt & OPT_f) { |
130 | fsync(outfd); | 149 | fsync(outfd); |
131 | } | 150 | } |
132 | } | 151 | } |
@@ -142,8 +161,8 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
142 | } | 161 | } |
143 | } | 162 | } |
144 | } | 163 | } |
145 | /* If loop was exited because SIGCHLD handler set fd_count to 0, | 164 | /* If loop was exited because SIGCHLD handler set bb_got_signal, |
146 | * there still can be some buffered output. But not loop forever: | 165 | * there still can be some buffered output. But dont loop forever: |
147 | * we won't pump orphaned grandchildren's output indefinitely. | 166 | * we won't pump orphaned grandchildren's output indefinitely. |
148 | * Testcase: running this in script: | 167 | * Testcase: running this in script: |
149 | * exec dd if=/dev/zero bs=1M count=1 | 168 | * exec dd if=/dev/zero bs=1M count=1 |
@@ -158,7 +177,7 @@ int script_main(int argc UNUSED_PARAM, char **argv) | |||
158 | restore: | 177 | restore: |
159 | if (attr_ok == 0) | 178 | if (attr_ok == 0) |
160 | tcsetattr(0, TCSAFLUSH, &tt); | 179 | tcsetattr(0, TCSAFLUSH, &tt); |
161 | if (!(opt & 8)) /* not -q */ | 180 | if (!(opt & OPT_q)) |
162 | printf("Script done, file is %s\n", fname); | 181 | printf("Script done, file is %s\n", fname); |
163 | return EXIT_SUCCESS; | 182 | return EXIT_SUCCESS; |
164 | } | 183 | } |