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 | } | ||
