aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-05-20 12:20:48 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-05-20 12:20:48 +0200
commite18255d1dadc9686daa328fa121423b47d2f6af4 (patch)
treeabea08a2f62c5fa9322086d5b0151b602636da2b
parente424423a7b164e0c343c180a944844fd27ccbe97 (diff)
parent38478a600f52eb8f00d260a2f99d8430b9aba1e8 (diff)
downloadbusybox-w32-e18255d1dadc9686daa328fa121423b47d2f6af4.tar.gz
busybox-w32-e18255d1dadc9686daa328fa121423b47d2f6af4.tar.bz2
busybox-w32-e18255d1dadc9686daa328fa121423b47d2f6af4.zip
Merge branch 'master' of git+ssh://vda@busybox.net/var/lib/git/busybox
-rw-r--r--include/applets.h1
-rw-r--r--include/platform.h166
-rw-r--r--include/usage.h10
-rw-r--r--libbb/login.c2
-rw-r--r--shell/hush.c35
-rw-r--r--util-linux/Config.in7
-rw-r--r--util-linux/Kbuild1
-rw-r--r--util-linux/script.c59
-rw-r--r--util-linux/scriptreplay.c38
9 files changed, 203 insertions, 116 deletions
diff --git a/include/applets.h b/include/applets.h
index 359440def..7838757f5 100644
--- a/include/applets.h
+++ b/include/applets.h
@@ -326,6 +326,7 @@ IF_RUNSV(APPLET(runsv, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
326IF_RUNSVDIR(APPLET(runsvdir, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 326IF_RUNSVDIR(APPLET(runsvdir, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
327IF_RX(APPLET(rx, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 327IF_RX(APPLET(rx, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
328IF_SCRIPT(APPLET(script, _BB_DIR_USR_BIN, _BB_SUID_NEVER)) 328IF_SCRIPT(APPLET(script, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
329IF_SCRIPTREPLAY(APPLET(scriptreplay, _BB_DIR_BIN, _BB_SUID_NEVER))
329IF_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER)) 330IF_SED(APPLET(sed, _BB_DIR_BIN, _BB_SUID_NEVER))
330IF_SELINUXENABLED(APPLET(selinuxenabled, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) 331IF_SELINUXENABLED(APPLET(selinuxenabled, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
331IF_SENDMAIL(APPLET(sendmail, _BB_DIR_USR_SBIN, _BB_SUID_NEVER)) 332IF_SENDMAIL(APPLET(sendmail, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
diff --git a/include/platform.h b/include/platform.h
index 317349fed..e2136a2ea 100644
--- a/include/platform.h
+++ b/include/platform.h
@@ -19,7 +19,7 @@
19/* __restrict is known in EGCS 1.2 and above. */ 19/* __restrict is known in EGCS 1.2 and above. */
20#if !__GNUC_PREREQ(2,92) 20#if !__GNUC_PREREQ(2,92)
21# ifndef __restrict 21# ifndef __restrict
22# define __restrict /* Ignore */ 22# define __restrict
23# endif 23# endif
24#endif 24#endif
25 25
@@ -61,14 +61,14 @@
61# define DEPRECATED __attribute__ ((__deprecated__)) 61# define DEPRECATED __attribute__ ((__deprecated__))
62# define UNUSED_PARAM_RESULT __attribute__ ((warn_unused_result)) 62# define UNUSED_PARAM_RESULT __attribute__ ((warn_unused_result))
63# else 63# else
64# define DEPRECATED /* n/a */ 64# define DEPRECATED
65# define UNUSED_PARAM_RESULT /* n/a */ 65# define UNUSED_PARAM_RESULT
66# endif 66# endif
67#else 67#else
68# define ALWAYS_INLINE inline /* n/a */ 68# define ALWAYS_INLINE inline
69# define NOINLINE /* n/a */ 69# define NOINLINE
70# define DEPRECATED /* n/a */ 70# define DEPRECATED
71# define UNUSED_PARAM_RESULT /* n/a */ 71# define UNUSED_PARAM_RESULT
72#endif 72#endif
73 73
74/* -fwhole-program makes all symbols local. The attribute externally_visible 74/* -fwhole-program makes all symbols local. The attribute externally_visible
@@ -144,19 +144,19 @@
144 144
145/* SWAP_LEnn means "convert CPU<->little_endian by swapping bytes" */ 145/* SWAP_LEnn means "convert CPU<->little_endian by swapping bytes" */
146#if BB_BIG_ENDIAN 146#if BB_BIG_ENDIAN
147#define SWAP_BE16(x) (x) 147# define SWAP_BE16(x) (x)
148#define SWAP_BE32(x) (x) 148# define SWAP_BE32(x) (x)
149#define SWAP_BE64(x) (x) 149# define SWAP_BE64(x) (x)
150#define SWAP_LE16(x) bswap_16(x) 150# define SWAP_LE16(x) bswap_16(x)
151#define SWAP_LE32(x) bswap_32(x) 151# define SWAP_LE32(x) bswap_32(x)
152#define SWAP_LE64(x) bswap_64(x) 152# define SWAP_LE64(x) bswap_64(x)
153#else 153#else
154#define SWAP_BE16(x) bswap_16(x) 154# define SWAP_BE16(x) bswap_16(x)
155#define SWAP_BE32(x) bswap_32(x) 155# define SWAP_BE32(x) bswap_32(x)
156#define SWAP_BE64(x) bswap_64(x) 156# define SWAP_BE64(x) bswap_64(x)
157#define SWAP_LE16(x) (x) 157# define SWAP_LE16(x) (x)
158#define SWAP_LE32(x) (x) 158# define SWAP_LE32(x) (x)
159#define SWAP_LE64(x) (x) 159# define SWAP_LE64(x) (x)
160#endif 160#endif
161 161
162/* ---- Unaligned access ------------------------------------ */ 162/* ---- Unaligned access ------------------------------------ */
@@ -165,15 +165,15 @@
165 * a lvalue. This makes it more likely to not swap them by mistake 165 * a lvalue. This makes it more likely to not swap them by mistake
166 */ 166 */
167#if defined(i386) || defined(__x86_64__) 167#if defined(i386) || defined(__x86_64__)
168#define move_from_unaligned16(v, u16p) ((v) = *(uint16_t*)(u16p)) 168# define move_from_unaligned16(v, u16p) ((v) = *(uint16_t*)(u16p))
169#define move_from_unaligned32(v, u32p) ((v) = *(uint32_t*)(u32p)) 169# define move_from_unaligned32(v, u32p) ((v) = *(uint32_t*)(u32p))
170#define move_to_unaligned32(u32p, v) (*(uint32_t*)(u32p) = (v)) 170# define move_to_unaligned32(u32p, v) (*(uint32_t*)(u32p) = (v))
171/* #elif ... - add your favorite arch today! */ 171/* #elif ... - add your favorite arch today! */
172#else 172#else
173/* performs reasonably well (gcc usually inlines memcpy here) */ 173/* performs reasonably well (gcc usually inlines memcpy here) */
174#define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2)) 174# define move_from_unaligned16(v, u16p) (memcpy(&(v), (u16p), 2))
175#define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4)) 175# define move_from_unaligned32(v, u32p) (memcpy(&(v), (u32p), 4))
176#define move_to_unaligned32(u32p, v) do { \ 176# define move_to_unaligned32(u32p, v) do { \
177 uint32_t __t = (v); \ 177 uint32_t __t = (v); \
178 memcpy((u32p), &__t, 4); \ 178 memcpy((u32p), &__t, 4); \
179} while (0) 179} while (0)
@@ -225,21 +225,21 @@ __extension__ typedef unsigned long long __u64;
225 225
226#if defined __GLIBC__ || defined __UCLIBC__ \ 226#if defined __GLIBC__ || defined __UCLIBC__ \
227 || defined __dietlibc__ || defined _NEWLIB_VERSION 227 || defined __dietlibc__ || defined _NEWLIB_VERSION
228#include <features.h> 228# include <features.h>
229#define HAVE_FEATURES_H 229# define HAVE_FEATURES_H
230#include <stdint.h> 230# include <stdint.h>
231#define HAVE_STDINT_H 231# define HAVE_STDINT_H
232#elif !defined __APPLE__ 232#elif !defined __APPLE__
233/* Largest integral types. */ 233/* Largest integral types. */
234#if __BIG_ENDIAN__ 234# if __BIG_ENDIAN__
235typedef long intmax_t; 235typedef long intmax_t;
236typedef unsigned long uintmax_t; 236typedef unsigned long uintmax_t;
237#else 237# else
238__extension__ 238__extension__
239typedef long long intmax_t; 239typedef long long intmax_t;
240__extension__ 240__extension__
241typedef unsigned long long uintmax_t; 241typedef unsigned long long uintmax_t;
242#endif 242# endif
243#endif 243#endif
244 244
245/* Size-saving "small" ints (arch-dependent) */ 245/* Size-saving "small" ints (arch-dependent) */
@@ -256,20 +256,20 @@ typedef unsigned smalluint;
256/* ISO C Standard: 7.16 Boolean type and values <stdbool.h> */ 256/* ISO C Standard: 7.16 Boolean type and values <stdbool.h> */
257#if (defined __digital__ && defined __unix__) 257#if (defined __digital__ && defined __unix__)
258/* old system without (proper) C99 support */ 258/* old system without (proper) C99 support */
259#define bool smalluint 259# define bool smalluint
260#else 260#else
261/* modern system, so use it */ 261/* modern system, so use it */
262#include <stdbool.h> 262# include <stdbool.h>
263#endif 263#endif
264 264
265/* Try to defeat gcc's alignment of "char message[]"-like data */ 265/* Try to defeat gcc's alignment of "char message[]"-like data */
266#if 1 /* if needed: !defined(arch1) && !defined(arch2) */ 266#if 1 /* if needed: !defined(arch1) && !defined(arch2) */
267#define ALIGN1 __attribute__((aligned(1))) 267# define ALIGN1 __attribute__((aligned(1)))
268#define ALIGN2 __attribute__((aligned(2))) 268# define ALIGN2 __attribute__((aligned(2)))
269#else 269#else
270/* Arches which MUST have 2 or 4 byte alignment for everything are here */ 270/* Arches which MUST have 2 or 4 byte alignment for everything are here */
271#define ALIGN1 271# define ALIGN1
272#define ALIGN2 272# define ALIGN2
273#endif 273#endif
274 274
275 275
@@ -281,13 +281,13 @@ typedef unsigned smalluint;
281#if ENABLE_NOMMU || \ 281#if ENABLE_NOMMU || \
282 (defined __UCLIBC__ && __UCLIBC_MAJOR__ >= 0 && __UCLIBC_MINOR__ >= 9 && \ 282 (defined __UCLIBC__ && __UCLIBC_MAJOR__ >= 0 && __UCLIBC_MINOR__ >= 9 && \
283 __UCLIBC_SUBLEVEL__ > 28 && !defined __ARCH_USE_MMU__) 283 __UCLIBC_SUBLEVEL__ > 28 && !defined __ARCH_USE_MMU__)
284#define BB_MMU 0 284# define BB_MMU 0
285#define USE_FOR_NOMMU(...) __VA_ARGS__ 285# define USE_FOR_NOMMU(...) __VA_ARGS__
286#define USE_FOR_MMU(...) 286# define USE_FOR_MMU(...)
287#else 287#else
288#define BB_MMU 1 288# define BB_MMU 1
289#define USE_FOR_NOMMU(...) 289# define USE_FOR_NOMMU(...)
290#define USE_FOR_MMU(...) __VA_ARGS__ 290# define USE_FOR_MMU(...) __VA_ARGS__
291#endif 291#endif
292 292
293/* Platforms that haven't got dprintf need to implement fdprintf() in 293/* Platforms that haven't got dprintf need to implement fdprintf() in
@@ -297,7 +297,7 @@ typedef unsigned smalluint;
297/* Needed for: glibc */ 297/* Needed for: glibc */
298/* Not needed for: dietlibc */ 298/* Not needed for: dietlibc */
299/* Others: ?? (add as needed) */ 299/* Others: ?? (add as needed) */
300#define fdprintf dprintf 300# define fdprintf dprintf
301#endif 301#endif
302 302
303#if defined(__dietlibc__) 303#if defined(__dietlibc__)
@@ -323,7 +323,6 @@ static ALWAYS_INLINE char* strchrnul(const char *s, char c)
323# define PRIu32 "u" 323# define PRIu32 "u"
324/* use legacy setpgrp(pid_t,pid_t) for now. move to platform.c */ 324/* use legacy setpgrp(pid_t,pid_t) for now. move to platform.c */
325# define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me,__me); } while (0) 325# define bb_setpgrp() do { pid_t __me = getpid(); setpgrp(__me,__me); } while (0)
326
327# if !defined ADJ_OFFSET_SINGLESHOT && defined MOD_CLKA && defined MOD_OFFSET 326# if !defined ADJ_OFFSET_SINGLESHOT && defined MOD_CLKA && defined MOD_OFFSET
328# define ADJ_OFFSET_SINGLESHOT (MOD_CLKA | MOD_OFFSET) 327# define ADJ_OFFSET_SINGLESHOT (MOD_CLKA | MOD_OFFSET)
329# endif 328# endif
@@ -344,44 +343,53 @@ static ALWAYS_INLINE char* strchrnul(const char *s, char c)
344#endif 343#endif
345 344
346#if defined(__linux__) 345#if defined(__linux__)
347#include <sys/mount.h> 346# include <sys/mount.h>
348/* Make sure we have all the new mount flags we actually try to use. */ 347/* Make sure we have all the new mount flags we actually try to use. */
349#ifndef MS_BIND 348# ifndef MS_BIND
350#define MS_BIND (1<<12) 349# define MS_BIND (1 << 12)
351#endif 350# endif
352#ifndef MS_MOVE 351# ifndef MS_MOVE
353#define MS_MOVE (1<<13) 352# define MS_MOVE (1 << 13)
354#endif 353# endif
355#ifndef MS_RECURSIVE 354# ifndef MS_RECURSIVE
356#define MS_RECURSIVE (1<<14) 355# define MS_RECURSIVE (1 << 14)
357#endif 356# endif
358#ifndef MS_SILENT 357# ifndef MS_SILENT
359#define MS_SILENT (1<<15) 358# define MS_SILENT (1 << 15)
360#endif 359# endif
361
362/* The shared subtree stuff, which went in around 2.6.15. */ 360/* The shared subtree stuff, which went in around 2.6.15. */
363#ifndef MS_UNBINDABLE 361# ifndef MS_UNBINDABLE
364#define MS_UNBINDABLE (1<<17) 362# define MS_UNBINDABLE (1 << 17)
365#endif 363# endif
366#ifndef MS_PRIVATE 364# ifndef MS_PRIVATE
367#define MS_PRIVATE (1<<18) 365# define MS_PRIVATE (1 << 18)
368#endif 366# endif
369#ifndef MS_SLAVE 367# ifndef MS_SLAVE
370#define MS_SLAVE (1<<19) 368# define MS_SLAVE (1 << 19)
371#endif 369# endif
372#ifndef MS_SHARED 370# ifndef MS_SHARED
373#define MS_SHARED (1<<20) 371# define MS_SHARED (1 << 20)
374#endif 372# endif
375#ifndef MS_RELATIME 373# ifndef MS_RELATIME
376#define MS_RELATIME (1 << 21) 374# define MS_RELATIME (1 << 21)
377#endif 375# endif
378 376
379#if !defined(BLKSSZGET) 377# if !defined(BLKSSZGET)
380#define BLKSSZGET _IO(0x12, 104) 378# define BLKSSZGET _IO(0x12, 104)
379# endif
380# if !defined(BLKGETSIZE64)
381# define BLKGETSIZE64 _IOR(0x12,114,size_t)
382# endif
381#endif 383#endif
382#if !defined(BLKGETSIZE64) 384
383#define BLKGETSIZE64 _IOR(0x12,114,size_t) 385/* The field domainname of struct utsname is Linux specific. */
386#if !defined(__linux__)
387# define HAVE_NO_UTSNAME_DOMAINNAME
384#endif 388#endif
389
390/* If this system doesn't have IUCLC bit in struct termios::c_iflag... */
391#ifndef IUCLC
392# define IUCLC 0
385#endif 393#endif
386 394
387#endif 395#endif
diff --git a/include/usage.h b/include/usage.h
index 123462a02..1e327fb97 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -3512,6 +3512,11 @@
3512 "\n -g Process group id(s)" \ 3512 "\n -g Process group id(s)" \
3513 "\n -u Process user name(s) and/or id(s)" \ 3513 "\n -u Process user name(s) and/or id(s)" \
3514 3514
3515#define scriptreplay_trivial_usage \
3516 "timingfile [typescript [divisor]]"
3517#define scriptreplay_full_usage "\n\n" \
3518 "Play back typescripts, using timing information"
3519
3515#define reset_trivial_usage \ 3520#define reset_trivial_usage \
3516 "" 3521 ""
3517#define reset_full_usage "\n\n" \ 3522#define reset_full_usage "\n\n" \
@@ -3706,13 +3711,16 @@
3706 "$ rx /tmp/foo\n" 3711 "$ rx /tmp/foo\n"
3707 3712
3708#define script_trivial_usage \ 3713#define script_trivial_usage \
3709 "[-afq] [-c COMMAND] [OUTFILE]" 3714 "[-afq" IF_SCRIPTREPLAY("t") "] [-c COMMAND] [OUTFILE]"
3710#define script_full_usage "\n\n" \ 3715#define script_full_usage "\n\n" \
3711 "Options:" \ 3716 "Options:" \
3712 "\n -a Append output" \ 3717 "\n -a Append output" \
3713 "\n -c Run COMMAND, not shell" \ 3718 "\n -c Run COMMAND, not shell" \
3714 "\n -f Flush output after each write" \ 3719 "\n -f Flush output after each write" \
3715 "\n -q Quiet" \ 3720 "\n -q Quiet" \
3721 IF_SCRIPTREPLAY( \
3722 "\n -t Send timing to stderr" \
3723 )
3716 3724
3717#define sed_trivial_usage \ 3725#define sed_trivial_usage \
3718 "[-efinr] pattern [files...]" 3726 "[-efinr] pattern [files...]"
diff --git a/libbb/login.c b/libbb/login.c
index b3e199ce4..98e641cce 100644
--- a/libbb/login.c
+++ b/libbb/login.c
@@ -62,10 +62,12 @@ void FAST_FUNC print_login_issue(const char *issue_file, const char *tty)
62 case 'm': 62 case 'm':
63 outbuf = uts.machine; 63 outbuf = uts.machine;
64 break; 64 break;
65#ifndef HAVE_NO_UTSNAME_DOMAINNAME
65 case 'D': 66 case 'D':
66 case 'o': 67 case 'o':
67 outbuf = uts.domainname; 68 outbuf = uts.domainname;
68 break; 69 break;
70#endif
69 case 'd': 71 case 'd':
70 strftime(buf, sizeof(buf), fmtstr_d, localtime(&t)); 72 strftime(buf, sizeof(buf), fmtstr_d, localtime(&t));
71 break; 73 break;
diff --git a/shell/hush.c b/shell/hush.c
index 370e0d71a..d6286b61c 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -445,6 +445,9 @@ struct globals {
445 int last_jobid; 445 int last_jobid;
446 pid_t saved_tty_pgrp; 446 pid_t saved_tty_pgrp;
447 struct pipe *job_list; 447 struct pipe *job_list;
448# define G_saved_tty_pgrp (G.saved_tty_pgrp)
449#else
450# define G_saved_tty_pgrp 0
448#endif 451#endif
449 smallint flag_SIGINT; 452 smallint flag_SIGINT;
450#if ENABLE_HUSH_LOOPS 453#if ENABLE_HUSH_LOOPS
@@ -1055,8 +1058,8 @@ enum {
1055 | (1 << SIGINT) 1058 | (1 << SIGINT)
1056 | (1 << SIGHUP) 1059 | (1 << SIGHUP)
1057 , 1060 ,
1058#if ENABLE_HUSH_JOB
1059 SPECIAL_JOB_SIGS = 0 1061 SPECIAL_JOB_SIGS = 0
1062#if ENABLE_HUSH_JOB
1060 | (1 << SIGTTIN) 1063 | (1 << SIGTTIN)
1061 | (1 << SIGTTOU) 1064 | (1 << SIGTTOU)
1062 | (1 << SIGTSTP) 1065 | (1 << SIGTSTP)
@@ -1088,8 +1091,8 @@ static void sigexit(int sig)
1088 1091
1089 /* Careful: we can end up here after [v]fork. Do not restore 1092 /* Careful: we can end up here after [v]fork. Do not restore
1090 * tty pgrp then, only top-level shell process does that */ 1093 * tty pgrp then, only top-level shell process does that */
1091 if (G.saved_tty_pgrp && getpid() == G.root_pid) 1094 if (G_saved_tty_pgrp && getpid() == G.root_pid)
1092 tcsetpgrp(G_interactive_fd, G.saved_tty_pgrp); 1095 tcsetpgrp(G_interactive_fd, G_saved_tty_pgrp);
1093 1096
1094 /* Not a signal, just exit */ 1097 /* Not a signal, just exit */
1095 if (sig <= 0) 1098 if (sig <= 0)
@@ -3400,7 +3403,7 @@ static int checkjobs_and_fg_shell(struct pipe* fg_pipe)
3400{ 3403{
3401 pid_t p; 3404 pid_t p;
3402 int rcode = checkjobs(fg_pipe); 3405 int rcode = checkjobs(fg_pipe);
3403 if (G.saved_tty_pgrp) { 3406 if (G_saved_tty_pgrp) {
3404 /* Job finished, move the shell to the foreground */ 3407 /* Job finished, move the shell to the foreground */
3405 p = getpgrp(); /* our process group id */ 3408 p = getpgrp(); /* our process group id */
3406 debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p); 3409 debug_printf_jobs("fg'ing ourself: getpgrp()=%d\n", (int)p);
@@ -3656,7 +3659,7 @@ static int run_pipe(struct pipe *pi)
3656 pgrp = getpid(); 3659 pgrp = getpid();
3657 if (setpgid(0, pgrp) == 0 3660 if (setpgid(0, pgrp) == 0
3658 && pi->followup != PIPE_BG 3661 && pi->followup != PIPE_BG
3659 && G.saved_tty_pgrp /* we have ctty */ 3662 && G_saved_tty_pgrp /* we have ctty */
3660 ) { 3663 ) {
3661 /* We do it in *every* child, not just first, 3664 /* We do it in *every* child, not just first,
3662 * to avoid races */ 3665 * to avoid races */
@@ -5954,7 +5957,7 @@ static void block_signals(int second_time)
5954 mask = (1 << SIGQUIT); 5957 mask = (1 << SIGQUIT);
5955 if (G_interactive_fd) { 5958 if (G_interactive_fd) {
5956 mask = (1 << SIGQUIT) | SPECIAL_INTERACTIVE_SIGS; 5959 mask = (1 << SIGQUIT) | SPECIAL_INTERACTIVE_SIGS;
5957 if (G.saved_tty_pgrp) /* we have ctty, job control sigs work */ 5960 if (G_saved_tty_pgrp) /* we have ctty, job control sigs work */
5958 mask |= SPECIAL_JOB_SIGS; 5961 mask |= SPECIAL_JOB_SIGS;
5959 } 5962 }
5960 G.non_DFL_mask = mask; 5963 G.non_DFL_mask = mask;
@@ -6235,10 +6238,10 @@ int hush_main(int argc, char **argv)
6235 */ 6238 */
6236#if ENABLE_HUSH_JOB 6239#if ENABLE_HUSH_JOB
6237 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) { 6240 if (isatty(STDIN_FILENO) && isatty(STDOUT_FILENO)) {
6238 G.saved_tty_pgrp = tcgetpgrp(STDIN_FILENO); 6241 G_saved_tty_pgrp = tcgetpgrp(STDIN_FILENO);
6239 debug_printf("saved_tty_pgrp:%d\n", G.saved_tty_pgrp); 6242 debug_printf("saved_tty_pgrp:%d\n", G_saved_tty_pgrp);
6240 if (G.saved_tty_pgrp < 0) 6243 if (G_saved_tty_pgrp < 0)
6241 G.saved_tty_pgrp = 0; 6244 G_saved_tty_pgrp = 0;
6242 6245
6243 /* try to dup stdin to high fd#, >= 255 */ 6246 /* try to dup stdin to high fd#, >= 255 */
6244 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255); 6247 G_interactive_fd = fcntl(STDIN_FILENO, F_DUPFD, 255);
@@ -6248,7 +6251,7 @@ int hush_main(int argc, char **argv)
6248 if (G_interactive_fd < 0) { 6251 if (G_interactive_fd < 0) {
6249 /* give up */ 6252 /* give up */
6250 G_interactive_fd = 0; 6253 G_interactive_fd = 0;
6251 G.saved_tty_pgrp = 0; 6254 G_saved_tty_pgrp = 0;
6252 } 6255 }
6253 } 6256 }
6254// TODO: track & disallow any attempts of user 6257// TODO: track & disallow any attempts of user
@@ -6258,7 +6261,7 @@ int hush_main(int argc, char **argv)
6258 if (G_interactive_fd) { 6261 if (G_interactive_fd) {
6259 close_on_exec_on(G_interactive_fd); 6262 close_on_exec_on(G_interactive_fd);
6260 6263
6261 if (G.saved_tty_pgrp) { 6264 if (G_saved_tty_pgrp) {
6262 /* If we were run as 'hush &', sleep until we are 6265 /* If we were run as 'hush &', sleep until we are
6263 * in the foreground (tty pgrp == our pgrp). 6266 * in the foreground (tty pgrp == our pgrp).
6264 * If we get started under a job aware app (like bash), 6267 * If we get started under a job aware app (like bash),
@@ -6266,8 +6269,8 @@ int hush_main(int argc, char **argv)
6266 * who gets the foreground */ 6269 * who gets the foreground */
6267 while (1) { 6270 while (1) {
6268 pid_t shell_pgrp = getpgrp(); 6271 pid_t shell_pgrp = getpgrp();
6269 G.saved_tty_pgrp = tcgetpgrp(G_interactive_fd); 6272 G_saved_tty_pgrp = tcgetpgrp(G_interactive_fd);
6270 if (G.saved_tty_pgrp == shell_pgrp) 6273 if (G_saved_tty_pgrp == shell_pgrp)
6271 break; 6274 break;
6272 /* send TTIN to ourself (should stop us) */ 6275 /* send TTIN to ourself (should stop us) */
6273 kill(- shell_pgrp, SIGTTIN); 6276 kill(- shell_pgrp, SIGTTIN);
@@ -6277,7 +6280,7 @@ int hush_main(int argc, char **argv)
6277 /* Block some signals */ 6280 /* Block some signals */
6278 block_signals(signal_mask_is_inited); 6281 block_signals(signal_mask_is_inited);
6279 6282
6280 if (G.saved_tty_pgrp) { 6283 if (G_saved_tty_pgrp) {
6281 /* Set other signals to restore saved_tty_pgrp */ 6284 /* Set other signals to restore saved_tty_pgrp */
6282 set_fatal_handlers(); 6285 set_fatal_handlers();
6283 /* Put ourselves in our own process group 6286 /* Put ourselves in our own process group
@@ -6690,7 +6693,7 @@ static int builtin_fg_bg(char **argv)
6690 found: 6693 found:
6691 /* TODO: bash prints a string representation 6694 /* TODO: bash prints a string representation
6692 * of job being foregrounded (like "sleep 1 | cat") */ 6695 * of job being foregrounded (like "sleep 1 | cat") */
6693 if (argv[0][0] == 'f' && G.saved_tty_pgrp) { 6696 if (argv[0][0] == 'f' && G_saved_tty_pgrp) {
6694 /* Put the job into the foreground. */ 6697 /* Put the job into the foreground. */
6695 tcsetpgrp(G_interactive_fd, pi->pgrp); 6698 tcsetpgrp(G_interactive_fd, pi->pgrp);
6696 } 6699 }
diff --git a/util-linux/Config.in b/util-linux/Config.in
index e5c053fcf..024550172 100644
--- a/util-linux/Config.in
+++ b/util-linux/Config.in
@@ -764,6 +764,13 @@ config SCRIPT
764 help 764 help
765 The script makes typescript of terminal session. 765 The script makes typescript of terminal session.
766 766
767config SCRIPTREPLAY
768 bool "scriptreplay"
769 default n
770 help
771 This program replays a typescript, using timing information
772 given by script -t.
773
767config SETARCH 774config SETARCH
768 bool "setarch" 775 bool "setarch"
769 default n 776 default n
diff --git a/util-linux/Kbuild b/util-linux/Kbuild
index ac071c620..eaad3319d 100644
--- a/util-linux/Kbuild
+++ b/util-linux/Kbuild
@@ -33,6 +33,7 @@ lib-$(CONFIG_RDEV) += rdev.o
33lib-$(CONFIG_READPROFILE) += readprofile.o 33lib-$(CONFIG_READPROFILE) += readprofile.o
34lib-$(CONFIG_RTCWAKE) += rtcwake.o 34lib-$(CONFIG_RTCWAKE) += rtcwake.o
35lib-$(CONFIG_SCRIPT) += script.o 35lib-$(CONFIG_SCRIPT) += script.o
36lib-$(CONFIG_SCRIPTREPLAY) += scriptreplay.o
36lib-$(CONFIG_SETARCH) += setarch.o 37lib-$(CONFIG_SETARCH) += setarch.o
37lib-$(CONFIG_SWAPONOFF) += swaponoff.o 38lib-$(CONFIG_SWAPONOFF) += swaponoff.o
38lib-$(CONFIG_SWITCH_ROOT) += switch_root.o 39lib-$(CONFIG_SWITCH_ROOT) += switch_root.o
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
16static smallint fd_count = 2;
17
18static void handle_sigchld(int sig UNUSED_PARAM)
19{
20 fd_count = 0;
21}
22
23int script_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 15int script_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
24int script_main(int argc UNUSED_PARAM, char **argv) 16int 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 }
diff --git a/util-linux/scriptreplay.c b/util-linux/scriptreplay.c
new file mode 100644
index 000000000..038dbdfe1
--- /dev/null
+++ b/util-linux/scriptreplay.c
@@ -0,0 +1,38 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * scriptreplay - play back typescripts, using timing information
4 *
5 * pascal.bellard@ads-lu.com
6 *
7 * Licensed under GPLv2 or later, see file License in this tarball for details.
8 *
9 */
10#include "libbb.h"
11
12int scriptreplay_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
13int scriptreplay_main(int argc UNUSED_PARAM, char **argv)
14{
15 const char *script = "typescript";
16 double delay, factor = 1000000.0;
17 int fd;
18 unsigned long count;
19 FILE *tfp;
20
21 if (argv[2]) {
22 script = argv[2];
23 if (argv[3])
24 factor /= atof(argv[3]);
25 }
26
27 tfp = xfopen_for_read(argv[1]);
28 fd = xopen(script, O_RDONLY);
29 while (fscanf(tfp, "%lf %lu\n", &delay, &count) == 2) {
30 usleep(delay * factor);
31 bb_copyfd_exact_size(fd, STDOUT_FILENO, count);
32 }
33#if ENABLE_FEATURE_CLEAN_UP
34 close(fd);
35 fclose(tfp);
36#endif
37 return EXIT_SUCCESS;
38}