diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-27 11:54:59 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-02-27 11:54:59 +0000 |
commit | 5014dada3fa0bb6f6873e28fe6491f0789239cdc (patch) | |
tree | 25cc7ed4e457d924131f3e7cdbab1e187a617639 | |
parent | 8195d20e36bfeeb30b3424e2635ba4757ec38137 (diff) | |
download | busybox-w32-5014dada3fa0bb6f6873e28fe6491f0789239cdc.tar.gz busybox-w32-5014dada3fa0bb6f6873e28fe6491f0789239cdc.tar.bz2 busybox-w32-5014dada3fa0bb6f6873e28fe6491f0789239cdc.zip |
script: new applet by Pascal Bellard <pascal.bellard AT ads-lu.com>
-rw-r--r-- | include/applets.h | 1 | ||||
-rw-r--r-- | include/libbb.h | 1 | ||||
-rw-r--r-- | include/usage.h | 9 | ||||
-rw-r--r-- | libbb/Kbuild | 1 | ||||
-rw-r--r-- | miscutils/Config.in | 6 | ||||
-rw-r--r-- | networking/telnetd.c | 47 | ||||
-rw-r--r-- | util-linux/Kbuild | 1 | ||||
-rw-r--r-- | util-linux/script.c | 195 |
8 files changed, 214 insertions, 47 deletions
diff --git a/include/applets.h b/include/applets.h index b2e89ee85..d4b6dbeaa 100644 --- a/include/applets.h +++ b/include/applets.h | |||
@@ -305,6 +305,7 @@ USE_RUNLEVEL(APPLET(runlevel, _BB_DIR_SBIN, _BB_SUID_NEVER)) | |||
305 | USE_RUNSV(APPLET(runsv, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 305 | USE_RUNSV(APPLET(runsv, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
306 | USE_RUNSVDIR(APPLET(runsvdir, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 306 | USE_RUNSVDIR(APPLET(runsvdir, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
307 | USE_RX(APPLET(rx, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | 307 | USE_RX(APPLET(rx, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) |
308 | USE_SCRIPT(APPLET(script, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) | ||
308 | USE_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER)) | 309 | USE_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER)) |
309 | USE_SELINUXENABLED(APPLET(selinuxenabled, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) | 310 | USE_SELINUXENABLED(APPLET(selinuxenabled, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) |
310 | USE_SENDMAIL(APPLET_ODDNAME(sendmail, sendgetmail, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sendmail)) | 311 | USE_SENDMAIL(APPLET_ODDNAME(sendmail, sendgetmail, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sendmail)) |
diff --git a/include/libbb.h b/include/libbb.h index 978cd2d87..707e8d69b 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -237,6 +237,7 @@ extern int recursive_action(const char *fileName, unsigned flags, | |||
237 | int (*dirAction) (const char *fileName, struct stat* statbuf, void* userData, int depth), | 237 | int (*dirAction) (const char *fileName, struct stat* statbuf, void* userData, int depth), |
238 | void* userData, unsigned depth); | 238 | void* userData, unsigned depth); |
239 | extern int device_open(const char *device, int mode); | 239 | extern int device_open(const char *device, int mode); |
240 | extern int getpty(char *line, int size); | ||
240 | extern int get_console_fd(void); | 241 | extern int get_console_fd(void); |
241 | extern char *find_block_device(const char *path); | 242 | extern char *find_block_device(const char *path); |
242 | /* bb_copyfd_XX print read/write errors and return -1 if they occur */ | 243 | /* bb_copyfd_XX print read/write errors and return -1 if they occur */ |
diff --git a/include/usage.h b/include/usage.h index 95cb69c73..4eac17401 100644 --- a/include/usage.h +++ b/include/usage.h | |||
@@ -3234,6 +3234,15 @@ USE_FEATURE_RUN_PARTS_FANCY("\n -l Prints names of all matching files even when | |||
3234 | #define rx_example_usage \ | 3234 | #define rx_example_usage \ |
3235 | "$ rx /tmp/foo\n" | 3235 | "$ rx /tmp/foo\n" |
3236 | 3236 | ||
3237 | #define script_trivial_usage \ | ||
3238 | "[-afq] [-c COMMAND] [OUTFILE]" | ||
3239 | #define script_full_usage \ | ||
3240 | "Options:" \ | ||
3241 | "\n -a Append output" \ | ||
3242 | "\n -c Run COMMAND, not shell" \ | ||
3243 | "\n -f Flush output after each write" \ | ||
3244 | "\n -q Quiet" | ||
3245 | |||
3237 | #define sed_trivial_usage \ | 3246 | #define sed_trivial_usage \ |
3238 | "[-efinr] pattern [files...]" | 3247 | "[-efinr] pattern [files...]" |
3239 | #define sed_full_usage \ | 3248 | #define sed_full_usage \ |
diff --git a/libbb/Kbuild b/libbb/Kbuild index aab016e85..fc87f625b 100644 --- a/libbb/Kbuild +++ b/libbb/Kbuild | |||
@@ -39,6 +39,7 @@ lib-y += get_console.o | |||
39 | lib-y += get_last_path_component.o | 39 | lib-y += get_last_path_component.o |
40 | lib-y += get_line_from_file.o | 40 | lib-y += get_line_from_file.o |
41 | lib-y += getopt32.o | 41 | lib-y += getopt32.o |
42 | lib-y += getpty.o | ||
42 | lib-y += herror_msg.o | 43 | lib-y += herror_msg.o |
43 | lib-y += herror_msg_and_die.o | 44 | lib-y += herror_msg_and_die.o |
44 | lib-y += human_readable.o | 45 | lib-y += human_readable.o |
diff --git a/miscutils/Config.in b/miscutils/Config.in index 73c765f2c..ac1e2b57c 100644 --- a/miscutils/Config.in +++ b/miscutils/Config.in | |||
@@ -410,6 +410,12 @@ config RX | |||
410 | help | 410 | help |
411 | Receive files using the Xmodem protocol. | 411 | Receive files using the Xmodem protocol. |
412 | 412 | ||
413 | config SCRIPT | ||
414 | bool "script" | ||
415 | default n | ||
416 | help | ||
417 | The script makes typescript of terminal session. | ||
418 | |||
413 | config STRINGS | 419 | config STRINGS |
414 | bool "strings" | 420 | bool "strings" |
415 | default n | 421 | default n |
diff --git a/networking/telnetd.c b/networking/telnetd.c index 0bffa9700..05de49e8a 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -153,53 +153,6 @@ remove_iacs(struct tsession *ts, int *pnum_totty) | |||
153 | } | 153 | } |
154 | 154 | ||
155 | 155 | ||
156 | static int | ||
157 | getpty(char *line, int size) | ||
158 | { | ||
159 | int p; | ||
160 | #if ENABLE_FEATURE_DEVPTS | ||
161 | p = open("/dev/ptmx", O_RDWR); | ||
162 | if (p > 0) { | ||
163 | const char *name; | ||
164 | grantpt(p); | ||
165 | unlockpt(p); | ||
166 | name = ptsname(p); | ||
167 | if (!name) { | ||
168 | bb_perror_msg("ptsname error (is /dev/pts mounted?)"); | ||
169 | return -1; | ||
170 | } | ||
171 | safe_strncpy(line, name, size); | ||
172 | return p; | ||
173 | } | ||
174 | #else | ||
175 | struct stat stb; | ||
176 | int i; | ||
177 | int j; | ||
178 | |||
179 | strcpy(line, "/dev/ptyXX"); | ||
180 | |||
181 | for (i = 0; i < 16; i++) { | ||
182 | line[8] = "pqrstuvwxyzabcde"[i]; | ||
183 | line[9] = '0'; | ||
184 | if (stat(line, &stb) < 0) { | ||
185 | continue; | ||
186 | } | ||
187 | for (j = 0; j < 16; j++) { | ||
188 | line[9] = j < 10 ? j + '0' : j - 10 + 'a'; | ||
189 | if (DEBUG) | ||
190 | fprintf(stderr, "Trying to open device: %s\n", line); | ||
191 | p = open(line, O_RDWR | O_NOCTTY); | ||
192 | if (p >= 0) { | ||
193 | line[5] = 't'; | ||
194 | return p; | ||
195 | } | ||
196 | } | ||
197 | } | ||
198 | #endif /* FEATURE_DEVPTS */ | ||
199 | return -1; | ||
200 | } | ||
201 | |||
202 | |||
203 | static struct tsession * | 156 | static struct tsession * |
204 | make_new_session( | 157 | make_new_session( |
205 | USE_FEATURE_TELNETD_STANDALONE(int sock) | 158 | USE_FEATURE_TELNETD_STANDALONE(int sock) |
diff --git a/util-linux/Kbuild b/util-linux/Kbuild index c71186e86..0f33c6be2 100644 --- a/util-linux/Kbuild +++ b/util-linux/Kbuild | |||
@@ -28,6 +28,7 @@ lib-$(CONFIG_PIVOT_ROOT) +=pivot_root.o | |||
28 | lib-$(CONFIG_RDATE) +=rdate.o | 28 | lib-$(CONFIG_RDATE) +=rdate.o |
29 | lib-$(CONFIG_READPROFILE) +=readprofile.o | 29 | lib-$(CONFIG_READPROFILE) +=readprofile.o |
30 | lib-$(CONFIG_RTCWAKE) +=rtcwake.o | 30 | lib-$(CONFIG_RTCWAKE) +=rtcwake.o |
31 | lib-$(CONFIG_SCRIPT) +=script.o | ||
31 | lib-$(CONFIG_SETARCH) +=setarch.o | 32 | lib-$(CONFIG_SETARCH) +=setarch.o |
32 | lib-$(CONFIG_SWAPONOFF) +=swaponoff.o | 33 | lib-$(CONFIG_SWAPONOFF) +=swaponoff.o |
33 | lib-$(CONFIG_SWITCH_ROOT) +=switch_root.o | 34 | lib-$(CONFIG_SWITCH_ROOT) +=switch_root.o |
diff --git a/util-linux/script.c b/util-linux/script.c new file mode 100644 index 000000000..fda726ed9 --- /dev/null +++ b/util-linux/script.c | |||
@@ -0,0 +1,195 @@ | |||
1 | /* vi: set sw=4 ts=4: */ | ||
2 | /* | ||
3 | * script implementation for busybox | ||
4 | * | ||
5 | * pascal.bellard@ads-lu.com | ||
6 | * | ||
7 | * Based on code from util-linux v 2.12r | ||
8 | * Copyright (c) 1980 | ||
9 | * The Regents of the University of California. All rights reserved. | ||
10 | * | ||
11 | * Licensed under GPLv2 or later, see file License in this tarball for details. | ||
12 | */ | ||
13 | |||
14 | #include "libbb.h" | ||
15 | |||
16 | struct globals { | ||
17 | int child_pid; | ||
18 | int attr_ok; /* NB: 0: ok */ | ||
19 | struct termios tt; | ||
20 | const char *fname; | ||
21 | }; | ||
22 | #define G (*ptr_to_globals) | ||
23 | #define child_pid (G.child_pid) | ||
24 | #define attr_ok (G.attr_ok ) | ||
25 | #define tt (G.tt ) | ||
26 | #define fname (G.fname ) | ||
27 | #define INIT_G() do { \ | ||
28 | PTR_TO_GLOBALS = xzalloc(sizeof(G)); \ | ||
29 | fname = "typescript"; \ | ||
30 | } while (0) | ||
31 | |||
32 | static void done(void) | ||
33 | { | ||
34 | if (child_pid) { /* we are parent */ | ||
35 | if (attr_ok == 0) | ||
36 | tcsetattr(0, TCSAFLUSH, &tt); | ||
37 | if (!(option_mask32 & 8)) /* not -q */ | ||
38 | printf("Script done, file is %s\n", fname); | ||
39 | } | ||
40 | exit(0); | ||
41 | } | ||
42 | |||
43 | #ifdef UNUSED | ||
44 | static void handle_sigchld(int sig) | ||
45 | { | ||
46 | /* wait for the exited child and exit */ | ||
47 | while (wait_any_nohang(&sig) > 0) | ||
48 | continue; | ||
49 | done(); | ||
50 | } | ||
51 | #endif | ||
52 | |||
53 | #if ENABLE_GETOPT_LONG | ||
54 | static const char getopt_longopts[] ALIGN1 = | ||
55 | "append\0" No_argument "a" | ||
56 | "command\0" Required_argument "c" | ||
57 | "flush\0" No_argument "f" | ||
58 | "quiet\0" No_argument "q" | ||
59 | ; | ||
60 | #endif | ||
61 | |||
62 | int script_main(int argc, char *argv[]) MAIN_EXTERNALLY_VISIBLE; | ||
63 | int script_main(int argc, char *argv[]) | ||
64 | { | ||
65 | int opt, pty; | ||
66 | int winsz_ok; | ||
67 | int mode; | ||
68 | struct termios rtt; | ||
69 | struct winsize win; | ||
70 | char line[32]; | ||
71 | const char *shell; | ||
72 | char shell_opt[] = "-i"; | ||
73 | char *shell_arg = NULL; | ||
74 | |||
75 | INIT_G(); | ||
76 | #if ENABLE_GETOPT_LONG | ||
77 | applet_long_options = getopt_longopts; | ||
78 | #endif | ||
79 | opt_complementary = "?1"; /* max one arg */ | ||
80 | opt = getopt32(argv, "ac:fq", &shell_arg); | ||
81 | //argc -= optind; | ||
82 | argv += optind; | ||
83 | if (argv[0]) { | ||
84 | fname = argv[0]; | ||
85 | } | ||
86 | mode = O_CREAT|O_TRUNC|O_WRONLY; | ||
87 | if (opt & 1) { | ||
88 | mode = O_CREAT|O_APPEND|O_WRONLY; | ||
89 | } | ||
90 | if (opt & 2) { | ||
91 | shell_opt[1] = 'c'; | ||
92 | } | ||
93 | if (!(opt & 8)) { /* not -q */ | ||
94 | printf("Script started, file is %s\n", fname); | ||
95 | } | ||
96 | shell = getenv("SHELL"); | ||
97 | if (shell == NULL) { | ||
98 | shell = _PATH_BSHELL; | ||
99 | } | ||
100 | |||
101 | pty = getpty(line, sizeof(line)); | ||
102 | if (pty < 0) { | ||
103 | bb_perror_msg_and_die("can't get pty"); | ||
104 | } | ||
105 | |||
106 | /* get current stdin's tty params */ | ||
107 | attr_ok = tcgetattr(0, &tt); | ||
108 | winsz_ok = ioctl(0, TIOCGWINSZ, (char *)&win); | ||
109 | |||
110 | rtt = tt; | ||
111 | cfmakeraw(&rtt); | ||
112 | rtt.c_lflag &= ~ECHO; | ||
113 | tcsetattr(0, TCSAFLUSH, &rtt); | ||
114 | |||
115 | /* We exit as soon as child exits */ | ||
116 | //signal(SIGCHLD, handle_sigchld); | ||
117 | signal(SIGCHLD, (void (*)(int)) done); | ||
118 | |||
119 | child_pid = vfork(); | ||
120 | if (child_pid < 0) { | ||
121 | bb_perror_msg_and_die("vfork"); | ||
122 | } | ||
123 | |||
124 | if (child_pid) { | ||
125 | /* parent */ | ||
126 | char buf[256]; | ||
127 | struct pollfd pfd[2]; | ||
128 | int outfd; | ||
129 | int fd_count = 2; | ||
130 | struct pollfd *ppfd = pfd; | ||
131 | |||
132 | outfd = xopen(fname, mode); | ||
133 | pfd[0].fd = 0; | ||
134 | pfd[0].events = POLLIN; | ||
135 | pfd[1].fd = pty; | ||
136 | pfd[1].events = POLLIN; | ||
137 | ndelay_on(pty); /* this descriptor is not shared, can do this */ | ||
138 | /* ndelay_on(0); - NO, stdin can be shared! */ | ||
139 | |||
140 | /* copy stdin to pty master input, | ||
141 | * copy pty master output to stdout and file */ | ||
142 | /* TODO: don't use full_write's, use proper write buffering */ | ||
143 | while (fd_count && safe_poll(ppfd, fd_count, -1) > 0) { | ||
144 | if (pfd[0].revents) { | ||
145 | int count = safe_read(0, buf, sizeof(buf)); | ||
146 | if (count <= 0) { | ||
147 | /* err/eof: don't read anymore */ | ||
148 | pfd[0].revents = 0; | ||
149 | ppfd++; | ||
150 | fd_count--; | ||
151 | } else { | ||
152 | full_write(pty, buf, count); | ||
153 | } | ||
154 | } | ||
155 | if (pfd[1].revents) { | ||
156 | int count; | ||
157 | errno = 0; | ||
158 | count = safe_read(pty, buf, sizeof(buf)); | ||
159 | if (count <= 0 && errno != EAGAIN) { | ||
160 | /* err/eof: don't read anymore */ | ||
161 | pfd[1].revents = 0; | ||
162 | fd_count--; | ||
163 | } | ||
164 | if (count > 0) { | ||
165 | full_write(1, buf, count); | ||
166 | full_write(outfd, buf, count); | ||
167 | if (opt & 4) { /* -f */ | ||
168 | fsync(outfd); | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | done(); /* does not return */ | ||
174 | } | ||
175 | |||
176 | /* child: make pty slave to be input, output, error; run shell */ | ||
177 | close(pty); /* close pty master */ | ||
178 | /* open pty slave to fd 0,1,2 */ | ||
179 | close(0); | ||
180 | xopen(line, O_RDWR); /* uses fd 0 */ | ||
181 | xdup2(0, 1); | ||
182 | xdup2(0, 2); | ||
183 | /* copy our original stdin tty's parameters to pty */ | ||
184 | if (attr_ok == 0) | ||
185 | tcsetattr(0, TCSAFLUSH, &tt); | ||
186 | if (winsz_ok == 0) | ||
187 | ioctl(0, TIOCSWINSZ, (char *)&win); | ||
188 | /* set pty as a controlling tty */ | ||
189 | setsid(); | ||
190 | ioctl(0, TIOCSCTTY, 0 /* 0: don't forcibly steal */); | ||
191 | |||
192 | /* signal(SIGCHLD, SIG_DFL); - exec does this for us */ | ||
193 | execl(shell, shell, shell_opt, shell_arg, NULL); | ||
194 | bb_simple_perror_msg_and_die(shell); | ||
195 | } | ||