aboutsummaryrefslogtreecommitdiff
path: root/libbb
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2021-10-13 14:37:51 +0100
committerRon Yorston <rmy@pobox.com>2021-10-13 14:37:51 +0100
commit0ecf1aea459571b48dc68ddc2b7b9265740fa960 (patch)
tree491d6184a44b8b525a4ca35759d622aecd7f6344 /libbb
parent4859ddcb20616718efbea12c6bf8b27c469b68de (diff)
parentaaf3d5ba74c5da97ff80b61f30cb8dd225d39096 (diff)
downloadbusybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.gz
busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.tar.bz2
busybox-w32-0ecf1aea459571b48dc68ddc2b7b9265740fa960.zip
Merge branch 'busybox' into merge
Diffstat (limited to 'libbb')
-rw-r--r--libbb/Config.src185
-rw-r--r--libbb/Kbuild.src1
-rw-r--r--libbb/appletlib.c23
-rw-r--r--libbb/const_hack.c16
-rw-r--r--libbb/dump.c2
-rw-r--r--libbb/lineedit.c94
-rw-r--r--libbb/vfork_daemon_rexec.c16
-rw-r--r--libbb/xreadlink.c75
8 files changed, 210 insertions, 202 deletions
diff --git a/libbb/Config.src b/libbb/Config.src
index 58c5fad50..24b31fad9 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -61,32 +61,73 @@ config SHA3_SMALL
61 64-bit x86: +270 bytes of code, 45% faster 61 64-bit x86: +270 bytes of code, 45% faster
62 32-bit x86: +450 bytes of code, 75% faster 62 32-bit x86: +450 bytes of code, 75% faster
63 63
64config FEATURE_FAST_TOP 64config FEATURE_NON_POSIX_CP
65 bool "Faster /proc scanning code (+100 bytes)" 65 bool "Non-POSIX, but safer, copying to special nodes"
66 default n # all "fast or small" options default to small 66 default y
67 help 67 help
68 This option makes top and ps ~20% faster (or 20% less CPU hungry), 68 With this option, "cp file symlink" will delete symlink
69 but code size is slightly bigger. 69 and create a regular file. This does not conform to POSIX,
70 but prevents a symlink attack.
71 Similarly, "cp file device" will not send file's data
72 to the device. (To do that, use "cat file >device")
70 73
71config FEATURE_ETC_NETWORKS 74config FEATURE_VERBOSE_CP_MESSAGE
72 bool "Support /etc/networks" 75 bool "Give more precise messages when copy fails (cp, mv etc)"
73 default n 76 default n
74 help 77 help
75 Enable support for network names in /etc/networks. This is 78 Error messages with this feature enabled:
76 a rarely used feature which allows you to use names
77 instead of IP/mask pairs in route command.
78 79
79config FEATURE_ETC_SERVICES 80 $ cp file /does_not_exist/file
80 bool "Consult /etc/services even for well-known ports" 81 cp: cannot create '/does_not_exist/file': Path does not exist
81 default n 82 $ cp file /vmlinuz/file
83 cp: cannot stat '/vmlinuz/file': Path has non-directory component
84
85 If this feature is not enabled, they will be, respectively:
86
87 cp: cannot create '/does_not_exist/file': No such file or directory
88 cp: cannot stat '/vmlinuz/file': Not a directory
89
90 This will cost you ~60 bytes.
91
92config FEATURE_USE_SENDFILE
93 bool "Use sendfile system call"
94 default y
95 help
96 When enabled, busybox will use the kernel sendfile() function
97 instead of read/write loops to copy data between file descriptors
98 (for example, cp command does this a lot).
99 If sendfile() doesn't work, copying code falls back to read/write
100 loop. sendfile() was originally implemented for faster I/O
101 from files to sockets, but since Linux 2.6.33 it was extended
102 to work for many more file types.
103
104config FEATURE_COPYBUF_KB
105 int "Copy buffer size, in kilobytes"
106 range 1 1024
107 default 4
108 help
109 Size of buffer used by cp, mv, install, wget etc.
110 Buffers which are 4 kb or less will be allocated on stack.
111 Bigger buffers will be allocated with mmap, with fallback to 4 kb
112 stack buffer if mmap fails.
113
114config MONOTONIC_SYSCALL
115 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
116 default y
117 help
118 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
119 time intervals (time, ping, traceroute etc need this).
120 Probably requires Linux 2.6+. If not selected, gettimeofday
121 will be used instead (which gives wrong results if date/time
122 is reset).
123
124config IOCTL_HEX2STR_ERROR
125 bool "Use ioctl names rather than hex values in error messages"
126 default y
82 help 127 help
83 Look up e.g. "telnet" and "http" in /etc/services file 128 Use ioctl names rather than hex values in error messages
84 instead of assuming ports 23 and 80. 129 (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this
85 This is almost never necessary (everybody uses standard ports), 130 saves about 1400 bytes.
86 and it makes sense to avoid reading this file.
87 If you disable this option, in the cases where port is explicitly
88 specified as a service name (e.g. "telnet HOST PORTNAME"),
89 it will still be looked up in /etc/services.
90 131
91config FEATURE_EDITING 132config FEATURE_EDITING
92 bool "Command line editing" 133 bool "Command line editing"
@@ -302,107 +343,3 @@ config UNICODE_PRESERVE_BROKEN
302 For example, this means that entering 'l', 's', ' ', 0xff, [Enter] 343 For example, this means that entering 'l', 's', ' ', 0xff, [Enter]
303 at shell prompt will list file named 0xff (single char name 344 at shell prompt will list file named 0xff (single char name
304 with char value 255), not file named '?'. 345 with char value 255), not file named '?'.
305
306config FEATURE_NON_POSIX_CP
307 bool "Non-POSIX, but safer, copying to special nodes"
308 default y
309 help
310 With this option, "cp file symlink" will delete symlink
311 and create a regular file. This does not conform to POSIX,
312 but prevents a symlink attack.
313 Similarly, "cp file device" will not send file's data
314 to the device. (To do that, use "cat file >device")
315
316config FEATURE_VERBOSE_CP_MESSAGE
317 bool "Give more precise messages when copy fails (cp, mv etc)"
318 default n
319 help
320 Error messages with this feature enabled:
321
322 $ cp file /does_not_exist/file
323 cp: cannot create '/does_not_exist/file': Path does not exist
324 $ cp file /vmlinuz/file
325 cp: cannot stat '/vmlinuz/file': Path has non-directory component
326
327 If this feature is not enabled, they will be, respectively:
328
329 cp: cannot create '/does_not_exist/file': No such file or directory
330 cp: cannot stat '/vmlinuz/file': Not a directory
331
332 This will cost you ~60 bytes.
333
334config FEATURE_USE_SENDFILE
335 bool "Use sendfile system call"
336 default y
337 help
338 When enabled, busybox will use the kernel sendfile() function
339 instead of read/write loops to copy data between file descriptors
340 (for example, cp command does this a lot).
341 If sendfile() doesn't work, copying code falls back to read/write
342 loop. sendfile() was originally implemented for faster I/O
343 from files to sockets, but since Linux 2.6.33 it was extended
344 to work for many more file types.
345
346config FEATURE_COPYBUF_KB
347 int "Copy buffer size, in kilobytes"
348 range 1 1024
349 default 4
350 help
351 Size of buffer used by cp, mv, install, wget etc.
352 Buffers which are 4 kb or less will be allocated on stack.
353 Bigger buffers will be allocated with mmap, with fallback to 4 kb
354 stack buffer if mmap fails.
355
356config FEATURE_SKIP_ROOTFS
357 bool "Skip rootfs in mount table"
358 default y
359 help
360 Ignore rootfs entry in mount table.
361
362 In Linux, kernel has a special filesystem, rootfs, which is initially
363 mounted on /. It contains initramfs data, if kernel is configured
364 to have one. Usually, another file system is mounted over / early
365 in boot process, and therefore most tools which manipulate
366 mount table, such as df, will skip rootfs entry.
367
368 However, some systems do not mount anything on /.
369 If you need to configure busybox for one of these systems,
370 you may find it useful to turn this option off to make df show
371 initramfs statistics.
372
373 Otherwise, choose Y.
374
375config MONOTONIC_SYSCALL
376 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
377 default y
378 help
379 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
380 time intervals (time, ping, traceroute etc need this).
381 Probably requires Linux 2.6+. If not selected, gettimeofday
382 will be used instead (which gives wrong results if date/time
383 is reset).
384
385config IOCTL_HEX2STR_ERROR
386 bool "Use ioctl names rather than hex values in error messages"
387 default y
388 help
389 Use ioctl names rather than hex values in error messages
390 (e.g. VT_DISALLOCATE rather than 0x5608). If disabled this
391 saves about 1400 bytes.
392
393config FEATURE_HWIB
394 bool "Support infiniband HW"
395 default y
396 help
397 Support for printing infiniband addresses in network applets.
398
399config FEATURE_TIMEZONE
400 bool "Allow timezone in dates"
401 default y
402 depends on DESKTOP
403 help
404 Permit the use of timezones when parsing user-provided data
405 strings, e.g. '1996-04-09 12:45:00 -0500'.
406
407 This requires support for the '%z' extension to strptime() which
408 may not be available in all implementations.
diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src
index 102e360af..60df3476f 100644
--- a/libbb/Kbuild.src
+++ b/libbb/Kbuild.src
@@ -21,6 +21,7 @@ lib-y += chomp.o
21lib-y += compare_string_array.o 21lib-y += compare_string_array.o
22lib-y += concat_path_file.o 22lib-y += concat_path_file.o
23lib-y += concat_subpath_file.o 23lib-y += concat_subpath_file.o
24lib-y += const_hack.o
24lib-y += copy_file.o 25lib-y += copy_file.o
25lib-y += copyfd.o 26lib-y += copyfd.o
26lib-y += crc32.o 27lib-y += crc32.o
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index e1f8bf432..6c0be4a83 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -262,8 +262,7 @@ void lbb_prepare(const char *applet
262 IF_FEATURE_INDIVIDUAL(, char **argv)) 262 IF_FEATURE_INDIVIDUAL(, char **argv))
263{ 263{
264#ifdef bb_cached_errno_ptr 264#ifdef bb_cached_errno_ptr
265 (*(int **)not_const_pp(&bb_errno)) = get_perrno(); 265 ASSIGN_CONST_PTR(&bb_errno, get_perrno());
266 barrier();
267#endif 266#endif
268 applet_name = applet; 267 applet_name = applet;
269 268
@@ -767,9 +766,9 @@ int scripted_main(int argc UNUSED_PARAM, char **argv)
767 int script = find_script_by_name(applet_name); 766 int script = find_script_by_name(applet_name);
768 if (script >= 0) 767 if (script >= 0)
769# if ENABLE_SHELL_ASH 768# if ENABLE_SHELL_ASH
770 exit(ash_main(-script - 1, argv)); 769 return ash_main(-script - 1, argv);
771# elif ENABLE_SHELL_HUSH 770# elif ENABLE_SHELL_HUSH
772 exit(hush_main(-script - 1, argv)); 771 return hush_main(-script - 1, argv);
773# else 772# else
774 return 1; 773 return 1;
775# endif 774# endif
@@ -1161,10 +1160,10 @@ int scripted_main(int argc UNUSED_PARAM, char **argv)
1161{ 1160{
1162# if ENABLE_SHELL_ASH 1161# if ENABLE_SHELL_ASH
1163 int script = 0; 1162 int script = 0;
1164 exit(ash_main(-script - 1, argv)); 1163 return ash_main(-script - 1, argv);
1165# elif ENABLE_SHELL_HUSH 1164# elif ENABLE_SHELL_HUSH
1166 int script = 0; 1165 int script = 0;
1167 exit(hush_main(-script - 1, argv)); 1166 return hush_main(-script - 1, argv);
1168# else 1167# else
1169 return 1; 1168 return 1;
1170# endif 1169# endif
@@ -1282,7 +1281,7 @@ int main(int argc UNUSED_PARAM, char **argv)
1282 1281
1283 full_write2_str(bb_basename(argv[0])); 1282 full_write2_str(bb_basename(argv[0]));
1284 full_write2_str(": no applets enabled\n"); 1283 full_write2_str(": no applets enabled\n");
1285 exit(127); 1284 return 127;
1286 1285
1287#else 1286#else
1288 1287
@@ -1314,8 +1313,14 @@ int main(int argc UNUSED_PARAM, char **argv)
1314 || ENABLE_FEATURE_PREFER_APPLETS 1313 || ENABLE_FEATURE_PREFER_APPLETS
1315 || !BB_MMU 1314 || !BB_MMU
1316 ) { 1315 ) {
1317 if (NUM_APPLETS > 1) 1316 if (NUM_APPLETS > 1) {
1318 set_task_comm(applet_name); 1317 /* Careful, do not trash comm of "SCRIPT.sh" -
1318 * the case when started from e.g. #!/bin/ash script.
1319 * (not limited to shells - #!/bin/awk scripts also exist)
1320 */
1321 if (re_execed_comm())
1322 set_task_comm(applet_name);
1323 }
1319 } 1324 }
1320 1325
1321 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */ 1326 parse_config_file(); /* ...maybe, if FEATURE_SUID_CONFIG */
diff --git a/libbb/const_hack.c b/libbb/const_hack.c
new file mode 100644
index 000000000..9575e6d67
--- /dev/null
+++ b/libbb/const_hack.c
@@ -0,0 +1,16 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Trick to assign a const ptr with barrier for clang
4 *
5 * Copyright (C) 2021 by YU Jincheng <shana@zju.edu.cn>
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */
9#include "libbb.h"
10
11#if defined(__clang_major__) && __clang_major__ >= 9
12void FAST_FUNC XZALLOC_CONST_PTR(const void *pptr, size_t size)
13{
14 ASSIGN_CONST_PTR(pptr, xzalloc(size));
15}
16#endif
diff --git a/libbb/dump.c b/libbb/dump.c
index ffae04786..d24057325 100644
--- a/libbb/dump.c
+++ b/libbb/dump.c
@@ -568,7 +568,7 @@ static void conv_u(PR *pr, unsigned char *p)
568 } 568 }
569} 569}
570 570
571static void display(priv_dumper_t* dumper) 571static NOINLINE void display(priv_dumper_t* dumper)
572{ 572{
573 unsigned char *bp; 573 unsigned char *bp;
574 unsigned char savech = '\0'; 574 unsigned char savech = '\0';
diff --git a/libbb/lineedit.c b/libbb/lineedit.c
index 7c46fa5db..8abc87976 100644
--- a/libbb/lineedit.c
+++ b/libbb/lineedit.c
@@ -135,10 +135,6 @@ enum {
135 : 0x7ff0 135 : 0x7ff0
136}; 136};
137 137
138#if ENABLE_USERNAME_OR_HOMEDIR
139static const char null_str[] ALIGN1 = "";
140#endif
141
142/* We try to minimize both static and stack usage. */ 138/* We try to minimize both static and stack usage. */
143struct lineedit_statics { 139struct lineedit_statics {
144 line_input_t *state; 140 line_input_t *state;
@@ -161,12 +157,13 @@ struct lineedit_statics {
161 157
162#if ENABLE_USERNAME_OR_HOMEDIR 158#if ENABLE_USERNAME_OR_HOMEDIR
163 char *user_buf; 159 char *user_buf;
164 char *home_pwd_buf; /* = (char*)null_str; */ 160 char *home_pwd_buf;
161 smallint got_user_strings;
165#endif 162#endif
166 163
167#if ENABLE_FEATURE_TAB_COMPLETION 164#if ENABLE_FEATURE_TAB_COMPLETION
168 char **matches;
169 unsigned num_matches; 165 unsigned num_matches;
166 char **matches;
170#endif 167#endif
171 168
172#if ENABLE_FEATURE_EDITING_WINCH 169#if ENABLE_FEATURE_EDITING_WINCH
@@ -192,7 +189,7 @@ struct lineedit_statics {
192}; 189};
193 190
194/* See lineedit_ptr_hack.c */ 191/* See lineedit_ptr_hack.c */
195extern struct lineedit_statics *const lineedit_ptr_to_statics; 192extern struct lineedit_statics *BB_GLOBAL_CONST lineedit_ptr_to_statics;
196 193
197#define S (*lineedit_ptr_to_statics) 194#define S (*lineedit_ptr_to_statics)
198#define state (S.state ) 195#define state (S.state )
@@ -207,15 +204,15 @@ extern struct lineedit_statics *const lineedit_ptr_to_statics;
207#define prompt_last_line (S.prompt_last_line) 204#define prompt_last_line (S.prompt_last_line)
208#define user_buf (S.user_buf ) 205#define user_buf (S.user_buf )
209#define home_pwd_buf (S.home_pwd_buf ) 206#define home_pwd_buf (S.home_pwd_buf )
210#define matches (S.matches ) 207#define got_user_strings (S.got_user_strings)
211#define num_matches (S.num_matches ) 208#define num_matches (S.num_matches )
209#define matches (S.matches )
212#define delptr (S.delptr ) 210#define delptr (S.delptr )
213#define newdelflag (S.newdelflag ) 211#define newdelflag (S.newdelflag )
214#define delbuf (S.delbuf ) 212#define delbuf (S.delbuf )
215 213
216#define INIT_S() do { \ 214#define INIT_S() do { \
217 (*(struct lineedit_statics**)not_const_pp(&lineedit_ptr_to_statics)) = xzalloc(sizeof(S)); \ 215 XZALLOC_CONST_PTR(&lineedit_ptr_to_statics, sizeof(S)); \
218 barrier(); \
219} while (0) 216} while (0)
220 217
221static void deinit_S(void) 218static void deinit_S(void)
@@ -227,14 +224,47 @@ static void deinit_S(void)
227#endif 224#endif
228#if ENABLE_USERNAME_OR_HOMEDIR 225#if ENABLE_USERNAME_OR_HOMEDIR
229 free(user_buf); 226 free(user_buf);
230 if (home_pwd_buf != null_str) 227 free(home_pwd_buf);
231 free(home_pwd_buf);
232#endif 228#endif
233 free(lineedit_ptr_to_statics); 229 free(lineedit_ptr_to_statics);
234} 230}
235#define DEINIT_S() deinit_S() 231#define DEINIT_S() deinit_S()
236 232
237 233
234#if ENABLE_USERNAME_OR_HOMEDIR
235/* Call getpwuid() only if necessary.
236 * E.g. if PS1=':', no user database reading is needed to generate prompt.
237 * (Unfortunately, default PS1='\w \$' needs it, \w abbreviates homedir
238 * as ~/... - for that it needs to *know* the homedir...)
239 */
240static void get_user_strings(void)
241{
242 struct passwd *entry;
243
244 got_user_strings = 1;
245 entry = getpwuid(geteuid());
246 if (entry) {
247 user_buf = xstrdup(entry->pw_name);
248 home_pwd_buf = xstrdup(entry->pw_dir);
249 }
250}
251
252static const char *get_username_str(void)
253{
254 if (!got_user_strings)
255 get_user_strings();
256 return user_buf ? user_buf : "";
257 /* btw, bash uses "I have no name!" string if uid has no entry */
258}
259
260static NOINLINE const char *get_homedir_or_NULL(void)
261{
262 if (!got_user_strings)
263 get_user_strings();
264 return home_pwd_buf;
265}
266#endif
267
238#if ENABLE_UNICODE_SUPPORT 268#if ENABLE_UNICODE_SUPPORT
239static size_t load_string(const char *src) 269static size_t load_string(const char *src)
240{ 270{
@@ -748,11 +778,11 @@ static char *username_path_completion(char *ud)
748 struct passwd *entry; 778 struct passwd *entry;
749#endif 779#endif
750 char *tilde_name = ud; 780 char *tilde_name = ud;
751 char *home = NULL; 781 const char *home = NULL;
752 782
753 ud++; /* skip ~ */ 783 ud++; /* skip ~ */
754 if (*ud == '/') { /* "~/..." */ 784 if (*ud == '/') { /* "~/..." */
755 home = home_pwd_buf; 785 home = get_homedir_or_NULL();
756# if !ENABLE_PLATFORM_MINGW32 786# if !ENABLE_PLATFORM_MINGW32
757 } else { 787 } else {
758 /* "~user/..." */ 788 /* "~user/..." */
@@ -1881,7 +1911,7 @@ vi_back_motion(void)
1881 input_backward(1); 1911 input_backward(1);
1882 } 1912 }
1883} 1913}
1884#endif 1914#endif /* ENABLE_FEATURE_EDITING_VI */
1885 1915
1886/* Modelled after bash 4.0 behavior of Ctrl-<arrow> */ 1916/* Modelled after bash 4.0 behavior of Ctrl-<arrow> */
1887static void ctrl_left(void) 1917static void ctrl_left(void)
@@ -1982,7 +2012,7 @@ static void ask_terminal(void)
1982 } 2012 }
1983} 2013}
1984#else 2014#else
1985#define ask_terminal() ((void)0) 2015# define ask_terminal() ((void)0)
1986#endif 2016#endif
1987 2017
1988/* Note about multi-line PS1 (e.g. "\n\w \u@\h\n> ") and prompt redrawing: 2018/* Note about multi-line PS1 (e.g. "\n\w \u@\h\n> ") and prompt redrawing:
@@ -2091,7 +2121,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2091 2121
2092 switch (c) { 2122 switch (c) {
2093 case 'u': 2123 case 'u':
2094 pbuf = user_buf ? user_buf : (char*)""; 2124 pbuf = (char*)get_username_str();
2095 break; 2125 break;
2096 case 'H': 2126 case 'H':
2097 case 'h': 2127 case 'h':
@@ -2113,14 +2143,15 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2113 case 'w': /* current dir */ 2143 case 'w': /* current dir */
2114 case 'W': /* basename of cur dir */ 2144 case 'W': /* basename of cur dir */
2115 if (!cwd_buf) { 2145 if (!cwd_buf) {
2146 const char *home;
2116 cwd_buf = xrealloc_getcwd_or_warn(NULL); 2147 cwd_buf = xrealloc_getcwd_or_warn(NULL);
2117 if (!cwd_buf) 2148 if (!cwd_buf)
2118 cwd_buf = (char *)bb_msg_unknown; 2149 cwd_buf = (char *)bb_msg_unknown;
2119 else if (home_pwd_buf[0]) { 2150 else if ((home = get_homedir_or_NULL()) != NULL && home[0]) {
2120 char *after_home_user; 2151 char *after_home_user;
2121 2152
2122 /* /home/user[/something] -> ~[/something] */ 2153 /* /home/user[/something] -> ~[/something] */
2123 after_home_user = is_prefixed_with(cwd_buf, home_pwd_buf); 2154 after_home_user = is_prefixed_with(cwd_buf, home);
2124 if (after_home_user 2155 if (after_home_user
2125 && (*after_home_user == '/' || *after_home_user == '\0') 2156 && (*after_home_user == '/' || *after_home_user == '\0')
2126 ) { 2157 ) {
@@ -2176,7 +2207,7 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2176 if (c == '\n') 2207 if (c == '\n')
2177 cmdedit_prmt_len = 0; 2208 cmdedit_prmt_len = 0;
2178 else if (flg_not_length != ']') { 2209 else if (flg_not_length != ']') {
2179#if ENABLE_UNICODE_SUPPORT 2210# if ENABLE_UNICODE_SUPPORT
2180 if (n == 1) { 2211 if (n == 1) {
2181 /* Only count single-byte characters and the first of multi-byte characters */ 2212 /* Only count single-byte characters and the first of multi-byte characters */
2182 if ((unsigned char)*pbuf < 0x80 /* single byte character */ 2213 if ((unsigned char)*pbuf < 0x80 /* single byte character */
@@ -2187,9 +2218,9 @@ static void parse_and_put_prompt(const char *prmt_ptr)
2187 } else { 2218 } else {
2188 cmdedit_prmt_len += unicode_strwidth(pbuf); 2219 cmdedit_prmt_len += unicode_strwidth(pbuf);
2189 } 2220 }
2190#else 2221# else
2191 cmdedit_prmt_len += n; 2222 cmdedit_prmt_len += n;
2192#endif 2223# endif
2193 } 2224 }
2194 } 2225 }
2195 prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf); 2226 prmt_mem_ptr = strcat(xrealloc(prmt_mem_ptr, prmt_size+1), pbuf);
@@ -2416,7 +2447,7 @@ static int32_t reverse_i_search(int timeout)
2416 } 2447 }
2417 2448
2418 /* Append this char */ 2449 /* Append this char */
2419#if ENABLE_UNICODE_SUPPORT 2450# if ENABLE_UNICODE_SUPPORT
2420 if (unicode_status == UNICODE_ON) { 2451 if (unicode_status == UNICODE_ON) {
2421 mbstate_t mbstate = { 0 }; 2452 mbstate_t mbstate = { 0 };
2422 char buf[MB_CUR_MAX + 1]; 2453 char buf[MB_CUR_MAX + 1];
@@ -2427,7 +2458,7 @@ static int32_t reverse_i_search(int timeout)
2427 strcpy(match_buf + match_buf_len, buf); 2458 strcpy(match_buf + match_buf_len, buf);
2428 } 2459 }
2429 } else 2460 } else
2430#endif 2461# endif
2431 if (match_buf_len < sizeof(match_buf) - 1) { 2462 if (match_buf_len < sizeof(match_buf) - 1) {
2432 match_buf[match_buf_len] = ic; 2463 match_buf[match_buf_len] = ic;
2433 match_buf[match_buf_len + 1] = '\0'; 2464 match_buf[match_buf_len + 1] = '\0';
@@ -2479,7 +2510,7 @@ static int32_t reverse_i_search(int timeout)
2479 2510
2480 return ic; 2511 return ic;
2481} 2512}
2482#endif 2513#endif /* ENABLE_FEATURE_REVERSE_SEARCH */
2483 2514
2484#if ENABLE_FEATURE_EDITING_WINCH 2515#if ENABLE_FEATURE_EDITING_WINCH
2485static void sigaction2(int sig, struct sigaction *act) 2516static void sigaction2(int sig, struct sigaction *act)
@@ -2521,7 +2552,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2521 //command_len = 0; - done by INIT_S() 2552 //command_len = 0; - done by INIT_S()
2522 //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */ 2553 //cmdedit_y = 0; /* quasireal y, not true if line > xt*yt */
2523 cmdedit_termw = 80; 2554 cmdedit_termw = 80;
2524 IF_USERNAME_OR_HOMEDIR(home_pwd_buf = (char*)null_str;)
2525 IF_FEATURE_EDITING_VI(delptr = delbuf;) 2555 IF_FEATURE_EDITING_VI(delptr = delbuf;)
2526 2556
2527#if !ENABLE_PLATFORM_MINGW32 2557#if !ENABLE_PLATFORM_MINGW32
@@ -2589,18 +2619,6 @@ int FAST_FUNC read_line_input(line_input_t *st, const char *prompt, char *comman
2589 tcsetattr_stdin_TCSANOW(&new_settings); 2619 tcsetattr_stdin_TCSANOW(&new_settings);
2590#endif 2620#endif
2591 2621
2592#if ENABLE_USERNAME_OR_HOMEDIR
2593 {
2594 struct passwd *entry;
2595
2596 entry = getpwuid(geteuid());
2597 if (entry) {
2598 user_buf = xstrdup(entry->pw_name);
2599 home_pwd_buf = xstrdup(entry->pw_dir);
2600 }
2601 }
2602#endif
2603
2604#if 0 2622#if 0
2605 for (i = 0; i <= state->max_history; i++) 2623 for (i = 0; i <= state->max_history; i++)
2606 bb_error_msg("history[%d]:'%s'", i, state->history[i]); 2624 bb_error_msg("history[%d]:'%s'", i, state->history[i]);
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 885c19f1a..151739ae2 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -28,6 +28,22 @@
28# ifndef PR_GET_NAME 28# ifndef PR_GET_NAME
29# define PR_GET_NAME 16 29# define PR_GET_NAME 16
30# endif 30# endif
31# if ENABLE_FEATURE_SH_STANDALONE || ENABLE_FEATURE_PREFER_APPLETS || !BB_MMU
32int FAST_FUNC re_execed_comm(void)
33{
34 const char *e, *expected_comm;
35 char comm[16];
36
37 BUILD_BUG_ON(CONFIG_BUSYBOX_EXEC_PATH[0] != '/');
38 e = CONFIG_BUSYBOX_EXEC_PATH;
39 /* Hopefully (strrchr(e) - e) evaluates to constant at compile time: */
40 expected_comm = bb_busybox_exec_path + (strrchr(e, '/') - e) + 1;
41
42 prctl(PR_GET_NAME, (long)comm, 0, 0, 0);
43 //bb_error_msg("comm:'%.*s' expected:'%s'", 16, comm, expected_comm);
44 return strcmp(comm, expected_comm) == 0;
45}
46# endif
31void FAST_FUNC set_task_comm(const char *comm) 47void FAST_FUNC set_task_comm(const char *comm)
32{ 48{
33 /* okay if too long (truncates) */ 49 /* okay if too long (truncates) */
diff --git a/libbb/xreadlink.c b/libbb/xreadlink.c
index 31680810b..024ee9047 100644
--- a/libbb/xreadlink.c
+++ b/libbb/xreadlink.c
@@ -130,7 +130,7 @@ char* FAST_FUNC xmalloc_realpath(const char *path)
130#endif 130#endif
131} 131}
132 132
133char* FAST_FUNC xmalloc_realpath_coreutils(const char *path) 133char* FAST_FUNC xmalloc_realpath_coreutils(char *path)
134{ 134{
135 char *buf; 135 char *buf;
136 136
@@ -144,32 +144,19 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path)
144 * (the directory must exist). 144 * (the directory must exist).
145 */ 145 */
146 if (!buf && errno == ENOENT) { 146 if (!buf && errno == ENOENT) {
147 char *last_slash = strrchr(path, '/'); 147 char *target, c, *last_slash;
148 if (last_slash) { 148 size_t i;
149 *last_slash++ = '\0'; 149
150 buf = xmalloc_realpath(path); 150 target = xmalloc_readlink(path);
151 if (buf) { 151 if (target) {
152 unsigned len = strlen(buf); 152 /*
153 buf = xrealloc(buf, len + strlen(last_slash) + 2); 153 * $ ln -s /bin/qwe symlink # note: /bin is a link to /usr/bin
154 buf[len++] = '/'; 154 * $ readlink -f symlink
155 strcpy(buf + len, last_slash); 155 * /usr/bin/qwe
156 } 156 * $ realpath symlink
157 } else { 157 * /usr/bin/qwe
158 char *target = xmalloc_readlink(path); 158 */
159 if (target) { 159 if (target[0] != '/') {
160 char *cwd;
161 if (target[0] == '/') {
162 /*
163 * $ ln -s /bin/qwe symlink # note: /bin is a link to /usr/bin
164 * $ readlink -f symlink
165 * /usr/bin/qwe/target_does_not_exist
166 * $ realpath symlink
167 * /usr/bin/qwe/target_does_not_exist
168 */
169 buf = xmalloc_realpath_coreutils(target);
170 free(target);
171 return buf;
172 }
173 /* 160 /*
174 * $ ln -s target_does_not_exist symlink 161 * $ ln -s target_does_not_exist symlink
175 * $ readlink -f symlink 162 * $ readlink -f symlink
@@ -177,13 +164,41 @@ char* FAST_FUNC xmalloc_realpath_coreutils(const char *path)
177 * $ realpath symlink 164 * $ realpath symlink
178 * /CURDIR/target_does_not_exist 165 * /CURDIR/target_does_not_exist
179 */ 166 */
180 cwd = xrealloc_getcwd_or_warn(NULL); 167 char *cwd = xrealloc_getcwd_or_warn(NULL);
181 buf = concat_path_file(cwd, target); 168 char *tmp = concat_path_file(cwd, target);
182 free(cwd); 169 free(cwd);
183 free(target); 170 free(target);
184 return buf; 171 target = tmp;
172 }
173 buf = xmalloc_realpath_coreutils(target);
174 free(target);
175 return buf;
176 }
177
178 /* ignore leading and trailing slashes */
179 while (path[0] == '/' && path[1] == '/')
180 ++path;
181 i = strlen(path) - 1;
182 while (i > 0 && path[i] == '/')
183 i--;
184 c = path[i + 1];
185 path[i + 1] = '\0';
186
187 last_slash = strrchr(path, '/');
188 if (last_slash == path)
189 buf = xstrdup(path);
190 else if (last_slash) {
191 *last_slash = '\0';
192 buf = xmalloc_realpath(path);
193 *last_slash++ = '/';
194 if (buf) {
195 unsigned len = strlen(buf);
196 buf = xrealloc(buf, len + strlen(last_slash) + 2);
197 buf[len++] = '/';
198 strcpy(buf + len, last_slash);
185 } 199 }
186 } 200 }
201 path[i + 1] = c;
187 } 202 }
188 203
189 return buf; 204 return buf;