diff options
author | Ron Yorston <rmy@pobox.com> | 2012-03-22 13:15:08 +0000 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-03-22 13:15:08 +0000 |
commit | c0d4367d6b581eb5989c02815880cf0fa2851ae8 (patch) | |
tree | 868c266e627e2d7f65ba5a4d5f98a1c421453181 /libbb | |
parent | f6bad5ef766b0447158e3de2f55c35f1f6cecb58 (diff) | |
parent | da4441c44f6efccb6f7b7588404d9c6bfb7b6af8 (diff) | |
download | busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.tar.gz busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.tar.bz2 busybox-w32-c0d4367d6b581eb5989c02815880cf0fa2851ae8.zip |
Merge commit 'da4441c44f6efccb6f7b7588404d9c6bfb7b6af8' into merge
Conflicts:
libbb/vfork_daemon_rexec.c
networking/wget.c
procps/ps.c
Diffstat (limited to 'libbb')
-rw-r--r-- | libbb/Config.src | 21 | ||||
-rw-r--r-- | libbb/copy_file.c | 8 | ||||
-rw-r--r-- | libbb/crc32.c | 2 | ||||
-rw-r--r-- | libbb/execable.c | 10 | ||||
-rw-r--r-- | libbb/find_mount_point.c | 2 | ||||
-rw-r--r-- | libbb/getopt32.c | 10 | ||||
-rw-r--r-- | libbb/lineedit.c | 12 | ||||
-rw-r--r-- | libbb/messages.c | 2 | ||||
-rw-r--r-- | libbb/platform.c | 11 | ||||
-rw-r--r-- | libbb/progress.c | 179 | ||||
-rw-r--r-- | libbb/systemd_support.c | 2 | ||||
-rw-r--r-- | libbb/vfork_daemon_rexec.c | 61 |
12 files changed, 196 insertions, 124 deletions
diff --git a/libbb/Config.src b/libbb/Config.src index 85892d3fe..18bdc5151 100644 --- a/libbb/Config.src +++ b/libbb/Config.src | |||
@@ -156,11 +156,30 @@ config FEATURE_COPYBUF_KB | |||
156 | range 1 1024 | 156 | range 1 1024 |
157 | default 4 | 157 | default 4 |
158 | help | 158 | help |
159 | Size of buffer used by cp, mv, install etc. | 159 | Size of buffer used by cp, mv, install, wget etc. |
160 | Buffers which are 4 kb or less will be allocated on stack. | 160 | Buffers which are 4 kb or less will be allocated on stack. |
161 | Bigger buffers will be allocated with mmap, with fallback to 4 kb | 161 | Bigger buffers will be allocated with mmap, with fallback to 4 kb |
162 | stack buffer if mmap fails. | 162 | stack buffer if mmap fails. |
163 | 163 | ||
164 | config FEATURE_SKIP_ROOTFS | ||
165 | bool "Skip rootfs in mount table" | ||
166 | default y | ||
167 | help | ||
168 | Ignore rootfs entry in mount table. | ||
169 | |||
170 | In Linux, kernel has a special filesystem, rootfs, which is initially | ||
171 | mounted on /. It contains initramfs data, if kernel is configured | ||
172 | to have one. Usually, another file system is mounted over / early | ||
173 | in boot process, and therefore most tools which manipulate | ||
174 | mount table, such as df, will skip rootfs entry. | ||
175 | |||
176 | However, some systems do not mount anything on /. | ||
177 | If you need to configure busybox for one of these systems, | ||
178 | you may find useful to turn this option off to make df show | ||
179 | initramfs statistic. | ||
180 | |||
181 | Otherwise, choose Y. | ||
182 | |||
164 | config MONOTONIC_SYSCALL | 183 | config MONOTONIC_SYSCALL |
165 | bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" | 184 | bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" |
166 | default n | 185 | default n |
diff --git a/libbb/copy_file.c b/libbb/copy_file.c index adbc2dea3..48aaf481d 100644 --- a/libbb/copy_file.c +++ b/libbb/copy_file.c | |||
@@ -78,9 +78,9 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) | |||
78 | /* NB: each struct stat is ~100 bytes */ | 78 | /* NB: each struct stat is ~100 bytes */ |
79 | struct stat source_stat; | 79 | struct stat source_stat; |
80 | struct stat dest_stat; | 80 | struct stat dest_stat; |
81 | signed char retval = 0; | 81 | smallint retval = 0; |
82 | signed char dest_exists = 0; | 82 | smallint dest_exists = 0; |
83 | signed char ovr; | 83 | smallint ovr; |
84 | 84 | ||
85 | /* Inverse of cp -d ("cp without -d") */ | 85 | /* Inverse of cp -d ("cp without -d") */ |
86 | #define FLAGS_DEREF (flags & (FILEUTILS_DEREFERENCE + FILEUTILS_DEREFERENCE_L0)) | 86 | #define FLAGS_DEREF (flags & (FILEUTILS_DEREFERENCE + FILEUTILS_DEREFERENCE_L0)) |
@@ -157,7 +157,6 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) | |||
157 | } | 157 | } |
158 | #endif | 158 | #endif |
159 | 159 | ||
160 | /* Create DEST */ | ||
161 | if (dest_exists) { | 160 | if (dest_exists) { |
162 | if (!S_ISDIR(dest_stat.st_mode)) { | 161 | if (!S_ISDIR(dest_stat.st_mode)) { |
163 | bb_error_msg("target '%s' is not a directory", dest); | 162 | bb_error_msg("target '%s' is not a directory", dest); |
@@ -166,6 +165,7 @@ int FAST_FUNC copy_file(const char *source, const char *dest, int flags) | |||
166 | /* race here: user can substitute a symlink between | 165 | /* race here: user can substitute a symlink between |
167 | * this check and actual creation of files inside dest */ | 166 | * this check and actual creation of files inside dest */ |
168 | } else { | 167 | } else { |
168 | /* Create DEST */ | ||
169 | mode_t mode; | 169 | mode_t mode; |
170 | saved_umask = umask(0); | 170 | saved_umask = umask(0); |
171 | 171 | ||
diff --git a/libbb/crc32.c b/libbb/crc32.c index c63bf0772..ac9836cc9 100644 --- a/libbb/crc32.c +++ b/libbb/crc32.c | |||
@@ -59,7 +59,7 @@ uint32_t FAST_FUNC crc32_block_endian0(uint32_t val, const void *buf, unsigned l | |||
59 | const void *end = (uint8_t*)buf + len; | 59 | const void *end = (uint8_t*)buf + len; |
60 | 60 | ||
61 | while (buf != end) { | 61 | while (buf != end) { |
62 | val = crc_table[(uint8_t)val ^ *(uint8_t*)buf] ^ (val >> 8); | 62 | val = crc_table[(uint8_t)val ^ *(uint8_t*)buf] ^ (val >> 8); |
63 | buf = (uint8_t*)buf + 1; | 63 | buf = (uint8_t*)buf + 1; |
64 | } | 64 | } |
65 | return val; | 65 | return val; |
diff --git a/libbb/execable.c b/libbb/execable.c index 3b144a730..e35dad208 100644 --- a/libbb/execable.c +++ b/libbb/execable.c | |||
@@ -101,12 +101,12 @@ int FAST_FUNC exists_execable(const char *filename) | |||
101 | } | 101 | } |
102 | 102 | ||
103 | #if ENABLE_FEATURE_PREFER_APPLETS | 103 | #if ENABLE_FEATURE_PREFER_APPLETS |
104 | /* just like the real execvp, but try to launch an applet named 'file' first | 104 | /* just like the real execvp, but try to launch an applet named 'file' first */ |
105 | */ | 105 | int FAST_FUNC BB_EXECVP(const char *file, char *const argv[]) |
106 | int FAST_FUNC bb_execvp(const char *file, char *const argv[]) | ||
107 | { | 106 | { |
108 | return execvp(find_applet_by_name(file) >= 0 ? bb_busybox_exec_path : file, | 107 | if (find_applet_by_name(file) >= 0) |
109 | argv); | 108 | execvp(bb_busybox_exec_path, argv); |
109 | return execvp(file, argv); | ||
110 | } | 110 | } |
111 | #endif | 111 | #endif |
112 | 112 | ||
diff --git a/libbb/find_mount_point.c b/libbb/find_mount_point.c index 361698a6b..56637ad92 100644 --- a/libbb/find_mount_point.c +++ b/libbb/find_mount_point.c | |||
@@ -43,7 +43,7 @@ struct mntent* FAST_FUNC find_mount_point(const char *name, int subdir_too) | |||
43 | /* rootfs mount in Linux 2.6 exists always, | 43 | /* rootfs mount in Linux 2.6 exists always, |
44 | * and it makes sense to always ignore it. | 44 | * and it makes sense to always ignore it. |
45 | * Otherwise people can't reference their "real" root! */ | 45 | * Otherwise people can't reference their "real" root! */ |
46 | if (strcmp(mountEntry->mnt_fsname, "rootfs") == 0) | 46 | if (ENABLE_FEATURE_SKIP_ROOTFS && strcmp(mountEntry->mnt_fsname, "rootfs") == 0) |
47 | continue; | 47 | continue; |
48 | 48 | ||
49 | if (strcmp(name, mountEntry->mnt_dir) == 0 | 49 | if (strcmp(name, mountEntry->mnt_dir) == 0 |
diff --git a/libbb/getopt32.c b/libbb/getopt32.c index 187cb3a79..053ffc349 100644 --- a/libbb/getopt32.c +++ b/libbb/getopt32.c | |||
@@ -80,9 +80,9 @@ const char *applet_long_options | |||
80 | This struct allows you to define long options: | 80 | This struct allows you to define long options: |
81 | 81 | ||
82 | static const char applet_longopts[] ALIGN1 = | 82 | static const char applet_longopts[] ALIGN1 = |
83 | //"name\0" has_arg val | 83 | //"name\0" has_arg val |
84 | "verbose\0" No_argument "v" | 84 | "verbose\0" No_argument "v" |
85 | ; | 85 | ; |
86 | applet_long_options = applet_longopts; | 86 | applet_long_options = applet_longopts; |
87 | 87 | ||
88 | The last member of struct option (val) typically is set to | 88 | The last member of struct option (val) typically is set to |
@@ -226,7 +226,7 @@ Special characters: | |||
226 | if specified together. In this case you must set | 226 | if specified together. In this case you must set |
227 | opt_complementary = "b--cf:c--bf:f--bc". If two of the | 227 | opt_complementary = "b--cf:c--bf:f--bc". If two of the |
228 | mutually exclusive options are found, getopt32 will call | 228 | mutually exclusive options are found, getopt32 will call |
229 | bb_show_usage() and die. | 229 | bb_show_usage() and die. |
230 | 230 | ||
231 | "x--x" Variation of the above, it means that -x option should occur | 231 | "x--x" Variation of the above, it means that -x option should occur |
232 | at most once. | 232 | at most once. |
@@ -531,7 +531,7 @@ getopt32(char **argv, const char *applet_opts, ...) | |||
531 | 531 | ||
532 | /* In case getopt32 was already called: | 532 | /* In case getopt32 was already called: |
533 | * reset the libc getopt() function, which keeps internal state. | 533 | * reset the libc getopt() function, which keeps internal state. |
534 | * run_nofork_applet_prime() does this, but we might end up here | 534 | * run_nofork_applet() does this, but we might end up here |
535 | * also via gunzip_main() -> gzip_main(). Play safe. | 535 | * also via gunzip_main() -> gzip_main(). Play safe. |
536 | */ | 536 | */ |
537 | #if defined(__GLIBC__) || ENABLE_PLATFORM_MINGW32 | 537 | #if defined(__GLIBC__) || ENABLE_PLATFORM_MINGW32 |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index f9658711a..92ecc330a 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -1817,10 +1817,9 @@ static void win_changed(int nsig) | |||
1817 | errno = sv_errno; | 1817 | errno = sv_errno; |
1818 | } | 1818 | } |
1819 | 1819 | ||
1820 | static int lineedit_read_key(char *read_key_buffer) | 1820 | static int lineedit_read_key(char *read_key_buffer, int timeout) |
1821 | { | 1821 | { |
1822 | int64_t ic; | 1822 | int64_t ic; |
1823 | int timeout = -1; | ||
1824 | #if ENABLE_UNICODE_SUPPORT | 1823 | #if ENABLE_UNICODE_SUPPORT |
1825 | char unicode_buf[MB_CUR_MAX + 1]; | 1824 | char unicode_buf[MB_CUR_MAX + 1]; |
1826 | int unicode_idx = 0; | 1825 | int unicode_idx = 0; |
@@ -1925,7 +1924,7 @@ static int isrtl_str(void) | |||
1925 | * 0 on ctrl-C (the line entered is still returned in 'command'), | 1924 | * 0 on ctrl-C (the line entered is still returned in 'command'), |
1926 | * >0 length of input string, including terminating '\n' | 1925 | * >0 length of input string, including terminating '\n' |
1927 | */ | 1926 | */ |
1928 | int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, line_input_t *st) | 1927 | int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *command, int maxsize, int timeout) |
1929 | { | 1928 | { |
1930 | int len; | 1929 | int len; |
1931 | #if ENABLE_FEATURE_TAB_COMPLETION | 1930 | #if ENABLE_FEATURE_TAB_COMPLETION |
@@ -2006,7 +2005,6 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2006 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; | 2005 | new_settings.c_cc[VINTR] = _POSIX_VDISABLE; |
2007 | tcsetattr_stdin_TCSANOW(&new_settings); | 2006 | tcsetattr_stdin_TCSANOW(&new_settings); |
2008 | 2007 | ||
2009 | /* Now initialize things */ | ||
2010 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); | 2008 | previous_SIGWINCH_handler = signal(SIGWINCH, win_changed); |
2011 | win_changed(0); /* do initial resizing */ | 2009 | win_changed(0); /* do initial resizing */ |
2012 | #if ENABLE_USERNAME_OR_HOMEDIR | 2010 | #if ENABLE_USERNAME_OR_HOMEDIR |
@@ -2048,7 +2046,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2048 | int32_t ic, ic_raw; | 2046 | int32_t ic, ic_raw; |
2049 | 2047 | ||
2050 | fflush_all(); | 2048 | fflush_all(); |
2051 | ic = ic_raw = lineedit_read_key(read_key_buffer); | 2049 | ic = ic_raw = lineedit_read_key(read_key_buffer, timeout); |
2052 | 2050 | ||
2053 | #if ENABLE_FEATURE_EDITING_VI | 2051 | #if ENABLE_FEATURE_EDITING_VI |
2054 | newdelflag = 1; | 2052 | newdelflag = 1; |
@@ -2209,7 +2207,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2209 | case 'd'|VI_CMDMODE_BIT: { | 2207 | case 'd'|VI_CMDMODE_BIT: { |
2210 | int nc, sc; | 2208 | int nc, sc; |
2211 | 2209 | ||
2212 | ic = lineedit_read_key(read_key_buffer); | 2210 | ic = lineedit_read_key(read_key_buffer, timeout); |
2213 | if (errno) /* error */ | 2211 | if (errno) /* error */ |
2214 | goto return_error_indicator; | 2212 | goto return_error_indicator; |
2215 | if (ic == ic_raw) { /* "cc", "dd" */ | 2213 | if (ic == ic_raw) { /* "cc", "dd" */ |
@@ -2273,7 +2271,7 @@ int FAST_FUNC read_line_input(const char *prompt, char *command, int maxsize, li | |||
2273 | break; | 2271 | break; |
2274 | case 'r'|VI_CMDMODE_BIT: | 2272 | case 'r'|VI_CMDMODE_BIT: |
2275 | //FIXME: unicode case? | 2273 | //FIXME: unicode case? |
2276 | ic = lineedit_read_key(read_key_buffer); | 2274 | ic = lineedit_read_key(read_key_buffer, timeout); |
2277 | if (errno) /* error */ | 2275 | if (errno) /* error */ |
2278 | goto return_error_indicator; | 2276 | goto return_error_indicator; |
2279 | if (ic < ' ' || ic > 255) { | 2277 | if (ic < ' ' || ic > 255) { |
diff --git a/libbb/messages.c b/libbb/messages.c index 9e7bd0fef..ef42b30d7 100644 --- a/libbb/messages.c +++ b/libbb/messages.c | |||
@@ -22,7 +22,7 @@ | |||
22 | const char bb_banner[] ALIGN1 = BANNER; | 22 | const char bb_banner[] ALIGN1 = BANNER; |
23 | 23 | ||
24 | 24 | ||
25 | const char bb_msg_memory_exhausted[] ALIGN1 = "memory exhausted"; | 25 | const char bb_msg_memory_exhausted[] ALIGN1 = "out of memory"; |
26 | const char bb_msg_invalid_date[] ALIGN1 = "invalid date '%s'"; | 26 | const char bb_msg_invalid_date[] ALIGN1 = "invalid date '%s'"; |
27 | const char bb_msg_unknown[] ALIGN1 = "(unknown)"; | 27 | const char bb_msg_unknown[] ALIGN1 = "(unknown)"; |
28 | const char bb_msg_can_not_create_raw_socket[] ALIGN1 = "can't create raw socket"; | 28 | const char bb_msg_can_not_create_raw_socket[] ALIGN1 = "can't create raw socket"; |
diff --git a/libbb/platform.c b/libbb/platform.c index 30d06e3a7..1441a84ac 100644 --- a/libbb/platform.c +++ b/libbb/platform.c | |||
@@ -147,3 +147,14 @@ char* FAST_FUNC strsep(char **stringp, const char *delim) | |||
147 | return start; | 147 | return start; |
148 | } | 148 | } |
149 | #endif | 149 | #endif |
150 | |||
151 | #ifndef HAVE_STPCPY | ||
152 | char* FAST_FUNC stpcpy(char *p, const char *to_add) | ||
153 | { | ||
154 | while ((*p = *to_add) != '\0') { | ||
155 | p++; | ||
156 | to_add++; | ||
157 | } | ||
158 | return p; | ||
159 | } | ||
160 | #endif | ||
diff --git a/libbb/progress.c b/libbb/progress.c index 40608b047..df43dad5c 100644 --- a/libbb/progress.c +++ b/libbb/progress.c | |||
@@ -52,101 +52,154 @@ static unsigned int get_tty2_width(void) | |||
52 | return width; | 52 | return width; |
53 | } | 53 | } |
54 | 54 | ||
55 | void FAST_FUNC bb_progress_init(bb_progress_t *p) | 55 | void FAST_FUNC bb_progress_init(bb_progress_t *p, const char *curfile) |
56 | { | 56 | { |
57 | #if ENABLE_UNICODE_SUPPORT | ||
58 | init_unicode(); | ||
59 | p->curfile = unicode_conv_to_printable_fixedwidth(/*NULL,*/ curfile, 20); | ||
60 | #else | ||
61 | p->curfile = curfile; | ||
62 | #endif | ||
57 | p->start_sec = monotonic_sec(); | 63 | p->start_sec = monotonic_sec(); |
58 | p->lastupdate_sec = p->start_sec; | 64 | p->last_update_sec = p->start_sec; |
59 | p->lastsize = 0; | 65 | p->last_change_sec = p->start_sec; |
60 | p->inited = 1; | 66 | p->last_size = 0; |
61 | } | 67 | } |
62 | 68 | ||
69 | /* File already had beg_size bytes. | ||
70 | * Then we started downloading. | ||
71 | * We downloaded "transferred" bytes so far. | ||
72 | * Download is expected to stop when total size (beg_size + transferred) | ||
73 | * will be "totalsize" bytes. | ||
74 | * If totalsize == 0, then it is unknown. | ||
75 | */ | ||
63 | void FAST_FUNC bb_progress_update(bb_progress_t *p, | 76 | void FAST_FUNC bb_progress_update(bb_progress_t *p, |
64 | const char *curfile, | 77 | uoff_t beg_size, |
65 | off_t beg_range, | 78 | uoff_t transferred, |
66 | off_t transferred, | 79 | uoff_t totalsize) |
67 | off_t totalsize) | ||
68 | { | 80 | { |
69 | uoff_t beg_and_transferred; | 81 | uoff_t beg_and_transferred; |
70 | unsigned since_last_update, elapsed; | 82 | unsigned since_last_update, elapsed; |
71 | unsigned ratio; | 83 | int barlength; |
72 | int barlength, i; | 84 | int kiloscale; |
73 | 85 | ||
74 | /* totalsize == 0 if it is unknown */ | 86 | //transferred = 1234; /* use for stall detection testing */ |
87 | //totalsize = 0; /* use for unknown size download testing */ | ||
75 | 88 | ||
76 | elapsed = monotonic_sec(); | 89 | elapsed = monotonic_sec(); |
77 | since_last_update = elapsed - p->lastupdate_sec; | 90 | since_last_update = elapsed - p->last_update_sec; |
78 | /* Do not update on every call | 91 | p->last_update_sec = elapsed; |
79 | * (we can be called on every network read!) */ | ||
80 | if (since_last_update == 0 && !totalsize) | ||
81 | return; | ||
82 | 92 | ||
83 | beg_and_transferred = beg_range + transferred; | 93 | if (totalsize != 0 && transferred >= totalsize - beg_size) { |
84 | ratio = 100; | 94 | /* Last call. Do not skip this update */ |
85 | if (beg_and_transferred < totalsize) { | 95 | transferred = totalsize - beg_size; /* sanitize just in case */ |
86 | /* Do not update on every call | 96 | } |
87 | * (we can be called on every network read!) */ | 97 | else if (since_last_update == 0) { |
88 | if (since_last_update == 0) | 98 | /* |
89 | return; | 99 | * Do not update on every call |
90 | /* long long helps to have it working even if !LFS */ | 100 | * (we can be called on every network read!) |
91 | ratio = 100ULL * beg_and_transferred / (uoff_t)totalsize; | 101 | */ |
102 | return; | ||
92 | } | 103 | } |
93 | 104 | ||
94 | #if ENABLE_UNICODE_SUPPORT | 105 | kiloscale = 0; |
95 | init_unicode(); | 106 | /* |
96 | { | 107 | * Scale sizes down if they are close to overflowing. |
97 | char *buf = unicode_conv_to_printable_fixedwidth(/*NULL,*/ curfile, 20); | 108 | * This allows calculations like (100 * transferred / totalsize) |
98 | fprintf(stderr, "\r%s%4u%% ", buf, ratio); | 109 | * without risking overflow: we guarantee 10 highest bits to be 0. |
99 | free(buf); | 110 | * Introduced error is less than 1 / 2^12 ~= 0.025% |
111 | */ | ||
112 | if (ULONG_MAX > 0xffffffff || sizeof(off_t) == 4 || sizeof(off_t) != 8) { | ||
113 | /* | ||
114 | * 64-bit CPU || small off_t: in either case, | ||
115 | * >> is cheap, single-word operation. | ||
116 | * ... || strange off_t: also use this code | ||
117 | * (it is safe, just suboptimal wrt code size), | ||
118 | * because 32/64 optimized one works only for 64-bit off_t. | ||
119 | */ | ||
120 | if (totalsize >= (1 << 22)) { | ||
121 | totalsize >>= 10; | ||
122 | beg_size >>= 10; | ||
123 | transferred >>= 10; | ||
124 | kiloscale = 1; | ||
125 | } | ||
126 | } else { | ||
127 | /* 32-bit CPU and 64-bit off_t. | ||
128 | * Use a 40-bit shift, it is easier to do on 32-bit CPU. | ||
129 | */ | ||
130 | if (totalsize >= (uoff_t)(1ULL << 54)) { | ||
131 | totalsize = (uint32_t)(totalsize >> 32) >> 8; | ||
132 | beg_size = (uint32_t)(beg_size >> 32) >> 8; | ||
133 | transferred = (uint32_t)(transferred >> 32) >> 8; | ||
134 | kiloscale = 4; | ||
135 | } | ||
100 | } | 136 | } |
101 | #else | ||
102 | fprintf(stderr, "\r%-20.20s%4u%% ", curfile, ratio); | ||
103 | #endif | ||
104 | 137 | ||
105 | barlength = get_tty2_width() - 49; | 138 | if (ENABLE_UNICODE_SUPPORT) |
106 | if (barlength > 0) { | 139 | fprintf(stderr, "\r%s", p->curfile); |
107 | /* god bless gcc for variable arrays :) */ | 140 | else |
108 | char buf[barlength + 1]; | 141 | fprintf(stderr, "\r%-20.20s", p->curfile); |
109 | unsigned stars = (unsigned)barlength * ratio / (unsigned)100; | 142 | |
110 | memset(buf, ' ', barlength); | 143 | beg_and_transferred = beg_size + transferred; |
111 | buf[barlength] = '\0'; | 144 | |
112 | memset(buf, '*', stars); | 145 | if (totalsize != 0) { |
113 | fprintf(stderr, "|%s|", buf); | 146 | unsigned ratio = 100 * beg_and_transferred / totalsize; |
147 | fprintf(stderr, "%4u%%", ratio); | ||
148 | |||
149 | barlength = get_tty2_width() - 49; | ||
150 | if (barlength > 0) { | ||
151 | /* god bless gcc for variable arrays :) */ | ||
152 | char buf[barlength + 1]; | ||
153 | unsigned stars = (unsigned)barlength * beg_and_transferred / totalsize; | ||
154 | memset(buf, ' ', barlength); | ||
155 | buf[barlength] = '\0'; | ||
156 | memset(buf, '*', stars); | ||
157 | fprintf(stderr, " |%s|", buf); | ||
158 | } | ||
114 | } | 159 | } |
115 | 160 | ||
116 | i = 0; | ||
117 | while (beg_and_transferred >= 100000) { | 161 | while (beg_and_transferred >= 100000) { |
118 | i++; | ||
119 | beg_and_transferred >>= 10; | 162 | beg_and_transferred >>= 10; |
163 | kiloscale++; | ||
120 | } | 164 | } |
121 | /* see http://en.wikipedia.org/wiki/Tera */ | 165 | /* see http://en.wikipedia.org/wiki/Tera */ |
122 | fprintf(stderr, "%6u%c ", (unsigned)beg_and_transferred, " kMGTPEZY"[i]); | 166 | fprintf(stderr, "%6u%c", (unsigned)beg_and_transferred, " kMGTPEZY"[kiloscale]); |
123 | #define beg_and_transferred dont_use_beg_and_transferred_below | 167 | #define beg_and_transferred dont_use_beg_and_transferred_below() |
124 | 168 | ||
125 | if (transferred > p->lastsize) { | 169 | since_last_update = elapsed - p->last_change_sec; |
126 | p->lastupdate_sec = elapsed; | 170 | if ((unsigned)transferred != p->last_size) { |
127 | p->lastsize = transferred; | 171 | p->last_change_sec = elapsed; |
172 | p->last_size = (unsigned)transferred; | ||
128 | if (since_last_update >= STALLTIME) { | 173 | if (since_last_update >= STALLTIME) { |
129 | /* We "cut off" these seconds from elapsed time | 174 | /* We "cut out" these seconds from elapsed time |
130 | * by adjusting start time */ | 175 | * by adjusting start time */ |
131 | p->start_sec += since_last_update; | 176 | p->start_sec += since_last_update; |
132 | } | 177 | } |
133 | since_last_update = 0; /* we are un-stalled now */ | 178 | since_last_update = 0; /* we are un-stalled now */ |
134 | } | 179 | } |
180 | |||
135 | elapsed -= p->start_sec; /* now it's "elapsed since start" */ | 181 | elapsed -= p->start_sec; /* now it's "elapsed since start" */ |
136 | 182 | ||
137 | if (since_last_update >= STALLTIME) { | 183 | if (since_last_update >= STALLTIME) { |
138 | fprintf(stderr, " - stalled -"); | 184 | fprintf(stderr, " - stalled -"); |
185 | } else if (!totalsize || !transferred || (int)elapsed < 0) { | ||
186 | fprintf(stderr, " --:--:-- ETA"); | ||
139 | } else { | 187 | } else { |
140 | off_t to_download = totalsize - beg_range; | 188 | unsigned eta, secs, hours; |
141 | if (!totalsize || transferred <= 0 || (int)elapsed <= 0 || transferred > to_download) { | 189 | |
142 | fprintf(stderr, "--:--:-- ETA"); | 190 | totalsize -= beg_size; /* now it's "total to upload" */ |
143 | } else { | 191 | |
144 | /* to_download / (transferred/elapsed) - elapsed: */ | 192 | /* Estimated remaining time = |
145 | /* (long long helps to have working ETA even if !LFS) */ | 193 | * estimated_sec_to_dl_totalsize_bytes - elapsed_sec = |
146 | unsigned eta = (unsigned long long)to_download*elapsed/(uoff_t)transferred - elapsed; | 194 | * totalsize / average_bytes_sec_so_far - elapsed = |
147 | unsigned secs = eta % 3600; | 195 | * totalsize / (transferred/elapsed) - elapsed = |
148 | unsigned hours = eta / 3600; | 196 | * totalsize * elapsed / transferred - elapsed |
149 | fprintf(stderr, "%02u:%02u:%02u ETA", hours, secs / 60, secs % 60); | 197 | */ |
150 | } | 198 | eta = totalsize * elapsed / transferred - elapsed; |
199 | if (eta >= 1000*60*60) | ||
200 | eta = 1000*60*60 - 1; | ||
201 | secs = eta % 3600; | ||
202 | hours = eta / 3600; | ||
203 | fprintf(stderr, "%3u:%02u:%02u ETA", hours, secs / 60, secs % 60); | ||
151 | } | 204 | } |
152 | } | 205 | } |
diff --git a/libbb/systemd_support.c b/libbb/systemd_support.c index 981296dbb..542a3efff 100644 --- a/libbb/systemd_support.c +++ b/libbb/systemd_support.c | |||
@@ -33,7 +33,7 @@ | |||
33 | //config: If you plan to use busybox daemons on a system where daemons | 33 | //config: If you plan to use busybox daemons on a system where daemons |
34 | //config: are controlled by systemd, enable this option. | 34 | //config: are controlled by systemd, enable this option. |
35 | //config: If you don't use systemd, it is still safe to enable it, | 35 | //config: If you don't use systemd, it is still safe to enable it, |
36 | //config: but yhe downside is increased code size. | 36 | //config: but the downside is increased code size. |
37 | 37 | ||
38 | //kbuild:lib-$(CONFIG_FEATURE_SYSTEMD) += systemd_support.o | 38 | //kbuild:lib-$(CONFIG_FEATURE_SYSTEMD) += systemd_support.o |
39 | 39 | ||
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index 1fbb1bba9..5d8056bd6 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c | |||
@@ -55,6 +55,7 @@ pid_t FAST_FUNC spawn(char **argv) | |||
55 | * Interested party can wait on pid and learn exit code. | 55 | * Interested party can wait on pid and learn exit code. |
56 | * If 111 - then it (most probably) failed to exec */ | 56 | * If 111 - then it (most probably) failed to exec */ |
57 | if (failed) { | 57 | if (failed) { |
58 | safe_waitpid(pid, NULL, 0); /* prevent zombie */ | ||
58 | errno = failed; | 59 | errno = failed; |
59 | return -1; | 60 | return -1; |
60 | } | 61 | } |
@@ -71,17 +72,22 @@ pid_t FAST_FUNC xspawn(char **argv) | |||
71 | } | 72 | } |
72 | 73 | ||
73 | #if ENABLE_FEATURE_PREFER_APPLETS | 74 | #if ENABLE_FEATURE_PREFER_APPLETS |
74 | void FAST_FUNC save_nofork_data(struct nofork_save_area *save) | 75 | struct nofork_save_area { |
76 | jmp_buf die_jmp; | ||
77 | const char *applet_name; | ||
78 | uint32_t option_mask32; | ||
79 | int die_sleep; | ||
80 | uint8_t xfunc_error_retval; | ||
81 | }; | ||
82 | static void save_nofork_data(struct nofork_save_area *save) | ||
75 | { | 83 | { |
76 | memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); | 84 | memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); |
77 | save->applet_name = applet_name; | 85 | save->applet_name = applet_name; |
78 | save->xfunc_error_retval = xfunc_error_retval; | 86 | save->xfunc_error_retval = xfunc_error_retval; |
79 | save->option_mask32 = option_mask32; | 87 | save->option_mask32 = option_mask32; |
80 | save->die_sleep = die_sleep; | 88 | save->die_sleep = die_sleep; |
81 | save->saved = 1; | ||
82 | } | 89 | } |
83 | 90 | static void restore_nofork_data(struct nofork_save_area *save) | |
84 | void FAST_FUNC restore_nofork_data(struct nofork_save_area *save) | ||
85 | { | 91 | { |
86 | memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); | 92 | memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); |
87 | applet_name = save->applet_name; | 93 | applet_name = save->applet_name; |
@@ -90,19 +96,17 @@ void FAST_FUNC restore_nofork_data(struct nofork_save_area *save) | |||
90 | die_sleep = save->die_sleep; | 96 | die_sleep = save->die_sleep; |
91 | } | 97 | } |
92 | 98 | ||
93 | int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **argv) | 99 | int FAST_FUNC run_nofork_applet(int applet_no, char **argv) |
94 | { | 100 | { |
95 | int rc, argc; | 101 | int rc, argc; |
102 | struct nofork_save_area old; | ||
103 | |||
104 | save_nofork_data(&old); | ||
96 | 105 | ||
97 | applet_name = APPLET_NAME(applet_no); | 106 | applet_name = APPLET_NAME(applet_no); |
98 | 107 | ||
99 | xfunc_error_retval = EXIT_FAILURE; | 108 | xfunc_error_retval = EXIT_FAILURE; |
100 | 109 | ||
101 | /* Special flag for xfunc_die(). If xfunc will "die" | ||
102 | * in NOFORK applet, xfunc_die() sees negative | ||
103 | * die_sleep and longjmp here instead. */ | ||
104 | die_sleep = -1; | ||
105 | |||
106 | /* In case getopt() or getopt32() was already called: | 110 | /* In case getopt() or getopt32() was already called: |
107 | * reset the libc getopt() function, which keeps internal state. | 111 | * reset the libc getopt() function, which keeps internal state. |
108 | * | 112 | * |
@@ -132,6 +136,11 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n | |||
132 | while (argv[argc]) | 136 | while (argv[argc]) |
133 | argc++; | 137 | argc++; |
134 | 138 | ||
139 | /* Special flag for xfunc_die(). If xfunc will "die" | ||
140 | * in NOFORK applet, xfunc_die() sees negative | ||
141 | * die_sleep and longjmp here instead. */ | ||
142 | die_sleep = -1; | ||
143 | |||
135 | rc = setjmp(die_jmp); | 144 | rc = setjmp(die_jmp); |
136 | if (!rc) { | 145 | if (!rc) { |
137 | /* Some callers (xargs) | 146 | /* Some callers (xargs) |
@@ -140,15 +149,6 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n | |||
140 | memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); | 149 | memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); |
141 | /* Finally we can call NOFORK applet's main() */ | 150 | /* Finally we can call NOFORK applet's main() */ |
142 | rc = applet_main[applet_no](argc, tmp_argv); | 151 | rc = applet_main[applet_no](argc, tmp_argv); |
143 | |||
144 | /* The whole reason behind nofork_save_area is that <applet>_main | ||
145 | * may exit non-locally! For example, in hush Ctrl-Z tries | ||
146 | * (modulo bugs) to dynamically create a child (backgrounded task) | ||
147 | * if it detects that Ctrl-Z was pressed when a NOFORK was running. | ||
148 | * Testcase: interactive "rm -i". | ||
149 | * Don't fool yourself into thinking "and <applet>_main() returns | ||
150 | * quickly here" and removing "useless" nofork_save_area code. */ | ||
151 | |||
152 | } else { /* xfunc died in NOFORK applet */ | 152 | } else { /* xfunc died in NOFORK applet */ |
153 | /* in case they meant to return 0... */ | 153 | /* in case they meant to return 0... */ |
154 | if (rc == -2222) | 154 | if (rc == -2222) |
@@ -156,7 +156,7 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n | |||
156 | } | 156 | } |
157 | 157 | ||
158 | /* Restoring some globals */ | 158 | /* Restoring some globals */ |
159 | restore_nofork_data(old); | 159 | restore_nofork_data(&old); |
160 | 160 | ||
161 | /* Other globals can be simply reset to defaults */ | 161 | /* Other globals can be simply reset to defaults */ |
162 | #ifdef __GLIBC__ | 162 | #ifdef __GLIBC__ |
@@ -167,15 +167,6 @@ int FAST_FUNC run_nofork_applet_prime(struct nofork_save_area *old, int applet_n | |||
167 | 167 | ||
168 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ | 168 | return rc & 0xff; /* don't confuse people with "exitcodes" >255 */ |
169 | } | 169 | } |
170 | |||
171 | int FAST_FUNC run_nofork_applet(int applet_no, char **argv) | ||
172 | { | ||
173 | struct nofork_save_area old; | ||
174 | |||
175 | /* Saving globals */ | ||
176 | save_nofork_data(&old); | ||
177 | return run_nofork_applet_prime(&old, applet_no, argv); | ||
178 | } | ||
179 | #endif /* FEATURE_PREFER_APPLETS */ | 170 | #endif /* FEATURE_PREFER_APPLETS */ |
180 | 171 | ||
181 | int FAST_FUNC spawn_and_wait(char **argv) | 172 | int FAST_FUNC spawn_and_wait(char **argv) |
@@ -185,17 +176,17 @@ int FAST_FUNC spawn_and_wait(char **argv) | |||
185 | int a = find_applet_by_name(argv[0]); | 176 | int a = find_applet_by_name(argv[0]); |
186 | 177 | ||
187 | if (a >= 0 && (APPLET_IS_NOFORK(a) | 178 | if (a >= 0 && (APPLET_IS_NOFORK(a) |
188 | #if BB_MMU | 179 | # if BB_MMU |
189 | || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */ | 180 | || APPLET_IS_NOEXEC(a) /* NOEXEC trick needs fork() */ |
190 | #endif | 181 | # endif |
191 | )) { | 182 | )) { |
192 | #if BB_MMU | 183 | # if BB_MMU |
193 | if (APPLET_IS_NOFORK(a)) | 184 | if (APPLET_IS_NOFORK(a)) |
194 | #endif | 185 | # endif |
195 | { | 186 | { |
196 | return run_nofork_applet(a, argv); | 187 | return run_nofork_applet(a, argv); |
197 | } | 188 | } |
198 | #if BB_MMU && !ENABLE_PLATFORM_MINGW32 | 189 | # if BB_MMU && !ENABLE_PLATFORM_MINGW32 |
199 | /* MMU only */ | 190 | /* MMU only */ |
200 | /* a->noexec is true */ | 191 | /* a->noexec is true */ |
201 | rc = fork(); | 192 | rc = fork(); |
@@ -204,7 +195,7 @@ int FAST_FUNC spawn_and_wait(char **argv) | |||
204 | /* child */ | 195 | /* child */ |
205 | xfunc_error_retval = EXIT_FAILURE; | 196 | xfunc_error_retval = EXIT_FAILURE; |
206 | run_applet_no_and_exit(a, argv); | 197 | run_applet_no_and_exit(a, argv); |
207 | #endif | 198 | # endif |
208 | } | 199 | } |
209 | #endif /* FEATURE_PREFER_APPLETS */ | 200 | #endif /* FEATURE_PREFER_APPLETS */ |
210 | rc = spawn(argv); | 201 | rc = spawn(argv); |