aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Config.in2
-rw-r--r--applets/.gitignore1
-rw-r--r--applets/Kbuild.src3
-rw-r--r--archival/libarchive/data_extract_to_command.c8
-rw-r--r--archival/libarchive/get_header_tar.c38
-rw-r--r--archival/tar.c14
-rw-r--r--console-tools/Config.src26
-rw-r--r--console-tools/openvt.c4
-rw-r--r--console-tools/showkey.c37
-rw-r--r--coreutils/Config.src2
-rw-r--r--coreutils/chroot.c8
-rw-r--r--coreutils/cksum.c1
-rw-r--r--coreutils/date.c3
-rw-r--r--coreutils/dd.c6
-rw-r--r--coreutils/ln.c6
-rw-r--r--coreutils/ls.c73
-rw-r--r--coreutils/printenv.c11
-rw-r--r--coreutils/split.c4
-rw-r--r--coreutils/test.c2
-rw-r--r--coreutils/tr.c6
-rw-r--r--docs/.gitignore1
-rw-r--r--e2fsprogs/Config.src2
-rw-r--r--findutils/xargs.c19
-rw-r--r--include/.gitignore4
-rw-r--r--include/archive.h51
-rw-r--r--include/libbb.h15
-rw-r--r--include/unicode.h4
-rw-r--r--include/usage.src.h58
-rw-r--r--init/init.c1
-rw-r--r--init/mesg.c60
-rw-r--r--libbb/Config.src2
-rw-r--r--libbb/appletlib.c20
-rw-r--r--libbb/bb_pwd.c4
-rw-r--r--libbb/get_shell_name.c27
-rw-r--r--libbb/getopt32.c15
-rw-r--r--libbb/inet_common.c16
-rw-r--r--libbb/procps.c14
-rw-r--r--libbb/progress.c10
-rw-r--r--libbb/setup_environment.c3
-rw-r--r--libbb/unicode.c28
-rw-r--r--libbb/xconnect.c5
-rw-r--r--loginutils/adduser.c30
-rw-r--r--loginutils/getty.c4
-rw-r--r--loginutils/login.c18
-rw-r--r--loginutils/passwd.c2
-rw-r--r--loginutils/su.c10
-rw-r--r--loginutils/sulogin.c4
-rw-r--r--loginutils/vlock.c13
-rw-r--r--miscutils/Config.src27
-rw-r--r--miscutils/conspy.c6
-rw-r--r--miscutils/crontab.c7
-rw-r--r--miscutils/nandwrite.c4
-rw-r--r--miscutils/ubi_attach_detach.c10
-rw-r--r--modutils/Config.src20
-rw-r--r--networking/Config.src64
-rw-r--r--networking/ftpd.c19
-rw-r--r--networking/ifupdown.c16
-rw-r--r--networking/nameif.c115
-rw-r--r--networking/nslookup.c4
-rw-r--r--networking/ping.c2
-rw-r--r--networking/route.c6
-rw-r--r--networking/udhcp/Config.src4
-rw-r--r--networking/udhcp/dhcpc.c142
-rw-r--r--networking/udhcp/dhcpc.h3
-rw-r--r--networking/wget.c36
-rw-r--r--networking/whois.c66
-rw-r--r--procps/Config.src7
-rw-r--r--procps/kill.c1
-rw-r--r--procps/pwdx.c60
-rw-r--r--runit/svlogd.c7
-rw-r--r--scripts/Makefile.IMA21
-rw-r--r--scripts/defconfig.tig17
-rw-r--r--shell/ash.c104
-rw-r--r--shell/hush.c147
-rw-r--r--shell/hush_test/hush-misc/return1.right1
-rwxr-xr-xshell/hush_test/hush-misc/return1.tests4
-rw-r--r--shell/hush_test/hush-misc/source1.right5
-rwxr-xr-xshell/hush_test/hush-misc/source1.tests10
-rw-r--r--sysklogd/Config.src3
-rw-r--r--sysklogd/klogd.c31
-rwxr-xr-xtestsuite/ls.tests10
-rwxr-xr-xtestsuite/mount.tests39
-rwxr-xr-xtestsuite/tar.tests17
-rw-r--r--util-linux/Config.src54
-rw-r--r--util-linux/more.c9
-rw-r--r--util-linux/mount.c80
-rw-r--r--util-linux/script.c5
87 files changed, 1253 insertions, 625 deletions
diff --git a/Config.in b/Config.in
index 0ab94d497..89e506a6a 100644
--- a/Config.in
+++ b/Config.in
@@ -408,7 +408,7 @@ config FEATURE_SUID_CONFIG_QUIET
408config SELINUX 408config SELINUX
409 bool "Support NSA Security Enhanced Linux" 409 bool "Support NSA Security Enhanced Linux"
410 default n 410 default n
411 depends on PLATFORM_LINUX 411 select PLATFORM_LINUX
412 help 412 help
413 Enable support for SELinux in applets ls, ps, and id. Also provide 413 Enable support for SELinux in applets ls, ps, and id. Also provide
414 the option of compiling in SELinux applets. 414 the option of compiling in SELinux applets.
diff --git a/applets/.gitignore b/applets/.gitignore
index cc932fcc0..459938d67 100644
--- a/applets/.gitignore
+++ b/applets/.gitignore
@@ -1,2 +1,3 @@
1/applet_tables 1/applet_tables
2/usage 2/usage
3/usage_pod
diff --git a/applets/Kbuild.src b/applets/Kbuild.src
index 9b9808f25..b61239948 100644
--- a/applets/Kbuild.src
+++ b/applets/Kbuild.src
@@ -42,3 +42,6 @@ quiet_cmd_gen_applet_tables = GEN include/applet_tables.h
42 42
43include/applet_tables.h: applets/applet_tables 43include/applet_tables.h: applets/applet_tables
44 $(call cmd,gen_applet_tables) 44 $(call cmd,gen_applet_tables)
45
46include/NUM_APPLETS.h: applets/applet_tables
47 $(call cmd,gen_applet_tables)
diff --git a/archival/libarchive/data_extract_to_command.c b/archival/libarchive/data_extract_to_command.c
index 2bbab7641..0e977049d 100644
--- a/archival/libarchive/data_extract_to_command.c
+++ b/archival/libarchive/data_extract_to_command.c
@@ -99,8 +99,12 @@ void FAST_FUNC data_extract_to_command(archive_handle_t *archive_handle)
99 close(p[1]); 99 close(p[1]);
100 xdup2(p[0], STDIN_FILENO); 100 xdup2(p[0], STDIN_FILENO);
101 signal(SIGPIPE, SIG_DFL); 101 signal(SIGPIPE, SIG_DFL);
102 execl(DEFAULT_SHELL, DEFAULT_SHELL_SHORT_NAME, "-c", archive_handle->tar__to_command, NULL); 102 execl(archive_handle->tar__to_command_shell,
103 bb_perror_msg_and_die("can't execute '%s'", DEFAULT_SHELL); 103 archive_handle->tar__to_command_shell,
104 "-c",
105 archive_handle->tar__to_command,
106 NULL);
107 bb_perror_msg_and_die("can't execute '%s'", archive_handle->tar__to_command_shell);
104 } 108 }
105 close(p[0]); 109 close(p[0]);
106 /* Our caller is expected to do signal(SIGPIPE, SIG_IGN) 110 /* Our caller is expected to do signal(SIGPIPE, SIG_IGN)
diff --git a/archival/libarchive/get_header_tar.c b/archival/libarchive/get_header_tar.c
index 2e0332792..f73cd338e 100644
--- a/archival/libarchive/get_header_tar.c
+++ b/archival/libarchive/get_header_tar.c
@@ -18,6 +18,35 @@ typedef uint32_t aliased_uint32_t FIX_ALIASING;
18typedef off_t aliased_off_t FIX_ALIASING; 18typedef off_t aliased_off_t FIX_ALIASING;
19 19
20 20
21const char* FAST_FUNC strip_unsafe_prefix(const char *str)
22{
23 const char *cp = str;
24 while (1) {
25 char *cp2;
26 if (*cp == '/') {
27 cp++;
28 continue;
29 }
30 if (strncmp(cp, "/../"+1, 3) == 0) {
31 cp += 3;
32 continue;
33 }
34 cp2 = strstr(cp, "/../");
35 if (!cp2)
36 break;
37 cp = cp2 + 4;
38 }
39 if (cp != str) {
40 static smallint warned = 0;
41 if (!warned) {
42 warned = 1;
43 bb_error_msg("removing leading '%.*s' from member names",
44 (int)(cp - str), str);
45 }
46 }
47 return cp;
48}
49
21/* NB: _DESTROYS_ str[len] character! */ 50/* NB: _DESTROYS_ str[len] character! */
22static unsigned long long getOctal(char *str, int len) 51static unsigned long long getOctal(char *str, int len)
23{ 52{
@@ -422,12 +451,9 @@ char FAST_FUNC get_header_tar(archive_handle_t *archive_handle)
422 p_linkname = NULL; 451 p_linkname = NULL;
423 } 452 }
424#endif 453#endif
425 if (strncmp(file_header->name, "/../"+1, 3) == 0 454
426 || strstr(file_header->name, "/../") 455 /* Everything up to and including last ".." component is stripped */
427 ) { 456 overlapping_strcpy(file_header->name, strip_unsafe_prefix(file_header->name));
428 bb_error_msg_and_die("name with '..' encountered: '%s'",
429 file_header->name);
430 }
431 457
432 /* Strip trailing '/' in directories */ 458 /* Strip trailing '/' in directories */
433 /* Must be done after mode is set as '/' is used to check if it's a directory */ 459 /* Must be done after mode is set as '/' is used to check if it's a directory */
diff --git a/archival/tar.c b/archival/tar.c
index 74d6fca91..52f3c364c 100644
--- a/archival/tar.c
+++ b/archival/tar.c
@@ -397,17 +397,8 @@ static int FAST_FUNC writeFileToTarball(const char *fileName, struct stat *statb
397 397
398 DBG("writeFileToTarball('%s')", fileName); 398 DBG("writeFileToTarball('%s')", fileName);
399 399
400 /* Strip leading '/' (must be before memorizing hardlink's name) */ 400 /* Strip leading '/' and such (must be before memorizing hardlink's name) */
401 header_name = fileName; 401 header_name = strip_unsafe_prefix(fileName);
402 while (header_name[0] == '/') {
403 static smallint warned;
404
405 if (!warned) {
406 bb_error_msg("removing leading '/' from member names");
407 warned = 1;
408 }
409 header_name++;
410 }
411 402
412 if (header_name[0] == '\0') 403 if (header_name[0] == '\0')
413 return TRUE; 404 return TRUE;
@@ -981,6 +972,7 @@ int tar_main(int argc UNUSED_PARAM, char **argv)
981 putenv((char*)"TAR_FILETYPE=f"); 972 putenv((char*)"TAR_FILETYPE=f");
982 signal(SIGPIPE, SIG_IGN); 973 signal(SIGPIPE, SIG_IGN);
983 tar_handle->action_data = data_extract_to_command; 974 tar_handle->action_data = data_extract_to_command;
975 IF_FEATURE_TAR_TO_COMMAND(tar_handle->tar__to_command_shell = xstrdup(get_shell_name());)
984 } 976 }
985 977
986 if (opt & OPT_KEEP_OLD) 978 if (opt & OPT_KEEP_OLD)
diff --git a/console-tools/Config.src b/console-tools/Config.src
index cdb26800e..c65704478 100644
--- a/console-tools/Config.src
+++ b/console-tools/Config.src
@@ -10,7 +10,7 @@ INSERT
10config CHVT 10config CHVT
11 bool "chvt" 11 bool "chvt"
12 default y 12 default y
13 depends on PLATFORM_LINUX 13 select PLATFORM_LINUX
14 help 14 help
15 This program is used to change to another terminal. 15 This program is used to change to another terminal.
16 Example: chvt 4 (change to terminal /dev/tty4) 16 Example: chvt 4 (change to terminal /dev/tty4)
@@ -18,7 +18,7 @@ config CHVT
18config FGCONSOLE 18config FGCONSOLE
19 bool "fgconsole" 19 bool "fgconsole"
20 default y 20 default y
21 depends on PLATFORM_LINUX 21 select PLATFORM_LINUX
22 help 22 help
23 This program prints active (foreground) console number. 23 This program prints active (foreground) console number.
24 24
@@ -31,14 +31,14 @@ config CLEAR
31config DEALLOCVT 31config DEALLOCVT
32 bool "deallocvt" 32 bool "deallocvt"
33 default y 33 default y
34 depends on PLATFORM_LINUX 34 select PLATFORM_LINUX
35 help 35 help
36 This program deallocates unused virtual consoles. 36 This program deallocates unused virtual consoles.
37 37
38config DUMPKMAP 38config DUMPKMAP
39 bool "dumpkmap" 39 bool "dumpkmap"
40 default y 40 default y
41 depends on PLATFORM_LINUX 41 select PLATFORM_LINUX
42 help 42 help
43 This program dumps the kernel's keyboard translation table to 43 This program dumps the kernel's keyboard translation table to
44 stdout, in binary format. You can then use loadkmap to load it. 44 stdout, in binary format. You can then use loadkmap to load it.
@@ -46,21 +46,21 @@ config DUMPKMAP
46config KBD_MODE 46config KBD_MODE
47 bool "kbd_mode" 47 bool "kbd_mode"
48 default y 48 default y
49 depends on PLATFORM_LINUX 49 select PLATFORM_LINUX
50 help 50 help
51 This program reports and sets keyboard mode. 51 This program reports and sets keyboard mode.
52 52
53config LOADFONT 53config LOADFONT
54 bool "loadfont" 54 bool "loadfont"
55 default y 55 default y
56 depends on PLATFORM_LINUX 56 select PLATFORM_LINUX
57 help 57 help
58 This program loads a console font from standard input. 58 This program loads a console font from standard input.
59 59
60config LOADKMAP 60config LOADKMAP
61 bool "loadkmap" 61 bool "loadkmap"
62 default y 62 default y
63 depends on PLATFORM_LINUX 63 select PLATFORM_LINUX
64 help 64 help
65 This program loads a keyboard translation table from 65 This program loads a keyboard translation table from
66 standard input. 66 standard input.
@@ -68,7 +68,7 @@ config LOADKMAP
68config OPENVT 68config OPENVT
69 bool "openvt" 69 bool "openvt"
70 default y 70 default y
71 depends on PLATFORM_LINUX 71 select PLATFORM_LINUX
72 help 72 help
73 This program is used to start a command on an unused 73 This program is used to start a command on an unused
74 virtual terminal. 74 virtual terminal.
@@ -100,7 +100,7 @@ config FEATURE_RESIZE_PRINT
100config SETCONSOLE 100config SETCONSOLE
101 bool "setconsole" 101 bool "setconsole"
102 default y 102 default y
103 depends on PLATFORM_LINUX 103 select PLATFORM_LINUX
104 help 104 help
105 This program redirects the system console to another device, 105 This program redirects the system console to another device,
106 like the current tty while logged in via telnet. 106 like the current tty while logged in via telnet.
@@ -115,7 +115,7 @@ config FEATURE_SETCONSOLE_LONG_OPTIONS
115config SETFONT 115config SETFONT
116 bool "setfont" 116 bool "setfont"
117 default y 117 default y
118 depends on PLATFORM_LINUX 118 select PLATFORM_LINUX
119 help 119 help
120 Allows to load console screen map. Useful for i18n. 120 Allows to load console screen map. Useful for i18n.
121 121
@@ -137,7 +137,7 @@ config DEFAULT_SETFONT_DIR
137config SETKEYCODES 137config SETKEYCODES
138 bool "setkeycodes" 138 bool "setkeycodes"
139 default y 139 default y
140 depends on PLATFORM_LINUX 140 select PLATFORM_LINUX
141 help 141 help
142 This program loads entries into the kernel's scancode-to-keycode 142 This program loads entries into the kernel's scancode-to-keycode
143 map, allowing unusual keyboards to generate usable keycodes. 143 map, allowing unusual keyboards to generate usable keycodes.
@@ -145,14 +145,14 @@ config SETKEYCODES
145config SETLOGCONS 145config SETLOGCONS
146 bool "setlogcons" 146 bool "setlogcons"
147 default y 147 default y
148 depends on PLATFORM_LINUX 148 select PLATFORM_LINUX
149 help 149 help
150 This program redirects the output console of kernel messages. 150 This program redirects the output console of kernel messages.
151 151
152config SHOWKEY 152config SHOWKEY
153 bool "showkey" 153 bool "showkey"
154 default y 154 default y
155 depends on PLATFORM_LINUX 155 select PLATFORM_LINUX
156 help 156 help
157 Shows keys pressed. 157 Shows keys pressed.
158 158
diff --git a/console-tools/openvt.c b/console-tools/openvt.c
index 6e0b589a0..56f50c6cd 100644
--- a/console-tools/openvt.c
+++ b/console-tools/openvt.c
@@ -144,9 +144,7 @@ int openvt_main(int argc UNUSED_PARAM, char **argv)
144 144
145 if (!argv[0]) { 145 if (!argv[0]) {
146 argv--; 146 argv--;
147 argv[0] = getenv("SHELL"); 147 argv[0] = (char *) get_shell_name();
148 if (!argv[0])
149 argv[0] = (char *) DEFAULT_SHELL;
150 /*argv[1] = NULL; - already is */ 148 /*argv[1] = NULL; - already is */
151 } 149 }
152 150
diff --git a/console-tools/showkey.c b/console-tools/showkey.c
index e7834f702..06df68bfd 100644
--- a/console-tools/showkey.c
+++ b/console-tools/showkey.c
@@ -56,37 +56,45 @@ int showkey_main(int argc UNUSED_PARAM, char **argv)
56 // FIXME: aks are all mutually exclusive 56 // FIXME: aks are all mutually exclusive
57 getopt32(argv, "aks"); 57 getopt32(argv, "aks");
58 58
59 // get keyboard settings
60 xioctl(STDIN_FILENO, KDGKBMODE, &kbmode);
61 printf("kb mode was %s\n\nPress any keys. Program terminates %s\n\n",
62 kbmode == K_RAW ? "RAW" :
63 (kbmode == K_XLATE ? "XLATE" :
64 (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" :
65 (kbmode == K_UNICODE ? "UNICODE" : "UNKNOWN")))
66 , (option_mask32 & OPT_a) ? "on EOF (ctrl-D)" : "10s after last keypress"
67 );
68
69 // prepare for raw mode 59 // prepare for raw mode
70 xget1(&tio, &tio0); 60 xget1(&tio, &tio0);
71 // put stdin in raw mode 61 // put stdin in raw mode
72 xset1(&tio); 62 xset1(&tio);
73 63
64#define press_keys "Press any keys, program terminates %s:\r\n\n"
65
74 if (option_mask32 & OPT_a) { 66 if (option_mask32 & OPT_a) {
67 // just read stdin char by char
75 unsigned char c; 68 unsigned char c;
76 69
77 // just read stdin char by char 70 printf(press_keys, "on EOF (ctrl-D)");
71
72 // read and show byte values
78 while (1 == read(STDIN_FILENO, &c, 1)) { 73 while (1 == read(STDIN_FILENO, &c, 1)) {
79 printf("%3u 0%03o 0x%02x\r\n", c, c, c); 74 printf("%3u 0%03o 0x%02x\r\n", c, c, c);
80 if (04 /*CTRL-D*/ == c) 75 if (04 /*CTRL-D*/ == c)
81 break; 76 break;
82 } 77 }
78
83 } else { 79 } else {
80 // we assume a PC keyboard
81 xioctl(STDIN_FILENO, KDGKBMODE, &kbmode);
82 printf("Keyboard mode was %s.\r\n\n",
83 kbmode == K_RAW ? "RAW" :
84 (kbmode == K_XLATE ? "XLATE" :
85 (kbmode == K_MEDIUMRAW ? "MEDIUMRAW" :
86 (kbmode == K_UNICODE ? "UNICODE" : "UNKNOWN")))
87 );
88
84 // set raw keyboard mode 89 // set raw keyboard mode
85 xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)((option_mask32 & OPT_k) ? K_MEDIUMRAW : K_RAW)); 90 xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)((option_mask32 & OPT_k) ? K_MEDIUMRAW : K_RAW));
86 91
87 // we should exit on any signal; signals should interrupt read 92 // we should exit on any signal; signals should interrupt read
88 bb_signals_recursive_norestart(BB_FATAL_SIGS, record_signo); 93 bb_signals_recursive_norestart(BB_FATAL_SIGS, record_signo);
89 94
95 // inform user that program ends after time of inactivity
96 printf(press_keys, "10s after last keypress");
97
90 // read and show scancodes 98 // read and show scancodes
91 while (!bb_got_signal) { 99 while (!bb_got_signal) {
92 char buf[18]; 100 char buf[18];
@@ -94,6 +102,7 @@ int showkey_main(int argc UNUSED_PARAM, char **argv)
94 102
95 // setup 10s watchdog 103 // setup 10s watchdog
96 alarm(10); 104 alarm(10);
105
97 // read scancodes 106 // read scancodes
98 n = read(STDIN_FILENO, buf, sizeof(buf)); 107 n = read(STDIN_FILENO, buf, sizeof(buf));
99 i = 0; 108 i = 0;
@@ -121,11 +130,13 @@ int showkey_main(int argc UNUSED_PARAM, char **argv)
121 } 130 }
122 puts("\r"); 131 puts("\r");
123 } 132 }
133
134 // restore keyboard mode
135 xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)kbmode);
124 } 136 }
125 137
126 // restore keyboard and console settings 138 // restore console settings
127 xset1(&tio0); 139 xset1(&tio0);
128 xioctl(STDIN_FILENO, KDSKBMODE, (void *)(ptrdiff_t)kbmode);
129 140
130 return EXIT_SUCCESS; 141 return EXIT_SUCCESS;
131} 142}
diff --git a/coreutils/Config.src b/coreutils/Config.src
index 6297f43a3..2769aa07d 100644
--- a/coreutils/Config.src
+++ b/coreutils/Config.src
@@ -594,7 +594,7 @@ config FEATURE_SPLIT_FANCY
594config STAT 594config STAT
595 bool "stat" 595 bool "stat"
596 default y 596 default y
597 depends on PLATFORM_LINUX # statfs() 597 select PLATFORM_LINUX # statfs()
598 help 598 help
599 display file or filesystem status. 599 display file or filesystem status.
600 600
diff --git a/coreutils/chroot.c b/coreutils/chroot.c
index b80a12ee0..5ac2e890e 100644
--- a/coreutils/chroot.c
+++ b/coreutils/chroot.c
@@ -23,11 +23,9 @@ int chroot_main(int argc UNUSED_PARAM, char **argv)
23 ++argv; 23 ++argv;
24 if (!*argv) { /* no 2nd param (PROG), use shell */ 24 if (!*argv) { /* no 2nd param (PROG), use shell */
25 argv -= 2; 25 argv -= 2;
26 argv[0] = getenv("SHELL"); 26 argv[0] = (char *) get_shell_name();
27 if (!argv[0]) { 27 argv[1] = (char *) "-i"; /* GNU coreutils 8.4 compat */
28 argv[0] = (char *) DEFAULT_SHELL; 28 /*argv[2] = NULL; - already is */
29 }
30 argv[1] = (char *) "-i";
31 } 29 }
32 30
33 BB_EXECVP_or_die(argv); 31 BB_EXECVP_or_die(argv);
diff --git a/coreutils/cksum.c b/coreutils/cksum.c
index 7a37e6add..53fb87a78 100644
--- a/coreutils/cksum.c
+++ b/coreutils/cksum.c
@@ -38,6 +38,7 @@ int cksum_main(int argc UNUSED_PARAM, char **argv)
38 38
39#define read_buf bb_common_bufsiz1 39#define read_buf bb_common_bufsiz1
40 while ((bytes_read = safe_read(fd, read_buf, sizeof(read_buf))) > 0) { 40 while ((bytes_read = safe_read(fd, read_buf, sizeof(read_buf))) > 0) {
41 length += bytes_read;
41 crc = crc32_block_endian1(crc, read_buf, bytes_read, crc32_table); 42 crc = crc32_block_endian1(crc, read_buf, bytes_read, crc32_table);
42 } 43 }
43 close(fd); 44 close(fd);
diff --git a/coreutils/date.c b/coreutils/date.c
index d36ed83fd..497031991 100644
--- a/coreutils/date.c
+++ b/coreutils/date.c
@@ -42,7 +42,8 @@
42//config:config FEATURE_DATE_NANO 42//config:config FEATURE_DATE_NANO
43//config: bool "Support %[num]N nanosecond format specifier" 43//config: bool "Support %[num]N nanosecond format specifier"
44//config: default n 44//config: default n
45//config: depends on DATE && PLATFORM_LINUX # syscall(__NR_clock_gettime) 45//config: depends on DATE # syscall(__NR_clock_gettime)
46//config: select PLATFORM_LINUX
46//config: help 47//config: help
47//config: Support %[num]N format specifier. Adds ~250 bytes of code. 48//config: Support %[num]N format specifier. Adds ~250 bytes of code.
48//config: 49//config:
diff --git a/coreutils/dd.c b/coreutils/dd.c
index da205ec69..544ece051 100644
--- a/coreutils/dd.c
+++ b/coreutils/dd.c
@@ -409,5 +409,11 @@ int dd_main(int argc UNUSED_PARAM, char **argv)
409 out_status: 409 out_status:
410 dd_output_status(0); 410 dd_output_status(0);
411 411
412 if (ENABLE_FEATURE_CLEAN_UP) {
413 free(obuf);
414 if (flags & FLAG_TWOBUFS)
415 free(ibuf);
416 }
417
412 return exitcode; 418 return exitcode;
413} 419}
diff --git a/coreutils/ln.c b/coreutils/ln.c
index ddad120d1..6da290c11 100644
--- a/coreutils/ln.c
+++ b/coreutils/ln.c
@@ -40,8 +40,12 @@ int ln_main(int argc, char **argv)
40 last = argv[argc - 1]; 40 last = argv[argc - 1];
41 argv += optind; 41 argv += optind;
42 42
43 if (argc == optind + 1) { 43 if (!argv[1]) {
44 /* "ln PATH/TO/FILE" -> "ln PATH/TO/FILE FILE" */
44 *--argv = last; 45 *--argv = last;
46 /* xstrdup is needed: "ln -s PATH/TO/FILE/" is equivalent to
47 * "ln -s PATH/TO/FILE/ FILE", not "ln -s PATH/TO/FILE FILE"
48 */
45 last = bb_get_last_path_component_strip(xstrdup(last)); 49 last = bb_get_last_path_component_strip(xstrdup(last));
46 } 50 }
47 51
diff --git a/coreutils/ls.c b/coreutils/ls.c
index 1afe28c8d..4a41db76a 100644
--- a/coreutils/ls.c
+++ b/coreutils/ls.c
@@ -1,6 +1,5 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* 2/*
3 * tiny-ls.c version 0.1.0: A minimalist 'ls'
4 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com> 3 * Copyright (C) 1996 Brian Candler <B.Candler@pobox.com>
5 * 4 *
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 5 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
@@ -159,7 +158,7 @@ STYLE_MASK = STYLE_SINGLE,
159 158
160/* which of the three times will be used */ 159/* which of the three times will be used */
161TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, 160TIME_CHANGE = (1 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
162TIME_ACCESS = (1 << 22) * ENABLE_FEATURE_LS_TIMESTAMPS, 161TIME_ACCESS = (2 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
163TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS, 162TIME_MASK = (3 << 21) * ENABLE_FEATURE_LS_TIMESTAMPS,
164 163
165/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */ 164/* how will the files be sorted (CONFIG_FEATURE_LS_SORTFILES) */
@@ -189,10 +188,11 @@ LIST_LONG = LIST_MODEBITS | LIST_NLINKS | LIST_ID_NAME | LIST_SIZE | \
189/* Not fully compatible - we show not only '/' but other chars too */ 188/* Not fully compatible - we show not only '/' but other chars too */
190/* -SXvhTw GNU options, busybox optionally supports */ 189/* -SXvhTw GNU options, busybox optionally supports */
191/* -T TABWIDTH is ignored (we don't use tabs on output) */ 190/* -T TABWIDTH is ignored (we don't use tabs on output) */
192/* -K SELinux mandated options, busybox optionally supports */ 191/* -KZ SELinux mandated options, busybox optionally supports */
192/* (coreutils 8.4 has no -K, remove it?) */
193/* -e I think we made this one up (looks similar to GNU --full-time) */ 193/* -e I think we made this one up (looks similar to GNU --full-time) */
194/* Std opts we do not support: */ 194/* We already used up all 32 bits, if we need to add more, candidates for removal: */
195/* -H Follow the links on command line only */ 195/* -K, -T, -e (add --full-time instead) */
196static const char ls_options[] ALIGN1 = 196static const char ls_options[] ALIGN1 =
197 "Cadil1gnsxQAk" /* 13 opts, total 13 */ 197 "Cadil1gnsxQAk" /* 13 opts, total 13 */
198 IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */ 198 IF_FEATURE_LS_TIMESTAMPS("cetu") /* 4, 17 */
@@ -203,7 +203,7 @@ static const char ls_options[] ALIGN1 =
203 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */ 203 IF_FEATURE_LS_FOLLOWLINKS("LH") /* 2, 28 */
204 IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */ 204 IF_FEATURE_HUMAN_READABLE("h") /* 1, 29 */
205 IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */ 205 IF_FEATURE_AUTOWIDTH("T:w:") /* 2, 31 */
206 ; 206 /* with --color, we use all 32 bits */;
207enum { 207enum {
208 //OPT_C = (1 << 0), 208 //OPT_C = (1 << 0),
209 //OPT_a = (1 << 1), 209 //OPT_a = (1 << 1),
@@ -234,8 +234,8 @@ enum {
234 OPTBIT_Z, /* 25 */ 234 OPTBIT_Z, /* 25 */
235 OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX, 235 OPTBIT_L = OPTBIT_K + 2 * ENABLE_SELINUX,
236 OPTBIT_H, /* 27 */ 236 OPTBIT_H, /* 27 */
237 OPTBIT_h = OPTBIT_L + 1 * ENABLE_FEATURE_LS_FOLLOWLINKS, 237 OPTBIT_h = OPTBIT_L + 2 * ENABLE_FEATURE_LS_FOLLOWLINKS,
238 OPTBIT_T = OPTBIT_h + 2 * ENABLE_FEATURE_HUMAN_READABLE, 238 OPTBIT_T = OPTBIT_h + 1 * ENABLE_FEATURE_HUMAN_READABLE,
239 OPTBIT_w, /* 30 */ 239 OPTBIT_w, /* 30 */
240 OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH, 240 OPTBIT_color = OPTBIT_T + 2 * ENABLE_FEATURE_AUTOWIDTH,
241 241
@@ -268,13 +268,13 @@ static const uint32_t opt_flags[] = {
268 LIST_INO, /* i */ 268 LIST_INO, /* i */
269 LIST_LONG | STYLE_LONG, /* l */ 269 LIST_LONG | STYLE_LONG, /* l */
270 STYLE_SINGLE, /* 1 */ 270 STYLE_SINGLE, /* 1 */
271 0, /* g (don't show owner) - handled via OPT_g */ 271 LIST_LONG | STYLE_LONG, /* g (don't show owner) - handled via OPT_g. assumes l */
272 LIST_ID_NUMERIC, /* n */ 272 LIST_ID_NUMERIC | LIST_LONG | STYLE_LONG, /* n (assumes l) */
273 LIST_BLOCKS, /* s */ 273 LIST_BLOCKS, /* s */
274 DISP_ROWS | STYLE_COLUMNAR, /* x */ 274 DISP_ROWS | STYLE_COLUMNAR, /* x */
275 0, /* Q (quote filename) - handled via OPT_Q */ 275 0, /* Q (quote filename) - handled via OPT_Q */
276 DISP_HIDDEN, /* A */ 276 DISP_HIDDEN, /* A */
277 ENABLE_SELINUX * LIST_CONTEXT, /* k (ignored if !SELINUX) */ 277 ENABLE_SELINUX * (LIST_CONTEXT|STYLE_SINGLE), /* k (ignored if !SELINUX) */
278#if ENABLE_FEATURE_LS_TIMESTAMPS 278#if ENABLE_FEATURE_LS_TIMESTAMPS
279 TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */ 279 TIME_CHANGE | (ENABLE_FEATURE_LS_SORTFILES * SORT_CTIME), /* c */
280 LIST_FULLTIME, /* e */ 280 LIST_FULLTIME, /* e */
@@ -295,8 +295,8 @@ static const uint32_t opt_flags[] = {
295 DISP_RECURSIVE, /* R */ 295 DISP_RECURSIVE, /* R */
296#endif 296#endif
297#if ENABLE_SELINUX 297#if ENABLE_SELINUX
298 LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME, /* K */ 298 LIST_MODEBITS|LIST_NLINKS|LIST_CONTEXT|LIST_SIZE|LIST_DATE_TIME|STYLE_SINGLE, /* K */
299 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT, /* Z */ 299 LIST_MODEBITS|LIST_ID_NAME|LIST_CONTEXT|STYLE_SINGLE, /* Z */
300#endif 300#endif
301 (1U << 31) 301 (1U << 31)
302 /* options after Z are not processed through opt_flags */ 302 /* options after Z are not processed through opt_flags */
@@ -682,19 +682,28 @@ static NOINLINE unsigned list_single(const struct dnode *dn)
682 682
683 if (all_fmt & LIST_INO) 683 if (all_fmt & LIST_INO)
684 column += printf("%7llu ", (long long) dn->dstat.st_ino); 684 column += printf("%7llu ", (long long) dn->dstat.st_ino);
685//TODO: -h should affect -s too:
685 if (all_fmt & LIST_BLOCKS) 686 if (all_fmt & LIST_BLOCKS)
686#if ENABLE_PLATFORM_MINGW32 687#if ENABLE_PLATFORM_MINGW32
687 /* MinGW does not have st_blocks */ 688 /* MinGW does not have st_blocks */
688 column += printf("%4"OFF_FMT"u ", (off_t)0); 689 column += printf("%6"OFF_FMT"u ", (off_t)0);
689#else 690#else
690 column += printf("%4"OFF_FMT"u ", (off_t) (dn->dstat.st_blocks >> 1)); 691 column += printf("%6"OFF_FMT"u ", (off_t) (dn->dstat.st_blocks >> 1));
691#endif 692#endif
692 if (all_fmt & LIST_MODEBITS) 693 if (all_fmt & LIST_MODEBITS)
693 column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode)); 694 column += printf("%-10s ", (char *) bb_mode_string(dn->dstat.st_mode));
694 if (all_fmt & LIST_NLINKS) 695 if (all_fmt & LIST_NLINKS)
695 column += printf("%4lu ", (long) dn->dstat.st_nlink); 696 column += printf("%4lu ", (long) dn->dstat.st_nlink);
697 if (all_fmt & LIST_ID_NUMERIC) {
698 if (option_mask32 & OPT_g)
699 column += printf("%-8u ", (int) dn->dstat.st_gid);
700 else
701 column += printf("%-8u %-8u ",
702 (int) dn->dstat.st_uid,
703 (int) dn->dstat.st_gid);
704 }
696#if ENABLE_FEATURE_LS_USERNAME 705#if ENABLE_FEATURE_LS_USERNAME
697 if (all_fmt & LIST_ID_NAME) { 706 else if (all_fmt & LIST_ID_NAME) {
698 if (option_mask32 & OPT_g) { 707 if (option_mask32 & OPT_g) {
699 column += printf("%-8.8s ", 708 column += printf("%-8.8s ",
700 get_cached_groupname(dn->dstat.st_gid)); 709 get_cached_groupname(dn->dstat.st_gid));
@@ -705,14 +714,6 @@ static NOINLINE unsigned list_single(const struct dnode *dn)
705 } 714 }
706 } 715 }
707#endif 716#endif
708 if (all_fmt & LIST_ID_NUMERIC) {
709 if (option_mask32 & OPT_g)
710 column += printf("%-8u ", (int) dn->dstat.st_gid);
711 else
712 column += printf("%-8u %-8u ",
713 (int) dn->dstat.st_uid,
714 (int) dn->dstat.st_gid);
715 }
716 if (all_fmt & LIST_SIZE) { 717 if (all_fmt & LIST_SIZE) {
717 if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) { 718 if (S_ISBLK(dn->dstat.st_mode) || S_ISCHR(dn->dstat.st_mode)) {
718 column += printf("%4u, %3u ", 719 column += printf("%4u, %3u ",
@@ -739,9 +740,12 @@ static NOINLINE unsigned list_single(const struct dnode *dn)
739 ttime = dn->dstat.st_ctime; 740 ttime = dn->dstat.st_ctime;
740 filetime = ctime(&ttime); 741 filetime = ctime(&ttime);
741 /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */ 742 /* filetime's format: "Wed Jun 30 21:49:08 1993\n" */
742 if (all_fmt & LIST_FULLTIME) 743 if (all_fmt & LIST_FULLTIME) { /* -e */
744 /* Note: coreutils 8.4 ls --full-time prints:
745 * 2009-07-13 17:49:27.000000000 +0200
746 */
743 column += printf("%.24s ", filetime); 747 column += printf("%.24s ", filetime);
744 else { /* LIST_DATE_TIME */ 748 } else { /* LIST_DATE_TIME */
745 /* current_time_t ~== time(NULL) */ 749 /* current_time_t ~== time(NULL) */
746 time_t age = current_time_t - ttime; 750 time_t age = current_time_t - ttime;
747 printf("%.6s ", filetime + 4); /* "Jun 30" */ 751 printf("%.6s ", filetime + 4); /* "Jun 30" */
@@ -1049,7 +1053,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1049 1053
1050 init_unicode(); 1054 init_unicode();
1051 1055
1052 all_fmt = ENABLE_FEATURE_LS_SORTFILES * SORT_NAME; 1056 if (ENABLE_FEATURE_LS_SORTFILES)
1057 all_fmt = SORT_NAME;
1053 1058
1054#if ENABLE_FEATURE_AUTOWIDTH 1059#if ENABLE_FEATURE_AUTOWIDTH
1055 /* obtain the terminal width */ 1060 /* obtain the terminal width */
@@ -1090,14 +1095,12 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1090 if (flags & TIME_MASK) 1095 if (flags & TIME_MASK)
1091 all_fmt &= ~TIME_MASK; 1096 all_fmt &= ~TIME_MASK;
1092 1097
1093 if (flags & LIST_CONTEXT)
1094 all_fmt |= STYLE_SINGLE;
1095 all_fmt |= flags; 1098 all_fmt |= flags;
1096 } 1099 }
1097 } 1100 }
1098 1101
1099#if ENABLE_FEATURE_LS_COLOR 1102#if ENABLE_FEATURE_LS_COLOR
1100 /* find color bit value - last position for short getopt */ 1103 /* set show_color = 1/0 */
1101 if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && isatty(STDOUT_FILENO)) { 1104 if (ENABLE_FEATURE_LS_COLOR_IS_DEFAULT && isatty(STDOUT_FILENO)) {
1102 char *p = getenv("LS_COLORS"); 1105 char *p = getenv("LS_COLORS");
1103 /* LS_COLORS is unset, or (not empty && not "none") ? */ 1106 /* LS_COLORS is unset, or (not empty && not "none") ? */
@@ -1130,11 +1133,8 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1130 if (all_fmt & TIME_ACCESS) 1133 if (all_fmt & TIME_ACCESS)
1131 all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME; 1134 all_fmt = (all_fmt & ~SORT_MASK) | SORT_ATIME;
1132 } 1135 }
1133 if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* only for long list */ 1136 if ((all_fmt & STYLE_MASK) != STYLE_LONG) /* not -l? */
1134 all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME); 1137 all_fmt &= ~(LIST_ID_NUMERIC|LIST_ID_NAME|LIST_FULLTIME);
1135 if (ENABLE_FEATURE_LS_USERNAME)
1136 if ((all_fmt & STYLE_MASK) == STYLE_LONG && (all_fmt & LIST_ID_NUMERIC))
1137 all_fmt &= ~LIST_ID_NAME; /* don't list names if numeric uid */
1138 1138
1139 /* choose a display format if one was not already specified by an option */ 1139 /* choose a display format if one was not already specified by an option */
1140 if (!(all_fmt & STYLE_MASK)) 1140 if (!(all_fmt & STYLE_MASK))
@@ -1153,7 +1153,10 @@ int ls_main(int argc UNUSED_PARAM, char **argv)
1153 do { 1153 do {
1154 cur = my_stat(*argv, *argv, 1154 cur = my_stat(*argv, *argv,
1155 /* follow links on command line unless -l, -s or -F: */ 1155 /* follow links on command line unless -l, -s or -F: */
1156 !((all_fmt & (STYLE_LONG|LIST_BLOCKS)) || (option_mask32 & OPT_F)) 1156 !((all_fmt & STYLE_MASK) == STYLE_LONG
1157 || (all_fmt & LIST_BLOCKS)
1158 || (option_mask32 & OPT_F)
1159 )
1157 /* ... or if -H: */ 1160 /* ... or if -H: */
1158 || (option_mask32 & OPT_H) 1161 || (option_mask32 & OPT_H)
1159 ); 1162 );
diff --git a/coreutils/printenv.c b/coreutils/printenv.c
index 33be5c096..d0fb71636 100644
--- a/coreutils/printenv.c
+++ b/coreutils/printenv.c
@@ -19,9 +19,14 @@ int printenv_main(int argc UNUSED_PARAM, char **argv)
19 19
20 /* no variables specified, show whole env */ 20 /* no variables specified, show whole env */
21 if (!argv[1]) { 21 if (!argv[1]) {
22 int e = 0; 22 char **e = environ;
23 while (environ[e]) 23
24 puts(environ[e++]); 24 /* environ can be NULL! (for example, after clearenv())
25 * Check for that:
26 */
27 if (e)
28 while (*e)
29 puts(*e++);
25 } else { 30 } else {
26 /* search for specified variables and print them out if found */ 31 /* search for specified variables and print them out if found */
27 char *arg, *env; 32 char *arg, *env;
diff --git a/coreutils/split.c b/coreutils/split.c
index db5a1727a..79316ed74 100644
--- a/coreutils/split.c
+++ b/coreutils/split.c
@@ -32,7 +32,7 @@ static char *next_file(char *old, unsigned suffix_len)
32 unsigned i = 1; 32 unsigned i = 1;
33 char *curr; 33 char *curr;
34 34
35 do { 35 while (1) {
36 curr = old + end - i; 36 curr = old + end - i;
37 if (*curr < 'z') { 37 if (*curr < 'z') {
38 *curr += 1; 38 *curr += 1;
@@ -43,7 +43,7 @@ static char *next_file(char *old, unsigned suffix_len)
43 return NULL; 43 return NULL;
44 } 44 }
45 *curr = 'a'; 45 *curr = 'a';
46 } while (1); 46 }
47 47
48 return old; 48 return old;
49} 49}
diff --git a/coreutils/test.c b/coreutils/test.c
index caecd7d02..cb15ed725 100644
--- a/coreutils/test.c
+++ b/coreutils/test.c
@@ -45,7 +45,7 @@
45/* This is a NOFORK applet. Be very careful! */ 45/* This is a NOFORK applet. Be very careful! */
46 46
47/* test_main() is called from shells, and we need to be extra careful here. 47/* test_main() is called from shells, and we need to be extra careful here.
48 * This is true regardless of PREFER_APPLETS and STANDALONE_SHELL 48 * This is true regardless of PREFER_APPLETS and SH_STANDALONE
49 * state. */ 49 * state. */
50 50
51/* test(1) accepts the following grammar: 51/* test(1) accepts the following grammar:
diff --git a/coreutils/tr.c b/coreutils/tr.c
index 21d77ef95..5b2b9a9a4 100644
--- a/coreutils/tr.c
+++ b/coreutils/tr.c
@@ -324,5 +324,11 @@ int tr_main(int argc UNUSED_PARAM, char **argv)
324 str2[out_index++] = last = coded; 324 str2[out_index++] = last = coded;
325 } 325 }
326 326
327 if (ENABLE_FEATURE_CLEAN_UP) {
328 free(vector);
329 free(str2);
330 free(str1);
331 }
332
327 return EXIT_SUCCESS; 333 return EXIT_SUCCESS;
328} 334}
diff --git a/docs/.gitignore b/docs/.gitignore
index 11d616360..3d1c5bd8a 100644
--- a/docs/.gitignore
+++ b/docs/.gitignore
@@ -1,4 +1,5 @@
1/busybox.1 1/busybox.1
2/BusyBox.html 2/BusyBox.html
3/busybox.net
3/BusyBox.txt 4/BusyBox.txt
4/busybox.pod 5/busybox.pod
diff --git a/e2fsprogs/Config.src b/e2fsprogs/Config.src
index 6043e9b57..743e1e11f 100644
--- a/e2fsprogs/Config.src
+++ b/e2fsprogs/Config.src
@@ -33,7 +33,7 @@ config FSCK
33config LSATTR 33config LSATTR
34 bool "lsattr" 34 bool "lsattr"
35 default y 35 default y
36 depends on PLATFORM_LINUX 36 select PLATFORM_LINUX
37 help 37 help
38 lsattr lists the file attributes on a second extended file system. 38 lsattr lists the file attributes on a second extended file system.
39 39
diff --git a/findutils/xargs.c b/findutils/xargs.c
index 0ec80f809..967737133 100644
--- a/findutils/xargs.c
+++ b/findutils/xargs.c
@@ -15,10 +15,6 @@
15 * http://www.opengroup.org/onlinepubs/007904975/utilities/xargs.html 15 * http://www.opengroup.org/onlinepubs/007904975/utilities/xargs.html
16 */ 16 */
17 17
18//applet:IF_XARGS(APPLET_NOEXEC(xargs, xargs, BB_DIR_USR_BIN, BB_SUID_DROP, xargs))
19
20//kbuild:lib-$(CONFIG_XARGS) += xargs.o
21
22//config:config XARGS 18//config:config XARGS
23//config: bool "xargs" 19//config: bool "xargs"
24//config: default y 20//config: default y
@@ -58,6 +54,10 @@
58//config: instead of whitespace, and the quotes and backslash 54//config: instead of whitespace, and the quotes and backslash
59//config: are not special. 55//config: are not special.
60 56
57//applet:IF_XARGS(APPLET_NOEXEC(xargs, xargs, BB_DIR_USR_BIN, BB_SUID_DROP, xargs))
58
59//kbuild:lib-$(CONFIG_XARGS) += xargs.o
60
61#include "libbb.h" 61#include "libbb.h"
62 62
63/* This is a NOEXEC applet. Be very careful! */ 63/* This is a NOEXEC applet. Be very careful! */
@@ -89,7 +89,9 @@ struct globals {
89 int idx; 89 int idx;
90} FIX_ALIASING; 90} FIX_ALIASING;
91#define G (*(struct globals*)&bb_common_bufsiz1) 91#define G (*(struct globals*)&bb_common_bufsiz1)
92#define INIT_G() do { } while (0) 92#define INIT_G() do { \
93 G.eof_str = NULL; /* need to clear by hand because we are NOEXEC applet */ \
94} while (0)
93 95
94 96
95/* 97/*
@@ -412,7 +414,12 @@ int xargs_main(int argc, char **argv)
412 414
413 INIT_G(); 415 INIT_G();
414 416
415 G.eof_str = NULL; 417#if ENABLE_DESKTOP && ENABLE_LONG_OPTS
418 /* For example, Fedora's build system uses --no-run-if-empty */
419 applet_long_options =
420 "no-run-if-empty\0" No_argument "r"
421 ;
422#endif
416 opt = getopt32(argv, OPTION_STR, &max_args, &max_chars, &G.eof_str, &G.eof_str); 423 opt = getopt32(argv, OPTION_STR, &max_args, &max_chars, &G.eof_str, &G.eof_str);
417 424
418 /* -E ""? You may wonder why not just omit -E? 425 /* -E ""? You may wonder why not just omit -E?
diff --git a/include/.gitignore b/include/.gitignore
index f0ce546cf..9d9b6c499 100644
--- a/include/.gitignore
+++ b/include/.gitignore
@@ -1,6 +1,10 @@
1/config 1/config
2 2
3/applets.h
3/applet_tables.h 4/applet_tables.h
4/autoconf.h 5/autoconf.h
6/bbconfigopts_bz2.h
5/bbconfigopts.h 7/bbconfigopts.h
8/NUM_APPLETS.h
6/usage_compressed.h 9/usage_compressed.h
10/usage.h
diff --git a/include/archive.h b/include/archive.h
index 49c478728..b139dc5be 100644
--- a/include/archive.h
+++ b/include/archive.h
@@ -84,6 +84,7 @@ typedef struct archive_handle_t {
84# endif 84# endif
85#if ENABLE_FEATURE_TAR_TO_COMMAND 85#if ENABLE_FEATURE_TAR_TO_COMMAND
86 char* tar__to_command; 86 char* tar__to_command;
87 const char* tar__to_command_shell;
87#endif 88#endif
88# if ENABLE_FEATURE_TAR_SELINUX 89# if ENABLE_FEATURE_TAR_SELINUX
89 char* tar__global_sctx; 90 char* tar__global_sctx;
@@ -159,37 +160,39 @@ typedef struct unpack_info_t {
159 time_t mtime; 160 time_t mtime;
160} unpack_info_t; 161} unpack_info_t;
161 162
162extern archive_handle_t *init_handle(void) FAST_FUNC; 163archive_handle_t *init_handle(void) FAST_FUNC;
163 164
164extern char filter_accept_all(archive_handle_t *archive_handle) FAST_FUNC; 165char filter_accept_all(archive_handle_t *archive_handle) FAST_FUNC;
165extern char filter_accept_list(archive_handle_t *archive_handle) FAST_FUNC; 166char filter_accept_list(archive_handle_t *archive_handle) FAST_FUNC;
166extern char filter_accept_list_reassign(archive_handle_t *archive_handle) FAST_FUNC; 167char filter_accept_list_reassign(archive_handle_t *archive_handle) FAST_FUNC;
167extern char filter_accept_reject_list(archive_handle_t *archive_handle) FAST_FUNC; 168char filter_accept_reject_list(archive_handle_t *archive_handle) FAST_FUNC;
168 169
169extern void unpack_ar_archive(archive_handle_t *ar_archive) FAST_FUNC; 170void unpack_ar_archive(archive_handle_t *ar_archive) FAST_FUNC;
170 171
171extern void data_skip(archive_handle_t *archive_handle) FAST_FUNC; 172void data_skip(archive_handle_t *archive_handle) FAST_FUNC;
172extern void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC; 173void data_extract_all(archive_handle_t *archive_handle) FAST_FUNC;
173extern void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC; 174void data_extract_to_stdout(archive_handle_t *archive_handle) FAST_FUNC;
174extern void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC; 175void data_extract_to_command(archive_handle_t *archive_handle) FAST_FUNC;
175 176
176extern void header_skip(const file_header_t *file_header) FAST_FUNC; 177void header_skip(const file_header_t *file_header) FAST_FUNC;
177extern void header_list(const file_header_t *file_header) FAST_FUNC; 178void header_list(const file_header_t *file_header) FAST_FUNC;
178extern void header_verbose_list(const file_header_t *file_header) FAST_FUNC; 179void header_verbose_list(const file_header_t *file_header) FAST_FUNC;
179 180
180extern char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC; 181char get_header_ar(archive_handle_t *archive_handle) FAST_FUNC;
181extern char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC; 182char get_header_cpio(archive_handle_t *archive_handle) FAST_FUNC;
182extern char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC; 183char get_header_tar(archive_handle_t *archive_handle) FAST_FUNC;
183extern char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC; 184char get_header_tar_gz(archive_handle_t *archive_handle) FAST_FUNC;
184extern char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC; 185char get_header_tar_bz2(archive_handle_t *archive_handle) FAST_FUNC;
185extern char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC; 186char get_header_tar_lzma(archive_handle_t *archive_handle) FAST_FUNC;
186 187
187extern void seek_by_jump(int fd, off_t amount) FAST_FUNC; 188void seek_by_jump(int fd, off_t amount) FAST_FUNC;
188extern void seek_by_read(int fd, off_t amount) FAST_FUNC; 189void seek_by_read(int fd, off_t amount) FAST_FUNC;
189 190
190extern void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC; 191const char *strip_unsafe_prefix(const char *str) FAST_FUNC;
191extern const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC; 192
192extern const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC; 193void data_align(archive_handle_t *archive_handle, unsigned boundary) FAST_FUNC;
194const llist_t *find_list_entry(const llist_t *list, const char *filename) FAST_FUNC;
195const llist_t *find_list_entry2(const llist_t *list, const char *filename) FAST_FUNC;
193 196
194/* A bit of bunzip2 internals are exposed for compressed help support: */ 197/* A bit of bunzip2 internals are exposed for compressed help support: */
195typedef struct bunzip_data bunzip_data; 198typedef struct bunzip_data bunzip_data;
diff --git a/include/libbb.h b/include/libbb.h
index 6564038e9..0006e7e55 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -855,14 +855,14 @@ char* xuid2uname(uid_t uid) FAST_FUNC;
855char* xgid2group(gid_t gid) FAST_FUNC; 855char* xgid2group(gid_t gid) FAST_FUNC;
856char* uid2uname(uid_t uid) FAST_FUNC; 856char* uid2uname(uid_t uid) FAST_FUNC;
857char* gid2group(gid_t gid) FAST_FUNC; 857char* gid2group(gid_t gid) FAST_FUNC;
858char* uid2uname_utoa(long uid) FAST_FUNC; 858char* uid2uname_utoa(uid_t uid) FAST_FUNC;
859char* gid2group_utoa(long gid) FAST_FUNC; 859char* gid2group_utoa(gid_t gid) FAST_FUNC;
860/* versions which cache results (useful for ps, ls etc) */ 860/* versions which cache results (useful for ps, ls etc) */
861const char* get_cached_username(uid_t uid) FAST_FUNC; 861const char* get_cached_username(uid_t uid) FAST_FUNC;
862const char* get_cached_groupname(gid_t gid) FAST_FUNC; 862const char* get_cached_groupname(gid_t gid) FAST_FUNC;
863void clear_username_cache(void) FAST_FUNC; 863void clear_username_cache(void) FAST_FUNC;
864/* internally usernames are saved in fixed-sized char[] buffers */ 864/* internally usernames are saved in fixed-sized char[] buffers */
865enum { USERNAME_MAX_SIZE = 16 - sizeof(int) }; 865enum { USERNAME_MAX_SIZE = 32 - sizeof(uid_t) };
866#if ENABLE_FEATURE_CHECK_NAMES 866#if ENABLE_FEATURE_CHECK_NAMES
867void die_if_bad_username(const char* name) FAST_FUNC; 867void die_if_bad_username(const char* name) FAST_FUNC;
868#else 868#else
@@ -1214,10 +1214,17 @@ char *bb_simplify_path(const char *path) FAST_FUNC;
1214/* Returns ptr to NUL */ 1214/* Returns ptr to NUL */
1215char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC; 1215char *bb_simplify_abs_path_inplace(char *path) FAST_FUNC;
1216 1216
1217#define FAIL_DELAY 3 1217#define LOGIN_FAIL_DELAY 3
1218extern void bb_do_delay(int seconds) FAST_FUNC; 1218extern void bb_do_delay(int seconds) FAST_FUNC;
1219extern void change_identity(const struct passwd *pw) FAST_FUNC; 1219extern void change_identity(const struct passwd *pw) FAST_FUNC;
1220extern void run_shell(const char *shell, int loginshell, const char *command, const char **additional_args) NORETURN FAST_FUNC; 1220extern void run_shell(const char *shell, int loginshell, const char *command, const char **additional_args) NORETURN FAST_FUNC;
1221
1222/* Returns $SHELL, getpwuid(getuid())->pw_shell, or DEFAULT_SHELL.
1223 * Note that getpwuid result might need xstrdup'ing
1224 * if there is a possibility of intervening getpwxxx() calls.
1225 */
1226const char *get_shell_name(void);
1227
1221#if ENABLE_SELINUX 1228#if ENABLE_SELINUX
1222extern void renew_current_security_context(void) FAST_FUNC; 1229extern void renew_current_security_context(void) FAST_FUNC;
1223extern void set_current_security_context(security_context_t sid) FAST_FUNC; 1230extern void set_current_security_context(security_context_t sid) FAST_FUNC;
diff --git a/include/unicode.h b/include/unicode.h
index dee02e777..0317a2151 100644
--- a/include/unicode.h
+++ b/include/unicode.h
@@ -27,6 +27,7 @@ enum {
27# define unicode_strwidth(string) strlen(string) 27# define unicode_strwidth(string) strlen(string)
28# define unicode_status UNICODE_OFF 28# define unicode_status UNICODE_OFF
29# define init_unicode() ((void)0) 29# define init_unicode() ((void)0)
30# define reinit_unicode(LANG) ((void)0)
30 31
31#else 32#else
32 33
@@ -67,6 +68,7 @@ char* FAST_FUNC unicode_conv_to_printable_fixedwidth(/*uni_stat_t *stats,*/ cons
67 68
68extern uint8_t unicode_status; 69extern uint8_t unicode_status;
69void init_unicode(void) FAST_FUNC; 70void init_unicode(void) FAST_FUNC;
71void reinit_unicode(const char *LANG) FAST_FUNC;
70 72
71# else 73# else
72 74
@@ -75,9 +77,11 @@ void init_unicode(void) FAST_FUNC;
75# if !ENABLE_FEATURE_CHECK_UNICODE_IN_ENV 77# if !ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
76# define unicode_status UNICODE_ON 78# define unicode_status UNICODE_ON
77# define init_unicode() ((void)0) 79# define init_unicode() ((void)0)
80# define reinit_unicode(LANG) ((void)0)
78# else 81# else
79extern uint8_t unicode_status; 82extern uint8_t unicode_status;
80void init_unicode(void) FAST_FUNC; 83void init_unicode(void) FAST_FUNC;
84void reinit_unicode(const char *LANG) FAST_FUNC;
81# endif 85# endif
82 86
83# undef MB_CUR_MAX 87# undef MB_CUR_MAX
diff --git a/include/usage.src.h b/include/usage.src.h
index c2575b561..d07b408a6 100644
--- a/include/usage.src.h
+++ b/include/usage.src.h
@@ -1273,23 +1273,6 @@ INSERT
1273 "\n -m Show \"mode not cleared\" warnings" \ 1273 "\n -m Show \"mode not cleared\" warnings" \
1274 "\n -f Force file system check" \ 1274 "\n -f Force file system check" \
1275 1275
1276#define ftpd_trivial_usage \
1277 "[-wvS] [-t N] [-T N] [DIR]"
1278#define ftpd_full_usage "\n\n" \
1279 "Anonymous FTP server\n" \
1280 "\n" \
1281 "ftpd should be used as an inetd service.\n" \
1282 "ftpd's line for inetd.conf:\n" \
1283 " 21 stream tcp nowait root ftpd ftpd /files/to/serve\n" \
1284 "It also can be ran from tcpsvd:\n" \
1285 " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n" \
1286 "\nOptions:" \
1287 "\n -w Allow upload" \
1288 "\n -v Log to stderr" \
1289 "\n -S Log to syslog" \
1290 "\n -t,-T Idle and absolute timeouts" \
1291 "\n DIR Change root to this directory" \
1292
1293#define ftpget_trivial_usage \ 1276#define ftpget_trivial_usage \
1294 "[OPTIONS] HOST [LOCAL_FILE] REMOTE_FILE" 1277 "[OPTIONS] HOST [LOCAL_FILE] REMOTE_FILE"
1295#define ftpget_full_usage "\n\n" \ 1278#define ftpget_full_usage "\n\n" \
@@ -2499,7 +2482,7 @@ INSERT
2499 "\n [r]slave Convert [recursively] to a slave subtree" \ 2482 "\n [r]slave Convert [recursively] to a slave subtree" \
2500 "\n [r]private Convert [recursively] to a private subtree" \ 2483 "\n [r]private Convert [recursively] to a private subtree" \
2501 "\n [un]bindable Make mount point [un]able to be bind mounted" \ 2484 "\n [un]bindable Make mount point [un]able to be bind mounted" \
2502 "\n bind Bind a file or directory to another location" \ 2485 "\n [r]bind Bind a file or directory [recursively] to another location" \
2503 "\n move Relocate an existing mount point" \ 2486 "\n move Relocate an existing mount point" \
2504 ) \ 2487 ) \
2505 "\n remount Remount a mounted filesystem, changing flags" \ 2488 "\n remount Remount a mounted filesystem, changing flags" \
@@ -2546,20 +2529,6 @@ INSERT
2546 "ras3 reset retension rewind rewoffline seek setblk setdensity\n" \ 2529 "ras3 reset retension rewind rewoffline seek setblk setdensity\n" \
2547 "setpart tell unload unlock weof wset" \ 2530 "setpart tell unload unlock weof wset" \
2548 2531
2549#define nameif_trivial_usage \
2550 "[-s] [-c FILE] [{IFNAME MACADDR}]"
2551#define nameif_full_usage "\n\n" \
2552 "Rename network interface while it in the down state\n" \
2553 "\nOptions:" \
2554 "\n -c FILE Use configuration file (default: /etc/mactab)" \
2555 "\n -s Use syslog (LOCAL0 facility)" \
2556 "\n IFNAME MACADDR new_interface_name interface_mac_address" \
2557
2558#define nameif_example_usage \
2559 "$ nameif -s dmz0 00:A0:C9:8C:F6:3F\n" \
2560 " or\n" \
2561 "$ nameif -c /etc/my_mactab_file\n" \
2562
2563#define nohup_trivial_usage \ 2532#define nohup_trivial_usage \
2564 "PROG ARGS" 2533 "PROG ARGS"
2565#define nohup_full_usage "\n\n" \ 2534#define nohup_full_usage "\n\n" \
@@ -4098,31 +4067,6 @@ INSERT
4098 "\n" \ 4067 "\n" \
4099 "\nUse 500ms to specify period in milliseconds" \ 4068 "\nUse 500ms to specify period in milliseconds" \
4100 4069
4101#define wget_trivial_usage \
4102 IF_FEATURE_WGET_LONG_OPTIONS( \
4103 "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" \
4104 " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n" \
4105 " [--no-check-certificate] [-U|--user-agent AGENT]" \
4106 IF_FEATURE_WGET_TIMEOUT("[-T SEC] ") " URL" \
4107 ) \
4108 IF_NOT_FEATURE_WGET_LONG_OPTIONS( \
4109 "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]" \
4110 IF_FEATURE_WGET_TIMEOUT("[-T SEC] ") " URL" \
4111 )
4112#define wget_full_usage "\n\n" \
4113 "Retrieve files via HTTP or FTP\n" \
4114 "\nOptions:" \
4115 "\n -s Spider mode - only check file existence" \
4116 "\n -c Continue retrieval of aborted transfer" \
4117 "\n -q Quiet" \
4118 "\n -P DIR Save to DIR (default .)" \
4119 IF_FEATURE_WGET_TIMEOUT( \
4120 "\n -T SEC Network read timeout is SEC seconds" \
4121 ) \
4122 "\n -O FILE Save to FILE ('-' for stdout)" \
4123 "\n -U STR Use STR for User-Agent header" \
4124 "\n -Y Use proxy ('on' or 'off')" \
4125
4126#define which_trivial_usage \ 4070#define which_trivial_usage \
4127 "[COMMAND]..." 4071 "[COMMAND]..."
4128#define which_full_usage "\n\n" \ 4072#define which_full_usage "\n\n" \
diff --git a/init/init.c b/init/init.c
index 586e34a18..ff9dc06a4 100644
--- a/init/init.c
+++ b/init/init.c
@@ -414,6 +414,7 @@ static void init_exec(const char *command)
414 char *word, *next; 414 char *word, *next;
415 int i = 0; 415 int i = 0;
416 next = strcpy(buf, command - dash); /* command including "-" */ 416 next = strcpy(buf, command - dash); /* command including "-" */
417 command = next + dash;
417 while ((word = strsep(&next, " \t")) != NULL) { 418 while ((word = strsep(&next, " \t")) != NULL) {
418 if (*word != '\0') { /* not two spaces/tabs together? */ 419 if (*word != '\0') { /* not two spaces/tabs together? */
419 cmd[i] = word; 420 cmd[i] = word;
diff --git a/init/mesg.c b/init/mesg.c
index 676ca2e24..8489e621c 100644
--- a/init/mesg.c
+++ b/init/mesg.c
@@ -7,16 +7,28 @@
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 */ 8 */
9 9
10//applet:IF_MESG(APPLET(mesg, BB_DIR_USR_BIN, BB_SUID_DROP))
11
12//kbuild:lib-$(CONFIG_MESG) += mesg.o
13
14//config:config MESG 10//config:config MESG
15//config: bool "mesg" 11//config: bool "mesg"
16//config: default y 12//config: default y
17//config: help 13//config: help
18//config: Mesg controls access to your terminal by others. It is typically 14//config: Mesg controls access to your terminal by others. It is typically
19//config: used to allow or disallow other users to write to your terminal 15//config: used to allow or disallow other users to write to your terminal
16//config:
17//config:config FEATURE_MESG_ENABLE_ONLY_GROUP
18//config: bool "Enable writing to tty only by group, not by everybody"
19//config: default y
20//config: depends on MESG
21//config: help
22//config: Usually, ttys are owned by group "tty", and "write" tool is
23//config: setgid to this group. This way, "mesg y" only needs to enable
24//config: "write by owning group" bit in tty mode.
25//config:
26//config: If you set this option to N, "mesg y" will enable writing
27//config: by anybody at all. This is not recommended.
28
29//applet:IF_MESG(APPLET(mesg, BB_DIR_USR_BIN, BB_SUID_DROP))
30
31//kbuild:lib-$(CONFIG_MESG) += mesg.o
20 32
21//usage:#define mesg_trivial_usage 33//usage:#define mesg_trivial_usage
22//usage: "[y|n]" 34//usage: "[y|n]"
@@ -27,7 +39,7 @@
27 39
28#include "libbb.h" 40#include "libbb.h"
29 41
30#ifdef USE_TTY_GROUP 42#if ENABLE_FEATURE_MESG_ENABLE_ONLY_GROUP
31#define S_IWGRP_OR_S_IWOTH S_IWGRP 43#define S_IWGRP_OR_S_IWOTH S_IWGRP
32#else 44#else
33#define S_IWGRP_OR_S_IWOTH (S_IWGRP | S_IWOTH) 45#define S_IWGRP_OR_S_IWOTH (S_IWGRP | S_IWOTH)
@@ -37,30 +49,28 @@ int mesg_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
37int mesg_main(int argc UNUSED_PARAM, char **argv) 49int mesg_main(int argc UNUSED_PARAM, char **argv)
38{ 50{
39 struct stat sb; 51 struct stat sb;
40 const char *tty; 52 mode_t m;
41 char c = 0; 53 char c = 0;
42 54
43 argv++; 55 argv++;
44 56
45 if (!argv[0] 57 if (argv[0]
46 || (!argv[1] && ((c = argv[0][0]) == 'y' || c == 'n')) 58 && (argv[1] || ((c = argv[0][0]) != 'y' && c != 'n'))
47 ) { 59 ) {
48 tty = xmalloc_ttyname(STDERR_FILENO); 60 bb_show_usage();
49 if (tty == NULL) { 61 }
50 tty = "ttyname"; 62
51 } else if (stat(tty, &sb) == 0) { 63 if (!isatty(STDERR_FILENO))
52 mode_t m; 64 bb_error_msg_and_die("not a tty");
53 if (c == 0) { 65
54 puts((sb.st_mode & (S_IWGRP|S_IWOTH)) ? "is y" : "is n"); 66 xfstat(STDERR_FILENO, &sb, "stderr");
55 return EXIT_SUCCESS; 67 if (c == 0) {
56 } 68 puts((sb.st_mode & (S_IWGRP|S_IWOTH)) ? "is y" : "is n");
57 m = (c == 'y') ? sb.st_mode | S_IWGRP_OR_S_IWOTH 69 return EXIT_SUCCESS;
58 : sb.st_mode & ~(S_IWGRP|S_IWOTH);
59 if (chmod(tty, m) == 0) {
60 return EXIT_SUCCESS;
61 }
62 }
63 bb_simple_perror_msg_and_die(tty);
64 } 70 }
65 bb_show_usage(); 71 m = (c == 'y') ? sb.st_mode | S_IWGRP_OR_S_IWOTH
72 : sb.st_mode & ~(S_IWGRP|S_IWOTH);
73 if (fchmod(STDERR_FILENO, m) != 0)
74 bb_perror_nomsg_and_die();
75 return EXIT_SUCCESS;
66} 76}
diff --git a/libbb/Config.src b/libbb/Config.src
index 18bdc5151..a25af23b4 100644
--- a/libbb/Config.src
+++ b/libbb/Config.src
@@ -183,7 +183,7 @@ config FEATURE_SKIP_ROOTFS
183config MONOTONIC_SYSCALL 183config MONOTONIC_SYSCALL
184 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall" 184 bool "Use clock_gettime(CLOCK_MONOTONIC) syscall"
185 default n 185 default n
186 depends on PLATFORM_LINUX 186 select PLATFORM_LINUX
187 help 187 help
188 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring 188 Use clock_gettime(CLOCK_MONOTONIC) syscall for measuring
189 time intervals (time, ping, traceroute etc need this). 189 time intervals (time, ping, traceroute etc need this).
diff --git a/libbb/appletlib.c b/libbb/appletlib.c
index 4e32414b4..50e53aa25 100644
--- a/libbb/appletlib.c
+++ b/libbb/appletlib.c
@@ -713,12 +713,22 @@ static int busybox_main(char **argv)
713 if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) { 713 if (ENABLE_FEATURE_INSTALLER && strcmp(argv[1], "--install") == 0) {
714 int use_symbolic_links; 714 int use_symbolic_links;
715 const char *busybox; 715 const char *busybox;
716
716 busybox = xmalloc_readlink(bb_busybox_exec_path); 717 busybox = xmalloc_readlink(bb_busybox_exec_path);
717 if (!busybox) 718 if (!busybox) {
718 busybox = bb_busybox_exec_path; 719 /* bb_busybox_exec_path is usually "/proc/self/exe".
719 /* busybox --install [-s] [DIR]: */ 720 * In chroot, readlink("/proc/self/exe") usually fails.
720 /* -s: make symlinks */ 721 * In such case, better use argv[0] as symlink target
721 /* DIR: directory to install links to */ 722 * if it is a full path name.
723 */
724 if (argv[0][0] != '/')
725 bb_error_msg_and_die("'%s' is not an absolute path", argv[0]);
726 busybox = argv[0];
727 }
728 /* busybox --install [-s] [DIR]:
729 * -s: make symlinks
730 * DIR: directory to install links to
731 */
722 use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && argv++); 732 use_symbolic_links = (argv[2] && strcmp(argv[2], "-s") == 0 && argv++);
723 install_links(busybox, use_symbolic_links, argv[2]); 733 install_links(busybox, use_symbolic_links, argv[2]);
724 return 0; 734 return 0;
diff --git a/libbb/bb_pwd.c b/libbb/bb_pwd.c
index 32406cb58..4829b723a 100644
--- a/libbb/bb_pwd.c
+++ b/libbb/bb_pwd.c
@@ -72,13 +72,13 @@ char* FAST_FUNC gid2group(gid_t gid)
72 return (gr) ? gr->gr_name : NULL; 72 return (gr) ? gr->gr_name : NULL;
73} 73}
74 74
75char* FAST_FUNC uid2uname_utoa(long uid) 75char* FAST_FUNC uid2uname_utoa(uid_t uid)
76{ 76{
77 char *name = uid2uname(uid); 77 char *name = uid2uname(uid);
78 return (name) ? name : utoa(uid); 78 return (name) ? name : utoa(uid);
79} 79}
80 80
81char* FAST_FUNC gid2group_utoa(long gid) 81char* FAST_FUNC gid2group_utoa(gid_t gid)
82{ 82{
83 char *name = gid2group(gid); 83 char *name = gid2group(gid);
84 return (name) ? name : utoa(gid); 84 return (name) ? name : utoa(gid);
diff --git a/libbb/get_shell_name.c b/libbb/get_shell_name.c
new file mode 100644
index 000000000..d196d293d
--- /dev/null
+++ b/libbb/get_shell_name.c
@@ -0,0 +1,27 @@
1/*
2 * Copyright 2011, Denys Vlasenko
3 *
4 * Licensed under GPLv2, see file LICENSE in this source tree.
5 */
6
7//kbuild:lib-y += get_shell_name.o
8
9#include "libbb.h"
10
11const char *get_shell_name(void)
12{
13 struct passwd *pw;
14 char *shell;
15
16 shell = getenv("SHELL");
17 if (shell && shell[0])
18 return shell;
19
20#if !ENABLE_PLATFORM_MINGW32
21 pw = getpwuid(getuid());
22 if (pw && pw->pw_shell && pw->pw_shell[0])
23 return pw->pw_shell;
24#endif
25
26 return DEFAULT_SHELL;
27}
diff --git a/libbb/getopt32.c b/libbb/getopt32.c
index 053ffc349..8087b3ba6 100644
--- a/libbb/getopt32.c
+++ b/libbb/getopt32.c
@@ -542,8 +542,6 @@ getopt32(char **argv, const char *applet_opts, ...)
542#endif 542#endif
543 /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */ 543 /* optarg = NULL; opterr = 0; optopt = 0; - do we need this?? */
544 544
545 pargv = NULL;
546
547 /* Note: just "getopt() <= 0" will not work well for 545 /* Note: just "getopt() <= 0" will not work well for
548 * "fake" short options, like this one: 546 * "fake" short options, like this one:
549 * wget $'-\203' "Test: test" http://kernel.org/ 547 * wget $'-\203' "Test: test" http://kernel.org/
@@ -574,19 +572,16 @@ getopt32(char **argv, const char *applet_opts, ...)
574 flags ^= trigger; 572 flags ^= trigger;
575 if (on_off->counter) 573 if (on_off->counter)
576 (*(on_off->counter))++; 574 (*(on_off->counter))++;
577 if (on_off->param_type == PARAM_LIST) { 575 if (optarg) {
578 if (optarg) 576 if (on_off->param_type == PARAM_LIST) {
579 llist_add_to_end((llist_t **)(on_off->optarg), optarg); 577 llist_add_to_end((llist_t **)(on_off->optarg), optarg);
580 } else if (on_off->param_type == PARAM_INT) { 578 } else if (on_off->param_type == PARAM_INT) {
581 if (optarg)
582//TODO: xatoi_positive indirectly pulls in printf machinery 579//TODO: xatoi_positive indirectly pulls in printf machinery
583 *(unsigned*)(on_off->optarg) = xatoi_positive(optarg); 580 *(unsigned*)(on_off->optarg) = xatoi_positive(optarg);
584 } else if (on_off->optarg) { 581 } else if (on_off->optarg) {
585 if (optarg)
586 *(char **)(on_off->optarg) = optarg; 582 *(char **)(on_off->optarg) = optarg;
583 }
587 } 584 }
588 if (pargv != NULL)
589 break;
590 } 585 }
591 586
592 /* check depending requires for given options */ 587 /* check depending requires for given options */
diff --git a/libbb/inet_common.c b/libbb/inet_common.c
index 6f585ebd9..207720e96 100644
--- a/libbb/inet_common.c
+++ b/libbb/inet_common.c
@@ -164,17 +164,17 @@ char* FAST_FUNC INET_rresolve(struct sockaddr_in *s_in, int numeric, uint32_t ne
164 164
165int FAST_FUNC INET6_resolve(const char *name, struct sockaddr_in6 *sin6) 165int FAST_FUNC INET6_resolve(const char *name, struct sockaddr_in6 *sin6)
166{ 166{
167 struct addrinfo req, *ai; 167 struct addrinfo req, *ai = NULL;
168 int s; 168 int s;
169 169
170 memset(&req, '\0', sizeof req); 170 memset(&req, 0, sizeof(req));
171 req.ai_family = AF_INET6; 171 req.ai_family = AF_INET6;
172 s = getaddrinfo(name, NULL, &req, &ai); 172 s = getaddrinfo(name, NULL, &req, &ai);
173 if (s) { 173 if (s != 0) {
174 bb_error_msg("getaddrinfo: %s: %d", name, s); 174 bb_error_msg("getaddrinfo: %s: %d", name, s);
175 return -1; 175 return -1;
176 } 176 }
177 memcpy(sin6, ai->ai_addr, sizeof(struct sockaddr_in6)); 177 memcpy(sin6, ai->ai_addr, sizeof(*sin6));
178 freeaddrinfo(ai); 178 freeaddrinfo(ai);
179 return 0; 179 return 0;
180} 180}
@@ -209,9 +209,11 @@ char* FAST_FUNC INET6_rresolve(struct sockaddr_in6 *sin6, int numeric)
209 return xstrdup("*"); 209 return xstrdup("*");
210 } 210 }
211 211
212 s = getnameinfo((struct sockaddr *) sin6, sizeof(struct sockaddr_in6), 212 s = getnameinfo((struct sockaddr *) sin6, sizeof(*sin6),
213 name, sizeof(name), NULL, 0, 0); 213 name, sizeof(name),
214 if (s) { 214 /*serv,servlen:*/ NULL, 0,
215 0);
216 if (s != 0) {
215 bb_error_msg("getnameinfo failed"); 217 bb_error_msg("getnameinfo failed");
216 return NULL; 218 return NULL;
217 } 219 }
diff --git a/libbb/procps.c b/libbb/procps.c
index c68d3e655..58772d4e9 100644
--- a/libbb/procps.c
+++ b/libbb/procps.c
@@ -12,13 +12,13 @@
12#include "libbb.h" 12#include "libbb.h"
13 13
14 14
15typedef struct unsigned_to_name_map_t { 15typedef struct id_to_name_map_t {
16 long id; 16 uid_t id;
17 char name[USERNAME_MAX_SIZE]; 17 char name[USERNAME_MAX_SIZE];
18} unsigned_to_name_map_t; 18} id_to_name_map_t;
19 19
20typedef struct cache_t { 20typedef struct cache_t {
21 unsigned_to_name_map_t *cache; 21 id_to_name_map_t *cache;
22 int size; 22 int size;
23} cache_t; 23} cache_t;
24 24
@@ -39,7 +39,7 @@ void FAST_FUNC clear_username_cache(void)
39#if 0 /* more generic, but we don't need that yet */ 39#if 0 /* more generic, but we don't need that yet */
40/* Returns -N-1 if not found. */ 40/* Returns -N-1 if not found. */
41/* cp->cache[N] is allocated and must be filled in this case */ 41/* cp->cache[N] is allocated and must be filled in this case */
42static int get_cached(cache_t *cp, unsigned id) 42static int get_cached(cache_t *cp, uid_t id)
43{ 43{
44 int i; 44 int i;
45 for (i = 0; i < cp->size; i++) 45 for (i = 0; i < cp->size; i++)
@@ -52,8 +52,8 @@ static int get_cached(cache_t *cp, unsigned id)
52} 52}
53#endif 53#endif
54 54
55static char* get_cached(cache_t *cp, long id, 55static char* get_cached(cache_t *cp, uid_t id,
56 char* FAST_FUNC x2x_utoa(long id)) 56 char* FAST_FUNC x2x_utoa(uid_t id))
57{ 57{
58 int i; 58 int i;
59 for (i = 0; i < cp->size; i++) 59 for (i = 0; i < cp->size; i++)
diff --git a/libbb/progress.c b/libbb/progress.c
index df43dad5c..372feb0c2 100644
--- a/libbb/progress.c
+++ b/libbb/progress.c
@@ -127,10 +127,12 @@ void FAST_FUNC bb_progress_update(bb_progress_t *p,
127 /* 32-bit CPU and 64-bit off_t. 127 /* 32-bit CPU and 64-bit off_t.
128 * Use a 40-bit shift, it is easier to do on 32-bit CPU. 128 * Use a 40-bit shift, it is easier to do on 32-bit CPU.
129 */ 129 */
130 if (totalsize >= (uoff_t)(1ULL << 54)) { 130/* ONE suppresses "warning: shift count >= width of type" */
131 totalsize = (uint32_t)(totalsize >> 32) >> 8; 131#define ONE (sizeof(off_t) > 4)
132 beg_size = (uint32_t)(beg_size >> 32) >> 8; 132 if (totalsize >= (uoff_t)(1ULL << 54*ONE)) {
133 transferred = (uint32_t)(transferred >> 32) >> 8; 133 totalsize = (uint32_t)(totalsize >> 32*ONE) >> 8;
134 beg_size = (uint32_t)(beg_size >> 32*ONE) >> 8;
135 transferred = (uint32_t)(transferred >> 32*ONE) >> 8;
134 kiloscale = 4; 136 kiloscale = 4;
135 } 137 }
136 } 138 }
diff --git a/libbb/setup_environment.c b/libbb/setup_environment.c
index a95fbc5bf..73229ca6c 100644
--- a/libbb/setup_environment.c
+++ b/libbb/setup_environment.c
@@ -32,6 +32,9 @@
32 32
33void FAST_FUNC setup_environment(const char *shell, int flags, const struct passwd *pw) 33void FAST_FUNC setup_environment(const char *shell, int flags, const struct passwd *pw)
34{ 34{
35 if (!shell || !shell[0])
36 shell = DEFAULT_SHELL;
37
35 /* Change the current working directory to be the home directory 38 /* Change the current working directory to be the home directory
36 * of the user */ 39 * of the user */
37 if (chdir(pw->pw_dir)) { 40 if (chdir(pw->pw_dir)) {
diff --git a/libbb/unicode.c b/libbb/unicode.c
index 08a4c7427..d01efd9a2 100644
--- a/libbb/unicode.c
+++ b/libbb/unicode.c
@@ -23,37 +23,43 @@ uint8_t unicode_status;
23 23
24/* Unicode support using libc locale support. */ 24/* Unicode support using libc locale support. */
25 25
26void FAST_FUNC init_unicode(void) 26void FAST_FUNC reinit_unicode(const char *LANG UNUSED_PARAM)
27{ 27{
28 static const char unicode_0x394[] = { 0xce, 0x94, 0 }; 28 static const char unicode_0x394[] = { 0xce, 0x94, 0 };
29 size_t width; 29 size_t width;
30 30
31 if (unicode_status != UNICODE_UNKNOWN) 31//TODO: call setlocale(LC_ALL, LANG) here?
32 return; 32
33 /* In unicode, this is a one character string */ 33 /* In unicode, this is a one character string */
34// can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused 34// can use unicode_strlen(string) too, but otherwise unicode_strlen() is unused
35 width = mbstowcs(NULL, unicode_0x394, INT_MAX); 35 width = mbstowcs(NULL, unicode_0x394, INT_MAX);
36 unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF); 36 unicode_status = (width == 1 ? UNICODE_ON : UNICODE_OFF);
37} 37}
38 38
39void FAST_FUNC init_unicode(void)
40{
41 if (unicode_status == UNICODE_UNKNOWN)
42 reinit_unicode(NULL /*getenv("LANG")*/);
43}
44
39#else 45#else
40 46
41/* Homegrown Unicode support. It knows only C and Unicode locales. */ 47/* Homegrown Unicode support. It knows only C and Unicode locales. */
42 48
43# if ENABLE_FEATURE_CHECK_UNICODE_IN_ENV 49# if ENABLE_FEATURE_CHECK_UNICODE_IN_ENV
44void FAST_FUNC init_unicode(void) 50void FAST_FUNC reinit_unicode(const char *LANG)
45{ 51{
46 char *lang;
47
48 if (unicode_status != UNICODE_UNKNOWN)
49 return;
50
51 unicode_status = UNICODE_OFF; 52 unicode_status = UNICODE_OFF;
52 lang = getenv("LANG"); 53 if (!LANG || !(strstr(LANG, ".utf") || strstr(LANG, ".UTF")))
53 if (!lang || !(strstr(lang, ".utf") || strstr(lang, ".UTF")))
54 return; 54 return;
55 unicode_status = UNICODE_ON; 55 unicode_status = UNICODE_ON;
56} 56}
57
58void FAST_FUNC init_unicode(void)
59{
60 if (unicode_status == UNICODE_UNKNOWN)
61 reinit_unicode(getenv("LANG"));
62}
57# endif 63# endif
58 64
59static size_t wcrtomb_internal(char *s, wchar_t wc) 65static size_t wcrtomb_internal(char *s, wchar_t wc)
diff --git a/libbb/xconnect.c b/libbb/xconnect.c
index 3a6585caa..127e2a5fc 100644
--- a/libbb/xconnect.c
+++ b/libbb/xconnect.c
@@ -255,7 +255,7 @@ IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;)
255 255
256 memset(&hint, 0 , sizeof(hint)); 256 memset(&hint, 0 , sizeof(hint));
257 hint.ai_family = af; 257 hint.ai_family = af;
258 /* Needed. Or else we will get each address thrice (or more) 258 /* Need SOCK_STREAM, or else we get each address thrice (or more)
259 * for each possible socket type (tcp,udp,raw...): */ 259 * for each possible socket type (tcp,udp,raw...): */
260 hint.ai_socktype = SOCK_STREAM; 260 hint.ai_socktype = SOCK_STREAM;
261 hint.ai_flags = ai_flags & ~DIE_ON_ERROR; 261 hint.ai_flags = ai_flags & ~DIE_ON_ERROR;
@@ -285,7 +285,8 @@ IF_NOT_FEATURE_IPV6(sa_family_t af = AF_INET;)
285 set_port: 285 set_port:
286 set_nport(r, htons(port)); 286 set_nport(r, htons(port));
287 ret: 287 ret:
288 freeaddrinfo(result); 288 if (result)
289 freeaddrinfo(result);
289 return r; 290 return r;
290} 291}
291#if !ENABLE_FEATURE_IPV6 292#if !ENABLE_FEATURE_IPV6
diff --git a/loginutils/adduser.c b/loginutils/adduser.c
index d938b80f3..0c675caf9 100644
--- a/loginutils/adduser.c
+++ b/loginutils/adduser.c
@@ -67,15 +67,24 @@ static void passwd_study(struct passwd *p)
67 67
68static void addgroup_wrapper(struct passwd *p, const char *group_name) 68static void addgroup_wrapper(struct passwd *p, const char *group_name)
69{ 69{
70 char *cmd; 70 char *argv[5];
71 71
72 if (group_name) /* Add user to existing group */ 72 argv[0] = (char*)"addgroup";
73 cmd = xasprintf("addgroup '%s' '%s'", p->pw_name, group_name); 73 if (group_name) {
74 else /* Add user to his own group with the first free gid found in passwd_study */ 74 /* Add user to existing group */
75 cmd = xasprintf("addgroup -g %u '%s'", (unsigned)p->pw_gid, p->pw_name); 75 argv[1] = p->pw_name;
76 /* Warning: to be compatible with external addgroup programs we should use --gid instead */ 76 argv[2] = (char*)group_name;
77 system(cmd); 77 argv[3] = NULL;
78 free(cmd); 78 } else {
79 /* Add user to his own group with the first free gid found in passwd_study */
80//TODO: to be compatible with external addgroup programs we should use --gid instead...
81 argv[1] = (char*)"-g";
82 argv[2] = utoa(p->pw_gid);
83 argv[3] = p->pw_name;
84 argv[4] = NULL;
85 }
86
87 spawn_and_wait(argv);
79} 88}
80 89
81static void passwd_wrapper(const char *login_name) NORETURN; 90static void passwd_wrapper(const char *login_name) NORETURN;
@@ -123,7 +132,8 @@ int adduser_main(int argc UNUSED_PARAM, char **argv)
123 } 132 }
124 133
125 pw.pw_gecos = (char *)"Linux User,,,"; 134 pw.pw_gecos = (char *)"Linux User,,,";
126 pw.pw_shell = (char *)DEFAULT_SHELL; 135 /* We assume that newly created users "inherit" root's shell setting */
136 pw.pw_shell = (char *)get_shell_name();
127 pw.pw_dir = NULL; 137 pw.pw_dir = NULL;
128 138
129 /* exactly one non-option arg */ 139 /* exactly one non-option arg */
diff --git a/loginutils/getty.c b/loginutils/getty.c
index 3f20c8e81..dfa15b3da 100644
--- a/loginutils/getty.c
+++ b/loginutils/getty.c
@@ -87,7 +87,7 @@ struct globals {
87 const char *login; /* login program */ 87 const char *login; /* login program */
88 const char *fakehost; 88 const char *fakehost;
89 const char *tty; /* name of tty */ 89 const char *tty; /* name of tty */
90 const char *initstring; /* modem init string */ 90 char *initstring; /* modem init string */
91 const char *issue; /* alternative issue file */ 91 const char *issue; /* alternative issue file */
92 int numspeed; /* number of baud rates to try */ 92 int numspeed; /* number of baud rates to try */
93 int speeds[MAX_SPEED]; /* baud rates to be tried */ 93 int speeds[MAX_SPEED]; /* baud rates to be tried */
@@ -176,7 +176,7 @@ static void parse_args(char **argv)
176 if (flags & F_INITSTRING) { 176 if (flags & F_INITSTRING) {
177 G.initstring = xstrdup(G.initstring); 177 G.initstring = xstrdup(G.initstring);
178 /* decode \ddd octal codes into chars */ 178 /* decode \ddd octal codes into chars */
179 strcpy_and_process_escape_sequences((char*)G.initstring, G.initstring); 179 strcpy_and_process_escape_sequences(G.initstring, G.initstring);
180 } 180 }
181 argv += optind; 181 argv += optind;
182 debug("after getopt\n"); 182 debug("after getopt\n");
diff --git a/loginutils/login.c b/loginutils/login.c
index 952b3aadd..ce0d1741f 100644
--- a/loginutils/login.c
+++ b/loginutils/login.c
@@ -198,7 +198,6 @@ int login_main(int argc UNUSED_PARAM, char **argv)
198 }; 198 };
199 char *fromhost; 199 char *fromhost;
200 char username[USERNAME_SIZE]; 200 char username[USERNAME_SIZE];
201 const char *shell;
202 int run_by_root; 201 int run_by_root;
203 unsigned opt; 202 unsigned opt;
204 int count = 0; 203 int count = 0;
@@ -279,6 +278,14 @@ int login_main(int argc UNUSED_PARAM, char **argv)
279 failed_msg = "set_item(TTY)"; 278 failed_msg = "set_item(TTY)";
280 goto pam_auth_failed; 279 goto pam_auth_failed;
281 } 280 }
281 /* set RHOST */
282 if (opt_host) {
283 pamret = pam_set_item(pamh, PAM_RHOST, opt_host);
284 if (pamret != PAM_SUCCESS) {
285 failed_msg = "set_item(RHOST)";
286 goto pam_auth_failed;
287 }
288 }
282 pamret = pam_authenticate(pamh, 0); 289 pamret = pam_authenticate(pamh, 0);
283 if (pamret != PAM_SUCCESS) { 290 if (pamret != PAM_SUCCESS) {
284 failed_msg = "authenticate"; 291 failed_msg = "authenticate";
@@ -356,7 +363,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
356#endif /* ENABLE_PAM */ 363#endif /* ENABLE_PAM */
357 auth_failed: 364 auth_failed:
358 opt &= ~LOGIN_OPT_f; 365 opt &= ~LOGIN_OPT_f;
359 bb_do_delay(FAIL_DELAY); 366 bb_do_delay(LOGIN_FAIL_DELAY);
360 /* TODO: doesn't sound like correct English phrase to me */ 367 /* TODO: doesn't sound like correct English phrase to me */
361 puts("Login incorrect"); 368 puts("Login incorrect");
362 if (++count == 3) { 369 if (++count == 3) {
@@ -391,10 +398,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
391 run_login_script(pw, full_tty); 398 run_login_script(pw, full_tty);
392 399
393 change_identity(pw); 400 change_identity(pw);
394 shell = pw->pw_shell; 401 setup_environment(pw->pw_shell,
395 if (!shell || !shell[0])
396 shell = DEFAULT_SHELL;
397 setup_environment(shell,
398 (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + SETUP_ENV_CHANGEENV, 402 (!(opt & LOGIN_OPT_p) * SETUP_ENV_CLEARENV) + SETUP_ENV_CHANGEENV,
399 pw); 403 pw);
400 404
@@ -442,7 +446,7 @@ int login_main(int argc UNUSED_PARAM, char **argv)
442 signal(SIGINT, SIG_DFL); 446 signal(SIGINT, SIG_DFL);
443 447
444 /* Exec login shell with no additional parameters */ 448 /* Exec login shell with no additional parameters */
445 run_shell(shell, 1, NULL, NULL); 449 run_shell(pw->pw_shell, 1, NULL, NULL);
446 450
447 /* return EXIT_FAILURE; - not reached */ 451 /* return EXIT_FAILURE; - not reached */
448} 452}
diff --git a/loginutils/passwd.c b/loginutils/passwd.c
index 728e61867..f3928cecc 100644
--- a/loginutils/passwd.c
+++ b/loginutils/passwd.c
@@ -28,7 +28,7 @@ static char* new_password(const struct passwd *pw, uid_t myuid, int algo)
28 if (strcmp(encrypted, pw->pw_passwd) != 0) { 28 if (strcmp(encrypted, pw->pw_passwd) != 0) {
29 syslog(LOG_WARNING, "incorrect password for %s", 29 syslog(LOG_WARNING, "incorrect password for %s",
30 pw->pw_name); 30 pw->pw_name);
31 bb_do_delay(FAIL_DELAY); 31 bb_do_delay(LOGIN_FAIL_DELAY);
32 puts("Incorrect password"); 32 puts("Incorrect password");
33 goto err_ret; 33 goto err_ret;
34 } 34 }
diff --git a/loginutils/su.c b/loginutils/su.c
index db303af6d..72dd0f06f 100644
--- a/loginutils/su.c
+++ b/loginutils/su.c
@@ -114,20 +114,14 @@ int su_main(int argc UNUSED_PARAM, char **argv)
114 opt_shell = getenv("SHELL"); 114 opt_shell = getenv("SHELL");
115 } 115 }
116 116
117 /* Make sure pw->pw_shell is non-NULL. It may be NULL when NEW_USER
118 * is a username that is retrieved via NIS (YP), that doesn't have
119 * a default shell listed. */
120 if (!pw->pw_shell || !pw->pw_shell[0])
121 pw->pw_shell = (char *)DEFAULT_SHELL;
122
123#if ENABLE_FEATURE_SU_CHECKS_SHELLS 117#if ENABLE_FEATURE_SU_CHECKS_SHELLS
124 if (opt_shell && cur_uid != 0 && restricted_shell(pw->pw_shell)) { 118 if (opt_shell && cur_uid != 0 && pw->pw_shell && restricted_shell(pw->pw_shell)) {
125 /* The user being su'd to has a nonstandard shell, and so is 119 /* The user being su'd to has a nonstandard shell, and so is
126 * probably a uucp account or has restricted access. Don't 120 * probably a uucp account or has restricted access. Don't
127 * compromise the account by allowing access with a standard 121 * compromise the account by allowing access with a standard
128 * shell. */ 122 * shell. */
129 bb_error_msg("using restricted shell"); 123 bb_error_msg("using restricted shell");
130 opt_shell = NULL; 124 opt_shell = NULL; /* ignore -s PROG */
131 } 125 }
132 /* else: user can run whatever he wants via "su -s PROG USER". 126 /* else: user can run whatever he wants via "su -s PROG USER".
133 * This is safe since PROG is run under user's uid/gid. */ 127 * This is safe since PROG is run under user's uid/gid. */
diff --git a/loginutils/sulogin.c b/loginutils/sulogin.c
index 307536721..0e5b59433 100644
--- a/loginutils/sulogin.c
+++ b/loginutils/sulogin.c
@@ -88,8 +88,8 @@ int sulogin_main(int argc UNUSED_PARAM, char **argv)
88 if (r == 0) { 88 if (r == 0) {
89 break; 89 break;
90 } 90 }
91 bb_do_delay(FAIL_DELAY); 91 bb_do_delay(LOGIN_FAIL_DELAY);
92 bb_error_msg("login incorrect"); 92 bb_info_msg("Login incorrect");
93 } 93 }
94 memset(cp, 0, strlen(cp)); 94 memset(cp, 0, strlen(cp));
95// signal(SIGALRM, SIG_DFL); 95// signal(SIGALRM, SIG_DFL);
diff --git a/loginutils/vlock.c b/loginutils/vlock.c
index 216b317f1..3299afa50 100644
--- a/loginutils/vlock.c
+++ b/loginutils/vlock.c
@@ -93,16 +93,17 @@ int vlock_main(int argc UNUSED_PARAM, char **argv)
93 term.c_lflag &= ~(ECHO | ECHOCTL); 93 term.c_lflag &= ~(ECHO | ECHOCTL);
94 tcsetattr_stdin_TCSANOW(&term); 94 tcsetattr_stdin_TCSANOW(&term);
95 95
96 do { 96 while (1) {
97 printf("Virtual console%s locked by %s.\n", 97 printf("Virtual console%s locked by %s.\n",
98 option_mask32 /*o_lock_all*/ ? "s" : "", 98 /* "s" if -a, else "": */ "s" + !option_mask32,
99 pw->pw_name); 99 pw->pw_name
100 );
100 if (correct_password(pw)) { 101 if (correct_password(pw)) {
101 break; 102 break;
102 } 103 }
103 bb_do_delay(FAIL_DELAY); 104 bb_do_delay(LOGIN_FAIL_DELAY);
104 puts("Password incorrect"); 105 puts("Incorrect password");
105 } while (1); 106 }
106 107
107#ifdef __linux__ 108#ifdef __linux__
108 ioctl(STDIN_FILENO, VT_SETMODE, &ovtm); 109 ioctl(STDIN_FILENO, VT_SETMODE, &ovtm);
diff --git a/miscutils/Config.src b/miscutils/Config.src
index b5866bbd7..61529141d 100644
--- a/miscutils/Config.src
+++ b/miscutils/Config.src
@@ -10,7 +10,7 @@ INSERT
10config ADJTIMEX 10config ADJTIMEX
11 bool "adjtimex" 11 bool "adjtimex"
12 default y 12 default y
13 depends on PLATFORM_LINUX 13 select PLATFORM_LINUX
14 help 14 help
15 Adjtimex reads and optionally sets adjustment parameters for 15 Adjtimex reads and optionally sets adjustment parameters for
16 the Linux clock adjustment algorithm. 16 the Linux clock adjustment algorithm.
@@ -39,7 +39,7 @@ config FEATURE_COMPRESS_BBCONFIG
39config BEEP 39config BEEP
40 bool "beep" 40 bool "beep"
41 default y 41 default y
42 depends on PLATFORM_LINUX 42 select PLATFORM_LINUX
43 help 43 help
44 The beep applets beeps in a given freq/Hz. 44 The beep applets beeps in a given freq/Hz.
45 45
@@ -194,7 +194,7 @@ config FEATURE_DC_LIBM
194config DEVFSD 194config DEVFSD
195 bool "devfsd (obsolete)" 195 bool "devfsd (obsolete)"
196 default n 196 default n
197 depends on PLATFORM_LINUX 197 select PLATFORM_LINUX
198 select FEATURE_SYSLOG 198 select FEATURE_SYSLOG
199 help 199 help
200 This is deprecated and should NOT be used anymore. 200 This is deprecated and should NOT be used anymore.
@@ -238,7 +238,7 @@ config DEVFSD_VERBOSE
238config FEATURE_DEVFS 238config FEATURE_DEVFS
239 bool "Use devfs names for all devices (obsolete)" 239 bool "Use devfs names for all devices (obsolete)"
240 default n 240 default n
241 depends on PLATFORM_LINUX 241 select PLATFORM_LINUX
242 help 242 help
243 This is obsolete and should NOT be used anymore. 243 This is obsolete and should NOT be used anymore.
244 Use linux >= 2.6 (optionally with hotplug) and mdev instead! 244 Use linux >= 2.6 (optionally with hotplug) and mdev instead!
@@ -258,7 +258,7 @@ config DEVMEM
258config EJECT 258config EJECT
259 bool "eject" 259 bool "eject"
260 default y 260 default y
261 depends on PLATFORM_LINUX 261 select PLATFORM_LINUX
262 help 262 help
263 Used to eject cdroms. (defaults to /dev/cdrom) 263 Used to eject cdroms. (defaults to /dev/cdrom)
264 264
@@ -273,7 +273,7 @@ config FEATURE_EJECT_SCSI
273config FBSPLASH 273config FBSPLASH
274 bool "fbsplash" 274 bool "fbsplash"
275 default y 275 default y
276 depends on PLATFORM_LINUX 276 select PLATFORM_LINUX
277 help 277 help
278 Shows splash image and progress bar on framebuffer device. 278 Shows splash image and progress bar on framebuffer device.
279 Can be used during boot phase of an embedded device. ~2kb. 279 Can be used during boot phase of an embedded device. ~2kb.
@@ -323,7 +323,7 @@ config FLASH_ERASEALL
323config IONICE 323config IONICE
324 bool "ionice" 324 bool "ionice"
325 default y 325 default y
326 depends on PLATFORM_LINUX 326 select PLATFORM_LINUX
327 help 327 help
328 Set/set program io scheduling class and priority 328 Set/set program io scheduling class and priority
329 Requires kernel >= 2.6.13 329 Requires kernel >= 2.6.13
@@ -429,7 +429,7 @@ config FEATURE_LESS_LINENUMS
429config HDPARM 429config HDPARM
430 bool "hdparm" 430 bool "hdparm"
431 default y 431 default y
432 depends on PLATFORM_LINUX 432 select PLATFORM_LINUX
433 help 433 help
434 Get/Set hard drive parameters. Primarily intended for ATA 434 Get/Set hard drive parameters. Primarily intended for ATA
435 drives. Adds about 13k (or around 30k if you enable the 435 drives. Adds about 13k (or around 30k if you enable the
@@ -546,7 +546,7 @@ config MT
546config RAIDAUTORUN 546config RAIDAUTORUN
547 bool "raidautorun" 547 bool "raidautorun"
548 default y 548 default y
549 depends on PLATFORM_LINUX 549 select PLATFORM_LINUX
550 help 550 help
551 raidautorun tells the kernel md driver to 551 raidautorun tells the kernel md driver to
552 search and start RAID arrays. 552 search and start RAID arrays.
@@ -554,7 +554,8 @@ config RAIDAUTORUN
554config READAHEAD 554config READAHEAD
555 bool "readahead" 555 bool "readahead"
556 default y 556 default y
557 depends on LFS && PLATFORM_LINUX 557 depends on LFS
558 select PLATFORM_LINUX
558 help 559 help
559 Preload the files listed on the command line into RAM cache so that 560 Preload the files listed on the command line into RAM cache so that
560 subsequent reads on these files will not block on disk I/O. 561 subsequent reads on these files will not block on disk I/O.
@@ -571,7 +572,7 @@ config READAHEAD
571config RFKILL 572config RFKILL
572 bool "rfkill" 573 bool "rfkill"
573 default n # doesn't build on Ubuntu 9.04 574 default n # doesn't build on Ubuntu 9.04
574 depends on PLATFORM_LINUX 575 select PLATFORM_LINUX
575 help 576 help
576 Enable/disable wireless devices. 577 Enable/disable wireless devices.
577 578
@@ -593,7 +594,7 @@ config RUNLEVEL
593config RX 594config RX
594 bool "rx" 595 bool "rx"
595 default y 596 default y
596 depends on PLATFORM_LINUX 597 select PLATFORM_LINUX
597 help 598 help
598 Receive files using the Xmodem protocol. 599 Receive files using the Xmodem protocol.
599 600
@@ -666,7 +667,7 @@ config WALL
666config WATCHDOG 667config WATCHDOG
667 bool "watchdog" 668 bool "watchdog"
668 default y 669 default y
669 depends on PLATFORM_LINUX 670 select PLATFORM_LINUX
670 help 671 help
671 The watchdog utility is used with hardware or software watchdog 672 The watchdog utility is used with hardware or software watchdog
672 device drivers. It opens the specified watchdog device special file 673 device drivers. It opens the specified watchdog device special file
diff --git a/miscutils/conspy.c b/miscutils/conspy.c
index 721eb6d59..9c5405332 100644
--- a/miscutils/conspy.c
+++ b/miscutils/conspy.c
@@ -17,7 +17,7 @@
17//config:config CONSPY 17//config:config CONSPY
18//config: bool "conspy" 18//config: bool "conspy"
19//config: default n 19//config: default n
20//config: depends on PLATFORM_LINUX 20//config: select PLATFORM_LINUX
21//config: help 21//config: help
22//config: A text-mode VNC like program for Linux virtual terminals. 22//config: A text-mode VNC like program for Linux virtual terminals.
23//config: example: conspy NUM shared access to console num 23//config: example: conspy NUM shared access to console num
@@ -316,10 +316,8 @@ static NOINLINE void start_shell_in_child(const char* tty_name)
316 int pid = xvfork(); 316 int pid = xvfork();
317 if (pid == 0) { 317 if (pid == 0) {
318 struct termios termchild; 318 struct termios termchild;
319 char *shell = getenv("SHELL"); 319 const char *shell = get_shell_name();
320 320
321 if (!shell)
322 shell = (char *) DEFAULT_SHELL;
323 signal(SIGHUP, SIG_IGN); 321 signal(SIGHUP, SIG_IGN);
324 // set tty as a controlling tty 322 // set tty as a controlling tty
325 setsid(); 323 setsid();
diff --git a/miscutils/crontab.c b/miscutils/crontab.c
index 163e15dce..16d7fdf69 100644
--- a/miscutils/crontab.c
+++ b/miscutils/crontab.c
@@ -20,8 +20,9 @@
20static void edit_file(const struct passwd *pas, const char *file) 20static void edit_file(const struct passwd *pas, const char *file)
21{ 21{
22 const char *ptr; 22 const char *ptr;
23 int pid = xvfork(); 23 pid_t pid;
24 24
25 pid = xvfork();
25 if (pid) { /* parent */ 26 if (pid) { /* parent */
26 wait4pid(pid); 27 wait4pid(pid);
27 return; 28 return;
@@ -30,7 +31,7 @@ static void edit_file(const struct passwd *pas, const char *file)
30 /* CHILD - change user and run editor */ 31 /* CHILD - change user and run editor */
31 /* initgroups, setgid, setuid */ 32 /* initgroups, setgid, setuid */
32 change_identity(pas); 33 change_identity(pas);
33 setup_environment(DEFAULT_SHELL, 34 setup_environment(pas->pw_shell,
34 SETUP_ENV_CHANGEENV | SETUP_ENV_TO_TMP, 35 SETUP_ENV_CHANGEENV | SETUP_ENV_TO_TMP,
35 pas); 36 pas);
36 ptr = getenv("VISUAL"); 37 ptr = getenv("VISUAL");
@@ -41,7 +42,7 @@ static void edit_file(const struct passwd *pas, const char *file)
41 } 42 }
42 43
43 BB_EXECLP(ptr, ptr, file, NULL); 44 BB_EXECLP(ptr, ptr, file, NULL);
44 bb_perror_msg_and_die("exec %s", ptr); 45 bb_perror_msg_and_die("can't execute '%s'", ptr);
45} 46}
46 47
47static int open_as_user(const struct passwd *pas, const char *file) 48static int open_as_user(const struct passwd *pas, const char *file)
diff --git a/miscutils/nandwrite.c b/miscutils/nandwrite.c
index c5e2fb841..c7fbe7d9c 100644
--- a/miscutils/nandwrite.c
+++ b/miscutils/nandwrite.c
@@ -17,14 +17,14 @@
17//config:config NANDWRITE 17//config:config NANDWRITE
18//config: bool "nandwrite" 18//config: bool "nandwrite"
19//config: default n 19//config: default n
20//config: depends on PLATFORM_LINUX 20//config: select PLATFORM_LINUX
21//config: help 21//config: help
22//config: Write to the specified MTD device, with bad blocks awareness 22//config: Write to the specified MTD device, with bad blocks awareness
23//config: 23//config:
24//config:config NANDDUMP 24//config:config NANDDUMP
25//config: bool "nanddump" 25//config: bool "nanddump"
26//config: default n 26//config: default n
27//config: depends on PLATFORM_LINUX 27//config: select PLATFORM_LINUX
28//config: help 28//config: help
29//config: Dump the content of raw NAND chip 29//config: Dump the content of raw NAND chip
30 30
diff --git a/miscutils/ubi_attach_detach.c b/miscutils/ubi_attach_detach.c
index fef9250ee..9007f8c3f 100644
--- a/miscutils/ubi_attach_detach.c
+++ b/miscutils/ubi_attach_detach.c
@@ -6,35 +6,35 @@
6//config:config UBIATTACH 6//config:config UBIATTACH
7//config: bool "ubiattach" 7//config: bool "ubiattach"
8//config: default y 8//config: default y
9//config: depends on PLATFORM_LINUX 9//config: select PLATFORM_LINUX
10//config: help 10//config: help
11//config: Attach MTD device to an UBI device. 11//config: Attach MTD device to an UBI device.
12//config: 12//config:
13//config:config UBIDETACH 13//config:config UBIDETACH
14//config: bool "ubidetach" 14//config: bool "ubidetach"
15//config: default y 15//config: default y
16//config: depends on PLATFORM_LINUX 16//config: select PLATFORM_LINUX
17//config: help 17//config: help
18//config: Detach MTD device from an UBI device. 18//config: Detach MTD device from an UBI device.
19//config: 19//config:
20//config:config UBIMKVOL 20//config:config UBIMKVOL
21//config: bool "ubimkvol" 21//config: bool "ubimkvol"
22//config: default y 22//config: default y
23//config: depends on PLATFORM_LINUX 23//config: select PLATFORM_LINUX
24//config: help 24//config: help
25//config: Create a UBI volume. 25//config: Create a UBI volume.
26//config: 26//config:
27//config:config UBIRMVOL 27//config:config UBIRMVOL
28//config: bool "ubirmvol" 28//config: bool "ubirmvol"
29//config: default y 29//config: default y
30//config: depends on PLATFORM_LINUX 30//config: select PLATFORM_LINUX
31//config: help 31//config: help
32//config: Delete a UBI volume. 32//config: Delete a UBI volume.
33//config: 33//config:
34//config:config UBIRSVOL 34//config:config UBIRSVOL
35//config: bool "ubirsvol" 35//config: bool "ubirsvol"
36//config: default y 36//config: default y
37//config: depends on PLATFORM_LINUX 37//config: select PLATFORM_LINUX
38//config: help 38//config: help
39//config: Resize a UBI volume. 39//config: Resize a UBI volume.
40 40
diff --git a/modutils/Config.src b/modutils/Config.src
index 4191d29f2..449ac65af 100644
--- a/modutils/Config.src
+++ b/modutils/Config.src
@@ -4,13 +4,13 @@
4# 4#
5 5
6menu "Linux Module Utilities" 6menu "Linux Module Utilities"
7depends on PLATFORM_LINUX
8 7
9INSERT 8INSERT
10 9
11config MODPROBE_SMALL 10config MODPROBE_SMALL
12 bool "Simplified modutils" 11 bool "Simplified modutils"
13 default y 12 default y
13 select PLATFORM_LINUX
14 help 14 help
15 Simplified modutils. 15 Simplified modutils.
16 16
@@ -45,6 +45,7 @@ config FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE
45 bool "Accept module options on modprobe command line" 45 bool "Accept module options on modprobe command line"
46 default y 46 default y
47 depends on MODPROBE_SMALL 47 depends on MODPROBE_SMALL
48 select PLATFORM_LINUX
48 help 49 help
49 Allow insmod and modprobe take module options from command line. 50 Allow insmod and modprobe take module options from command line.
50 51
@@ -59,6 +60,7 @@ config INSMOD
59 bool "insmod" 60 bool "insmod"
60 default n 61 default n
61 depends on !MODPROBE_SMALL 62 depends on !MODPROBE_SMALL
63 select PLATFORM_LINUX
62 help 64 help
63 insmod is used to load specified modules in the running kernel. 65 insmod is used to load specified modules in the running kernel.
64 66
@@ -66,6 +68,7 @@ config RMMOD
66 bool "rmmod" 68 bool "rmmod"
67 default n 69 default n
68 depends on !MODPROBE_SMALL 70 depends on !MODPROBE_SMALL
71 select PLATFORM_LINUX
69 help 72 help
70 rmmod is used to unload specified modules from the kernel. 73 rmmod is used to unload specified modules from the kernel.
71 74
@@ -73,6 +76,7 @@ config LSMOD
73 bool "lsmod" 76 bool "lsmod"
74 default n 77 default n
75 depends on !MODPROBE_SMALL 78 depends on !MODPROBE_SMALL
79 select PLATFORM_LINUX
76 help 80 help
77 lsmod is used to display a list of loaded modules. 81 lsmod is used to display a list of loaded modules.
78 82
@@ -80,6 +84,7 @@ config FEATURE_LSMOD_PRETTY_2_6_OUTPUT
80 bool "Pretty output" 84 bool "Pretty output"
81 default n 85 default n
82 depends on LSMOD 86 depends on LSMOD
87 select PLATFORM_LINUX
83 help 88 help
84 This option makes output format of lsmod adjusted to 89 This option makes output format of lsmod adjusted to
85 the format of module-init-tools for Linux kernel 2.6. 90 the format of module-init-tools for Linux kernel 2.6.
@@ -89,6 +94,7 @@ config MODPROBE
89 bool "modprobe" 94 bool "modprobe"
90 default n 95 default n
91 depends on !MODPROBE_SMALL 96 depends on !MODPROBE_SMALL
97 select PLATFORM_LINUX
92 help 98 help
93 Handle the loading of modules, and their dependencies on a high 99 Handle the loading of modules, and their dependencies on a high
94 level. 100 level.
@@ -97,6 +103,7 @@ config FEATURE_MODPROBE_BLACKLIST
97 bool "Blacklist support" 103 bool "Blacklist support"
98 default n 104 default n
99 depends on MODPROBE 105 depends on MODPROBE
106 select PLATFORM_LINUX
100 help 107 help
101 Say 'y' here to enable support for the 'blacklist' command in 108 Say 'y' here to enable support for the 'blacklist' command in
102 modprobe.conf. This prevents the alias resolver to resolve 109 modprobe.conf. This prevents the alias resolver to resolve
@@ -108,6 +115,7 @@ config DEPMOD
108 bool "depmod" 115 bool "depmod"
109 default n 116 default n
110 depends on !MODPROBE_SMALL 117 depends on !MODPROBE_SMALL
118 select PLATFORM_LINUX
111 help 119 help
112 depmod generates modules.dep (and potentially modules.alias 120 depmod generates modules.dep (and potentially modules.alias
113 and modules.symbols) that contain dependency information 121 and modules.symbols) that contain dependency information
@@ -119,6 +127,7 @@ config FEATURE_2_4_MODULES
119 bool "Support version 2.2/2.4 Linux kernels" 127 bool "Support version 2.2/2.4 Linux kernels"
120 default n 128 default n
121 depends on INSMOD || RMMOD || LSMOD 129 depends on INSMOD || RMMOD || LSMOD
130 select PLATFORM_LINUX
122 help 131 help
123 Support module loading for 2.2.x and 2.4.x Linux kernels. 132 Support module loading for 2.2.x and 2.4.x Linux kernels.
124 This increases size considerably. Say N unless you plan 133 This increases size considerably. Say N unless you plan
@@ -128,6 +137,7 @@ config FEATURE_INSMOD_TRY_MMAP
128 bool "Try to load module from a mmap'ed area" 137 bool "Try to load module from a mmap'ed area"
129 default n 138 default n
130 depends on INSMOD || MODPROBE_SMALL 139 depends on INSMOD || MODPROBE_SMALL
140 select PLATFORM_LINUX
131 help 141 help
132 This option causes module loading code to try to mmap 142 This option causes module loading code to try to mmap
133 module first. If it does not work (for example, 143 module first. If it does not work (for example,
@@ -144,6 +154,7 @@ config FEATURE_INSMOD_VERSION_CHECKING
144 bool "Enable module version checking" 154 bool "Enable module version checking"
145 default n 155 default n
146 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) 156 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
157 select PLATFORM_LINUX
147 help 158 help
148 Support checking of versions for modules. This is used to 159 Support checking of versions for modules. This is used to
149 ensure that the kernel and module are made for each other. 160 ensure that the kernel and module are made for each other.
@@ -152,6 +163,7 @@ config FEATURE_INSMOD_KSYMOOPS_SYMBOLS
152 bool "Add module symbols to kernel symbol table" 163 bool "Add module symbols to kernel symbol table"
153 default n 164 default n
154 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) 165 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
166 select PLATFORM_LINUX
155 help 167 help
156 By adding module symbols to the kernel symbol table, Oops messages 168 By adding module symbols to the kernel symbol table, Oops messages
157 occuring within kernel modules can be properly debugged. By enabling 169 occuring within kernel modules can be properly debugged. By enabling
@@ -163,6 +175,7 @@ config FEATURE_INSMOD_LOADINKMEM
163 bool "In kernel memory optimization (uClinux only)" 175 bool "In kernel memory optimization (uClinux only)"
164 default n 176 default n
165 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE) 177 depends on FEATURE_2_4_MODULES && (INSMOD || MODPROBE)
178 select PLATFORM_LINUX
166 help 179 help
167 This is a special uClinux only memory optimization that lets insmod 180 This is a special uClinux only memory optimization that lets insmod
168 load the specified kernel module directly into kernel space, reducing 181 load the specified kernel module directly into kernel space, reducing
@@ -173,6 +186,7 @@ config FEATURE_INSMOD_LOAD_MAP
173 bool "Enable insmod load map (-m) option" 186 bool "Enable insmod load map (-m) option"
174 default n 187 default n
175 depends on FEATURE_2_4_MODULES && INSMOD 188 depends on FEATURE_2_4_MODULES && INSMOD
189 select PLATFORM_LINUX
176 help 190 help
177 Enabling this, one would be able to get a load map 191 Enabling this, one would be able to get a load map
178 output on stdout. This makes kernel module debugging 192 output on stdout. This makes kernel module debugging
@@ -184,6 +198,7 @@ config FEATURE_INSMOD_LOAD_MAP_FULL
184 bool "Symbols in load map" 198 bool "Symbols in load map"
185 default y 199 default y
186 depends on FEATURE_INSMOD_LOAD_MAP && !MODPROBE_SMALL 200 depends on FEATURE_INSMOD_LOAD_MAP && !MODPROBE_SMALL
201 select PLATFORM_LINUX
187 help 202 help
188 Without this option, -m will only output section 203 Without this option, -m will only output section
189 load map. With this option, -m will also output 204 load map. With this option, -m will also output
@@ -193,6 +208,7 @@ config FEATURE_CHECK_TAINTED_MODULE
193 bool "Support tainted module checking with new kernels" 208 bool "Support tainted module checking with new kernels"
194 default y 209 default y
195 depends on (LSMOD || FEATURE_2_4_MODULES) && !MODPROBE_SMALL 210 depends on (LSMOD || FEATURE_2_4_MODULES) && !MODPROBE_SMALL
211 select PLATFORM_LINUX
196 help 212 help
197 Support checking for tainted modules. These are usually binary 213 Support checking for tainted modules. These are usually binary
198 only modules that will make the linux-kernel list ignore your 214 only modules that will make the linux-kernel list ignore your
@@ -203,6 +219,7 @@ config FEATURE_MODUTILS_ALIAS
203 bool "Support for module.aliases file" 219 bool "Support for module.aliases file"
204 default y 220 default y
205 depends on DEPMOD || MODPROBE 221 depends on DEPMOD || MODPROBE
222 select PLATFORM_LINUX
206 help 223 help
207 Generate and parse modules.alias containing aliases for bus 224 Generate and parse modules.alias containing aliases for bus
208 identifiers: 225 identifiers:
@@ -219,6 +236,7 @@ config FEATURE_MODUTILS_SYMBOLS
219 bool "Support for module.symbols file" 236 bool "Support for module.symbols file"
220 default y 237 default y
221 depends on DEPMOD || MODPROBE 238 depends on DEPMOD || MODPROBE
239 select PLATFORM_LINUX
222 help 240 help
223 Generate and parse modules.symbols containing aliases for 241 Generate and parse modules.symbols containing aliases for
224 symbol_request() kernel calls, such as: 242 symbol_request() kernel calls, such as:
diff --git a/networking/Config.src b/networking/Config.src
index 274fcae3a..8aeba0ef9 100644
--- a/networking/Config.src
+++ b/networking/Config.src
@@ -51,21 +51,21 @@ config VERBOSE_RESOLUTION_ERRORS
51config ARP 51config ARP
52 bool "arp" 52 bool "arp"
53 default y 53 default y
54 depends on PLATFORM_LINUX 54 select PLATFORM_LINUX
55 help 55 help
56 Manipulate the system ARP cache. 56 Manipulate the system ARP cache.
57 57
58config ARPING 58config ARPING
59 bool "arping" 59 bool "arping"
60 default y 60 default y
61 depends on PLATFORM_LINUX 61 select PLATFORM_LINUX
62 help 62 help
63 Ping hosts by ARP packets. 63 Ping hosts by ARP packets.
64 64
65config BRCTL 65config BRCTL
66 bool "brctl" 66 bool "brctl"
67 default y 67 default y
68 depends on PLATFORM_LINUX 68 select PLATFORM_LINUX
69 help 69 help
70 Manage ethernet bridges. 70 Manage ethernet bridges.
71 Supports addbr/delbr and addif/delif. 71 Supports addbr/delbr and addif/delif.
@@ -98,7 +98,7 @@ config DNSD
98config ETHER_WAKE 98config ETHER_WAKE
99 bool "ether-wake" 99 bool "ether-wake"
100 default y 100 default y
101 depends on PLATFORM_LINUX 101 select PLATFORM_LINUX
102 help 102 help
103 Send a magic packet to wake up sleeping machines. 103 Send a magic packet to wake up sleeping machines.
104 104
@@ -281,7 +281,7 @@ config FEATURE_HTTPD_GZIP
281config IFCONFIG 281config IFCONFIG
282 bool "ifconfig" 282 bool "ifconfig"
283 default y 283 default y
284 depends on PLATFORM_LINUX 284 select PLATFORM_LINUX
285 help 285 help
286 Ifconfig is used to configure the kernel-resident network interfaces. 286 Ifconfig is used to configure the kernel-resident network interfaces.
287 287
@@ -329,7 +329,7 @@ config FEATURE_IFCONFIG_BROADCAST_PLUS
329config IFENSLAVE 329config IFENSLAVE
330 bool "ifenslave" 330 bool "ifenslave"
331 default y 331 default y
332 depends on PLATFORM_LINUX 332 select PLATFORM_LINUX
333 help 333 help
334 Userspace application to bind several interfaces 334 Userspace application to bind several interfaces
335 to a logical interface (use with kernel bonding driver). 335 to a logical interface (use with kernel bonding driver).
@@ -337,7 +337,7 @@ config IFENSLAVE
337config IFPLUGD 337config IFPLUGD
338 bool "ifplugd" 338 bool "ifplugd"
339 default y 339 default y
340 depends on PLATFORM_LINUX 340 select PLATFORM_LINUX
341 help 341 help
342 Network interface plug detection daemon. 342 Network interface plug detection daemon.
343 343
@@ -379,7 +379,8 @@ config FEATURE_IFUPDOWN_IP
379config FEATURE_IFUPDOWN_IP_BUILTIN 379config FEATURE_IFUPDOWN_IP_BUILTIN
380 bool "Use busybox ip applet" 380 bool "Use busybox ip applet"
381 default y 381 default y
382 depends on FEATURE_IFUPDOWN_IP && PLATFORM_LINUX 382 depends on FEATURE_IFUPDOWN_IP
383 select PLATFORM_LINUX
383 select IP 384 select IP
384 select FEATURE_IP_ADDRESS 385 select FEATURE_IP_ADDRESS
385 select FEATURE_IP_LINK 386 select FEATURE_IP_LINK
@@ -498,7 +499,7 @@ config FEATURE_INETD_RPC
498config IP 499config IP
499 bool "ip" 500 bool "ip"
500 default y 501 default y
501 depends on PLATFORM_LINUX 502 select PLATFORM_LINUX
502 help 503 help
503 The "ip" applet is a TCP/IP interface configuration and routing 504 The "ip" applet is a TCP/IP interface configuration and routing
504 utility. You generally don't need "ip" to use busybox with 505 utility. You generally don't need "ip" to use busybox with
@@ -611,39 +612,10 @@ config FEATURE_IPCALC_LONG_OPTIONS
611 help 612 help
612 Support long options for the ipcalc applet. 613 Support long options for the ipcalc applet.
613 614
614config NAMEIF
615 bool "nameif"
616 default y
617 depends on PLATFORM_LINUX
618 select FEATURE_SYSLOG
619 help
620 nameif is used to rename network interface by its MAC address.
621 Renamed interfaces MUST be in the down state.
622 It is possible to use a file (default: /etc/mactab)
623 with list of new interface names and MACs.
624 Maximum interface name length: IFNAMSIZ = 16
625 File fields are separated by space or tab.
626 File format:
627 # Comment
628 new_interface_name XX:XX:XX:XX:XX:XX
629
630config FEATURE_NAMEIF_EXTENDED
631 bool "Extended nameif"
632 default y
633 depends on NAMEIF
634 help
635 This extends the nameif syntax to support the bus_info and driver
636 checks. The syntax is compatible to the normal nameif.
637 File format:
638 new_interface_name driver=asix bus=usb-0000:00:08.2-3
639 new_interface_name bus=usb-0000:00:08.2-3 00:80:C8:38:91:B5
640 new_interface_name mac=00:80:C8:38:91:B5
641 new_interface_name 00:80:C8:38:91:B5
642
643config NETSTAT 615config NETSTAT
644 bool "netstat" 616 bool "netstat"
645 default y 617 default y
646 depends on PLATFORM_LINUX 618 select PLATFORM_LINUX
647 help 619 help
648 netstat prints information about the Linux networking subsystem. 620 netstat prints information about the Linux networking subsystem.
649 621
@@ -672,7 +644,7 @@ config NSLOOKUP
672config NTPD 644config NTPD
673 bool "ntpd" 645 bool "ntpd"
674 default y 646 default y
675 depends on PLATFORM_LINUX 647 select PLATFORM_LINUX
676 help 648 help
677 The NTP client/server daemon. 649 The NTP client/server daemon.
678 650
@@ -693,14 +665,14 @@ config PSCAN
693config ROUTE 665config ROUTE
694 bool "route" 666 bool "route"
695 default y 667 default y
696 depends on PLATFORM_LINUX 668 select PLATFORM_LINUX
697 help 669 help
698 Route displays or manipulates the kernel's IP routing tables. 670 Route displays or manipulates the kernel's IP routing tables.
699 671
700config SLATTACH 672config SLATTACH
701 bool "slattach" 673 bool "slattach"
702 default y 674 default y
703 depends on PLATFORM_LINUX 675 select PLATFORM_LINUX
704 help 676 help
705 slattach is a small utility to attach network interfaces to serial 677 slattach is a small utility to attach network interfaces to serial
706 lines. 678 lines.
@@ -887,7 +859,7 @@ config TFTP_DEBUG
887config TRACEROUTE 859config TRACEROUTE
888 bool "traceroute" 860 bool "traceroute"
889 default y 861 default y
890 depends on PLATFORM_LINUX 862 select PLATFORM_LINUX
891 help 863 help
892 Utility to trace the route of IP packets. 864 Utility to trace the route of IP packets.
893 865
@@ -924,7 +896,7 @@ config FEATURE_TRACEROUTE_USE_ICMP
924config TUNCTL 896config TUNCTL
925 bool "tunctl" 897 bool "tunctl"
926 default y 898 default y
927 depends on PLATFORM_LINUX 899 select PLATFORM_LINUX
928 help 900 help
929 tunctl creates or deletes tun devices. 901 tunctl creates or deletes tun devices.
930 902
@@ -957,7 +929,7 @@ config UDPSVD
957config VCONFIG 929config VCONFIG
958 bool "vconfig" 930 bool "vconfig"
959 default y 931 default y
960 depends on PLATFORM_LINUX 932 select PLATFORM_LINUX
961 help 933 help
962 Creates, removes, and configures VLAN interfaces 934 Creates, removes, and configures VLAN interfaces
963 935
@@ -1004,7 +976,7 @@ config FEATURE_WGET_TIMEOUT
1004config ZCIP 976config ZCIP
1005 bool "zcip" 977 bool "zcip"
1006 default y 978 default y
1007 depends on PLATFORM_LINUX 979 select PLATFORM_LINUX
1008 select FEATURE_SYSLOG 980 select FEATURE_SYSLOG
1009 help 981 help
1010 ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927. 982 ZCIP provides ZeroConf IPv4 address selection, according to RFC 3927.
diff --git a/networking/ftpd.c b/networking/ftpd.c
index 64068e467..b59135667 100644
--- a/networking/ftpd.c
+++ b/networking/ftpd.c
@@ -12,6 +12,23 @@
12 * You have to run this daemon via inetd. 12 * You have to run this daemon via inetd.
13 */ 13 */
14 14
15//usage:#define ftpd_trivial_usage
16//usage: "[-wvS] [-t N] [-T N] [DIR]"
17//usage:#define ftpd_full_usage "\n\n"
18//usage: "Anonymous FTP server\n"
19//usage: "\n"
20//usage: "ftpd should be used as an inetd service.\n"
21//usage: "ftpd's line for inetd.conf:\n"
22//usage: " 21 stream tcp nowait root ftpd ftpd /files/to/serve\n"
23//usage: "It also can be ran from tcpsvd:\n"
24//usage: " tcpsvd -vE 0.0.0.0 21 ftpd /files/to/serve\n"
25//usage: "\nOptions:"
26//usage: "\n -w Allow upload"
27//usage: "\n -v Log errors to stderr. -vv: verbose log"
28//usage: "\n -S Log errors to syslog. -SS: verbose log"
29//usage: "\n -t,-T Idle and absolute timeouts"
30//usage: "\n DIR Change root to this directory"
31
15#include "libbb.h" 32#include "libbb.h"
16#include <syslog.h> 33#include <syslog.h>
17#include <netinet/tcp.h> 34#include <netinet/tcp.h>
@@ -206,7 +223,7 @@ cmdio_write_error(unsigned status)
206{ 223{
207 *(uint32_t *) G.msg_err = status; 224 *(uint32_t *) G.msg_err = status;
208 xwrite(STDOUT_FILENO, G.msg_err, sizeof("NNN " MSG_ERR) - 1); 225 xwrite(STDOUT_FILENO, G.msg_err, sizeof("NNN " MSG_ERR) - 1);
209 if (G.verbose > 1) 226 if (G.verbose > 0)
210 verbose_log(G.msg_err); 227 verbose_log(G.msg_err);
211} 228}
212#define WRITE_ERR(a) cmdio_write_error(STRNUM32sp(a)) 229#define WRITE_ERR(a) cmdio_write_error(STRNUM32sp(a))
diff --git a/networking/ifupdown.c b/networking/ifupdown.c
index 59df4e80f..7706a84b7 100644
--- a/networking/ifupdown.c
+++ b/networking/ifupdown.c
@@ -106,6 +106,7 @@ enum {
106struct globals { 106struct globals {
107 char **my_environ; 107 char **my_environ;
108 const char *startup_PATH; 108 const char *startup_PATH;
109 char *shell;
109} FIX_ALIASING; 110} FIX_ALIASING;
110#define G (*(struct globals*)&bb_common_bufsiz1) 111#define G (*(struct globals*)&bb_common_bufsiz1)
111#define INIT_G() do { } while (0) 112#define INIT_G() do { } while (0)
@@ -986,11 +987,10 @@ static int doit(char *str)
986 987
987 fflush_all(); 988 fflush_all();
988 child = vfork(); 989 child = vfork();
989 switch (child) { 990 if (child < 0) /* failure */
990 case -1: /* failure */
991 return 0; 991 return 0;
992 case 0: /* child */ 992 if (child == 0) { /* child */
993 execle(DEFAULT_SHELL, DEFAULT_SHELL, "-c", str, (char *) NULL, G.my_environ); 993 execle(G.shell, G.shell, "-c", str, (char *) NULL, G.my_environ);
994 _exit(127); 994 _exit(127);
995 } 995 }
996 safe_waitpid(child, &status, 0); 996 safe_waitpid(child, &status, 0);
@@ -1165,6 +1165,7 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv)
1165 INIT_G(); 1165 INIT_G();
1166 1166
1167 G.startup_PATH = getenv("PATH"); 1167 G.startup_PATH = getenv("PATH");
1168 G.shell = xstrdup(get_shell_name());
1168 1169
1169 cmds = iface_down; 1170 cmds = iface_down;
1170 if (applet_name[2] == 'u') { 1171 if (applet_name[2] == 'u') {
@@ -1220,13 +1221,13 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv)
1220 /* ifup */ 1221 /* ifup */
1221 if (iface_state) { 1222 if (iface_state) {
1222 bb_error_msg("interface %s already configured", iface); 1223 bb_error_msg("interface %s already configured", iface);
1223 continue; 1224 goto next;
1224 } 1225 }
1225 } else { 1226 } else {
1226 /* ifdown */ 1227 /* ifdown */
1227 if (!iface_state) { 1228 if (!iface_state) {
1228 bb_error_msg("interface %s not configured", iface); 1229 bb_error_msg("interface %s not configured", iface);
1229 continue; 1230 goto next;
1230 } 1231 }
1231 } 1232 }
1232 llist_free(state_list, free); 1233 llist_free(state_list, free);
@@ -1316,6 +1317,9 @@ int ifupdown_main(int argc UNUSED_PARAM, char **argv)
1316 fclose(state_fp); 1317 fclose(state_fp);
1317 llist_free(state_list, free); 1318 llist_free(state_list, free);
1318 } 1319 }
1320 next:
1321 free(iface);
1322 free(liface);
1319 } 1323 }
1320 1324
1321 return any_failures; 1325 return any_failures;
diff --git a/networking/nameif.c b/networking/nameif.c
index d02c2c11b..78719edac 100644
--- a/networking/nameif.c
+++ b/networking/nameif.c
@@ -10,6 +10,66 @@
10 * Licensed under GPLv2 or later, see file LICENSE in this source tree. 10 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
11 */ 11 */
12 12
13//config:config NAMEIF
14//config: bool "nameif"
15//config: default y
16//config: select PLATFORM_LINUX
17//config: select FEATURE_SYSLOG
18//config: help
19//config: nameif is used to rename network interface by its MAC address.
20//config: Renamed interfaces MUST be in the down state.
21//config: It is possible to use a file (default: /etc/mactab)
22//config: with list of new interface names and MACs.
23//config: Maximum interface name length: IFNAMSIZ = 16
24//config: File fields are separated by space or tab.
25//config: File format:
26//config: # Comment
27//config: new_interface_name XX:XX:XX:XX:XX:XX
28//config:
29//config:config FEATURE_NAMEIF_EXTENDED
30//config: bool "Extended nameif"
31//config: default y
32//config: depends on NAMEIF
33//config: help
34//config: This extends the nameif syntax to support the bus_info, driver,
35//config: phyaddr selectors. The syntax is compatible to the normal nameif.
36//config: File format:
37//config: new_interface_name driver=asix bus=usb-0000:00:08.2-3
38//config: new_interface_name bus=usb-0000:00:08.2-3 00:80:C8:38:91:B5
39//config: new_interface_name phy_address=2 00:80:C8:38:91:B5
40//config: new_interface_name mac=00:80:C8:38:91:B5
41//config: new_interface_name 00:80:C8:38:91:B5
42
43//usage:#define nameif_trivial_usage
44//usage: IF_NOT_FEATURE_NAMEIF_EXTENDED(
45//usage: "[-s] [-c FILE] [IFNAME HWADDR]..."
46//usage: )
47//usage: IF_FEATURE_NAMEIF_EXTENDED(
48//usage: "[-s] [-c FILE] [IFNAME SELECTOR]..."
49//usage: )
50//usage:#define nameif_full_usage "\n\n"
51//usage: "Rename network interface while it in the down state."
52//usage: IF_NOT_FEATURE_NAMEIF_EXTENDED(
53//usage: "\nThe device with address HWADDR is renamed to IFACE."
54//usage: )
55//usage: IF_FEATURE_NAMEIF_EXTENDED(
56//usage: "\nThe device matched by SELECTOR is renamed to IFACE."
57//usage: "\nSELECTOR can be a combination of:"
58//usage: "\n driver=STRING"
59//usage: "\n bus=STRING"
60//usage: "\n phy_address=NUM"
61//usage: "\n [mac=]XX:XX:XX:XX:XX:XX"
62//usage: )
63//usage: "\n"
64//usage: "\nOptions:"
65//usage: "\n -c FILE Configuration file (default: /etc/mactab)"
66//usage: "\n -s Log to syslog"
67//usage:
68//usage:#define nameif_example_usage
69//usage: "$ nameif -s dmz0 00:A0:C9:8C:F6:3F\n"
70//usage: " or\n"
71//usage: "$ nameif -c /etc/my_mactab_file\n"
72
13#include "libbb.h" 73#include "libbb.h"
14#include <syslog.h> 74#include <syslog.h>
15#include <net/if.h> 75#include <net/if.h>
@@ -38,6 +98,7 @@ typedef struct ethtable_s {
38#if ENABLE_FEATURE_NAMEIF_EXTENDED 98#if ENABLE_FEATURE_NAMEIF_EXTENDED
39 char *bus_info; 99 char *bus_info;
40 char *driver; 100 char *driver;
101 int32_t phy_address;
41#endif 102#endif
42} ethtable_t; 103} ethtable_t;
43 104
@@ -59,6 +120,25 @@ struct ethtool_drvinfo {
59 uint32_t eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */ 120 uint32_t eedump_len; /* Size of data from ETHTOOL_GEEPROM (bytes) */
60 uint32_t regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */ 121 uint32_t regdump_len; /* Size of data from ETHTOOL_GREGS (bytes) */
61}; 122};
123
124struct ethtool_cmd {
125 __u32 cmd;
126 __u32 supported; /* Features this interface supports */
127 __u32 advertising; /* Features this interface advertises */
128 __u16 speed; /* The forced speed, 10Mb, 100Mb, gigabit */
129 __u8 duplex; /* Duplex, half or full */
130 __u8 port; /* Which connector port */
131 __u8 phy_address;
132 __u8 transceiver; /* Which transceiver to use */
133 __u8 autoneg; /* Enable or disable autonegotiation */
134 __u32 maxtxpkt; /* Tx pkts before generating tx int */
135 __u32 maxrxpkt; /* Rx pkts before generating rx int */
136 __u16 speed_hi;
137 __u16 reserved2;
138 __u32 reserved[3];
139};
140
141#define ETHTOOL_GSET 0x00000001 /* Get settings. */
62#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */ 142#define ETHTOOL_GDRVINFO 0x00000003 /* Get driver info. */
63#endif 143#endif
64 144
@@ -74,6 +154,7 @@ static void nameif_parse_selector(ethtable_t *ch, char *selector)
74#endif 154#endif
75 selector = skip_whitespace(selector); 155 selector = skip_whitespace(selector);
76#if ENABLE_FEATURE_NAMEIF_EXTENDED 156#if ENABLE_FEATURE_NAMEIF_EXTENDED
157 ch->phy_address = -1;
77 if (*selector == '\0') 158 if (*selector == '\0')
78 break; 159 break;
79 /* Search for the end .... */ 160 /* Search for the end .... */
@@ -87,6 +168,9 @@ static void nameif_parse_selector(ethtable_t *ch, char *selector)
87 } else if (strncmp(selector, "driver=", 7) == 0) { 168 } else if (strncmp(selector, "driver=", 7) == 0) {
88 ch->driver = xstrdup(selector + 7); 169 ch->driver = xstrdup(selector + 7);
89 found_selector++; 170 found_selector++;
171 } else if (strncmp(selector, "phyaddr=", 8) == 0) {
172 ch->phy_address = xatoi_positive(selector + 8);
173 found_selector++;
90 } else { 174 } else {
91#endif 175#endif
92 lmac = xmalloc(ETH_ALEN); 176 lmac = xmalloc(ETH_ALEN);
@@ -133,7 +217,7 @@ void delete_eth_table(ethtable_t *ch);
133#endif 217#endif
134 218
135int nameif_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 219int nameif_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
136int nameif_main(int argc, char **argv) 220int nameif_main(int argc UNUSED_PARAM, char **argv)
137{ 221{
138 ethtable_t *clist = NULL; 222 ethtable_t *clist = NULL;
139 const char *fname = "/etc/mactab"; 223 const char *fname = "/etc/mactab";
@@ -148,17 +232,15 @@ int nameif_main(int argc, char **argv)
148 * can't hurt. 2>/dev/null if you don't like it: */ 232 * can't hurt. 2>/dev/null if you don't like it: */
149 logmode |= LOGMODE_SYSLOG; 233 logmode |= LOGMODE_SYSLOG;
150 } 234 }
151 argc -= optind;
152 argv += optind; 235 argv += optind;
153 236
154 if (argc & 1) 237 if (argv[0]) {
155 bb_show_usage(); 238 do {
156 239 if (!argv[1])
157 if (argc) { 240 bb_show_usage();
158 while (*argv) { 241 prepend_new_eth_table(&clist, argv[0], argv[1]);
159 char *ifname = xstrdup(*argv++); 242 argv += 2;
160 prepend_new_eth_table(&clist, ifname, *argv++); 243 } while (*argv);
161 }
162 } else { 244 } else {
163 parser = config_open(fname); 245 parser = config_open(fname);
164 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL)) 246 while (config_read(parser, token, 2, 2, "# \t", PARSE_NORMAL))
@@ -173,8 +255,9 @@ int nameif_main(int argc, char **argv)
173 struct ifreq ifr; 255 struct ifreq ifr;
174#if ENABLE_FEATURE_NAMEIF_EXTENDED 256#if ENABLE_FEATURE_NAMEIF_EXTENDED
175 struct ethtool_drvinfo drvinfo; 257 struct ethtool_drvinfo drvinfo;
258 struct ethtool_cmd eth_settings;
176#endif 259#endif
177 if (parser->lineno < 2) 260 if (parser->lineno <= 2)
178 continue; /* Skip the first two lines */ 261 continue; /* Skip the first two lines */
179 262
180 /* Find the current interface name and copy it to ifr.ifr_name */ 263 /* Find the current interface name and copy it to ifr.ifr_name */
@@ -182,8 +265,14 @@ int nameif_main(int argc, char **argv)
182 strncpy_IFNAMSIZ(ifr.ifr_name, token[0]); 265 strncpy_IFNAMSIZ(ifr.ifr_name, token[0]);
183 266
184#if ENABLE_FEATURE_NAMEIF_EXTENDED 267#if ENABLE_FEATURE_NAMEIF_EXTENDED
268 /* Check for phy address */
269 memset(&eth_settings, 0, sizeof(eth_settings));
270 eth_settings.cmd = ETHTOOL_GSET;
271 ifr.ifr_data = (caddr_t) &eth_settings;
272 ioctl(ctl_sk, SIOCETHTOOL, &ifr);
273
185 /* Check for driver etc. */ 274 /* Check for driver etc. */
186 memset(&drvinfo, 0, sizeof(struct ethtool_drvinfo)); 275 memset(&drvinfo, 0, sizeof(drvinfo));
187 drvinfo.cmd = ETHTOOL_GDRVINFO; 276 drvinfo.cmd = ETHTOOL_GDRVINFO;
188 ifr.ifr_data = (caddr_t) &drvinfo; 277 ifr.ifr_data = (caddr_t) &drvinfo;
189 /* Get driver and businfo first, so we have it in drvinfo */ 278 /* Get driver and businfo first, so we have it in drvinfo */
@@ -198,6 +287,8 @@ int nameif_main(int argc, char **argv)
198 continue; 287 continue;
199 if (ch->driver && strcmp(ch->driver, drvinfo.driver) != 0) 288 if (ch->driver && strcmp(ch->driver, drvinfo.driver) != 0)
200 continue; 289 continue;
290 if (ch->phy_address != -1 && ch->phy_address != eth_settings.phy_address)
291 continue;
201#endif 292#endif
202 if (ch->mac && memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != 0) 293 if (ch->mac && memcmp(ch->mac, ifr.ifr_hwaddr.sa_data, ETH_ALEN) != 0)
203 continue; 294 continue;
diff --git a/networking/nslookup.c b/networking/nslookup.c
index dcac7379e..67fc01547 100644
--- a/networking/nslookup.c
+++ b/networking/nslookup.c
@@ -66,7 +66,7 @@ static int print_host(const char *hostname, const char *header)
66 // hint.ai_flags = AI_CANONNAME; 66 // hint.ai_flags = AI_CANONNAME;
67 rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result); 67 rc = getaddrinfo(hostname, NULL /*service*/, &hint, &result);
68 68
69 if (!rc) { 69 if (rc == 0) {
70 struct addrinfo *cur = result; 70 struct addrinfo *cur = result;
71 unsigned cnt = 0; 71 unsigned cnt = 0;
72 72
@@ -94,7 +94,7 @@ static int print_host(const char *hostname, const char *header)
94 bb_error_msg("can't resolve '%s'", hostname); 94 bb_error_msg("can't resolve '%s'", hostname);
95#endif 95#endif
96 } 96 }
97 if (ENABLE_FEATURE_CLEAN_UP) 97 if (ENABLE_FEATURE_CLEAN_UP && result)
98 freeaddrinfo(result); 98 freeaddrinfo(result);
99 return (rc != 0); 99 return (rc != 0);
100} 100}
diff --git a/networking/ping.c b/networking/ping.c
index c2ff42e2c..7a9c2d1f0 100644
--- a/networking/ping.c
+++ b/networking/ping.c
@@ -32,7 +32,7 @@
32//config:config PING 32//config:config PING
33//config: bool "ping" 33//config: bool "ping"
34//config: default y 34//config: default y
35//config: depends on PLATFORM_LINUX 35//config: select PLATFORM_LINUX
36//config: help 36//config: help
37//config: ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to 37//config: ping uses the ICMP protocol's mandatory ECHO_REQUEST datagram to
38//config: elicit an ICMP ECHO_RESPONSE from a host or gateway. 38//config: elicit an ICMP ECHO_RESPONSE from a host or gateway.
diff --git a/networking/route.c b/networking/route.c
index b7d08dd63..98a03ded7 100644
--- a/networking/route.c
+++ b/networking/route.c
@@ -537,6 +537,7 @@ void FAST_FUNC bb_displayroutes(int noresolve, int netstatfmt)
537 printf("%-6d %-2d %7d %s\n", metric, ref, use, devname); 537 printf("%-6d %-2d %7d %s\n", metric, ref, use, devname);
538 } 538 }
539 } 539 }
540 fclose(fp);
540} 541}
541 542
542#if ENABLE_FEATURE_IPV6 543#if ENABLE_FEATURE_IPV6
@@ -604,7 +605,7 @@ static void INET6_displayroutes(void)
604 set_flags(flags, (iflags & IPV6_MASK)); 605 set_flags(flags, (iflags & IPV6_MASK));
605 606
606 r = 0; 607 r = 0;
607 do { 608 while (1) {
608 inet_pton(AF_INET6, addr6x + r, 609 inet_pton(AF_INET6, addr6x + r,
609 (struct sockaddr *) &snaddr6.sin6_addr); 610 (struct sockaddr *) &snaddr6.sin6_addr);
610 snaddr6.sin6_family = AF_INET6; 611 snaddr6.sin6_family = AF_INET6;
@@ -623,8 +624,9 @@ static void INET6_displayroutes(void)
623 free(naddr6); 624 free(naddr6);
624 break; 625 break;
625 } 626 }
626 } while (1); 627 }
627 } 628 }
629 fclose(fp);
628} 630}
629 631
630#endif 632#endif
diff --git a/networking/udhcp/Config.src b/networking/udhcp/Config.src
index 750a53a32..9cd8cbbae 100644
--- a/networking/udhcp/Config.src
+++ b/networking/udhcp/Config.src
@@ -8,7 +8,7 @@ INSERT
8config UDHCPD 8config UDHCPD
9 bool "udhcp server (udhcpd)" 9 bool "udhcp server (udhcpd)"
10 default y 10 default y
11 depends on PLATFORM_LINUX 11 select PLATFORM_LINUX
12 help 12 help
13 udhcpd is a DHCP server geared primarily toward embedded systems, 13 udhcpd is a DHCP server geared primarily toward embedded systems,
14 while striving to be fully functional and RFC compliant. 14 while striving to be fully functional and RFC compliant.
@@ -66,7 +66,7 @@ config DHCPD_LEASES_FILE
66config UDHCPC 66config UDHCPC
67 bool "udhcp client (udhcpc)" 67 bool "udhcp client (udhcpc)"
68 default y 68 default y
69 depends on PLATFORM_LINUX 69 select PLATFORM_LINUX
70 help 70 help
71 udhcpc is a DHCP client geared primarily toward embedded systems, 71 udhcpc is a DHCP client geared primarily toward embedded systems,
72 while striving to be fully functional and RFC compliant. 72 while striving to be fully functional and RFC compliant.
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index d97a404fa..ca82d37e6 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -38,6 +38,67 @@
38/* struct client_config_t client_config is in bb_common_bufsiz1 */ 38/* struct client_config_t client_config is in bb_common_bufsiz1 */
39 39
40 40
41#if ENABLE_LONG_OPTS
42static const char udhcpc_longopts[] ALIGN1 =
43 "clientid-none\0" No_argument "C"
44 "vendorclass\0" Required_argument "V"
45 "hostname\0" Required_argument "H"
46 "fqdn\0" Required_argument "F"
47 "interface\0" Required_argument "i"
48 "now\0" No_argument "n"
49 "pidfile\0" Required_argument "p"
50 "quit\0" No_argument "q"
51 "release\0" No_argument "R"
52 "request\0" Required_argument "r"
53 "script\0" Required_argument "s"
54 "timeout\0" Required_argument "T"
55 "version\0" No_argument "v"
56 "retries\0" Required_argument "t"
57 "tryagain\0" Required_argument "A"
58 "syslog\0" No_argument "S"
59 "request-option\0" Required_argument "O"
60 "no-default-options\0" No_argument "o"
61 "foreground\0" No_argument "f"
62 "background\0" No_argument "b"
63 "broadcast\0" No_argument "B"
64 IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a")
65 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
66 ;
67#endif
68/* Must match getopt32 option string order */
69enum {
70 OPT_C = 1 << 0,
71 OPT_V = 1 << 1,
72 OPT_H = 1 << 2,
73 OPT_h = 1 << 3,
74 OPT_F = 1 << 4,
75 OPT_i = 1 << 5,
76 OPT_n = 1 << 6,
77 OPT_p = 1 << 7,
78 OPT_q = 1 << 8,
79 OPT_R = 1 << 9,
80 OPT_r = 1 << 10,
81 OPT_s = 1 << 11,
82 OPT_T = 1 << 12,
83 OPT_t = 1 << 13,
84 OPT_S = 1 << 14,
85 OPT_A = 1 << 15,
86 OPT_O = 1 << 16,
87 OPT_o = 1 << 17,
88 OPT_x = 1 << 18,
89 OPT_f = 1 << 19,
90 OPT_B = 1 << 20,
91/* The rest has variable bit positions, need to be clever */
92 OPTBIT_B = 20,
93 USE_FOR_MMU( OPTBIT_b,)
94 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
95 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
96 USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,)
97 IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
98 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
99};
100
101
41/*** Script execution code ***/ 102/*** Script execution code ***/
42 103
43/* get a rough idea of how long an option will be (rounding up...) */ 104/* get a rough idea of how long an option will be (rounding up...) */
@@ -346,11 +407,19 @@ static ALWAYS_INLINE uint32_t random_xid(void)
346/* Initialize the packet with the proper defaults */ 407/* Initialize the packet with the proper defaults */
347static void init_packet(struct dhcp_packet *packet, char type) 408static void init_packet(struct dhcp_packet *packet, char type)
348{ 409{
410 uint16_t secs;
411
349 /* Fill in: op, htype, hlen, cookie fields; message type option: */ 412 /* Fill in: op, htype, hlen, cookie fields; message type option: */
350 udhcp_init_header(packet, type); 413 udhcp_init_header(packet, type);
351 414
352 packet->xid = random_xid(); 415 packet->xid = random_xid();
353 416
417 client_config.last_secs = monotonic_sec();
418 if (client_config.first_secs == 0)
419 client_config.first_secs = client_config.last_secs;
420 secs = client_config.last_secs - client_config.first_secs;
421 packet->secs = htons(secs);
422
354 memcpy(packet->chaddr, client_config.client_mac, 6); 423 memcpy(packet->chaddr, client_config.client_mac, 6);
355 if (client_config.clientid) 424 if (client_config.clientid)
356 udhcp_add_binary_option(packet, client_config.clientid); 425 udhcp_add_binary_option(packet, client_config.clientid);
@@ -391,6 +460,10 @@ static void add_client_options(struct dhcp_packet *packet)
391 if (client_config.fqdn) 460 if (client_config.fqdn)
392 udhcp_add_binary_option(packet, client_config.fqdn); 461 udhcp_add_binary_option(packet, client_config.fqdn);
393 462
463 /* Request broadcast replies if we have no IP addr */
464 if ((option_mask32 & OPT_B) && packet->ciaddr == 0)
465 packet->flags |= htons(BROADCAST_FLAG);
466
394 /* Add -x options if any */ 467 /* Add -x options if any */
395 { 468 {
396 struct option_set *curr = client_config.options; 469 struct option_set *curr = client_config.options;
@@ -783,6 +856,7 @@ static void change_listen_mode(int new_mode)
783 /* else LISTEN_NONE: sockfd stays closed */ 856 /* else LISTEN_NONE: sockfd stays closed */
784} 857}
785 858
859/* Called only on SIGUSR1 */
786static void perform_renew(void) 860static void perform_renew(void)
787{ 861{
788 bb_info_msg("Performing a DHCP renew"); 862 bb_info_msg("Performing a DHCP renew");
@@ -853,13 +927,14 @@ static void client_background(void)
853//usage:# define IF_UDHCP_VERBOSE(...) 927//usage:# define IF_UDHCP_VERBOSE(...)
854//usage:#endif 928//usage:#endif
855//usage:#define udhcpc_trivial_usage 929//usage:#define udhcpc_trivial_usage
856//usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCR] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n" 930//usage: "[-fbnq"IF_UDHCP_VERBOSE("v")"oCRB] [-i IFACE] [-r IP] [-s PROG] [-p PIDFILE]\n"
857//usage: " [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]") 931//usage: " [-H HOSTNAME] [-V VENDOR] [-x OPT:VAL]... [-O OPT]..." IF_FEATURE_UDHCP_PORT(" [-P N]")
858//usage:#define udhcpc_full_usage "\n" 932//usage:#define udhcpc_full_usage "\n"
859//usage: IF_LONG_OPTS( 933//usage: IF_LONG_OPTS(
860//usage: "\n -i,--interface IFACE Interface to use (default eth0)" 934//usage: "\n -i,--interface IFACE Interface to use (default eth0)"
861//usage: "\n -p,--pidfile FILE Create pidfile" 935//usage: "\n -p,--pidfile FILE Create pidfile"
862//usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 936//usage: "\n -s,--script PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
937//usage: "\n -B,--broadcast Request broadcast replies"
863//usage: "\n -t,--retries N Send up to N discover packets" 938//usage: "\n -t,--retries N Send up to N discover packets"
864//usage: "\n -T,--timeout N Pause between packets (default 3 seconds)" 939//usage: "\n -T,--timeout N Pause between packets (default 3 seconds)"
865//usage: "\n -A,--tryagain N Wait N seconds after failure (default 20)" 940//usage: "\n -A,--tryagain N Wait N seconds after failure (default 20)"
@@ -897,6 +972,7 @@ static void client_background(void)
897//usage: "\n -i IFACE Interface to use (default eth0)" 972//usage: "\n -i IFACE Interface to use (default eth0)"
898//usage: "\n -p FILE Create pidfile" 973//usage: "\n -p FILE Create pidfile"
899//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")" 974//usage: "\n -s PROG Run PROG at DHCP events (default "CONFIG_UDHCPC_DEFAULT_SCRIPT")"
975//usage: "\n -B Request broadcast replies"
900//usage: "\n -t N Send up to N discover packets" 976//usage: "\n -t N Send up to N discover packets"
901//usage: "\n -T N Pause between packets (default 3 seconds)" 977//usage: "\n -T N Pause between packets (default 3 seconds)"
902//usage: "\n -A N Wait N seconds (default 20) after failure" 978//usage: "\n -A N Wait N seconds (default 20) after failure"
@@ -961,63 +1037,6 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
961 struct dhcp_packet packet; 1037 struct dhcp_packet packet;
962 fd_set rfds; 1038 fd_set rfds;
963 1039
964#if ENABLE_LONG_OPTS
965 static const char udhcpc_longopts[] ALIGN1 =
966 "clientid-none\0" No_argument "C"
967 "vendorclass\0" Required_argument "V"
968 "hostname\0" Required_argument "H"
969 "fqdn\0" Required_argument "F"
970 "interface\0" Required_argument "i"
971 "now\0" No_argument "n"
972 "pidfile\0" Required_argument "p"
973 "quit\0" No_argument "q"
974 "release\0" No_argument "R"
975 "request\0" Required_argument "r"
976 "script\0" Required_argument "s"
977 "timeout\0" Required_argument "T"
978 "version\0" No_argument "v"
979 "retries\0" Required_argument "t"
980 "tryagain\0" Required_argument "A"
981 "syslog\0" No_argument "S"
982 "request-option\0" Required_argument "O"
983 "no-default-options\0" No_argument "o"
984 "foreground\0" No_argument "f"
985 "background\0" No_argument "b"
986 IF_FEATURE_UDHCPC_ARPING("arping\0" No_argument "a")
987 IF_FEATURE_UDHCP_PORT("client-port\0" Required_argument "P")
988 ;
989#endif
990 enum {
991 OPT_C = 1 << 0,
992 OPT_V = 1 << 1,
993 OPT_H = 1 << 2,
994 OPT_h = 1 << 3,
995 OPT_F = 1 << 4,
996 OPT_i = 1 << 5,
997 OPT_n = 1 << 6,
998 OPT_p = 1 << 7,
999 OPT_q = 1 << 8,
1000 OPT_R = 1 << 9,
1001 OPT_r = 1 << 10,
1002 OPT_s = 1 << 11,
1003 OPT_T = 1 << 12,
1004 OPT_t = 1 << 13,
1005 OPT_S = 1 << 14,
1006 OPT_A = 1 << 15,
1007 OPT_O = 1 << 16,
1008 OPT_o = 1 << 17,
1009 OPT_x = 1 << 18,
1010 OPT_f = 1 << 19,
1011/* The rest has variable bit positions, need to be clever */
1012 OPTBIT_f = 19,
1013 USE_FOR_MMU( OPTBIT_b,)
1014 IF_FEATURE_UDHCPC_ARPING(OPTBIT_a,)
1015 IF_FEATURE_UDHCP_PORT( OPTBIT_P,)
1016 USE_FOR_MMU( OPT_b = 1 << OPTBIT_b,)
1017 IF_FEATURE_UDHCPC_ARPING(OPT_a = 1 << OPTBIT_a,)
1018 IF_FEATURE_UDHCP_PORT( OPT_P = 1 << OPTBIT_P,)
1019 };
1020
1021 /* Default options */ 1040 /* Default options */
1022 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;) 1041 IF_FEATURE_UDHCP_PORT(SERVER_PORT = 67;)
1023 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;) 1042 IF_FEATURE_UDHCP_PORT(CLIENT_PORT = 68;)
@@ -1033,7 +1052,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1033#endif 1052#endif
1034 ; 1053 ;
1035 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;) 1054 IF_LONG_OPTS(applet_long_options = udhcpc_longopts;)
1036 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:f" 1055 opt = getopt32(argv, "CV:H:h:F:i:np:qRr:s:T:t:SA:O:ox:fB"
1037 USE_FOR_MMU("b") 1056 USE_FOR_MMU("b")
1038 IF_FEATURE_UDHCPC_ARPING("a") 1057 IF_FEATURE_UDHCPC_ARPING("a")
1039 IF_FEATURE_UDHCP_PORT("P:") 1058 IF_FEATURE_UDHCP_PORT("P:")
@@ -1250,6 +1269,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1250 case BOUND: 1269 case BOUND:
1251 /* 1/2 lease passed, enter renewing state */ 1270 /* 1/2 lease passed, enter renewing state */
1252 state = RENEWING; 1271 state = RENEWING;
1272 client_config.first_secs = 0; /* make secs field count from 0 */
1253 change_listen_mode(LISTEN_KERNEL); 1273 change_listen_mode(LISTEN_KERNEL);
1254 log1("Entering renew state"); 1274 log1("Entering renew state");
1255 /* fall right through */ 1275 /* fall right through */
@@ -1289,6 +1309,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1289 bb_info_msg("Lease lost, entering init state"); 1309 bb_info_msg("Lease lost, entering init state");
1290 udhcp_run_script(NULL, "deconfig"); 1310 udhcp_run_script(NULL, "deconfig");
1291 state = INIT_SELECTING; 1311 state = INIT_SELECTING;
1312 client_config.first_secs = 0; /* make secs field count from 0 */
1292 /*timeout = 0; - already is */ 1313 /*timeout = 0; - already is */
1293 packet_num = 0; 1314 packet_num = 0;
1294 continue; 1315 continue;
@@ -1305,6 +1326,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1305 /* note: udhcp_sp_read checks FD_ISSET before reading */ 1326 /* note: udhcp_sp_read checks FD_ISSET before reading */
1306 switch (udhcp_sp_read(&rfds)) { 1327 switch (udhcp_sp_read(&rfds)) {
1307 case SIGUSR1: 1328 case SIGUSR1:
1329 client_config.first_secs = 0; /* make secs field count from 0 */
1308 perform_renew(); 1330 perform_renew();
1309 if (state == RENEW_REQUESTED) 1331 if (state == RENEW_REQUESTED)
1310 goto case_RENEW_REQUESTED; 1332 goto case_RENEW_REQUESTED;
@@ -1436,6 +1458,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1436 udhcp_run_script(NULL, "deconfig"); 1458 udhcp_run_script(NULL, "deconfig");
1437 change_listen_mode(LISTEN_RAW); 1459 change_listen_mode(LISTEN_RAW);
1438 state = INIT_SELECTING; 1460 state = INIT_SELECTING;
1461 client_config.first_secs = 0; /* make secs field count from 0 */
1439 requested_ip = 0; 1462 requested_ip = 0;
1440 timeout = tryagain_timeout; 1463 timeout = tryagain_timeout;
1441 packet_num = 0; 1464 packet_num = 0;
@@ -1483,6 +1506,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv)
1483 change_listen_mode(LISTEN_RAW); 1506 change_listen_mode(LISTEN_RAW);
1484 sleep(3); /* avoid excessive network traffic */ 1507 sleep(3); /* avoid excessive network traffic */
1485 state = INIT_SELECTING; 1508 state = INIT_SELECTING;
1509 client_config.first_secs = 0; /* make secs field count from 0 */
1486 requested_ip = 0; 1510 requested_ip = 0;
1487 timeout = 0; 1511 timeout = 0;
1488 packet_num = 0; 1512 packet_num = 0;
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h
index 9ef053a1b..2b3599120 100644
--- a/networking/udhcp/dhcpc.h
+++ b/networking/udhcp/dhcpc.h
@@ -21,6 +21,9 @@ struct client_config_t {
21 uint8_t *vendorclass; /* Optional vendor class-id to use */ 21 uint8_t *vendorclass; /* Optional vendor class-id to use */
22 uint8_t *hostname; /* Optional hostname to use */ 22 uint8_t *hostname; /* Optional hostname to use */
23 uint8_t *fqdn; /* Optional fully qualified domain name to use */ 23 uint8_t *fqdn; /* Optional fully qualified domain name to use */
24
25 uint16_t first_secs;
26 uint16_t last_secs;
24} FIX_ALIASING; 27} FIX_ALIASING;
25 28
26/* server_config sits in 1st half of bb_common_bufsiz1 */ 29/* server_config sits in 1st half of bb_common_bufsiz1 */
diff --git a/networking/wget.c b/networking/wget.c
index bbc161be8..41ec7f6dc 100644
--- a/networking/wget.c
+++ b/networking/wget.c
@@ -8,6 +8,32 @@
8 * Copyright (C) 2010 Bradley M. Kuhn <bkuhn@ebb.org> 8 * Copyright (C) 2010 Bradley M. Kuhn <bkuhn@ebb.org>
9 * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. 9 * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2.
10 */ 10 */
11
12//usage:#define wget_trivial_usage
13//usage: IF_FEATURE_WGET_LONG_OPTIONS(
14//usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n"
15//usage: " [--header 'header: value'] [-Y|--proxy on/off] [-P DIR]\n"
16//usage: " [--no-check-certificate] [-U|--user-agent AGENT]"
17//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
18//usage: )
19//usage: IF_NOT_FEATURE_WGET_LONG_OPTIONS(
20//usage: "[-csq] [-O FILE] [-Y on/off] [-P DIR] [-U AGENT]"
21//usage: IF_FEATURE_WGET_TIMEOUT(" [-T SEC]") " URL..."
22//usage: )
23//usage:#define wget_full_usage "\n\n"
24//usage: "Retrieve files via HTTP or FTP\n"
25//usage: "\nOptions:"
26//usage: "\n -s Spider mode - only check file existence"
27//usage: "\n -c Continue retrieval of aborted transfer"
28//usage: "\n -q Quiet"
29//usage: "\n -P DIR Save to DIR (default .)"
30//usage: IF_FEATURE_WGET_TIMEOUT(
31//usage: "\n -T SEC Network read timeout is SEC seconds"
32//usage: )
33//usage: "\n -O FILE Save to FILE ('-' for stdout)"
34//usage: "\n -U STR Use STR for User-Agent header"
35//usage: "\n -Y Use proxy ('on' or 'off')"
36
11#include "libbb.h" 37#include "libbb.h"
12 38
13//#define log_io(...) bb_error_msg(__VA_ARGS__) 39//#define log_io(...) bb_error_msg(__VA_ARGS__)
@@ -604,8 +630,14 @@ static void download_one_url(const char *url)
604 if (G.fname_out[0] == '/' || !G.fname_out[0]) 630 if (G.fname_out[0] == '/' || !G.fname_out[0])
605 G.fname_out = (char*)"index.html"; 631 G.fname_out = (char*)"index.html";
606 /* -P DIR is considered only if there was no -O FILE */ 632 /* -P DIR is considered only if there was no -O FILE */
607 if (G.dir_prefix) 633 else {
608 G.fname_out = fname_out_alloc = concat_path_file(G.dir_prefix, G.fname_out); 634 if (G.dir_prefix)
635 G.fname_out = fname_out_alloc = concat_path_file(G.dir_prefix, G.fname_out);
636 else {
637 /* redirects may free target.path later, need to make a copy */
638 G.fname_out = fname_out_alloc = xstrdup(G.fname_out);
639 }
640 }
609 } 641 }
610#if ENABLE_FEATURE_WGET_STATUSBAR 642#if ENABLE_FEATURE_WGET_STATUSBAR
611 G.curfile = bb_get_last_path_component_nostrip(G.fname_out); 643 G.curfile = bb_get_last_path_component_nostrip(G.fname_out);
diff --git a/networking/whois.c b/networking/whois.c
new file mode 100644
index 000000000..4eab9e5fe
--- /dev/null
+++ b/networking/whois.c
@@ -0,0 +1,66 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * whois - tiny client for the whois directory service
4 *
5 * Copyright (c) 2011 Pere Orga <gotrunks@gmail.com>
6 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
7 */
8/* TODO
9 * Add ipv6 support
10 * Add proxy support
11 */
12
13//config:config WHOIS
14//config: bool "whois"
15//config: default y
16//config: help
17//config: whois is a client for the whois directory service
18
19//applet:IF_WHOIS(APPLET(whois, BB_DIR_USR_BIN, BB_SUID_DROP))
20
21//kbuild:lib-$(CONFIG_WHOIS) += whois.o
22
23//usage:#define whois_trivial_usage
24//usage: "[-h SERVER] [-p PORT] NAME..."
25//usage:#define whois_full_usage "\n\n"
26//usage: "Query WHOIS info about NAME\n"
27//usage: "\nOptions:"
28//usage: "\n -h,-p Server to query"
29
30#include "libbb.h"
31
32static void pipe_out(int fd)
33{
34 FILE *fp;
35 char buf[1024];
36
37 fp = xfdopen_for_read(fd);
38 while (fgets(buf, sizeof(buf), fp)) {
39 char *p = strpbrk(buf, "\r\n");
40 if (p)
41 *p = '\0';
42 puts(buf);
43 }
44
45 fclose(fp); /* closes fd too */
46}
47
48int whois_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
49int whois_main(int argc UNUSED_PARAM, char **argv)
50{
51 int port = 43;
52 const char *host = "whois-servers.net";
53
54 opt_complementary = "-1:p+";
55 getopt32(argv, "h:p:", &host, &port);
56
57 argv += optind;
58 do {
59 int fd = create_and_connect_stream_or_die(host, port);
60 fdprintf(fd, "%s\r\n", *argv);
61 pipe_out(fd);
62 }
63 while (*++argv);
64
65 return EXIT_SUCCESS;
66}
diff --git a/procps/Config.src b/procps/Config.src
index cf664eeb2..3e7df0b81 100644
--- a/procps/Config.src
+++ b/procps/Config.src
@@ -10,7 +10,7 @@ INSERT
10config FREE 10config FREE
11 bool "free" 11 bool "free"
12 default y 12 default y
13 depends on PLATFORM_LINUX #sysinfo() 13 select PLATFORM_LINUX #sysinfo()
14 help 14 help
15 free displays the total amount of free and used physical and swap 15 free displays the total amount of free and used physical and swap
16 memory in the system, as well as the buffers used by the kernel. 16 memory in the system, as well as the buffers used by the kernel.
@@ -99,7 +99,8 @@ config FEATURE_PS_WIDE
99config FEATURE_PS_TIME 99config FEATURE_PS_TIME
100 bool "Enable time and elapsed time output" 100 bool "Enable time and elapsed time output"
101 default y 101 default y
102 depends on PS && DESKTOP && PLATFORM_LINUX #sysinfo() 102 depends on PS && DESKTOP
103 select PLATFORM_LINUX
103 help 104 help
104 Support -o time and -o etime output specifiers. 105 Support -o time and -o etime output specifiers.
105 106
@@ -196,7 +197,7 @@ config FEATURE_SHOW_THREADS
196config UPTIME 197config UPTIME
197 bool "uptime" 198 bool "uptime"
198 default y 199 default y
199 depends on PLATFORM_LINUX #sysinfo() 200 select PLATFORM_LINUX #sysinfo()
200 help 201 help
201 uptime gives a one line display of the current time, how long 202 uptime gives a one line display of the current time, how long
202 the system has been running, how many users are currently logged 203 the system has been running, how many users are currently logged
diff --git a/procps/kill.c b/procps/kill.c
index e6f27af50..599152250 100644
--- a/procps/kill.c
+++ b/procps/kill.c
@@ -221,6 +221,7 @@ int kill_main(int argc, char **argv)
221 pid = bb_strtoi(arg, &end, 10); 221 pid = bb_strtoi(arg, &end, 10);
222 if (errno && (errno != EINVAL || *end != ' ')) { 222 if (errno && (errno != EINVAL || *end != ' ')) {
223 bb_error_msg("invalid number '%s'", arg); 223 bb_error_msg("invalid number '%s'", arg);
224 *end = '\0';
224 errors++; 225 errors++;
225 } else if (kill(pid, signo) != 0) { 226 } else if (kill(pid, signo) != 0) {
226 bb_perror_msg("can't kill pid %d", (int)pid); 227 bb_perror_msg("can't kill pid %d", (int)pid);
diff --git a/procps/pwdx.c b/procps/pwdx.c
new file mode 100644
index 000000000..781810488
--- /dev/null
+++ b/procps/pwdx.c
@@ -0,0 +1,60 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * pwdx implementation for busybox
4 *
5 * Copyright (c) 2004 Nicholas Miell
6 * ported from procps by Pere Orga <gotrunks@gmail.com> 2011
7 *
8 * Licensed under GPLv2, see file LICENSE in this source tree.
9 */
10
11//config:config PWDX
12//config: bool "pwdx"
13//config: default y
14//config: help
15//config: Report current working directory of a process
16
17//applet:IF_PWDX(APPLET(pwdx, BB_DIR_USR_BIN, BB_SUID_DROP))
18
19//kbuild:lib-$(CONFIG_PWDX) += pwdx.o
20
21//usage:#define pwdx_trivial_usage
22//usage: "PID..."
23//usage:#define pwdx_full_usage "\n\n"
24//usage: "Show current directory for PIDs\n"
25
26#include "libbb.h"
27
28int pwdx_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
29int pwdx_main(int argc UNUSED_PARAM, char **argv)
30{
31 opt_complementary = "-1";
32 getopt32(argv, "");
33 argv += optind;
34
35 do {
36 char buf[sizeof("/proc/%u/cwd") + sizeof(int)*3];
37 unsigned pid;
38 char *s;
39 char *arg = *argv;
40
41 // Allowed on the command line:
42 // /proc/NUM
43 // NUM
44 if (strncmp(arg, "/proc/", 6) == 0)
45 arg += 6;
46
47 pid = bb_strtou(arg, NULL, 10);
48 if (errno)
49 bb_error_msg_and_die("invalid process id: '%s'", arg);
50
51 sprintf(buf, "/proc/%u/cwd", pid);
52
53 s = xmalloc_readlink(buf);
54 // "pwdx /proc/1" says "/proc/1: DIR", not "1: DIR"
55 printf("%s: %s\n", *argv, s ? s : strerror(errno == ENOENT ? ESRCH : errno));
56 free(s);
57 } while (*++argv);
58
59 return EXIT_SUCCESS;
60}
diff --git a/runit/svlogd.c b/runit/svlogd.c
index cfa20a773..b0ba21bb6 100644
--- a/runit/svlogd.c
+++ b/runit/svlogd.c
@@ -187,6 +187,7 @@ struct globals {
187 unsigned nearest_rotate; 187 unsigned nearest_rotate;
188 188
189 void* (*memRchr)(const void *, int, size_t); 189 void* (*memRchr)(const void *, int, size_t);
190 char *shell;
190 191
191 smallint exitasap; 192 smallint exitasap;
192 smallint rotateasap; 193 smallint rotateasap;
@@ -382,6 +383,9 @@ static void processorstart(struct logdir *ld)
382 /* vfork'ed child trashes this byte, save... */ 383 /* vfork'ed child trashes this byte, save... */
383 sv_ch = ld->fnsave[26]; 384 sv_ch = ld->fnsave[26];
384 385
386 if (!G.shell)
387 G.shell = xstrdup(get_shell_name());
388
385 while ((pid = vfork()) == -1) 389 while ((pid = vfork()) == -1)
386 pause2cannot("vfork for processor", ld->name); 390 pause2cannot("vfork for processor", ld->name);
387 if (!pid) { 391 if (!pid) {
@@ -416,8 +420,7 @@ static void processorstart(struct logdir *ld)
416 fd = xopen("newstate", O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT); 420 fd = xopen("newstate", O_WRONLY|O_NDELAY|O_TRUNC|O_CREAT);
417 xmove_fd(fd, 5); 421 xmove_fd(fd, 5);
418 422
419// getenv("SHELL")? 423 execl(G.shell, G.shell, "-c", ld->processor, (char*) NULL);
420 execl(DEFAULT_SHELL, DEFAULT_SHELL_SHORT_NAME, "-c", ld->processor, (char*) NULL);
421 bb_perror_msg_and_die(FATAL"can't %s processor %s", "run", ld->name); 424 bb_perror_msg_and_die(FATAL"can't %s processor %s", "run", ld->name);
422 } 425 }
423 ld->fnsave[26] = sv_ch; /* ...restore */ 426 ld->fnsave[26] = sv_ch; /* ...restore */
diff --git a/scripts/Makefile.IMA b/scripts/Makefile.IMA
index a62618ae0..0eced2982 100644
--- a/scripts/Makefile.IMA
+++ b/scripts/Makefile.IMA
@@ -9,7 +9,10 @@ objtree := $(CURDIR)
9src := $(srctree) 9src := $(srctree)
10obj := $(objtree) 10obj := $(objtree)
11 11
12# Look for make include files relative to root of kernel src 12# Make generated files
13DUMMY := $(shell $(Q)$(srctree)/scripts/gen_build_files.sh $(srctree) $(objtree) >&2)
14
15# Look for make include files relative to root of src
13MAKEFLAGS += --include-dir=$(srctree) 16MAKEFLAGS += --include-dir=$(srctree)
14 17
15default: busybox 18default: busybox
@@ -121,6 +124,9 @@ lib-y:=
121include miscutils/Kbuild 124include miscutils/Kbuild
122lib-all-y += $(patsubst %,miscutils/%,$(sort $(lib-y))) 125lib-all-y += $(patsubst %,miscutils/%,$(sort $(lib-y)))
123lib-y:= 126lib-y:=
127include mailutils/Kbuild
128lib-all-y += $(patsubst %,mailutils/%,$(sort $(lib-y)))
129lib-y:=
124include coreutils/libcoreutils/Kbuild 130include coreutils/libcoreutils/Kbuild
125lib-all-y += $(patsubst %,coreutils/libcoreutils/%,$(sort $(lib-y))) 131lib-all-y += $(patsubst %,coreutils/libcoreutils/%,$(sort $(lib-y)))
126lib-y:= 132lib-y:=
@@ -168,7 +174,7 @@ lib-all-y += $(patsubst %,libbb/%,$(sort $(lib-y)))
168lib-y:= 174lib-y:=
169 175
170comma:=, 176comma:=,
171busybox_unstripped.o: $(usage_stuff) include/applet_tables.h include/autoconf.h 177busybox_unstripped.o: $(usage_stuff) include/applet_tables.h include/NUM_APPLETS.h include/autoconf.h
172 $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) \ 178 $(CC) $(CPPFLAGS) $(CFLAGS) $(EXTRA_CFLAGS) \
173 $(patsubst %,-Wl$(comma)%,$(LDFLAGS) $(EXTRA_LDFLAGS)) \ 179 $(patsubst %,-Wl$(comma)%,$(LDFLAGS) $(EXTRA_LDFLAGS)) \
174 -DGCC_COMBINE=1 \ 180 -DGCC_COMBINE=1 \
@@ -194,14 +200,9 @@ busybox: busybox_unstripped.o
194include/autoconf.h: .config 200include/autoconf.h: .config
195 $(MAKE) -f $(srctree)/Makefile silentoldconfig 201 $(MAKE) -f $(srctree)/Makefile silentoldconfig
196 202
203# Override rules for host compile
197applets/usage: include/autoconf.h 204applets/usage: include/autoconf.h
198 $(HOSTCC) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -I$(srctree)/include -o applets/usage applets/usage.c 205 $(HOSTCC) -Wall -O2 -I$(srctree)/include -o applets/usage applets/usage.c
199 206
200applets/applet_tables: include/autoconf.h 207applets/applet_tables: include/autoconf.h
201 $(HOSTCC) -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -I$(srctree)/include -o applets/applet_tables applets/applet_tables.c 208 $(HOSTCC) -Wall -O2 -I$(srctree)/include -o applets/applet_tables applets/applet_tables.c
202
203include/usage_compressed.h: include/usage.h applets/usage
204 $(srctree)/applets/usage_compressed include/usage_compressed.h applets
205
206include/applet_tables.h: include/applets.h
207 applets/applet_tables include/applet_tables.h
diff --git a/scripts/defconfig.tig b/scripts/defconfig.tig
index 52fddfbf6..3dd02983f 100644
--- a/scripts/defconfig.tig
+++ b/scripts/defconfig.tig
@@ -1,7 +1,7 @@
1# 1#
2# Automatically generated make config: don't edit 2# Automatically generated make config: don't edit
3# Busybox version: 1.19.0.git 3# Busybox version: 1.19.0.git
4# Thu Mar 22 12:00:44 2012 4# Thu Mar 22 13:52:53 2012
5# 5#
6CONFIG_HAVE_DOT_CONFIG=y 6CONFIG_HAVE_DOT_CONFIG=y
7# CONFIG_PLATFORM_POSIX is not set 7# CONFIG_PLATFORM_POSIX is not set
@@ -431,6 +431,7 @@ CONFIG_FEATURE_KILL_DELAY=0
431# CONFIG_FEATURE_INITRD is not set 431# CONFIG_FEATURE_INITRD is not set
432CONFIG_INIT_TERMINAL_TYPE="" 432CONFIG_INIT_TERMINAL_TYPE=""
433# CONFIG_MESG is not set 433# CONFIG_MESG is not set
434# CONFIG_FEATURE_MESG_ENABLE_ONLY_GROUP is not set
434 435
435# 436#
436# Login/Password Management Utilities 437# Login/Password Management Utilities
@@ -476,6 +477,10 @@ CONFIG_LAST_SYSTEM_ID=0
476# CONFIG_FSCK is not set 477# CONFIG_FSCK is not set
477# CONFIG_LSATTR is not set 478# CONFIG_LSATTR is not set
478# CONFIG_TUNE2FS is not set 479# CONFIG_TUNE2FS is not set
480
481#
482# Linux Module Utilities
483#
479# CONFIG_MODINFO is not set 484# CONFIG_MODINFO is not set
480# CONFIG_MODPROBE_SMALL is not set 485# CONFIG_MODPROBE_SMALL is not set
481# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set 486# CONFIG_FEATURE_MODPROBE_SMALL_OPTIONS_ON_CMDLINE is not set
@@ -487,6 +492,10 @@ CONFIG_LAST_SYSTEM_ID=0
487# CONFIG_MODPROBE is not set 492# CONFIG_MODPROBE is not set
488# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set 493# CONFIG_FEATURE_MODPROBE_BLACKLIST is not set
489# CONFIG_DEPMOD is not set 494# CONFIG_DEPMOD is not set
495
496#
497# Options common to multiple modutils
498#
490# CONFIG_FEATURE_2_4_MODULES is not set 499# CONFIG_FEATURE_2_4_MODULES is not set
491# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set 500# CONFIG_FEATURE_INSMOD_TRY_MMAP is not set
492# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set 501# CONFIG_FEATURE_INSMOD_VERSION_CHECKING is not set
@@ -693,6 +702,8 @@ CONFIG_STRINGS=y
693# 702#
694# Networking Utilities 703# Networking Utilities
695# 704#
705# CONFIG_NAMEIF is not set
706# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
696# CONFIG_NBDCLIENT is not set 707# CONFIG_NBDCLIENT is not set
697# CONFIG_NC is not set 708# CONFIG_NC is not set
698# CONFIG_NC_SERVER is not set 709# CONFIG_NC_SERVER is not set
@@ -701,6 +712,7 @@ CONFIG_STRINGS=y
701# CONFIG_PING is not set 712# CONFIG_PING is not set
702# CONFIG_PING6 is not set 713# CONFIG_PING6 is not set
703# CONFIG_FEATURE_FANCY_PING is not set 714# CONFIG_FEATURE_FANCY_PING is not set
715# CONFIG_WHOIS is not set
704# CONFIG_FEATURE_IPV6 is not set 716# CONFIG_FEATURE_IPV6 is not set
705# CONFIG_FEATURE_UNIX_LOCAL is not set 717# CONFIG_FEATURE_UNIX_LOCAL is not set
706# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set 718# CONFIG_FEATURE_PREFER_IPV4_ADDRESS is not set
@@ -773,8 +785,6 @@ CONFIG_IFUPDOWN_IFSTATE_PATH=""
773# CONFIG_IPCALC is not set 785# CONFIG_IPCALC is not set
774# CONFIG_FEATURE_IPCALC_FANCY is not set 786# CONFIG_FEATURE_IPCALC_FANCY is not set
775# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set 787# CONFIG_FEATURE_IPCALC_LONG_OPTIONS is not set
776# CONFIG_NAMEIF is not set
777# CONFIG_FEATURE_NAMEIF_EXTENDED is not set
778# CONFIG_NETSTAT is not set 788# CONFIG_NETSTAT is not set
779# CONFIG_FEATURE_NETSTAT_WIDE is not set 789# CONFIG_FEATURE_NETSTAT_WIDE is not set
780# CONFIG_FEATURE_NETSTAT_PRG is not set 790# CONFIG_FEATURE_NETSTAT_PRG is not set
@@ -855,6 +865,7 @@ CONFIG_FEATURE_MIME_CHARSET=""
855# CONFIG_PMAP is not set 865# CONFIG_PMAP is not set
856# CONFIG_POWERTOP is not set 866# CONFIG_POWERTOP is not set
857# CONFIG_PSTREE is not set 867# CONFIG_PSTREE is not set
868# CONFIG_PWDX is not set
858# CONFIG_SMEMCAP is not set 869# CONFIG_SMEMCAP is not set
859# CONFIG_FREE is not set 870# CONFIG_FREE is not set
860# CONFIG_FUSER is not set 871# CONFIG_FUSER is not set
diff --git a/shell/ash.c b/shell/ash.c
index fd9141661..d12a483a3 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -56,6 +56,9 @@
56#include <fnmatch.h> 56#include <fnmatch.h>
57#include <sys/times.h> 57#include <sys/times.h>
58 58
59#include "busybox.h" /* for applet_names */
60#include "unicode.h"
61
59#include "shell_common.h" 62#include "shell_common.h"
60#if ENABLE_SH_MATH_SUPPORT 63#if ENABLE_SH_MATH_SUPPORT
61# include "math.h" 64# include "math.h"
@@ -86,13 +89,6 @@
86# error "Do not even bother, ash will not run on NOMMU machine" 89# error "Do not even bother, ash will not run on NOMMU machine"
87#endif 90#endif
88 91
89//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
90//applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
91//applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash))
92
93//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
94//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
95
96//config:config ASH 92//config:config ASH
97//config: bool "ash" 93//config: bool "ash"
98//config: default y 94//config: default y
@@ -204,12 +200,12 @@
204//config: variable each time it is displayed. 200//config: variable each time it is displayed.
205//config: 201//config:
206 202
207//usage:#define ash_trivial_usage NOUSAGE_STR 203//applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
208//usage:#define ash_full_usage "" 204//applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
209//usage:#define sh_trivial_usage NOUSAGE_STR 205//applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash))
210//usage:#define sh_full_usage "" 206
211//usage:#define bash_trivial_usage NOUSAGE_STR 207//kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
212//usage:#define bash_full_usage "" 208//kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
213 209
214#if ENABLE_PLATFORM_MINGW32 210#if ENABLE_PLATFORM_MINGW32
215struct forkshell; 211struct forkshell;
@@ -3705,12 +3701,12 @@ set_curjob(struct job *jp, unsigned mode)
3705 3701
3706 /* first remove from list */ 3702 /* first remove from list */
3707 jpp = curp = &curjob; 3703 jpp = curp = &curjob;
3708 do { 3704 while (1) {
3709 jp1 = *jpp; 3705 jp1 = *jpp;
3710 if (jp1 == jp) 3706 if (jp1 == jp)
3711 break; 3707 break;
3712 jpp = &jp1->prev_job; 3708 jpp = &jp1->prev_job;
3713 } while (1); 3709 }
3714 *jpp = jp1->prev_job; 3710 *jpp = jp1->prev_job;
3715 3711
3716 /* Then re-insert in correct position */ 3712 /* Then re-insert in correct position */
@@ -3726,14 +3722,14 @@ set_curjob(struct job *jp, unsigned mode)
3726 case CUR_RUNNING: 3722 case CUR_RUNNING:
3727 /* newly created job or backgrounded job, 3723 /* newly created job or backgrounded job,
3728 put after all stopped jobs. */ 3724 put after all stopped jobs. */
3729 do { 3725 while (1) {
3730 jp1 = *jpp; 3726 jp1 = *jpp;
3731#if JOBS 3727#if JOBS
3732 if (!jp1 || jp1->state != JOBSTOPPED) 3728 if (!jp1 || jp1->state != JOBSTOPPED)
3733#endif 3729#endif
3734 break; 3730 break;
3735 jpp = &jp1->prev_job; 3731 jpp = &jp1->prev_job;
3736 } while (1); 3732 }
3737 /* FALLTHROUGH */ 3733 /* FALLTHROUGH */
3738#if JOBS 3734#if JOBS
3739 case CUR_STOPPED: 3735 case CUR_STOPPED:
@@ -3906,7 +3902,7 @@ setjobctl(int on)
3906 goto out; 3902 goto out;
3907 /* fd is a tty at this point */ 3903 /* fd is a tty at this point */
3908 close_on_exec_on(fd); 3904 close_on_exec_on(fd);
3909 do { /* while we are in the background */ 3905 while (1) { /* while we are in the background */
3910 pgrp = tcgetpgrp(fd); 3906 pgrp = tcgetpgrp(fd);
3911 if (pgrp < 0) { 3907 if (pgrp < 0) {
3912 out: 3908 out:
@@ -3917,7 +3913,7 @@ setjobctl(int on)
3917 if (pgrp == getpgrp()) 3913 if (pgrp == getpgrp())
3918 break; 3914 break;
3919 killpg(0, SIGTTIN); 3915 killpg(0, SIGTTIN);
3920 } while (1); 3916 }
3921 initialpgrp = pgrp; 3917 initialpgrp = pgrp;
3922 3918
3923 setsignal(SIGTSTP); 3919 setsignal(SIGTSTP);
@@ -6328,7 +6324,7 @@ expari(int quotes)
6328 p = expdest - 1; 6324 p = expdest - 1;
6329 *p = '\0'; 6325 *p = '\0';
6330 p--; 6326 p--;
6331 do { 6327 while (1) {
6332 int esc; 6328 int esc;
6333 6329
6334 while ((unsigned char)*p != CTLARI) { 6330 while ((unsigned char)*p != CTLARI) {
@@ -6346,7 +6342,7 @@ expari(int quotes)
6346 } 6342 }
6347 6343
6348 p -= esc + 1; 6344 p -= esc + 1;
6349 } while (1); 6345 }
6350 6346
6351 begoff = p - start; 6347 begoff = p - start;
6352 6348
@@ -7754,8 +7750,6 @@ static int builtinloc = -1; /* index in path of %builtin, or -1 */
7754static void 7750static void
7755tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp) 7751tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **envp)
7756{ 7752{
7757 int repeated = 0;
7758
7759#if ENABLE_FEATURE_SH_STANDALONE 7753#if ENABLE_FEATURE_SH_STANDALONE
7760 if (applet_no >= 0) { 7754 if (applet_no >= 0) {
7761 if (APPLET_IS_NOEXEC(applet_no)) { 7755 if (APPLET_IS_NOEXEC(applet_no)) {
@@ -7779,25 +7773,36 @@ tryexec(IF_FEATURE_SH_STANDALONE(int applet_no,) char *cmd, char **argv, char **
7779#else 7773#else
7780 execve(cmd, argv, envp); 7774 execve(cmd, argv, envp);
7781#endif 7775#endif
7782 if (repeated) { 7776 if (cmd == (char*) bb_busybox_exec_path) {
7777 /* We already visited ENOEXEC branch below, don't do it again */
7778//TODO: try execve(initial_argv0_of_shell, argv, envp) before giving up?
7783 free(argv); 7779 free(argv);
7784 return; 7780 return;
7785 } 7781 }
7786 if (errno == ENOEXEC) { 7782 if (errno == ENOEXEC) {
7783 /* Run "cmd" as a shell script:
7784 * http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
7785 * "If the execve() function fails with ENOEXEC, the shell
7786 * shall execute a command equivalent to having a shell invoked
7787 * with the command name as its first operand,
7788 * with any remaining arguments passed to the new shell"
7789 *
7790 * That is, do not use $SHELL, user's shell, or /bin/sh;
7791 * just call ourselves.
7792 */
7787 char **ap; 7793 char **ap;
7788 char **new; 7794 char **new;
7789 7795
7790 for (ap = argv; *ap; ap++) 7796 for (ap = argv; *ap; ap++)
7791 continue; 7797 continue;
7792 ap = new = ckmalloc((ap - argv + 2) * sizeof(ap[0])); 7798 new = ckmalloc((ap - argv + 2) * sizeof(new[0]));
7793 ap[1] = cmd; 7799 new[0] = (char*) "ash";
7794 ap[0] = cmd = (char *)DEFAULT_SHELL; 7800 new[1] = cmd;
7795 ap += 2; 7801 ap = new + 2;
7796 argv++; 7802 while ((*ap++ = *++argv) != NULL)
7797 while ((*ap++ = *argv++) != NULL)
7798 continue; 7803 continue;
7804 cmd = (char*) bb_busybox_exec_path;
7799 argv = new; 7805 argv = new;
7800 repeated++;
7801 goto repeat; 7806 goto repeat;
7802 } 7807 }
7803} 7808}
@@ -10126,6 +10131,11 @@ preadfd(void)
10126# if ENABLE_FEATURE_TAB_COMPLETION 10131# if ENABLE_FEATURE_TAB_COMPLETION
10127 line_input_state->path_lookup = pathval(); 10132 line_input_state->path_lookup = pathval();
10128# endif 10133# endif
10134 /* Unicode support should be activated even if LANG is set
10135 * _during_ shell execution, not only if it was set when
10136 * shell was started. Therefore, re-check LANG every time:
10137 */
10138 reinit_unicode(lookupvar("LANG"));
10129 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout); 10139 nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout);
10130 if (nr == 0) { 10140 if (nr == 0) {
10131 /* Ctrl+C pressed */ 10141 /* Ctrl+C pressed */
@@ -10673,7 +10683,7 @@ options(int cmdline)
10673 else if (*argptr == NULL) 10683 else if (*argptr == NULL)
10674 setparam(argptr); 10684 setparam(argptr);
10675 } 10685 }
10676 break; /* "-" or "--" terminates options */ 10686 break; /* "-" or "--" terminates options */
10677 } 10687 }
10678 } 10688 }
10679 /* first char was + or - */ 10689 /* first char was + or - */
@@ -10775,10 +10785,10 @@ setcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
10775 10785
10776 if (!argv[1]) 10786 if (!argv[1])
10777 return showvars(nullstr, 0, VUNSET); 10787 return showvars(nullstr, 0, VUNSET);
10788
10778 INT_OFF; 10789 INT_OFF;
10779 retval = 1; 10790 retval = options(/*cmdline:*/ 0);
10780 if (!options(0)) { /* if no parse error... */ 10791 if (retval == 0) { /* if no parse error... */
10781 retval = 0;
10782 optschanged(); 10792 optschanged();
10783 if (*argptr != NULL) { 10793 if (*argptr != NULL) {
10784 setparam(argptr); 10794 setparam(argptr);
@@ -13525,14 +13535,32 @@ init(void)
13525 setvar("PPID", utoa(getppid()), 0); 13535 setvar("PPID", utoa(getppid()), 0);
13526 13536
13527 p = lookupvar("PWD"); 13537 p = lookupvar("PWD");
13528 if (p) 13538 if (p) {
13529 if (*p != '/' || stat(p, &st1) || stat(".", &st2) 13539 if (*p != '/' || stat(p, &st1) || stat(".", &st2)
13530 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) 13540 || st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino
13541 ) {
13531 p = '\0'; 13542 p = '\0';
13543 }
13544 }
13532 setpwd(p, 0); 13545 setpwd(p, 0);
13533 } 13546 }
13534} 13547}
13535 13548
13549
13550//usage:#define ash_trivial_usage
13551//usage: "[-/+OPTIONS] [-/+o OPT]... [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
13552//usage:#define ash_full_usage "\n\n"
13553//usage: "Unix shell interpreter"
13554
13555//usage:#if ENABLE_FEATURE_SH_IS_ASH
13556//usage:# define sh_trivial_usage ash_trivial_usage
13557//usage:# define sh_full_usage ash_full_usage
13558//usage:#endif
13559//usage:#if ENABLE_FEATURE_BASH_IS_ASH
13560//usage:# define bash_trivial_usage ash_trivial_usage
13561//usage:# define bash_full_usage ash_full_usage
13562//usage:#endif
13563
13536/* 13564/*
13537 * Process the shell command line arguments. 13565 * Process the shell command line arguments.
13538 */ 13566 */
@@ -13550,7 +13578,7 @@ procargs(char **argv)
13550 for (i = 0; i < NOPTS; i++) 13578 for (i = 0; i < NOPTS; i++)
13551 optlist[i] = 2; 13579 optlist[i] = 2;
13552 argptr = xargv; 13580 argptr = xargv;
13553 if (options(1)) { 13581 if (options(/*cmdline:*/ 1)) {
13554 /* it already printed err message */ 13582 /* it already printed err message */
13555 raise_exception(EXERROR); 13583 raise_exception(EXERROR);
13556 } 13584 }
diff --git a/shell/hush.c b/shell/hush.c
index 4d9e5f8c7..e4c3a7d77 100644
--- a/shell/hush.c
+++ b/shell/hush.c
@@ -81,7 +81,6 @@
81 * $ "export" i=`echo 'aaa bbb'`; echo "$i" 81 * $ "export" i=`echo 'aaa bbb'`; echo "$i"
82 * aaa 82 * aaa
83 */ 83 */
84#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
85#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \ 84#if !(defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) \
86 || defined(__APPLE__) \ 85 || defined(__APPLE__) \
87 ) 86 )
@@ -93,6 +92,8 @@
93# include <fnmatch.h> 92# include <fnmatch.h>
94#endif 93#endif
95 94
95#include "busybox.h" /* for APPLET_IS_NOFORK/NOEXEC */
96#include "unicode.h"
96#include "shell_common.h" 97#include "shell_common.h"
97#include "math.h" 98#include "math.h"
98#include "match.h" 99#include "match.h"
@@ -105,14 +106,6 @@
105# define PIPE_BUF 4096 /* amount of buffering in a pipe */ 106# define PIPE_BUF 4096 /* amount of buffering in a pipe */
106#endif 107#endif
107 108
108//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
109//applet:IF_MSH(APPLET(msh, BB_DIR_BIN, BB_SUID_DROP))
110//applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, sh))
111//applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, bash))
112
113//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
114//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
115
116//config:config HUSH 109//config:config HUSH
117//config: bool "hush" 110//config: bool "hush"
118//config: default y 111//config: default y
@@ -249,20 +242,35 @@
249//config: msh is deprecated and will be removed, please migrate to hush. 242//config: msh is deprecated and will be removed, please migrate to hush.
250//config: 243//config:
251 244
245//applet:IF_HUSH(APPLET(hush, BB_DIR_BIN, BB_SUID_DROP))
246//applet:IF_MSH(APPLET(msh, BB_DIR_BIN, BB_SUID_DROP))
247//applet:IF_FEATURE_SH_IS_HUSH(APPLET_ODDNAME(sh, hush, BB_DIR_BIN, BB_SUID_DROP, sh))
248//applet:IF_FEATURE_BASH_IS_HUSH(APPLET_ODDNAME(bash, hush, BB_DIR_BIN, BB_SUID_DROP, bash))
249
250//kbuild:lib-$(CONFIG_HUSH) += hush.o match.o shell_common.o
251//kbuild:lib-$(CONFIG_HUSH_RANDOM_SUPPORT) += random.o
252
252/* -i (interactive) and -s (read stdin) are also accepted, 253/* -i (interactive) and -s (read stdin) are also accepted,
253 * but currently do nothing, therefore aren't shown in help. 254 * but currently do nothing, therefore aren't shown in help.
254 * NOMMU-specific options are not meant to be used by users, 255 * NOMMU-specific options are not meant to be used by users,
255 * therefore we don't show them either. 256 * therefore we don't show them either.
256 */ 257 */
257//usage:#define hush_trivial_usage 258//usage:#define hush_trivial_usage
258//usage: "[-nx] [-c SCRIPT]" 259//usage: "[-nx] [-c 'SCRIPT' [ARG0 [ARGS]] / FILE [ARGS]]"
259//usage:#define hush_full_usage "" 260//usage:#define hush_full_usage "\n\n"
261//usage: "Unix shell interpreter"
262
260//usage:#define msh_trivial_usage hush_trivial_usage 263//usage:#define msh_trivial_usage hush_trivial_usage
261//usage:#define msh_full_usage "" 264//usage:#define msh_full_usage hush_full_usage
262//usage:#define sh_trivial_usage NOUSAGE_STR 265
263//usage:#define sh_full_usage "" 266//usage:#if ENABLE_FEATURE_SH_IS_HUSH
264//usage:#define bash_trivial_usage NOUSAGE_STR 267//usage:# define sh_trivial_usage hush_trivial_usage
265//usage:#define bash_full_usage "" 268//usage:# define sh_full_usage hush_full_usage
269//usage:#endif
270//usage:#if ENABLE_FEATURE_BASH_IS_HUSH
271//usage:# define bash_trivial_usage hush_trivial_usage
272//usage:# define bash_full_usage hush_full_usage
273//usage:#endif
266 274
267 275
268/* Build knobs */ 276/* Build knobs */
@@ -1087,17 +1095,10 @@ static void syntax_error_unterm_str(unsigned lineno, const char *s)
1087 die_if_script(lineno, "syntax error: unterminated %s", s); 1095 die_if_script(lineno, "syntax error: unterminated %s", s);
1088} 1096}
1089 1097
1090/* It so happens that all such cases are totally fatal
1091 * even if shell is interactive: EOF while looking for closing
1092 * delimiter. There is nowhere to read stuff from after that,
1093 * it's EOF! The only choice is to terminate.
1094 */
1095static void syntax_error_unterm_ch(unsigned lineno, char ch) NORETURN;
1096static void syntax_error_unterm_ch(unsigned lineno, char ch) 1098static void syntax_error_unterm_ch(unsigned lineno, char ch)
1097{ 1099{
1098 char msg[2] = { ch, '\0' }; 1100 char msg[2] = { ch, '\0' };
1099 syntax_error_unterm_str(lineno, msg); 1101 syntax_error_unterm_str(lineno, msg);
1100 xfunc_die();
1101} 1102}
1102 1103
1103static void syntax_error_unexpected_ch(unsigned lineno, int ch) 1104static void syntax_error_unexpected_ch(unsigned lineno, int ch)
@@ -1899,6 +1900,12 @@ static void get_user_input(struct in_str *i)
1899 /* Enable command line editing only while a command line 1900 /* Enable command line editing only while a command line
1900 * is actually being read */ 1901 * is actually being read */
1901 do { 1902 do {
1903 /* Unicode support should be activated even if LANG is set
1904 * _during_ shell execution, not only if it was set when
1905 * shell was started. Therefore, re-check LANG every time:
1906 */
1907 reinit_unicode(get_local_var_value("LANG"));
1908
1902 G.flag_SIGINT = 0; 1909 G.flag_SIGINT = 0;
1903 /* buglet: SIGINT will not make new prompt to appear _at once_, 1910 /* buglet: SIGINT will not make new prompt to appear _at once_,
1904 * only after <Enter>. (^C will work) */ 1911 * only after <Enter>. (^C will work) */
@@ -3525,39 +3532,40 @@ static int parse_group(o_string *dest, struct parse_context *ctx,
3525 3532
3526#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS 3533#if ENABLE_HUSH_TICK || ENABLE_SH_MATH_SUPPORT || ENABLE_HUSH_DOLLAR_OPS
3527/* Subroutines for copying $(...) and `...` things */ 3534/* Subroutines for copying $(...) and `...` things */
3528static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote); 3535static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote);
3529/* '...' */ 3536/* '...' */
3530static void add_till_single_quote(o_string *dest, struct in_str *input) 3537static int add_till_single_quote(o_string *dest, struct in_str *input)
3531{ 3538{
3532 while (1) { 3539 while (1) {
3533 int ch = i_getch(input); 3540 int ch = i_getch(input);
3534 if (ch == EOF) { 3541 if (ch == EOF) {
3535 syntax_error_unterm_ch('\''); 3542 syntax_error_unterm_ch('\'');
3536 /*xfunc_die(); - redundant */ 3543 return 0;
3537 } 3544 }
3538 if (ch == '\'') 3545 if (ch == '\'')
3539 return; 3546 return 1;
3540 o_addchr(dest, ch); 3547 o_addchr(dest, ch);
3541 } 3548 }
3542} 3549}
3543/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */ 3550/* "...\"...`..`...." - do we need to handle "...$(..)..." too? */
3544static void add_till_double_quote(o_string *dest, struct in_str *input) 3551static int add_till_double_quote(o_string *dest, struct in_str *input)
3545{ 3552{
3546 while (1) { 3553 while (1) {
3547 int ch = i_getch(input); 3554 int ch = i_getch(input);
3548 if (ch == EOF) { 3555 if (ch == EOF) {
3549 syntax_error_unterm_ch('"'); 3556 syntax_error_unterm_ch('"');
3550 /*xfunc_die(); - redundant */ 3557 return 0;
3551 } 3558 }
3552 if (ch == '"') 3559 if (ch == '"')
3553 return; 3560 return 1;
3554 if (ch == '\\') { /* \x. Copy both chars. */ 3561 if (ch == '\\') { /* \x. Copy both chars. */
3555 o_addchr(dest, ch); 3562 o_addchr(dest, ch);
3556 ch = i_getch(input); 3563 ch = i_getch(input);
3557 } 3564 }
3558 o_addchr(dest, ch); 3565 o_addchr(dest, ch);
3559 if (ch == '`') { 3566 if (ch == '`') {
3560 add_till_backquote(dest, input, /*in_dquote:*/ 1); 3567 if (!add_till_backquote(dest, input, /*in_dquote:*/ 1))
3568 return 0;
3561 o_addchr(dest, ch); 3569 o_addchr(dest, ch);
3562 continue; 3570 continue;
3563 } 3571 }
@@ -3578,12 +3586,12 @@ static void add_till_double_quote(o_string *dest, struct in_str *input)
3578 * Example Output 3586 * Example Output
3579 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST 3587 * echo `echo '\'TEST\`echo ZZ\`BEST` \TESTZZBEST
3580 */ 3588 */
3581static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquote) 3589static int add_till_backquote(o_string *dest, struct in_str *input, int in_dquote)
3582{ 3590{
3583 while (1) { 3591 while (1) {
3584 int ch = i_getch(input); 3592 int ch = i_getch(input);
3585 if (ch == '`') 3593 if (ch == '`')
3586 return; 3594 return 1;
3587 if (ch == '\\') { 3595 if (ch == '\\') {
3588 /* \x. Copy both unless it is \`, \$, \\ and maybe \" */ 3596 /* \x. Copy both unless it is \`, \$, \\ and maybe \" */
3589 ch = i_getch(input); 3597 ch = i_getch(input);
@@ -3597,7 +3605,7 @@ static void add_till_backquote(o_string *dest, struct in_str *input, int in_dquo
3597 } 3605 }
3598 if (ch == EOF) { 3606 if (ch == EOF) {
3599 syntax_error_unterm_ch('`'); 3607 syntax_error_unterm_ch('`');
3600 /*xfunc_die(); - redundant */ 3608 return 0;
3601 } 3609 }
3602 o_addchr(dest, ch); 3610 o_addchr(dest, ch);
3603 } 3611 }
@@ -3633,7 +3641,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
3633 ch = i_getch(input); 3641 ch = i_getch(input);
3634 if (ch == EOF) { 3642 if (ch == EOF) {
3635 syntax_error_unterm_ch(end_ch); 3643 syntax_error_unterm_ch(end_ch);
3636 /*xfunc_die(); - redundant */ 3644 return 0;
3637 } 3645 }
3638 if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) { 3646 if (ch == end_ch IF_HUSH_BASH_COMPAT( || ch == end_char2)) {
3639 if (!dbl) 3647 if (!dbl)
@@ -3647,22 +3655,26 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
3647 o_addchr(dest, ch); 3655 o_addchr(dest, ch);
3648 if (ch == '(' || ch == '{') { 3656 if (ch == '(' || ch == '{') {
3649 ch = (ch == '(' ? ')' : '}'); 3657 ch = (ch == '(' ? ')' : '}');
3650 add_till_closing_bracket(dest, input, ch); 3658 if (!add_till_closing_bracket(dest, input, ch))
3659 return 0;
3651 o_addchr(dest, ch); 3660 o_addchr(dest, ch);
3652 continue; 3661 continue;
3653 } 3662 }
3654 if (ch == '\'') { 3663 if (ch == '\'') {
3655 add_till_single_quote(dest, input); 3664 if (!add_till_single_quote(dest, input))
3665 return 0;
3656 o_addchr(dest, ch); 3666 o_addchr(dest, ch);
3657 continue; 3667 continue;
3658 } 3668 }
3659 if (ch == '"') { 3669 if (ch == '"') {
3660 add_till_double_quote(dest, input); 3670 if (!add_till_double_quote(dest, input))
3671 return 0;
3661 o_addchr(dest, ch); 3672 o_addchr(dest, ch);
3662 continue; 3673 continue;
3663 } 3674 }
3664 if (ch == '`') { 3675 if (ch == '`') {
3665 add_till_backquote(dest, input, /*in_dquote:*/ 0); 3676 if (!add_till_backquote(dest, input, /*in_dquote:*/ 0))
3677 return 0;
3666 o_addchr(dest, ch); 3678 o_addchr(dest, ch);
3667 continue; 3679 continue;
3668 } 3680 }
@@ -3671,7 +3683,7 @@ static int add_till_closing_bracket(o_string *dest, struct in_str *input, unsign
3671 ch = i_getch(input); 3683 ch = i_getch(input);
3672 if (ch == EOF) { 3684 if (ch == EOF) {
3673 syntax_error_unterm_ch(')'); 3685 syntax_error_unterm_ch(')');
3674 /*xfunc_die(); - redundant */ 3686 return 0;
3675 } 3687 }
3676 o_addchr(dest, ch); 3688 o_addchr(dest, ch);
3677 continue; 3689 continue;
@@ -3742,8 +3754,8 @@ static int parse_dollar(o_string *as_string,
3742 ) { 3754 ) {
3743 bad_dollar_syntax: 3755 bad_dollar_syntax:
3744 syntax_error_unterm_str("${name}"); 3756 syntax_error_unterm_str("${name}");
3745 debug_printf_parse("parse_dollar return 1: unterminated ${name}\n"); 3757 debug_printf_parse("parse_dollar return 0: unterminated ${name}\n");
3746 return 1; 3758 return 0;
3747 } 3759 }
3748 nommu_addchr(as_string, ch); 3760 nommu_addchr(as_string, ch);
3749 ch |= quote_mask; 3761 ch |= quote_mask;
@@ -3799,6 +3811,8 @@ static int parse_dollar(o_string *as_string,
3799 pos = dest->length; 3811 pos = dest->length;
3800#if ENABLE_HUSH_DOLLAR_OPS 3812#if ENABLE_HUSH_DOLLAR_OPS
3801 last_ch = add_till_closing_bracket(dest, input, end_ch); 3813 last_ch = add_till_closing_bracket(dest, input, end_ch);
3814 if (last_ch == 0) /* error? */
3815 return 0;
3802#else 3816#else
3803#error Simple code to only allow ${var} is not implemented 3817#error Simple code to only allow ${var} is not implemented
3804#endif 3818#endif
@@ -3843,7 +3857,8 @@ static int parse_dollar(o_string *as_string,
3843 o_addchr(dest, /*quote_mask |*/ '+'); 3857 o_addchr(dest, /*quote_mask |*/ '+');
3844 if (!BB_MMU) 3858 if (!BB_MMU)
3845 pos = dest->length; 3859 pos = dest->length;
3846 add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG); 3860 if (!add_till_closing_bracket(dest, input, ')' | DOUBLE_CLOSE_CHAR_FLAG))
3861 return 0; /* error */
3847 if (as_string) { 3862 if (as_string) {
3848 o_addstr(as_string, dest->data + pos); 3863 o_addstr(as_string, dest->data + pos);
3849 o_addchr(as_string, ')'); 3864 o_addchr(as_string, ')');
@@ -3858,7 +3873,8 @@ static int parse_dollar(o_string *as_string,
3858 o_addchr(dest, quote_mask | '`'); 3873 o_addchr(dest, quote_mask | '`');
3859 if (!BB_MMU) 3874 if (!BB_MMU)
3860 pos = dest->length; 3875 pos = dest->length;
3861 add_till_closing_bracket(dest, input, ')'); 3876 if (!add_till_closing_bracket(dest, input, ')'))
3877 return 0; /* error */
3862 if (as_string) { 3878 if (as_string) {
3863 o_addstr(as_string, dest->data + pos); 3879 o_addstr(as_string, dest->data + pos);
3864 o_addchr(as_string, ')'); 3880 o_addchr(as_string, ')');
@@ -3885,8 +3901,8 @@ static int parse_dollar(o_string *as_string,
3885 default: 3901 default:
3886 o_addQchr(dest, '$'); 3902 o_addQchr(dest, '$');
3887 } 3903 }
3888 debug_printf_parse("parse_dollar return 0\n"); 3904 debug_printf_parse("parse_dollar return 1 (ok)\n");
3889 return 0; 3905 return 1;
3890#undef as_string 3906#undef as_string
3891} 3907}
3892 3908
@@ -3927,13 +3943,13 @@ static int encode_string(o_string *as_string,
3927 if (ch != EOF) 3943 if (ch != EOF)
3928 nommu_addchr(as_string, ch); 3944 nommu_addchr(as_string, ch);
3929 if (ch == dquote_end) { /* may be only '"' or EOF */ 3945 if (ch == dquote_end) { /* may be only '"' or EOF */
3930 debug_printf_parse("encode_string return 0\n"); 3946 debug_printf_parse("encode_string return 1 (ok)\n");
3931 return 0; 3947 return 1;
3932 } 3948 }
3933 /* note: can't move it above ch == dquote_end check! */ 3949 /* note: can't move it above ch == dquote_end check! */
3934 if (ch == EOF) { 3950 if (ch == EOF) {
3935 syntax_error_unterm_ch('"'); 3951 syntax_error_unterm_ch('"');
3936 /*xfunc_die(); - redundant */ 3952 return 0; /* error */
3937 } 3953 }
3938 next = '\0'; 3954 next = '\0';
3939 if (ch != '\n') { 3955 if (ch != '\n') {
@@ -3964,10 +3980,10 @@ static int encode_string(o_string *as_string,
3964 goto again; 3980 goto again;
3965 } 3981 }
3966 if (ch == '$') { 3982 if (ch == '$') {
3967 if (parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80) != 0) { 3983 if (!parse_dollar(as_string, dest, input, /*quote_mask:*/ 0x80)) {
3968 debug_printf_parse("encode_string return 1: " 3984 debug_printf_parse("encode_string return 0: "
3969 "parse_dollar returned non-0\n"); 3985 "parse_dollar returned 0 (error)\n");
3970 return 1; 3986 return 0;
3971 } 3987 }
3972 goto again; 3988 goto again;
3973 } 3989 }
@@ -3976,7 +3992,8 @@ static int encode_string(o_string *as_string,
3976 //unsigned pos = dest->length; 3992 //unsigned pos = dest->length;
3977 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3993 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3978 o_addchr(dest, 0x80 | '`'); 3994 o_addchr(dest, 0x80 | '`');
3979 add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'); 3995 if (!add_till_backquote(dest, input, /*in_dquote:*/ dquote_end == '"'))
3996 return 0; /* error */
3980 o_addchr(dest, SPECIAL_VAR_SYMBOL); 3997 o_addchr(dest, SPECIAL_VAR_SYMBOL);
3981 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos); 3998 //debug_printf_subst("SUBST RES3 '%s'\n", dest->data + pos);
3982 goto again; 3999 goto again;
@@ -4047,8 +4064,8 @@ static struct pipe *parse_stream(char **pstring,
4047 /* end_trigger == '}' case errors out earlier, 4064 /* end_trigger == '}' case errors out earlier,
4048 * checking only ')' */ 4065 * checking only ')' */
4049 if (end_trigger == ')') { 4066 if (end_trigger == ')') {
4050 syntax_error_unterm_ch('('); /* exits */ 4067 syntax_error_unterm_ch('(');
4051 /* goto parse_error; */ 4068 goto parse_error;
4052 } 4069 }
4053 4070
4054 if (done_word(&dest, &ctx)) { 4071 if (done_word(&dest, &ctx)) {
@@ -4339,9 +4356,9 @@ static struct pipe *parse_stream(char **pstring,
4339 dest.has_quoted_part = 1; 4356 dest.has_quoted_part = 1;
4340 break; 4357 break;
4341 case '$': 4358 case '$':
4342 if (parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0) != 0) { 4359 if (!parse_dollar(&ctx.as_string, &dest, input, /*quote_mask:*/ 0)) {
4343 debug_printf_parse("parse_stream parse error: " 4360 debug_printf_parse("parse_stream parse error: "
4344 "parse_dollar returned non-0\n"); 4361 "parse_dollar returned 0 (error)\n");
4345 goto parse_error; 4362 goto parse_error;
4346 } 4363 }
4347 break; 4364 break;
@@ -4351,7 +4368,7 @@ static struct pipe *parse_stream(char **pstring,
4351 ch = i_getch(input); 4368 ch = i_getch(input);
4352 if (ch == EOF) { 4369 if (ch == EOF) {
4353 syntax_error_unterm_ch('\''); 4370 syntax_error_unterm_ch('\'');
4354 /*xfunc_die(); - redundant */ 4371 goto parse_error;
4355 } 4372 }
4356 nommu_addchr(&ctx.as_string, ch); 4373 nommu_addchr(&ctx.as_string, ch);
4357 if (ch == '\'') 4374 if (ch == '\'')
@@ -4363,7 +4380,7 @@ static struct pipe *parse_stream(char **pstring,
4363 dest.has_quoted_part = 1; 4380 dest.has_quoted_part = 1;
4364 if (dest.o_assignment == NOT_ASSIGNMENT) 4381 if (dest.o_assignment == NOT_ASSIGNMENT)
4365 dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS; 4382 dest.o_expflags |= EXP_FLAG_ESC_GLOB_CHARS;
4366 if (encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1)) 4383 if (!encode_string(&ctx.as_string, &dest, input, '"', /*process_bkslash:*/ 1))
4367 goto parse_error; 4384 goto parse_error;
4368 dest.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS; 4385 dest.o_expflags &= ~EXP_FLAG_ESC_GLOB_CHARS;
4369 break; 4386 break;
@@ -4374,7 +4391,8 @@ static struct pipe *parse_stream(char **pstring,
4374 o_addchr(&dest, SPECIAL_VAR_SYMBOL); 4391 o_addchr(&dest, SPECIAL_VAR_SYMBOL);
4375 o_addchr(&dest, '`'); 4392 o_addchr(&dest, '`');
4376 pos = dest.length; 4393 pos = dest.length;
4377 add_till_backquote(&dest, input, /*in_dquote:*/ 0); 4394 if (!add_till_backquote(&dest, input, /*in_dquote:*/ 0))
4395 goto parse_error;
4378# if !BB_MMU 4396# if !BB_MMU
4379 o_addstr(&ctx.as_string, dest.data + pos); 4397 o_addstr(&ctx.as_string, dest.data + pos);
4380 o_addchr(&ctx.as_string, '`'); 4398 o_addchr(&ctx.as_string, '`');
@@ -4650,6 +4668,7 @@ static char *encode_then_expand_string(const char *str, int process_bkslash, int
4650 */ 4668 */
4651 setup_string_in_str(&input, str); 4669 setup_string_in_str(&input, str);
4652 encode_string(NULL, &dest, &input, EOF, process_bkslash); 4670 encode_string(NULL, &dest, &input, EOF, process_bkslash);
4671//TODO: error check (encode_string returns 0 on error)?
4653 //bb_error_msg("'%s' -> '%s'", str, dest.data); 4672 //bb_error_msg("'%s' -> '%s'", str, dest.data);
4654 exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash); 4673 exp_str = expand_string_to_string(dest.data, /*unbackslash:*/ do_unbackslash);
4655 //bb_error_msg("'%s' -> '%s'", dest.data, exp_str); 4674 //bb_error_msg("'%s' -> '%s'", dest.data, exp_str);
@@ -5540,6 +5559,10 @@ static void parse_and_run_stream(struct in_str *inp, int end_trigger)
5540 debug_printf_exec("parse_and_run_stream: run_and_free_list\n"); 5559 debug_printf_exec("parse_and_run_stream: run_and_free_list\n");
5541 run_and_free_list(pipe_list); 5560 run_and_free_list(pipe_list);
5542 empty = 0; 5561 empty = 0;
5562#if ENABLE_HUSH_FUNCTIONS
5563 if (G.flag_return_in_progress == 1)
5564 break;
5565#endif
5543 } 5566 }
5544} 5567}
5545 5568
@@ -8607,6 +8630,8 @@ static int FAST_FUNC builtin_source(char **argv)
8607#endif 8630#endif
8608 save_and_replace_G_args(&sv, argv); 8631 save_and_replace_G_args(&sv, argv);
8609 8632
8633//TODO: syntax errors in sourced file should never abort the "calling" script.
8634//Try: bash -c '. ./bad_file; echo YES'
8610 parse_and_run_file(input); 8635 parse_and_run_file(input);
8611 fclose(input); 8636 fclose(input);
8612 8637
diff --git a/shell/hush_test/hush-misc/return1.right b/shell/hush_test/hush-misc/return1.right
new file mode 100644
index 000000000..7b24a35ff
--- /dev/null
+++ b/shell/hush_test/hush-misc/return1.right
@@ -0,0 +1 @@
Ok:0
diff --git a/shell/hush_test/hush-misc/return1.tests b/shell/hush_test/hush-misc/return1.tests
new file mode 100755
index 000000000..eeb92ef3f
--- /dev/null
+++ b/shell/hush_test/hush-misc/return1.tests
@@ -0,0 +1,4 @@
1echo "true && return; echo Should not be printed" >return_sourced
2. ./return_sourced
3rm return_sourced
4echo Ok:$?
diff --git a/shell/hush_test/hush-misc/source1.right b/shell/hush_test/hush-misc/source1.right
new file mode 100644
index 000000000..d4256034b
--- /dev/null
+++ b/shell/hush_test/hush-misc/source1.right
@@ -0,0 +1,5 @@
1hush: syntax error: unterminated ${name}
2line2
3Ok1:0
4hush: syntax error: unterminated '
5Ok2:1
diff --git a/shell/hush_test/hush-misc/source1.tests b/shell/hush_test/hush-misc/source1.tests
new file mode 100755
index 000000000..c13888359
--- /dev/null
+++ b/shell/hush_test/hush-misc/source1.tests
@@ -0,0 +1,10 @@
1echo 'echo ${^}
2echo line2' >sourced1
3. ./sourced1
4echo Ok1:$?
5
6echo "echo '" >sourced1
7. ./sourced1
8echo Ok2:$?
9
10rm sourced1
diff --git a/sysklogd/Config.src b/sysklogd/Config.src
index 1e5987275..d62dc5f5c 100644
--- a/sysklogd/Config.src
+++ b/sysklogd/Config.src
@@ -119,7 +119,8 @@ config KLOGD
119config FEATURE_KLOGD_KLOGCTL 119config FEATURE_KLOGD_KLOGCTL
120 bool "Use the klogctl() interface" 120 bool "Use the klogctl() interface"
121 default y 121 default y
122 depends on KLOGD && PLATFORM_LINUX 122 depends on KLOGD
123 select PLATFORM_LINUX
123 help 124 help
124 The klogd applet supports two interfaces for reading 125 The klogd applet supports two interfaces for reading
125 kernel messages. Linux provides the klogctl() interface 126 kernel messages. Linux provides the klogctl() interface
diff --git a/sysklogd/klogd.c b/sysklogd/klogd.c
index 0d4c2578d..db32065fb 100644
--- a/sysklogd/klogd.c
+++ b/sysklogd/klogd.c
@@ -150,12 +150,41 @@ int klogd_main(int argc UNUSED_PARAM, char **argv)
150 */ 150 */
151 klogd_open(); 151 klogd_open();
152 openlog("kernel", 0, LOG_KERN); 152 openlog("kernel", 0, LOG_KERN);
153 /*
154 * glibc problem: for some reason, glibc changes LOG_KERN to LOG_USER
155 * above. The logic behind this is that standard
156 * http://pubs.opengroup.org/onlinepubs/9699919799/functions/syslog.html
157 * says the following about openlog and syslog:
158 * "LOG_USER
159 * Messages generated by arbitrary processes.
160 * This is the default facility identifier if none is specified."
161 *
162 * I believe glibc misinterpreted this text as "if openlog's
163 * third parameter is 0 (=LOG_KERN), treat it as LOG_USER".
164 * Whereas it was meant to say "if *syslog* is called with facility
165 * 0 in its 1st parameter without prior call to openlog, then perform
166 * implicit openlog(LOG_USER)".
167 *
168 * As a result of this, eh, feature, standard klogd was forced
169 * to open-code its own openlog and syslog implementation (!).
170 *
171 * Note that prohibiting openlog(LOG_KERN) on libc level does not
172 * add any security: any process can open a socket to "/dev/log"
173 * and write a string "<0>Voila, a LOG_KERN + LOG_EMERG message"
174 *
175 * Google code search tells me there is no widespread use of
176 * openlog("foo", 0, 0), thus fixing glibc won't break userspace.
177 *
178 * The bug against glibc was filed:
179 * bugzilla.redhat.com/show_bug.cgi?id=547000
180 */
153 181
154 if (i) 182 if (i)
155 klogd_setloglevel(i); 183 klogd_setloglevel(i);
156 184
157 bb_signals(BB_FATAL_SIGS, record_signo);
158 signal(SIGHUP, SIG_IGN); 185 signal(SIGHUP, SIG_IGN);
186 /* We want klogd_read to not be restarted, thus _norestart: */
187 bb_signals_recursive_norestart(BB_FATAL_SIGS, record_signo);
159 188
160 syslog(LOG_NOTICE, "klogd started: %s", bb_banner); 189 syslog(LOG_NOTICE, "klogd started: %s", bb_banner);
161 190
diff --git a/testsuite/ls.tests b/testsuite/ls.tests
index 1669579e7..e2284658d 100755
--- a/testsuite/ls.tests
+++ b/testsuite/ls.tests
@@ -251,6 +251,16 @@ test x"$CONFIG_UNICODE_SUPPORT" = x"y" \
2510110_5.3.2__U+FFFF_=_ef_bf_bf_=_"?"_______________________________________| 2510110_5.3.2__U+FFFF_=_ef_bf_bf_=_"?"_______________________________________|
252' "" "" 252' "" ""
253 253
254rm -rf ls.testdir 2>/dev/null
255mkdir ls.testdir || exit 1
256
257# testing "test name" "command" "expected result" "file input" "stdin"
258
259testing "ls symlink_to_dir" \
260"touch ls.testdir/A ls.testdir/B; ln -s ls.testdir ls.link; ls ls.link; ls -1 ls.link/; ls -1 ls.link; rm -f ls.link" \
261"A\nB\nA\nB\nA\nB\n" \
262"" ""
263
254# Clean up 264# Clean up
255rm -rf ls.testdir 2>/dev/null 265rm -rf ls.testdir 2>/dev/null
256 266
diff --git a/testsuite/mount.tests b/testsuite/mount.tests
index d3d2400e8..58eeb2ec5 100755
--- a/testsuite/mount.tests
+++ b/testsuite/mount.tests
@@ -20,7 +20,7 @@ if test x"$CONFIG_MKFS_MINIX" != x"y" \
20 exit 0 20 exit 0
21fi 21fi
22 22
23testdir=$PWD/mount.testdir 23testdir="$PWD/mount.testdir"
24 24
25dd if=/dev/zero of=mount.image1m count=1 bs=1M 2>/dev/null || { echo "dd error"; exit 1; } 25dd if=/dev/zero of=mount.image1m count=1 bs=1M 2>/dev/null || { echo "dd error"; exit 1; }
26mkfs.minix -v mount.image1m >/dev/null 2>&1 || { echo "mkfs.minix error"; exit 1; } 26mkfs.minix -v mount.image1m >/dev/null 2>&1 || { echo "mkfs.minix error"; exit 1; }
@@ -44,4 +44,41 @@ umount -d "$testdir"
44rmdir "$testdir" 44rmdir "$testdir"
45rm mount.image1m 45rm mount.image1m
46 46
47
48# Bug: mount.shared1 directory shows no files (has to show files a and b)
49testing "mount bind+rshared" "\
50mkdir -p mount.dir mount.shared1 mount.shared2
51touch mount.dir/a mount.dir/b
52
53mount --bind mount.shared1 mount.shared1 2>&1
54mount --make-rshared mount.shared1 2>&1
55mount --bind mount.shared2 mount.shared2 2>&1
56mount --make-rshared mount.shared2 2>&1
57
58mount --bind mount.shared2 mount.shared1 2>&1
59mount --bind mount.dir mount.shared2 2>&1
60
61ls -R mount.dir mount.shared1 mount.shared2 2>&1
62
63umount mount.dir mount.shared1 mount.shared2 2>/dev/null
64umount mount.dir mount.shared1 mount.shared2 2>/dev/null
65umount mount.dir mount.shared1 mount.shared2 2>/dev/null
66rm -f mount.dir/a mount.dir/b mount.dir/c
67rmdir mount.dir mount.shared1 mount.shared2
68" \
69"\
70mount.dir:
71a
72b
73
74mount.shared1:
75a
76b
77
78mount.shared2:
79a
80b
81" \
82 "" ""
83
47exit $FAILCOUNT 84exit $FAILCOUNT
diff --git a/testsuite/tar.tests b/testsuite/tar.tests
index 472064f7f..534135df8 100755
--- a/testsuite/tar.tests
+++ b/testsuite/tar.tests
@@ -168,6 +168,23 @@ Ok
168" \ 168" \
169"" "" 169"" ""
170 170
171# On extract, everything up to and including last ".." component is stripped
172testing "tar strips /../ on extract" "\
173rm -rf input_* test.tar 2>/dev/null
174mkdir input_dir
175echo Ok >input_dir/file
176tar cf test.tar ./../tar.tempdir/input_dir/../input_dir 2>&1
177rm -rf input_* 2>/dev/null
178tar -vxf test.tar 2>&1
179cat input_dir/file 2>&1
180" "\
181tar: removing leading './../tar.tempdir/input_dir/../' from member names
182input_dir/
183input_dir/file
184Ok
185" \
186"" ""
187
171 188
172cd .. && rm -rf tar.tempdir || exit 1 189cd .. && rm -rf tar.tempdir || exit 1
173 190
diff --git a/util-linux/Config.src b/util-linux/Config.src
index 941a47f90..90606bcae 100644
--- a/util-linux/Config.src
+++ b/util-linux/Config.src
@@ -10,7 +10,7 @@ INSERT
10config ACPID 10config ACPID
11 bool "acpid" 11 bool "acpid"
12 default y 12 default y
13 depends on PLATFORM_LINUX 13 select PLATFORM_LINUX
14 help 14 help
15 acpid listens to ACPI events coming either in textual form from 15 acpid listens to ACPI events coming either in textual form from
16 /proc/acpi/event (though it is marked deprecated it is still widely 16 /proc/acpi/event (though it is marked deprecated it is still widely
@@ -33,7 +33,7 @@ config FEATURE_ACPID_COMPAT
33config BLKID 33config BLKID
34 bool "blkid" 34 bool "blkid"
35 default y 35 default y
36 depends on PLATFORM_LINUX 36 select PLATFORM_LINUX
37 select VOLUMEID 37 select VOLUMEID
38 help 38 help
39 Lists labels and UUIDs of all filesystems. 39 Lists labels and UUIDs of all filesystems.
@@ -50,7 +50,7 @@ config FEATURE_BLKID_TYPE
50config DMESG 50config DMESG
51 bool "dmesg" 51 bool "dmesg"
52 default y 52 default y
53 depends on PLATFORM_LINUX 53 select PLATFORM_LINUX
54 help 54 help
55 dmesg is used to examine or control the kernel ring buffer. When the 55 dmesg is used to examine or control the kernel ring buffer. When the
56 Linux kernel prints messages to the system log, they are stored in 56 Linux kernel prints messages to the system log, they are stored in
@@ -84,7 +84,7 @@ config FEATURE_DMESG_PRETTY
84config FBSET 84config FBSET
85 bool "fbset" 85 bool "fbset"
86 default y 86 default y
87 depends on PLATFORM_LINUX 87 select PLATFORM_LINUX
88 help 88 help
89 fbset is used to show or change the settings of a Linux frame buffer 89 fbset is used to show or change the settings of a Linux frame buffer
90 device. The frame buffer device provides a simple and unique 90 device. The frame buffer device provides a simple and unique
@@ -113,7 +113,7 @@ config FEATURE_FBSET_READMODE
113config FDFLUSH 113config FDFLUSH
114 bool "fdflush" 114 bool "fdflush"
115 default y 115 default y
116 depends on PLATFORM_LINUX 116 select PLATFORM_LINUX
117 help 117 help
118 fdflush is only needed when changing media on slightly-broken 118 fdflush is only needed when changing media on slightly-broken
119 removable media drives. It is used to make Linux believe that a 119 removable media drives. It is used to make Linux believe that a
@@ -126,14 +126,14 @@ config FDFLUSH
126config FDFORMAT 126config FDFORMAT
127 bool "fdformat" 127 bool "fdformat"
128 default y 128 default y
129 depends on PLATFORM_LINUX 129 select PLATFORM_LINUX
130 help 130 help
131 fdformat is used to low-level format a floppy disk. 131 fdformat is used to low-level format a floppy disk.
132 132
133config FDISK 133config FDISK
134 bool "fdisk" 134 bool "fdisk"
135 default y 135 default y
136 depends on PLATFORM_LINUX 136 select PLATFORM_LINUX
137 help 137 help
138 The fdisk utility is used to divide hard disks into one or more 138 The fdisk utility is used to divide hard disks into one or more
139 logical disks, which are generally called partitions. This utility 139 logical disks, which are generally called partitions. This utility
@@ -209,7 +209,7 @@ config FEATURE_FDISK_ADVANCED
209config FINDFS 209config FINDFS
210 bool "findfs" 210 bool "findfs"
211 default y 211 default y
212 depends on PLATFORM_LINUX 212 select PLATFORM_LINUX
213 select VOLUMEID 213 select VOLUMEID
214 help 214 help
215 Prints the name of a filesystem with given label or UUID. 215 Prints the name of a filesystem with given label or UUID.
@@ -225,7 +225,7 @@ config FLOCK
225config FREERAMDISK 225config FREERAMDISK
226 bool "freeramdisk" 226 bool "freeramdisk"
227 default y 227 default y
228 depends on PLATFORM_LINUX 228 select PLATFORM_LINUX
229 help 229 help
230 Linux allows you to create ramdisks. This utility allows you to 230 Linux allows you to create ramdisks. This utility allows you to
231 delete them and completely free all memory that was used for the 231 delete them and completely free all memory that was used for the
@@ -248,14 +248,14 @@ config FSCK_MINIX
248config MKFS_EXT2 248config MKFS_EXT2
249 bool "mkfs_ext2" 249 bool "mkfs_ext2"
250 default y 250 default y
251 depends on PLATFORM_LINUX 251 select PLATFORM_LINUX
252 help 252 help
253 Utility to create EXT2 filesystems. 253 Utility to create EXT2 filesystems.
254 254
255config MKFS_MINIX 255config MKFS_MINIX
256 bool "mkfs_minix" 256 bool "mkfs_minix"
257 default y 257 default y
258 depends on PLATFORM_LINUX 258 select PLATFORM_LINUX
259 help 259 help
260 The minix filesystem is a nice, small, compact, read-write filesystem 260 The minix filesystem is a nice, small, compact, read-write filesystem
261 with little overhead. If you wish to be able to create minix 261 with little overhead. If you wish to be able to create minix
@@ -273,7 +273,7 @@ config FEATURE_MINIX2
273config MKFS_REISER 273config MKFS_REISER
274 bool "mkfs_reiser" 274 bool "mkfs_reiser"
275 default n 275 default n
276 depends on PLATFORM_LINUX 276 select PLATFORM_LINUX
277 help 277 help
278 Utility to create ReiserFS filesystems. 278 Utility to create ReiserFS filesystems.
279 Note: this applet needs a lot of testing and polishing. 279 Note: this applet needs a lot of testing and polishing.
@@ -281,7 +281,7 @@ config MKFS_REISER
281config MKFS_VFAT 281config MKFS_VFAT
282 bool "mkfs_vfat" 282 bool "mkfs_vfat"
283 default y 283 default y
284 depends on PLATFORM_LINUX 284 select PLATFORM_LINUX
285 help 285 help
286 Utility to create FAT32 filesystems. 286 Utility to create FAT32 filesystems.
287 287
@@ -330,7 +330,7 @@ config HD
330config HWCLOCK 330config HWCLOCK
331 bool "hwclock" 331 bool "hwclock"
332 default y 332 default y
333 depends on PLATFORM_LINUX 333 select PLATFORM_LINUX
334 help 334 help
335 The hwclock utility is used to read and set the hardware clock 335 The hwclock utility is used to read and set the hardware clock
336 on a system. This is primarily used to set the current time on 336 on a system. This is primarily used to set the current time on
@@ -369,7 +369,7 @@ config IPCRM
369config IPCS 369config IPCS
370 bool "ipcs" 370 bool "ipcs"
371 default y 371 default y
372 depends on PLATFORM_LINUX 372 select PLATFORM_LINUX
373 help 373 help
374 The ipcs utility is used to provide information on the currently 374 The ipcs utility is used to provide information on the currently
375 allocated System V interprocess (IPC) objects in the system. 375 allocated System V interprocess (IPC) objects in the system.
@@ -377,7 +377,7 @@ config IPCS
377config LOSETUP 377config LOSETUP
378 bool "losetup" 378 bool "losetup"
379 default y 379 default y
380 depends on PLATFORM_LINUX 380 select PLATFORM_LINUX
381 help 381 help
382 losetup is used to associate or detach a loop device with a regular 382 losetup is used to associate or detach a loop device with a regular
383 file or block device, and to query the status of a loop device. This 383 file or block device, and to query the status of a loop device. This
@@ -386,7 +386,7 @@ config LOSETUP
386config LSPCI 386config LSPCI
387 bool "lspci" 387 bool "lspci"
388 default y 388 default y
389 #depends on PLATFORM_LINUX 389 #select PLATFORM_LINUX
390 help 390 help
391 lspci is a utility for displaying information about PCI buses in the 391 lspci is a utility for displaying information about PCI buses in the
392 system and devices connected to them. 392 system and devices connected to them.
@@ -396,7 +396,7 @@ config LSPCI
396config LSUSB 396config LSUSB
397 bool "lsusb" 397 bool "lsusb"
398 default y 398 default y
399 #depends on PLATFORM_LINUX 399 #select PLATFORM_LINUX
400 help 400 help
401 lsusb is a utility for displaying information about USB buses in the 401 lsusb is a utility for displaying information about USB buses in the
402 system and devices connected to them. 402 system and devices connected to them.
@@ -406,7 +406,7 @@ config LSUSB
406config MDEV 406config MDEV
407 bool "mdev" 407 bool "mdev"
408 default y 408 default y
409 depends on PLATFORM_LINUX 409 select PLATFORM_LINUX
410 help 410 help
411 mdev is a mini-udev implementation for dynamically creating device 411 mdev is a mini-udev implementation for dynamically creating device
412 nodes in the /dev directory. 412 nodes in the /dev directory.
@@ -494,7 +494,7 @@ config MORE
494config MOUNT 494config MOUNT
495 bool "mount" 495 bool "mount"
496 default y 496 default y
497 depends on PLATFORM_LINUX 497 select PLATFORM_LINUX
498 help 498 help
499 All files and filesystems in Unix are arranged into one big directory 499 All files and filesystems in Unix are arranged into one big directory
500 tree. The 'mount' utility is used to graft a filesystem onto a 500 tree. The 'mount' utility is used to graft a filesystem onto a
@@ -577,7 +577,7 @@ config FEATURE_MOUNT_FSTAB
577config PIVOT_ROOT 577config PIVOT_ROOT
578 bool "pivot_root" 578 bool "pivot_root"
579 default y 579 default y
580 depends on PLATFORM_LINUX 580 select PLATFORM_LINUX
581 help 581 help
582 The pivot_root utility swaps the mount points for the root filesystem 582 The pivot_root utility swaps the mount points for the root filesystem
583 with some other mounted filesystem. This allows you to do all sorts 583 with some other mounted filesystem. This allows you to do all sorts
@@ -605,14 +605,14 @@ config RDEV
605config READPROFILE 605config READPROFILE
606 bool "readprofile" 606 bool "readprofile"
607 default y 607 default y
608 #depends on PLATFORM_LINUX 608 #select PLATFORM_LINUX
609 help 609 help
610 This allows you to parse /proc/profile for basic profiling. 610 This allows you to parse /proc/profile for basic profiling.
611 611
612config RTCWAKE 612config RTCWAKE
613 bool "rtcwake" 613 bool "rtcwake"
614 default y 614 default y
615 depends on PLATFORM_LINUX 615 select PLATFORM_LINUX
616 help 616 help
617 Enter a system sleep state until specified wakeup time. 617 Enter a system sleep state until specified wakeup time.
618 618
@@ -632,7 +632,7 @@ config SCRIPTREPLAY
632config SETARCH 632config SETARCH
633 bool "setarch" 633 bool "setarch"
634 default y 634 default y
635 depends on PLATFORM_LINUX 635 select PLATFORM_LINUX
636 help 636 help
637 The linux32 utility is used to create a 32bit environment for the 637 The linux32 utility is used to create a 32bit environment for the
638 specified program (usually a shell). It only makes sense to have 638 specified program (usually a shell). It only makes sense to have
@@ -642,7 +642,7 @@ config SETARCH
642config SWAPONOFF 642config SWAPONOFF
643 bool "swaponoff" 643 bool "swaponoff"
644 default y 644 default y
645 depends on PLATFORM_LINUX 645 select PLATFORM_LINUX
646 help 646 help
647 This option enables both the 'swapon' and the 'swapoff' utilities. 647 This option enables both the 'swapon' and the 'swapoff' utilities.
648 Once you have created some swap space using 'mkswap', you also need 648 Once you have created some swap space using 'mkswap', you also need
@@ -661,7 +661,7 @@ config FEATURE_SWAPON_PRI
661config SWITCH_ROOT 661config SWITCH_ROOT
662 bool "switch_root" 662 bool "switch_root"
663 default y 663 default y
664 depends on PLATFORM_LINUX 664 select PLATFORM_LINUX
665 help 665 help
666 The switch_root utility is used from initramfs to select a new 666 The switch_root utility is used from initramfs to select a new
667 root device. Under initramfs, you have to use this instead of 667 root device. Under initramfs, you have to use this instead of
@@ -681,7 +681,7 @@ config SWITCH_ROOT
681config UMOUNT 681config UMOUNT
682 bool "umount" 682 bool "umount"
683 default y 683 default y
684 depends on PLATFORM_LINUX 684 select PLATFORM_LINUX
685 help 685 help
686 When you want to remove a mounted filesystem from its current mount 686 When you want to remove a mounted filesystem from its current mount
687 point, for example when you are shutting down the system, the 687 point, for example when you are shutting down the system, the
diff --git a/util-linux/more.c b/util-linux/more.c
index c424a0e4b..7160b8b00 100644
--- a/util-linux/more.c
+++ b/util-linux/more.c
@@ -113,9 +113,12 @@ int more_main(int argc UNUSED_PARAM, char **argv)
113 loop_top: 113 loop_top:
114 if (input != 'r' && please_display_more_prompt) { 114 if (input != 'r' && please_display_more_prompt) {
115 len = printf("--More-- "); 115 len = printf("--More-- ");
116 if (st.st_size > 0) { 116 if (st.st_size != 0) {
117 uoff_t d = (uoff_t)st.st_size / 100;
118 if (d == 0)
119 d = 1;
117 len += printf("(%u%% of %"OFF_FMT"u bytes)", 120 len += printf("(%u%% of %"OFF_FMT"u bytes)",
118 (int) (ftello(file)*100 / st.st_size), 121 (int) ((uoff_t)ftello(file) / d),
119 st.st_size); 122 st.st_size);
120 } 123 }
121 fflush_all(); 124 fflush_all();
@@ -159,7 +162,7 @@ int more_main(int argc UNUSED_PARAM, char **argv)
159 /* Crudely convert tabs into spaces, which are 162 /* Crudely convert tabs into spaces, which are
160 * a bajillion times easier to deal with. */ 163 * a bajillion times easier to deal with. */
161 if (c == '\t') { 164 if (c == '\t') {
162 spaces = CONVERTED_TAB_SIZE - 1; 165 spaces = ((unsigned)~len) % CONVERTED_TAB_SIZE;
163 c = ' '; 166 c = ' ';
164 } 167 }
165 168
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 0baa74c7c..722d0be92 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -181,6 +181,7 @@ static const int32_t mount_options[] = {
181 /* "relatime" */ MS_RELATIME, 181 /* "relatime" */ MS_RELATIME,
182 /* "norelatime" */ ~MS_RELATIME, 182 /* "norelatime" */ ~MS_RELATIME,
183 /* "loud" */ ~MS_SILENT, 183 /* "loud" */ ~MS_SILENT,
184 /* "rbind" */ MS_BIND|MS_RECURSIVE,
184 185
185 // action flags 186 // action flags
186 /* "union" */ MS_UNION, 187 /* "union" */ MS_UNION,
@@ -192,7 +193,7 @@ static const int32_t mount_options[] = {
192 /* "unbindable" */ MS_UNBINDABLE, 193 /* "unbindable" */ MS_UNBINDABLE,
193 /* "rshared" */ MS_SHARED|MS_RECURSIVE, 194 /* "rshared" */ MS_SHARED|MS_RECURSIVE,
194 /* "rslave" */ MS_SLAVE|MS_RECURSIVE, 195 /* "rslave" */ MS_SLAVE|MS_RECURSIVE,
195 /* "rprivate" */ MS_SLAVE|MS_RECURSIVE, 196 /* "rprivate" */ MS_PRIVATE|MS_RECURSIVE,
196 /* "runbindable" */ MS_UNBINDABLE|MS_RECURSIVE, 197 /* "runbindable" */ MS_UNBINDABLE|MS_RECURSIVE,
197 ) 198 )
198 199
@@ -236,6 +237,7 @@ static const char mount_option_str[] =
236 "relatime\0" 237 "relatime\0"
237 "norelatime\0" 238 "norelatime\0"
238 "loud\0" 239 "loud\0"
240 "rbind\0"
239 241
240 // action flags 242 // action flags
241 "union\0" 243 "union\0"
@@ -279,6 +281,61 @@ enum { GETMNTENT_BUFSIZE = COMMON_BUFSIZE - offsetof(struct globals, getmntent_b
279#define fslist (G.fslist ) 281#define fslist (G.fslist )
280#define getmntent_buf (G.getmntent_buf ) 282#define getmntent_buf (G.getmntent_buf )
281 283
284#if ENABLE_FEATURE_MTAB_SUPPORT
285/*
286 * update_mtab_entry_on_move() is used to update entry in case of mount --move.
287 * we are looking for existing entries mnt_dir which is equal to mnt_fsname of
288 * input mntent and replace it by new one.
289 */
290static void FAST_FUNC update_mtab_entry_on_move(const struct mntent *mp)
291{
292 struct mntent *entries, *m;
293 int i, count;
294 FILE *mountTable;
295
296 mountTable = setmntent(bb_path_mtab_file, "r");
297 if (!mountTable) {
298 bb_perror_msg(bb_path_mtab_file);
299 return;
300 }
301
302 entries = NULL;
303 count = 0;
304 while ((m = getmntent(mountTable)) != NULL) {
305 entries = xrealloc_vector(entries, 3, count);
306 entries[count].mnt_fsname = xstrdup(m->mnt_fsname);
307 entries[count].mnt_dir = xstrdup(m->mnt_dir);
308 entries[count].mnt_type = xstrdup(m->mnt_type);
309 entries[count].mnt_opts = xstrdup(m->mnt_opts);
310 entries[count].mnt_freq = m->mnt_freq;
311 entries[count].mnt_passno = m->mnt_passno;
312 count++;
313 }
314 endmntent(mountTable);
315
316 mountTable = setmntent(bb_path_mtab_file, "w");
317 if (mountTable) {
318 for (i = 0; i < count; i++) {
319 if (strcmp(entries[i].mnt_dir, mp->mnt_fsname) != 0)
320 addmntent(mountTable, &entries[i]);
321 else
322 addmntent(mountTable, mp);
323 }
324 endmntent(mountTable);
325 } else if (errno != EROFS)
326 bb_perror_msg(bb_path_mtab_file);
327
328 if (ENABLE_FEATURE_CLEAN_UP) {
329 for (i = 0; i < count; i++) {
330 free(entries[i].mnt_fsname);
331 free(entries[i].mnt_dir);
332 free(entries[i].mnt_type);
333 free(entries[i].mnt_opts);
334 }
335 free(entries);
336 }
337}
338#endif
282 339
283#if ENABLE_FEATURE_MOUNT_VERBOSE 340#if ENABLE_FEATURE_MOUNT_VERBOSE
284static int verbose_mount(const char *source, const char *target, 341static int verbose_mount(const char *source, const char *target,
@@ -496,12 +553,11 @@ static int mount_it_now(struct mntent *mp, long vfsflags, char *filteropts)
496 int i; 553 int i;
497 554
498 if (!mountTable) { 555 if (!mountTable) {
499 bb_error_msg("no %s", bb_path_mtab_file); 556 bb_perror_msg(bb_path_mtab_file);
500 goto ret; 557 goto ret;
501 } 558 }
502 559
503 // Add vfs string flags 560 // Add vfs string flags
504
505 for (i = 0; mount_options[i] != MS_REMOUNT; i++) { 561 for (i = 0; mount_options[i] != MS_REMOUNT; i++) {
506 if (mount_options[i] > 0 && (mount_options[i] & vfsflags)) 562 if (mount_options[i] > 0 && (mount_options[i] & vfsflags))
507 append_mount_options(&(mp->mnt_opts), option_str); 563 append_mount_options(&(mp->mnt_opts), option_str);
@@ -509,24 +565,28 @@ static int mount_it_now(struct mntent *mp, long vfsflags, char *filteropts)
509 } 565 }
510 566
511 // Remove trailing / (if any) from directory we mounted on 567 // Remove trailing / (if any) from directory we mounted on
512
513 i = strlen(mp->mnt_dir) - 1; 568 i = strlen(mp->mnt_dir) - 1;
514 if (i > 0 && mp->mnt_dir[i] == '/') mp->mnt_dir[i] = '\0'; 569 while (i > 0 && mp->mnt_dir[i] == '/')
570 mp->mnt_dir[i--] = '\0';
515 571
516 // Convert to canonical pathnames as needed 572 // Convert to canonical pathnames as needed
517
518 mp->mnt_dir = bb_simplify_path(mp->mnt_dir); 573 mp->mnt_dir = bb_simplify_path(mp->mnt_dir);
519 fsname = 0; 574 fsname = NULL;
520 if (!mp->mnt_type || !*mp->mnt_type) { // bind mount 575 if (!mp->mnt_type || !*mp->mnt_type) { // bind mount
521 mp->mnt_fsname = fsname = bb_simplify_path(mp->mnt_fsname); 576 mp->mnt_fsname = fsname = bb_simplify_path(mp->mnt_fsname);
522 mp->mnt_type = (char*)"bind"; 577 mp->mnt_type = (char*)"bind";
523 } 578 }
524 mp->mnt_freq = mp->mnt_passno = 0; 579 mp->mnt_freq = mp->mnt_passno = 0;
525 580
526 // Write and close. 581 // Write and close
527 582#if ENABLE_FEATURE_MTAB_SUPPORT
528 addmntent(mountTable, mp); 583 if (vfsflags & MS_MOVE)
584 update_mtab_entry_on_move(mp);
585 else
586#endif
587 addmntent(mountTable, mp);
529 endmntent(mountTable); 588 endmntent(mountTable);
589
530 if (ENABLE_FEATURE_CLEAN_UP) { 590 if (ENABLE_FEATURE_CLEAN_UP) {
531 free(mp->mnt_dir); 591 free(mp->mnt_dir);
532 free(fsname); 592 free(fsname);
diff --git a/util-linux/script.c b/util-linux/script.c
index b9317fc7c..47efc4526 100644
--- a/util-linux/script.c
+++ b/util-linux/script.c
@@ -65,10 +65,7 @@ int script_main(int argc UNUSED_PARAM, char **argv)
65 if (!(opt & OPT_q)) { 65 if (!(opt & OPT_q)) {
66 printf("Script started, file is %s\n", fname); 66 printf("Script started, file is %s\n", fname);
67 } 67 }
68 shell = getenv("SHELL"); 68 shell = get_shell_name();
69 if (shell == NULL) {
70 shell = DEFAULT_SHELL;
71 }
72 69
73 pty = xgetpty(pty_line); 70 pty = xgetpty(pty_line);
74 71