diff options
author | Ron Yorston <rmy@pobox.com> | 2012-10-10 12:56:24 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2012-10-10 12:56:24 +0100 |
commit | 981a6fcd1323a77d5829c7d574bb40fd1b96dc4d (patch) | |
tree | a1e3aadf4de65d7a525c7dd6172546ff577777d5 | |
parent | 19436cc0ee509a5e356c04f0026919abd417bec4 (diff) | |
parent | eab343e7e1e5331df833aa69f14584e4a6c738f1 (diff) | |
download | busybox-w32-981a6fcd1323a77d5829c7d574bb40fd1b96dc4d.tar.gz busybox-w32-981a6fcd1323a77d5829c7d574bb40fd1b96dc4d.tar.bz2 busybox-w32-981a6fcd1323a77d5829c7d574bb40fd1b96dc4d.zip |
Merge branch 'busybox' into merge
-rw-r--r-- | coreutils/stat.c | 4 | ||||
-rw-r--r-- | debianutils/mktemp.c | 40 | ||||
-rw-r--r-- | e2fsprogs/old_e2fsprogs/lsattr.c | 2 | ||||
-rw-r--r-- | include/libbb.h | 2 | ||||
-rw-r--r-- | libbb/get_shell_name.c | 2 | ||||
-rw-r--r-- | libbb/lineedit.c | 3 | ||||
-rw-r--r-- | libbb/procps.c | 2 | ||||
-rw-r--r-- | libbb/signals.c | 6 | ||||
-rw-r--r-- | loginutils/adduser.c | 22 | ||||
-rw-r--r-- | miscutils/flashcp.c | 3 | ||||
-rw-r--r-- | modutils/modprobe-small.c | 11 | ||||
-rw-r--r-- | networking/Config.src | 4 | ||||
-rw-r--r-- | networking/brctl.c | 4 | ||||
-rw-r--r-- | networking/telnet.c | 55 | ||||
-rw-r--r-- | networking/telnetd.c | 1 | ||||
-rw-r--r-- | networking/udhcp/d6_dhcpc.c | 4 | ||||
-rw-r--r-- | networking/udhcp/dhcpc.c | 61 | ||||
-rw-r--r-- | procps/Config.src | 54 | ||||
-rw-r--r-- | procps/ps.c | 6 | ||||
-rw-r--r-- | procps/top.c | 161 | ||||
-rw-r--r-- | scripts/kconfig/mconf.c | 16 | ||||
-rw-r--r-- | shell/ash.c | 41 |
22 files changed, 314 insertions, 190 deletions
diff --git a/coreutils/stat.c b/coreutils/stat.c index 4959de40e..e6b0e95de 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c | |||
@@ -459,7 +459,7 @@ static bool do_statfs(const char *filename, const char *format) | |||
459 | : getfilecon(filename, &scontext) | 459 | : getfilecon(filename, &scontext) |
460 | ) < 0 | 460 | ) < 0 |
461 | ) { | 461 | ) { |
462 | bb_perror_msg(filename); | 462 | bb_simple_perror_msg(filename); |
463 | return 0; | 463 | return 0; |
464 | } | 464 | } |
465 | } | 465 | } |
@@ -573,7 +573,7 @@ static bool do_stat(const char *filename, const char *format) | |||
573 | : getfilecon(filename, &scontext) | 573 | : getfilecon(filename, &scontext) |
574 | ) < 0 | 574 | ) < 0 |
575 | ) { | 575 | ) { |
576 | bb_perror_msg(filename); | 576 | bb_simple_perror_msg(filename); |
577 | return 0; | 577 | return 0; |
578 | } | 578 | } |
579 | } | 579 | } |
diff --git a/debianutils/mktemp.c b/debianutils/mktemp.c index dbe430955..983d7a246 100644 --- a/debianutils/mktemp.c +++ b/debianutils/mktemp.c | |||
@@ -38,7 +38,7 @@ | |||
38 | //usage: "TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).\n" | 38 | //usage: "TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).\n" |
39 | //usage: "Without TEMPLATE, -t tmp.XXXXXX is assumed.\n" | 39 | //usage: "Without TEMPLATE, -t tmp.XXXXXX is assumed.\n" |
40 | //usage: "\n -d Make directory, not file" | 40 | //usage: "\n -d Make directory, not file" |
41 | ////usage: "\n -q Fail silently on errors" - we ignore this opt | 41 | //usage: "\n -q Fail silently on errors" |
42 | //usage: "\n -t Prepend base directory name to TEMPLATE" | 42 | //usage: "\n -t Prepend base directory name to TEMPLATE" |
43 | //usage: "\n -p DIR Use DIR as a base directory (implies -t)" | 43 | //usage: "\n -p DIR Use DIR as a base directory (implies -t)" |
44 | //usage: "\n -u Do not create anything; print a name" | 44 | //usage: "\n -u Do not create anything; print a name" |
@@ -71,7 +71,6 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv) | |||
71 | if (!path || path[0] == '\0') | 71 | if (!path || path[0] == '\0') |
72 | path = "/tmp"; | 72 | path = "/tmp"; |
73 | 73 | ||
74 | /* -q is ignored */ | ||
75 | opt_complementary = "?1"; /* 1 argument max */ | 74 | opt_complementary = "?1"; /* 1 argument max */ |
76 | opts = getopt32(argv, "dqtp:u", &path); | 75 | opts = getopt32(argv, "dqtp:u", &path); |
77 | 76 | ||
@@ -83,33 +82,32 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv) | |||
83 | chp = xstrdup("tmp.XXXXXX"); | 82 | chp = xstrdup("tmp.XXXXXX"); |
84 | opts |= OPT_t; | 83 | opts |= OPT_t; |
85 | } | 84 | } |
86 | 85 | #if 0 | |
87 | if (opts & OPT_u) { | 86 | /* Don't allow directory separator in template */ |
88 | /* Remove (up to) 6 X's */ | 87 | if ((opts & OPT_t) && bb_basename(chp) != chp) { |
89 | unsigned len = strlen(chp); | 88 | errno = EINVAL; |
90 | int cnt = len > 6 ? 6 : len; | 89 | goto error; |
91 | while (--cnt >= 0 && chp[--len] == 'X') | ||
92 | chp[len] = '\0'; | ||
93 | |||
94 | chp = tempnam(opts & (OPT_t|OPT_p) ? path : "./", chp); | ||
95 | if (!chp) | ||
96 | return EXIT_FAILURE; | ||
97 | if (!(opts & (OPT_t|OPT_p))) | ||
98 | chp += 2; | ||
99 | goto ret; | ||
100 | } | 90 | } |
101 | 91 | #endif | |
102 | if (opts & (OPT_t|OPT_p)) | 92 | if (opts & (OPT_t|OPT_p)) |
103 | chp = concat_path_file(path, chp); | 93 | chp = concat_path_file(path, chp); |
104 | 94 | ||
105 | if (opts & OPT_d) { | 95 | if (opts & OPT_u) { |
96 | chp = mktemp(chp); | ||
97 | if (chp[0] == '\0') | ||
98 | goto error; | ||
99 | } else if (opts & OPT_d) { | ||
106 | if (mkdtemp(chp) == NULL) | 100 | if (mkdtemp(chp) == NULL) |
107 | return EXIT_FAILURE; | 101 | goto error; |
108 | } else { | 102 | } else { |
109 | if (mkstemp(chp) < 0) | 103 | if (mkstemp(chp) < 0) |
110 | return EXIT_FAILURE; | 104 | goto error; |
111 | } | 105 | } |
112 | ret: | ||
113 | puts(chp); | 106 | puts(chp); |
114 | return EXIT_SUCCESS; | 107 | return EXIT_SUCCESS; |
108 | error: | ||
109 | if (opts & OPT_q) | ||
110 | return EXIT_FAILURE; | ||
111 | /* don't use chp as it gets mangled in case of error */ | ||
112 | bb_perror_nomsg_and_die(); | ||
115 | } | 113 | } |
diff --git a/e2fsprogs/old_e2fsprogs/lsattr.c b/e2fsprogs/old_e2fsprogs/lsattr.c index 9e0e4cb60..9eab68b5b 100644 --- a/e2fsprogs/old_e2fsprogs/lsattr.c +++ b/e2fsprogs/old_e2fsprogs/lsattr.c | |||
@@ -93,7 +93,7 @@ static int lsattr_dir_proc(const char *dir_name, struct dirent *de, | |||
93 | path = concat_path_file(dir_name, de->d_name); | 93 | path = concat_path_file(dir_name, de->d_name); |
94 | 94 | ||
95 | if (lstat(path, &st) == -1) | 95 | if (lstat(path, &st) == -1) |
96 | bb_perror_msg(path); | 96 | bb_simple_perror_msg(path); |
97 | else { | 97 | else { |
98 | if (de->d_name[0] != '.' || (flags & OPT_ALL)) { | 98 | if (de->d_name[0] != '.' || (flags & OPT_ALL)) { |
99 | list_attributes(path); | 99 | list_attributes(path); |
diff --git a/include/libbb.h b/include/libbb.h index 5012209f8..a749c0b92 100644 --- a/include/libbb.h +++ b/include/libbb.h | |||
@@ -1264,7 +1264,7 @@ extern void run_shell(const char *shell, int loginshell, const char *command, co | |||
1264 | * Note that getpwuid result might need xstrdup'ing | 1264 | * Note that getpwuid result might need xstrdup'ing |
1265 | * if there is a possibility of intervening getpwxxx() calls. | 1265 | * if there is a possibility of intervening getpwxxx() calls. |
1266 | */ | 1266 | */ |
1267 | const char *get_shell_name(void); | 1267 | const char *get_shell_name(void) FAST_FUNC; |
1268 | 1268 | ||
1269 | #if ENABLE_SELINUX | 1269 | #if ENABLE_SELINUX |
1270 | extern void renew_current_security_context(void) FAST_FUNC; | 1270 | extern void renew_current_security_context(void) FAST_FUNC; |
diff --git a/libbb/get_shell_name.c b/libbb/get_shell_name.c index c930afd94..5aebe9cdc 100644 --- a/libbb/get_shell_name.c +++ b/libbb/get_shell_name.c | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | #include "libbb.h" | 9 | #include "libbb.h" |
10 | 10 | ||
11 | const char *get_shell_name(void) | 11 | const char* FAST_FUNC get_shell_name(void) |
12 | { | 12 | { |
13 | struct passwd *pw; | 13 | struct passwd *pw; |
14 | char *shell; | 14 | char *shell; |
diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 65dffe56d..8a276d941 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c | |||
@@ -2754,7 +2754,8 @@ int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize) | |||
2754 | { | 2754 | { |
2755 | fputs(prompt, stdout); | 2755 | fputs(prompt, stdout); |
2756 | fflush_all(); | 2756 | fflush_all(); |
2757 | fgets(command, maxsize, stdin); | 2757 | if (!fgets(command, maxsize, stdin)) |
2758 | return -1; | ||
2758 | return strlen(command); | 2759 | return strlen(command); |
2759 | } | 2760 | } |
2760 | 2761 | ||
diff --git a/libbb/procps.c b/libbb/procps.c index 1080e0165..c6977da51 100644 --- a/libbb/procps.c +++ b/libbb/procps.c | |||
@@ -586,6 +586,8 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) | |||
586 | buf[sz] = '\0'; | 586 | buf[sz] = '\0'; |
587 | while (--sz >= 0 && buf[sz] == '\0') | 587 | while (--sz >= 0 && buf[sz] == '\0') |
588 | continue; | 588 | continue; |
589 | /* Prevent basename("process foo/bar") = "bar" */ | ||
590 | strchrnul(buf, ' ')[0] = '\0'; | ||
589 | base = bb_basename(buf); /* before we replace argv0's NUL with space */ | 591 | base = bb_basename(buf); /* before we replace argv0's NUL with space */ |
590 | while (sz >= 0) { | 592 | while (sz >= 0) { |
591 | if ((unsigned char)(buf[sz]) < ' ') | 593 | if ((unsigned char)(buf[sz]) < ' ') |
diff --git a/libbb/signals.c b/libbb/signals.c index cdc37b1ef..56512473a 100644 --- a/libbb/signals.c +++ b/libbb/signals.c | |||
@@ -39,7 +39,7 @@ void FAST_FUNC bb_signals(int sigs, void (*f)(int)) | |||
39 | 39 | ||
40 | while (sigs) { | 40 | while (sigs) { |
41 | if (sigs & bit) { | 41 | if (sigs & bit) { |
42 | sigs &= ~bit; | 42 | sigs -= bit; |
43 | signal(sig_no, f); | 43 | signal(sig_no, f); |
44 | } | 44 | } |
45 | sig_no++; | 45 | sig_no++; |
@@ -60,7 +60,7 @@ void FAST_FUNC bb_signals_recursive_norestart(int sigs, void (*f)(int)) | |||
60 | 60 | ||
61 | while (sigs) { | 61 | while (sigs) { |
62 | if (sigs & bit) { | 62 | if (sigs & bit) { |
63 | sigs &= ~bit; | 63 | sigs -= bit; |
64 | sigaction_set(sig_no, &sa); | 64 | sigaction_set(sig_no, &sa); |
65 | } | 65 | } |
66 | sig_no++; | 66 | sig_no++; |
@@ -97,7 +97,7 @@ void FAST_FUNC kill_myself_with_sig(int sig) | |||
97 | signal(sig, SIG_DFL); | 97 | signal(sig, SIG_DFL); |
98 | sig_unblock(sig); | 98 | sig_unblock(sig); |
99 | raise(sig); | 99 | raise(sig); |
100 | _exit(EXIT_FAILURE); /* Should not reach it */ | 100 | _exit(sig | 128); /* Should not reach it */ |
101 | } | 101 | } |
102 | 102 | ||
103 | void FAST_FUNC signal_SA_RESTART_empty_mask(int sig, void (*handler)(int)) | 103 | void FAST_FUNC signal_SA_RESTART_empty_mask(int sig, void (*handler)(int)) |
diff --git a/loginutils/adduser.c b/loginutils/adduser.c index 1d082c876..dc0244476 100644 --- a/loginutils/adduser.c +++ b/loginutils/adduser.c | |||
@@ -9,9 +9,9 @@ | |||
9 | */ | 9 | */ |
10 | 10 | ||
11 | //usage:#define adduser_trivial_usage | 11 | //usage:#define adduser_trivial_usage |
12 | //usage: "[OPTIONS] USER" | 12 | //usage: "[OPTIONS] USER [GROUP]" |
13 | //usage:#define adduser_full_usage "\n\n" | 13 | //usage:#define adduser_full_usage "\n\n" |
14 | //usage: "Add a user\n" | 14 | //usage: "Create new user, or add USER to GROUP\n" |
15 | //usage: "\n -h DIR Home directory" | 15 | //usage: "\n -h DIR Home directory" |
16 | //usage: "\n -g GECOS GECOS field" | 16 | //usage: "\n -g GECOS GECOS field" |
17 | //usage: "\n -s SHELL Login shell" | 17 | //usage: "\n -s SHELL Login shell" |
@@ -80,7 +80,7 @@ static void passwd_study(struct passwd *p) | |||
80 | } | 80 | } |
81 | } | 81 | } |
82 | 82 | ||
83 | static void addgroup_wrapper(struct passwd *p, const char *group_name) | 83 | static int addgroup_wrapper(struct passwd *p, const char *group_name) |
84 | { | 84 | { |
85 | char *argv[6]; | 85 | char *argv[6]; |
86 | 86 | ||
@@ -110,7 +110,7 @@ static void addgroup_wrapper(struct passwd *p, const char *group_name) | |||
110 | argv[5] = NULL; | 110 | argv[5] = NULL; |
111 | } | 111 | } |
112 | 112 | ||
113 | spawn_and_wait(argv); | 113 | return spawn_and_wait(argv); |
114 | } | 114 | } |
115 | 115 | ||
116 | static void passwd_wrapper(const char *login_name) NORETURN; | 116 | static void passwd_wrapper(const char *login_name) NORETURN; |
@@ -162,9 +162,9 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) | |||
162 | pw.pw_shell = (char *)get_shell_name(); | 162 | pw.pw_shell = (char *)get_shell_name(); |
163 | pw.pw_dir = NULL; | 163 | pw.pw_dir = NULL; |
164 | 164 | ||
165 | /* exactly one non-option arg */ | 165 | /* at most two non-option args */ |
166 | /* disable interactive passwd for system accounts */ | 166 | /* disable interactive passwd for system accounts */ |
167 | opt_complementary = "=1:SD:u+"; | 167 | opt_complementary = "?2:SD:u+"; |
168 | if (sizeof(pw.pw_uid) == sizeof(int)) { | 168 | if (sizeof(pw.pw_uid) == sizeof(int)) { |
169 | opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &pw.pw_uid); | 169 | opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &pw.pw_uid); |
170 | } else { | 170 | } else { |
@@ -175,9 +175,16 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) | |||
175 | } | 175 | } |
176 | } | 176 | } |
177 | argv += optind; | 177 | argv += optind; |
178 | pw.pw_name = argv[0]; | ||
179 | |||
180 | if (!opts && argv[1]) { | ||
181 | /* if called with two non-option arguments, adduser | ||
182 | * will add an existing user to an existing group. | ||
183 | */ | ||
184 | return addgroup_wrapper(&pw, argv[1]); | ||
185 | } | ||
178 | 186 | ||
179 | /* fill in the passwd struct */ | 187 | /* fill in the passwd struct */ |
180 | pw.pw_name = argv[0]; | ||
181 | die_if_bad_username(pw.pw_name); | 188 | die_if_bad_username(pw.pw_name); |
182 | if (!pw.pw_dir) { | 189 | if (!pw.pw_dir) { |
183 | /* create string for $HOME if not specified already */ | 190 | /* create string for $HOME if not specified already */ |
@@ -205,7 +212,6 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) | |||
205 | } | 212 | } |
206 | if (ENABLE_FEATURE_CLEAN_UP) | 213 | if (ENABLE_FEATURE_CLEAN_UP) |
207 | free(p); | 214 | free(p); |
208 | |||
209 | #if ENABLE_FEATURE_SHADOWPASSWDS | 215 | #if ENABLE_FEATURE_SHADOWPASSWDS |
210 | /* /etc/shadow fields: | 216 | /* /etc/shadow fields: |
211 | * 1. username | 217 | * 1. username |
diff --git a/miscutils/flashcp.c b/miscutils/flashcp.c index 790f9c01f..81cde9072 100644 --- a/miscutils/flashcp.c +++ b/miscutils/flashcp.c | |||
@@ -50,7 +50,6 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv) | |||
50 | int fd_f, fd_d; /* input file and mtd device file descriptors */ | 50 | int fd_f, fd_d; /* input file and mtd device file descriptors */ |
51 | int i; | 51 | int i; |
52 | uoff_t erase_count; | 52 | uoff_t erase_count; |
53 | unsigned opts; | ||
54 | struct mtd_info_user mtd; | 53 | struct mtd_info_user mtd; |
55 | struct erase_info_user e; | 54 | struct erase_info_user e; |
56 | struct stat statb; | 55 | struct stat statb; |
@@ -59,7 +58,7 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv) | |||
59 | RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE); | 58 | RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE); |
60 | 59 | ||
61 | opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */ | 60 | opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */ |
62 | opts = getopt32(argv, "v"); | 61 | /*opts =*/ getopt32(argv, "v"); |
63 | argv += optind; | 62 | argv += optind; |
64 | // filename = *argv++; | 63 | // filename = *argv++; |
65 | // devicename = *argv; | 64 | // devicename = *argv; |
diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index bd855f628..5b7836344 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c | |||
@@ -594,11 +594,18 @@ static void process_module(char *name, const char *cmdline_options) | |||
594 | bb_perror_msg("remove '%s'", name); | 594 | bb_perror_msg("remove '%s'", name); |
595 | goto ret; | 595 | goto ret; |
596 | } | 596 | } |
597 | /* N.B. we do not stop here - | 597 | |
598 | if (applet_name[0] == 'r') { | ||
599 | /* rmmod: do not remove dependencies, exit */ | ||
600 | goto ret; | ||
601 | } | ||
602 | |||
603 | /* modprobe -r: we do not stop here - | ||
598 | * continue to unload modules on which the module depends: | 604 | * continue to unload modules on which the module depends: |
599 | * "-r --remove: option causes modprobe to remove a module. | 605 | * "-r --remove: option causes modprobe to remove a module. |
600 | * If the modules it depends on are also unused, modprobe | 606 | * If the modules it depends on are also unused, modprobe |
601 | * will try to remove them, too." */ | 607 | * will try to remove them, too." |
608 | */ | ||
602 | } | 609 | } |
603 | 610 | ||
604 | if (!info) { | 611 | if (!info) { |
diff --git a/networking/Config.src b/networking/Config.src index e2376d548..e1ae0c9d5 100644 --- a/networking/Config.src +++ b/networking/Config.src | |||
@@ -82,12 +82,12 @@ config FEATURE_BRCTL_FANCY | |||
82 | This adds about 600 bytes. | 82 | This adds about 600 bytes. |
83 | 83 | ||
84 | config FEATURE_BRCTL_SHOW | 84 | config FEATURE_BRCTL_SHOW |
85 | bool "Support show, showmac and showstp" | 85 | bool "Support show" |
86 | default y | 86 | default y |
87 | depends on BRCTL && FEATURE_BRCTL_FANCY | 87 | depends on BRCTL && FEATURE_BRCTL_FANCY |
88 | help | 88 | help |
89 | Add support for option which prints the current config: | 89 | Add support for option which prints the current config: |
90 | showmacs, showstp, show | 90 | show |
91 | 91 | ||
92 | config DNSD | 92 | config DNSD |
93 | bool "dnsd" | 93 | bool "dnsd" |
diff --git a/networking/brctl.c b/networking/brctl.c index 7289e641f..b4f5809df 100644 --- a/networking/brctl.c +++ b/networking/brctl.c | |||
@@ -129,7 +129,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
129 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" | 129 | "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" |
130 | "setpathcost\0" "setportprio\0" "setbridgeprio\0" | 130 | "setpathcost\0" "setportprio\0" "setbridgeprio\0" |
131 | ) | 131 | ) |
132 | IF_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); | 132 | IF_FEATURE_BRCTL_SHOW("show\0"); |
133 | 133 | ||
134 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif | 134 | enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif |
135 | IF_FEATURE_BRCTL_FANCY(, | 135 | IF_FEATURE_BRCTL_FANCY(, |
@@ -137,7 +137,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) | |||
137 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, | 137 | ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, |
138 | ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio | 138 | ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio |
139 | ) | 139 | ) |
140 | IF_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) | 140 | IF_FEATURE_BRCTL_SHOW(, ARG_show) |
141 | }; | 141 | }; |
142 | 142 | ||
143 | int fd; | 143 | int fd; |
diff --git a/networking/telnet.c b/networking/telnet.c index e8e51dce4..58a691916 100644 --- a/networking/telnet.c +++ b/networking/telnet.c | |||
@@ -186,40 +186,35 @@ static void con_escape(void) | |||
186 | 186 | ||
187 | static void handle_net_output(int len) | 187 | static void handle_net_output(int len) |
188 | { | 188 | { |
189 | /* here we could do smart tricks how to handle 0xFF:s in output | ||
190 | * stream like writing twice every sequence of FF:s (thus doing | ||
191 | * many write()s. But I think interactive telnet application does | ||
192 | * not need to be 100% 8-bit clean, so changing every 0xff:s to | ||
193 | * 0x7f:s | ||
194 | * | ||
195 | * 2002-mar-21, Przemyslaw Czerpak (druzus@polbox.com) | ||
196 | * I don't agree. | ||
197 | * first - I cannot use programs like sz/rz | ||
198 | * second - the 0x0D is sent as one character and if the next | ||
199 | * char is 0x0A then it's eaten by a server side. | ||
200 | * third - why do you have to make 'many write()s'? | ||
201 | * I don't understand. | ||
202 | * So I implemented it. It's really useful for me. I hope that | ||
203 | * other people will find it interesting too. | ||
204 | */ | ||
205 | byte outbuf[2 * DATABUFSIZE]; | 189 | byte outbuf[2 * DATABUFSIZE]; |
206 | byte *p = (byte*)G.buf; | 190 | byte *dst = outbuf; |
207 | int j = 0; | 191 | byte *src = (byte*)G.buf; |
192 | byte *end = src + len; | ||
208 | 193 | ||
209 | for (; len > 0; len--, p++) { | 194 | while (src < end) { |
210 | byte c = *p; | 195 | byte c = *src++; |
211 | if (c == 0x1d) { | 196 | if (c == 0x1d) { |
212 | con_escape(); | 197 | con_escape(); |
213 | return; | 198 | return; |
214 | } | 199 | } |
215 | outbuf[j++] = c; | 200 | *dst = c; |
216 | if (c == IAC) | 201 | if (c == IAC) |
217 | outbuf[j++] = c; /* IAC -> IAC IAC */ | 202 | *++dst = c; /* IAC -> IAC IAC */ |
218 | else if (c == '\r') | 203 | else |
219 | outbuf[j++] = '\0'; /* CR -> CR NUL */ | 204 | if (c == '\r' || c == '\n') { |
205 | /* Enter key sends '\r' in raw mode and '\n' in cooked one. | ||
206 | * | ||
207 | * See RFC 1123 3.3.1 Telnet End-of-Line Convention. | ||
208 | * Using CR LF instead of other allowed possibilities | ||
209 | * like CR NUL - easier to talk to HTTP/SMTP servers. | ||
210 | */ | ||
211 | *dst = '\r'; /* Enter -> CR LF */ | ||
212 | *++dst = '\n'; | ||
213 | } | ||
214 | dst++; | ||
220 | } | 215 | } |
221 | if (j > 0) | 216 | if (dst - outbuf != 0) |
222 | full_write(netfd, outbuf, j); | 217 | full_write(netfd, outbuf, dst - outbuf); |
223 | } | 218 | } |
224 | 219 | ||
225 | static void handle_net_input(int len) | 220 | static void handle_net_input(int len) |
@@ -398,20 +393,20 @@ static void put_iac_naws(byte c, int x, int y) | |||
398 | } | 393 | } |
399 | #endif | 394 | #endif |
400 | 395 | ||
401 | static char const escapecharis[] ALIGN1 = "\r\nEscape character is "; | ||
402 | |||
403 | static void setConMode(void) | 396 | static void setConMode(void) |
404 | { | 397 | { |
405 | if (G.telflags & UF_ECHO) { | 398 | if (G.telflags & UF_ECHO) { |
406 | if (G.charmode == CHM_TRY) { | 399 | if (G.charmode == CHM_TRY) { |
407 | G.charmode = CHM_ON; | 400 | G.charmode = CHM_ON; |
408 | printf("\r\nEntering character mode%s'^]'.\r\n", escapecharis); | 401 | printf("\r\nEntering %s mode" |
402 | "\r\nEscape character is '^%c'.\r\n", "character", ']'); | ||
409 | rawmode(); | 403 | rawmode(); |
410 | } | 404 | } |
411 | } else { | 405 | } else { |
412 | if (G.charmode != CHM_OFF) { | 406 | if (G.charmode != CHM_OFF) { |
413 | G.charmode = CHM_OFF; | 407 | G.charmode = CHM_OFF; |
414 | printf("\r\nEntering line mode%s'^C'.\r\n", escapecharis); | 408 | printf("\r\nEntering %s mode" |
409 | "\r\nEscape character is '^%c'.\r\n", "line", 'C'); | ||
415 | cookmode(); | 410 | cookmode(); |
416 | } | 411 | } |
417 | } | 412 | } |
diff --git a/networking/telnetd.c b/networking/telnetd.c index 33020f1b4..9e7a84cce 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c | |||
@@ -125,6 +125,7 @@ remove_iacs(struct tsession *ts, int *pnum_totty) | |||
125 | /* We map \r\n ==> \r for pragmatic reasons. | 125 | /* We map \r\n ==> \r for pragmatic reasons. |
126 | * Many client implementations send \r\n when | 126 | * Many client implementations send \r\n when |
127 | * the user hits the CarriageReturn key. | 127 | * the user hits the CarriageReturn key. |
128 | * See RFC 1123 3.3.1 Telnet End-of-Line Convention. | ||
128 | */ | 129 | */ |
129 | if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0')) | 130 | if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0')) |
130 | ptr++; | 131 | ptr++; |
diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index dda4a9112..c44220bf9 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c | |||
@@ -1111,7 +1111,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1111 | 1111 | ||
1112 | switch (state) { | 1112 | switch (state) { |
1113 | case INIT_SELECTING: | 1113 | case INIT_SELECTING: |
1114 | if (packet_num < discover_retries) { | 1114 | if (!discover_retries || packet_num < discover_retries) { |
1115 | if (packet_num == 0) | 1115 | if (packet_num == 0) |
1116 | xid = random_xid(); | 1116 | xid = random_xid(); |
1117 | /* multicast */ | 1117 | /* multicast */ |
@@ -1140,7 +1140,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) | |||
1140 | packet_num = 0; | 1140 | packet_num = 0; |
1141 | continue; | 1141 | continue; |
1142 | case REQUESTING: | 1142 | case REQUESTING: |
1143 | if (packet_num < discover_retries) { | 1143 | if (!discover_retries || packet_num < discover_retries) { |
1144 | /* send multicast select packet */ | 1144 | /* send multicast select packet */ |
1145 | send_d6_select(xid); | 1145 | send_d6_select(xid); |
1146 | timeout = discover_timeout; | 1146 | timeout = discover_timeout; |
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index bc1db7087..f72217c84 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c | |||
@@ -26,8 +26,8 @@ | |||
26 | #include "dhcpc.h" | 26 | #include "dhcpc.h" |
27 | 27 | ||
28 | #include <netinet/if_ether.h> | 28 | #include <netinet/if_ether.h> |
29 | #include <netpacket/packet.h> | ||
30 | #include <linux/filter.h> | 29 | #include <linux/filter.h> |
30 | #include <linux/if_packet.h> | ||
31 | 31 | ||
32 | /* "struct client_config_t client_config" is in bb_common_bufsiz1 */ | 32 | /* "struct client_config_t client_config" is in bb_common_bufsiz1 */ |
33 | 33 | ||
@@ -836,12 +836,31 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
836 | int bytes; | 836 | int bytes; |
837 | struct ip_udp_dhcp_packet packet; | 837 | struct ip_udp_dhcp_packet packet; |
838 | uint16_t check; | 838 | uint16_t check; |
839 | unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; | ||
840 | struct iovec iov; | ||
841 | struct msghdr msg; | ||
842 | struct cmsghdr *cmsg; | ||
839 | 843 | ||
840 | bytes = safe_read(fd, &packet, sizeof(packet)); | 844 | /* used to use just safe_read(fd, &packet, sizeof(packet)) |
841 | if (bytes < 0) { | 845 | * but we need to check for TP_STATUS_CSUMNOTREADY :( |
842 | log1("Packet read error, ignoring"); | 846 | */ |
843 | /* NB: possible down interface, etc. Caller should pause. */ | 847 | iov.iov_base = &packet; |
844 | return bytes; /* returns -1 */ | 848 | iov.iov_len = sizeof(packet); |
849 | memset(&msg, 0, sizeof(msg)); | ||
850 | msg.msg_iov = &iov; | ||
851 | msg.msg_iovlen = 1; | ||
852 | msg.msg_control = cmsgbuf; | ||
853 | msg.msg_controllen = sizeof(cmsgbuf); | ||
854 | for (;;) { | ||
855 | bytes = recvmsg(fd, &msg, 0); | ||
856 | if (bytes < 0) { | ||
857 | if (errno == EINTR) | ||
858 | continue; | ||
859 | log1("Packet read error, ignoring"); | ||
860 | /* NB: possible down interface, etc. Caller should pause. */ | ||
861 | return bytes; /* returns -1 */ | ||
862 | } | ||
863 | break; | ||
845 | } | 864 | } |
846 | 865 | ||
847 | if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { | 866 | if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { |
@@ -878,6 +897,20 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
878 | return -2; | 897 | return -2; |
879 | } | 898 | } |
880 | 899 | ||
900 | for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { | ||
901 | if (cmsg->cmsg_level == SOL_PACKET | ||
902 | && cmsg->cmsg_type == PACKET_AUXDATA | ||
903 | ) { | ||
904 | /* some VMs don't checksum UDP and TCP data | ||
905 | * they send to the same physical machine, | ||
906 | * here we detect this case: | ||
907 | */ | ||
908 | struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg); | ||
909 | if (aux->tp_status & TP_STATUS_CSUMNOTREADY) | ||
910 | goto skip_udp_sum_check; | ||
911 | } | ||
912 | } | ||
913 | |||
881 | /* verify UDP checksum. IP header has to be modified for this */ | 914 | /* verify UDP checksum. IP header has to be modified for this */ |
882 | memset(&packet.ip, 0, offsetof(struct iphdr, protocol)); | 915 | memset(&packet.ip, 0, offsetof(struct iphdr, protocol)); |
883 | /* ip.xx fields which are not memset: protocol, check, saddr, daddr */ | 916 | /* ip.xx fields which are not memset: protocol, check, saddr, daddr */ |
@@ -888,6 +921,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) | |||
888 | log1("Packet with bad UDP checksum received, ignoring"); | 921 | log1("Packet with bad UDP checksum received, ignoring"); |
889 | return -2; | 922 | return -2; |
890 | } | 923 | } |
924 | skip_udp_sum_check: | ||
891 | 925 | ||
892 | if (packet.data.cookie != htonl(DHCP_MAGIC)) { | 926 | if (packet.data.cookie != htonl(DHCP_MAGIC)) { |
893 | bb_info_msg("Packet with bad magic, ignoring"); | 927 | bb_info_msg("Packet with bad magic, ignoring"); |
@@ -983,7 +1017,7 @@ static int udhcp_raw_socket(int ifindex) | |||
983 | log1("Opening raw socket on ifindex %d", ifindex); //log2? | 1017 | log1("Opening raw socket on ifindex %d", ifindex); //log2? |
984 | 1018 | ||
985 | fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); | 1019 | fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); |
986 | log1("Got raw socket fd %d", fd); //log2? | 1020 | log1("Got raw socket fd"); //log2? |
987 | 1021 | ||
988 | sock.sll_family = AF_PACKET; | 1022 | sock.sll_family = AF_PACKET; |
989 | sock.sll_protocol = htons(ETH_P_IP); | 1023 | sock.sll_protocol = htons(ETH_P_IP); |
@@ -995,7 +1029,14 @@ static int udhcp_raw_socket(int ifindex) | |||
995 | /* Ignoring error (kernel may lack support for this) */ | 1029 | /* Ignoring error (kernel may lack support for this) */ |
996 | if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, | 1030 | if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, |
997 | sizeof(filter_prog)) >= 0) | 1031 | sizeof(filter_prog)) >= 0) |
998 | log1("Attached filter to raw socket fd %d", fd); // log? | 1032 | log1("Attached filter to raw socket fd"); // log? |
1033 | } | ||
1034 | |||
1035 | if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, | ||
1036 | &const_int_1, sizeof(int)) < 0 | ||
1037 | ) { | ||
1038 | if (errno != ENOPROTOOPT) | ||
1039 | log1("Can't set PACKET_AUXDATA on raw socket"); | ||
999 | } | 1040 | } |
1000 | 1041 | ||
1001 | log1("Created raw socket"); | 1042 | log1("Created raw socket"); |
@@ -1401,7 +1442,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1401 | 1442 | ||
1402 | switch (state) { | 1443 | switch (state) { |
1403 | case INIT_SELECTING: | 1444 | case INIT_SELECTING: |
1404 | if (packet_num < discover_retries) { | 1445 | if (!discover_retries || packet_num < discover_retries) { |
1405 | if (packet_num == 0) | 1446 | if (packet_num == 0) |
1406 | xid = random_xid(); | 1447 | xid = random_xid(); |
1407 | /* broadcast */ | 1448 | /* broadcast */ |
@@ -1430,7 +1471,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) | |||
1430 | packet_num = 0; | 1471 | packet_num = 0; |
1431 | continue; | 1472 | continue; |
1432 | case REQUESTING: | 1473 | case REQUESTING: |
1433 | if (packet_num < discover_retries) { | 1474 | if (!discover_retries || packet_num < discover_retries) { |
1434 | /* send broadcast select packet */ | 1475 | /* send broadcast select packet */ |
1435 | send_select(xid, server_addr, requested_ip); | 1476 | send_select(xid, server_addr, requested_ip); |
1436 | timeout = discover_timeout; | 1477 | timeout = discover_timeout; |
diff --git a/procps/Config.src b/procps/Config.src index 5cd47c84f..527d9ee0c 100644 --- a/procps/Config.src +++ b/procps/Config.src | |||
@@ -140,60 +140,6 @@ config BB_SYSCTL | |||
140 | help | 140 | help |
141 | Configure kernel parameters at runtime. | 141 | Configure kernel parameters at runtime. |
142 | 142 | ||
143 | config TOP | ||
144 | bool "top" | ||
145 | default y | ||
146 | help | ||
147 | The top program provides a dynamic real-time view of a running | ||
148 | system. | ||
149 | |||
150 | config FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
151 | bool "Show CPU per-process usage percentage" | ||
152 | default y | ||
153 | depends on TOP | ||
154 | help | ||
155 | Make top display CPU usage for each process. | ||
156 | This adds about 2k. | ||
157 | |||
158 | config FEATURE_TOP_CPU_GLOBAL_PERCENTS | ||
159 | bool "Show CPU global usage percentage" | ||
160 | default y | ||
161 | depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
162 | help | ||
163 | Makes top display "CPU: NN% usr NN% sys..." line. | ||
164 | This adds about 0.5k. | ||
165 | |||
166 | config FEATURE_TOP_SMP_CPU | ||
167 | bool "SMP CPU usage display ('c' key)" | ||
168 | default y | ||
169 | depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS | ||
170 | help | ||
171 | Allow 'c' key to switch between individual/cumulative CPU stats | ||
172 | This adds about 0.5k. | ||
173 | |||
174 | config FEATURE_TOP_DECIMALS | ||
175 | bool "Show 1/10th of a percent in CPU/mem statistics" | ||
176 | default y | ||
177 | depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
178 | help | ||
179 | Show 1/10th of a percent in CPU/mem statistics. | ||
180 | This adds about 0.3k. | ||
181 | |||
182 | config FEATURE_TOP_SMP_PROCESS | ||
183 | bool "Show CPU process runs on ('j' field)" | ||
184 | default y | ||
185 | depends on TOP | ||
186 | help | ||
187 | Show CPU where process was last found running on. | ||
188 | This is the 'j' field. | ||
189 | |||
190 | config FEATURE_TOPMEM | ||
191 | bool "Topmem command ('s' key)" | ||
192 | default y | ||
193 | depends on TOP | ||
194 | help | ||
195 | Enable 's' in top (gives lots of memory info). | ||
196 | |||
197 | config FEATURE_SHOW_THREADS | 143 | config FEATURE_SHOW_THREADS |
198 | bool "Support for showing threads in ps/pstree/top" | 144 | bool "Support for showing threads in ps/pstree/top" |
199 | default y | 145 | default y |
diff --git a/procps/ps.c b/procps/ps.c index dc6fda61d..e14356482 100644 --- a/procps/ps.c +++ b/procps/ps.c | |||
@@ -665,9 +665,9 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
665 | time_t now = now; | 665 | time_t now = now; |
666 | long uptime; | 666 | long uptime; |
667 | #endif | 667 | #endif |
668 | int opts = 0; | ||
669 | /* If we support any options, parse argv */ | 668 | /* If we support any options, parse argv */ |
670 | #if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS || ENABLE_FEATURE_PS_WIDE || ENABLE_FEATURE_PS_LONG | 669 | #if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS || ENABLE_FEATURE_PS_WIDE || ENABLE_FEATURE_PS_LONG |
670 | int opts = 0; | ||
671 | # if ENABLE_FEATURE_PS_WIDE | 671 | # if ENABLE_FEATURE_PS_WIDE |
672 | /* -w is a bit complicated */ | 672 | /* -w is a bit complicated */ |
673 | int w_count = 0; | 673 | int w_count = 0; |
@@ -721,10 +721,10 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) | |||
721 | * We also show STIME (standard says that -f shows it, -l doesn't). | 721 | * We also show STIME (standard says that -f shows it, -l doesn't). |
722 | */ | 722 | */ |
723 | puts("S UID PID PPID VSZ RSS TTY STIME TIME CMD"); | 723 | puts("S UID PID PPID VSZ RSS TTY STIME TIME CMD"); |
724 | #if ENABLE_FEATURE_PS_LONG | 724 | # if ENABLE_FEATURE_PS_LONG |
725 | now = time(NULL); | 725 | now = time(NULL); |
726 | uptime = get_uptime(); | 726 | uptime = get_uptime(); |
727 | #endif | 727 | # endif |
728 | } | 728 | } |
729 | else { | 729 | else { |
730 | puts(" PID USER VSZ STAT COMMAND"); | 730 | puts(" PID USER VSZ STAT COMMAND"); |
diff --git a/procps/top.c b/procps/top.c index 15eb624cc..b08444a76 100644 --- a/procps/top.c +++ b/procps/top.c | |||
@@ -50,6 +50,60 @@ | |||
50 | * chroot . ./top -bn1 >top1.out | 50 | * chroot . ./top -bn1 >top1.out |
51 | */ | 51 | */ |
52 | 52 | ||
53 | //config:config TOP | ||
54 | //config: bool "top" | ||
55 | //config: default y | ||
56 | //config: help | ||
57 | //config: The top program provides a dynamic real-time view of a running | ||
58 | //config: system. | ||
59 | //config: | ||
60 | //config:config FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
61 | //config: bool "Show CPU per-process usage percentage" | ||
62 | //config: default y | ||
63 | //config: depends on TOP | ||
64 | //config: help | ||
65 | //config: Make top display CPU usage for each process. | ||
66 | //config: This adds about 2k. | ||
67 | //config: | ||
68 | //config:config FEATURE_TOP_CPU_GLOBAL_PERCENTS | ||
69 | //config: bool "Show CPU global usage percentage" | ||
70 | //config: default y | ||
71 | //config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
72 | //config: help | ||
73 | //config: Makes top display "CPU: NN% usr NN% sys..." line. | ||
74 | //config: This adds about 0.5k. | ||
75 | //config: | ||
76 | //config:config FEATURE_TOP_SMP_CPU | ||
77 | //config: bool "SMP CPU usage display ('c' key)" | ||
78 | //config: default y | ||
79 | //config: depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS | ||
80 | //config: help | ||
81 | //config: Allow 'c' key to switch between individual/cumulative CPU stats | ||
82 | //config: This adds about 0.5k. | ||
83 | //config: | ||
84 | //config:config FEATURE_TOP_DECIMALS | ||
85 | //config: bool "Show 1/10th of a percent in CPU/mem statistics" | ||
86 | //config: default y | ||
87 | //config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE | ||
88 | //config: help | ||
89 | //config: Show 1/10th of a percent in CPU/mem statistics. | ||
90 | //config: This adds about 0.3k. | ||
91 | //config: | ||
92 | //config:config FEATURE_TOP_SMP_PROCESS | ||
93 | //config: bool "Show CPU process runs on ('j' field)" | ||
94 | //config: default y | ||
95 | //config: depends on TOP | ||
96 | //config: help | ||
97 | //config: Show CPU where process was last found running on. | ||
98 | //config: This is the 'j' field. | ||
99 | //config: | ||
100 | //config:config FEATURE_TOPMEM | ||
101 | //config: bool "Topmem command ('s' key)" | ||
102 | //config: default y | ||
103 | //config: depends on TOP | ||
104 | //config: help | ||
105 | //config: Enable 's' in top (gives lots of memory info). | ||
106 | |||
53 | #include "libbb.h" | 107 | #include "libbb.h" |
54 | 108 | ||
55 | 109 | ||
@@ -99,8 +153,13 @@ struct globals { | |||
99 | #if ENABLE_FEATURE_TOP_SMP_CPU | 153 | #if ENABLE_FEATURE_TOP_SMP_CPU |
100 | smallint smp_cpu_info; /* one/many cpu info lines? */ | 154 | smallint smp_cpu_info; /* one/many cpu info lines? */ |
101 | #endif | 155 | #endif |
156 | unsigned lines; /* screen height */ | ||
102 | #if ENABLE_FEATURE_USE_TERMIOS | 157 | #if ENABLE_FEATURE_USE_TERMIOS |
103 | struct termios initial_settings; | 158 | struct termios initial_settings; |
159 | int scroll_ofs; | ||
160 | #define G_scroll_ofs G.scroll_ofs | ||
161 | #else | ||
162 | #define G_scroll_ofs 0 | ||
104 | #endif | 163 | #endif |
105 | #if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | 164 | #if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
106 | cmp_funcp sort_function[1]; | 165 | cmp_funcp sort_function[1]; |
@@ -118,6 +177,9 @@ struct globals { | |||
118 | jiffy_counts_t *cpu_jif, *cpu_prev_jif; | 177 | jiffy_counts_t *cpu_jif, *cpu_prev_jif; |
119 | int num_cpus; | 178 | int num_cpus; |
120 | #endif | 179 | #endif |
180 | #if ENABLE_FEATURE_USE_TERMIOS | ||
181 | char kbd_input[KEYCODE_BUFFER_SIZE]; | ||
182 | #endif | ||
121 | char line_buf[80]; | 183 | char line_buf[80]; |
122 | }; //FIX_ALIASING; - large code growth | 184 | }; //FIX_ALIASING; - large code growth |
123 | enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) }; | 185 | enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) }; |
@@ -602,9 +664,9 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) | |||
602 | 664 | ||
603 | /* Ok, all preliminary data is ready, go through the list */ | 665 | /* Ok, all preliminary data is ready, go through the list */ |
604 | scr_width += 2; /* account for leading '\n' and trailing NUL */ | 666 | scr_width += 2; /* account for leading '\n' and trailing NUL */ |
605 | if (lines_rem > ntop) | 667 | if (lines_rem > ntop - G_scroll_ofs) |
606 | lines_rem = ntop; | 668 | lines_rem = ntop - G_scroll_ofs; |
607 | s = top; | 669 | s = top + G_scroll_ofs; |
608 | while (--lines_rem >= 0) { | 670 | while (--lines_rem >= 0) { |
609 | unsigned col; | 671 | unsigned col; |
610 | CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); | 672 | CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); |
@@ -649,14 +711,14 @@ static void clearmems(void) | |||
649 | clear_username_cache(); | 711 | clear_username_cache(); |
650 | free(top); | 712 | free(top); |
651 | top = NULL; | 713 | top = NULL; |
652 | ntop = 0; | ||
653 | } | 714 | } |
654 | 715 | ||
655 | #if ENABLE_FEATURE_USE_TERMIOS | 716 | #if ENABLE_FEATURE_USE_TERMIOS |
656 | 717 | ||
657 | static void reset_term(void) | 718 | static void reset_term(void) |
658 | { | 719 | { |
659 | tcsetattr_stdin_TCSANOW(&initial_settings); | 720 | if (!OPT_BATCH_MODE) |
721 | tcsetattr_stdin_TCSANOW(&initial_settings); | ||
660 | if (ENABLE_FEATURE_CLEAN_UP) { | 722 | if (ENABLE_FEATURE_CLEAN_UP) { |
661 | clearmems(); | 723 | clearmems(); |
662 | # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE | 724 | # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE |
@@ -665,10 +727,10 @@ static void reset_term(void) | |||
665 | } | 727 | } |
666 | } | 728 | } |
667 | 729 | ||
668 | static void sig_catcher(int sig UNUSED_PARAM) | 730 | static void sig_catcher(int sig) |
669 | { | 731 | { |
670 | reset_term(); | 732 | reset_term(); |
671 | _exit(EXIT_FAILURE); | 733 | kill_myself_with_sig(sig); |
672 | } | 734 | } |
673 | 735 | ||
674 | #endif /* FEATURE_USE_TERMIOS */ | 736 | #endif /* FEATURE_USE_TERMIOS */ |
@@ -793,7 +855,7 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width) | |||
793 | { | 855 | { |
794 | #define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" | 856 | #define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" |
795 | #define MIN_WIDTH sizeof(HDR_STR) | 857 | #define MIN_WIDTH sizeof(HDR_STR) |
796 | const topmem_status_t *s = topmem; | 858 | const topmem_status_t *s = topmem + G_scroll_ofs; |
797 | 859 | ||
798 | display_topmem_header(scr_width, &lines_rem); | 860 | display_topmem_header(scr_width, &lines_rem); |
799 | strcpy(line_buf, HDR_STR " COMMAND"); | 861 | strcpy(line_buf, HDR_STR " COMMAND"); |
@@ -801,8 +863,8 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width) | |||
801 | printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf); | 863 | printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf); |
802 | lines_rem--; | 864 | lines_rem--; |
803 | 865 | ||
804 | if (lines_rem > ntop) | 866 | if (lines_rem > ntop - G_scroll_ofs) |
805 | lines_rem = ntop; | 867 | lines_rem = ntop - G_scroll_ofs; |
806 | while (--lines_rem >= 0) { | 868 | while (--lines_rem >= 0) { |
807 | /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */ | 869 | /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */ |
808 | ulltoa6_and_space(s->pid , &line_buf[0*6]); | 870 | ulltoa6_and_space(s->pid , &line_buf[0*6]); |
@@ -856,26 +918,63 @@ enum { | |||
856 | #if ENABLE_FEATURE_USE_TERMIOS | 918 | #if ENABLE_FEATURE_USE_TERMIOS |
857 | static unsigned handle_input(unsigned scan_mask, unsigned interval) | 919 | static unsigned handle_input(unsigned scan_mask, unsigned interval) |
858 | { | 920 | { |
859 | unsigned char c; | ||
860 | struct pollfd pfd[1]; | 921 | struct pollfd pfd[1]; |
861 | 922 | ||
923 | if (option_mask32 & OPT_EOF) { | ||
924 | /* EOF on stdin ("top </dev/null") */ | ||
925 | sleep(interval); | ||
926 | return scan_mask; | ||
927 | } | ||
928 | |||
862 | pfd[0].fd = 0; | 929 | pfd[0].fd = 0; |
863 | pfd[0].events = POLLIN; | 930 | pfd[0].events = POLLIN; |
864 | 931 | ||
865 | while (1) { | 932 | while (1) { |
866 | if (safe_poll(pfd, 1, interval * 1000) <= 0) | 933 | int32_t c; |
867 | return scan_mask; | ||
868 | interval = 0; | ||
869 | 934 | ||
870 | if (safe_read(STDIN_FILENO, &c, 1) != 1) { /* error/EOF? */ | 935 | c = read_key(STDIN_FILENO, G.kbd_input, interval * 1000); |
936 | if (c == -1 && errno != EAGAIN) { | ||
937 | /* error/EOF */ | ||
871 | option_mask32 |= OPT_EOF; | 938 | option_mask32 |= OPT_EOF; |
872 | return scan_mask; | 939 | break; |
873 | } | 940 | } |
941 | interval = 0; | ||
874 | 942 | ||
875 | if (c == initial_settings.c_cc[VINTR]) | 943 | if (c == initial_settings.c_cc[VINTR]) |
876 | return EXIT_MASK; | 944 | return EXIT_MASK; |
877 | if (c == initial_settings.c_cc[VEOF]) | 945 | if (c == initial_settings.c_cc[VEOF]) |
878 | return EXIT_MASK; | 946 | return EXIT_MASK; |
947 | |||
948 | if (c == KEYCODE_UP) { | ||
949 | G_scroll_ofs--; | ||
950 | goto normalize_ofs; | ||
951 | } | ||
952 | if (c == KEYCODE_DOWN) { | ||
953 | G_scroll_ofs++; | ||
954 | goto normalize_ofs; | ||
955 | } | ||
956 | if (c == KEYCODE_HOME) { | ||
957 | G_scroll_ofs = 0; | ||
958 | break; | ||
959 | } | ||
960 | if (c == KEYCODE_END) { | ||
961 | G_scroll_ofs = ntop - G.lines / 2; | ||
962 | goto normalize_ofs; | ||
963 | } | ||
964 | if (c == KEYCODE_PAGEUP) { | ||
965 | G_scroll_ofs -= G.lines / 2; | ||
966 | goto normalize_ofs; | ||
967 | } | ||
968 | if (c == KEYCODE_PAGEDOWN) { | ||
969 | G_scroll_ofs += G.lines / 2; | ||
970 | normalize_ofs: | ||
971 | if (G_scroll_ofs >= ntop) | ||
972 | G_scroll_ofs = ntop - 1; | ||
973 | if (G_scroll_ofs < 0) | ||
974 | G_scroll_ofs = 0; | ||
975 | break; | ||
976 | } | ||
977 | |||
879 | c |= 0x20; /* lowercase */ | 978 | c |= 0x20; /* lowercase */ |
880 | if (c == 'q') | 979 | if (c == 'q') |
881 | return EXIT_MASK; | 980 | return EXIT_MASK; |
@@ -1011,7 +1110,7 @@ int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | |||
1011 | int top_main(int argc UNUSED_PARAM, char **argv) | 1110 | int top_main(int argc UNUSED_PARAM, char **argv) |
1012 | { | 1111 | { |
1013 | int iterations; | 1112 | int iterations; |
1014 | unsigned lines, col; | 1113 | unsigned col; |
1015 | unsigned interval; | 1114 | unsigned interval; |
1016 | char *str_interval, *str_iterations; | 1115 | char *str_interval, *str_iterations; |
1017 | unsigned scan_mask = TOP_MASK; | 1116 | unsigned scan_mask = TOP_MASK; |
@@ -1062,10 +1161,13 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1062 | sort_function[0] = mem_sort; | 1161 | sort_function[0] = mem_sort; |
1063 | #endif | 1162 | #endif |
1064 | 1163 | ||
1164 | if (OPT_BATCH_MODE) { | ||
1165 | option_mask32 |= OPT_EOF; | ||
1166 | } | ||
1065 | #if ENABLE_FEATURE_USE_TERMIOS | 1167 | #if ENABLE_FEATURE_USE_TERMIOS |
1066 | tcgetattr(0, (void *) &initial_settings); | 1168 | else { |
1067 | memcpy(&new_settings, &initial_settings, sizeof(new_settings)); | 1169 | tcgetattr(0, (void *) &initial_settings); |
1068 | if (!OPT_BATCH_MODE) { | 1170 | memcpy(&new_settings, &initial_settings, sizeof(new_settings)); |
1069 | /* unbuffered input, turn off echo */ | 1171 | /* unbuffered input, turn off echo */ |
1070 | new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL); | 1172 | new_settings.c_lflag &= ~(ISIG | ICANON | ECHO | ECHONL); |
1071 | tcsetattr_stdin_TCSANOW(&new_settings); | 1173 | tcsetattr_stdin_TCSANOW(&new_settings); |
@@ -1081,15 +1183,15 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1081 | procps_status_t *p = NULL; | 1183 | procps_status_t *p = NULL; |
1082 | 1184 | ||
1083 | if (OPT_BATCH_MODE) { | 1185 | if (OPT_BATCH_MODE) { |
1084 | lines = INT_MAX; | 1186 | G.lines = INT_MAX; |
1085 | col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */ | 1187 | col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */ |
1086 | } else { | 1188 | } else { |
1087 | lines = 24; /* default */ | 1189 | G.lines = 24; /* default */ |
1088 | col = 79; | 1190 | col = 79; |
1089 | #if ENABLE_FEATURE_USE_TERMIOS | 1191 | #if ENABLE_FEATURE_USE_TERMIOS |
1090 | /* We output to stdout, we need size of stdout (not stdin)! */ | 1192 | /* We output to stdout, we need size of stdout (not stdin)! */ |
1091 | get_terminal_width_height(STDOUT_FILENO, &col, &lines); | 1193 | get_terminal_width_height(STDOUT_FILENO, &col, &G.lines); |
1092 | if (lines < 5 || col < 10) { | 1194 | if (G.lines < 5 || col < 10) { |
1093 | sleep(interval); | 1195 | sleep(interval); |
1094 | continue; | 1196 | continue; |
1095 | } | 1197 | } |
@@ -1099,6 +1201,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1099 | } | 1201 | } |
1100 | 1202 | ||
1101 | /* read process IDs & status for all the processes */ | 1203 | /* read process IDs & status for all the processes */ |
1204 | ntop = 0; | ||
1102 | while ((p = procps_scan(p, scan_mask)) != NULL) { | 1205 | while ((p = procps_scan(p, scan_mask)) != NULL) { |
1103 | int n; | 1206 | int n; |
1104 | #if ENABLE_FEATURE_TOPMEM | 1207 | #if ENABLE_FEATURE_TOPMEM |
@@ -1165,10 +1268,10 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1165 | } | 1268 | } |
1166 | #endif | 1269 | #endif |
1167 | if (scan_mask != TOPMEM_MASK) | 1270 | if (scan_mask != TOPMEM_MASK) |
1168 | display_process_list(lines, col); | 1271 | display_process_list(G.lines, col); |
1169 | #if ENABLE_FEATURE_TOPMEM | 1272 | #if ENABLE_FEATURE_TOPMEM |
1170 | else | 1273 | else |
1171 | display_topmem_process_list(lines, col); | 1274 | display_topmem_process_list(G.lines, col); |
1172 | #endif | 1275 | #endif |
1173 | clearmems(); | 1276 | clearmems(); |
1174 | if (iterations >= 0 && !--iterations) | 1277 | if (iterations >= 0 && !--iterations) |
@@ -1176,11 +1279,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) | |||
1176 | #if !ENABLE_FEATURE_USE_TERMIOS | 1279 | #if !ENABLE_FEATURE_USE_TERMIOS |
1177 | sleep(interval); | 1280 | sleep(interval); |
1178 | #else | 1281 | #else |
1179 | if (option_mask32 & OPT_EOF) | 1282 | scan_mask = handle_input(scan_mask, interval); |
1180 | /* EOF on stdin ("top </dev/null") */ | ||
1181 | sleep(interval); | ||
1182 | else | ||
1183 | scan_mask = handle_input(scan_mask, interval); | ||
1184 | #endif /* FEATURE_USE_TERMIOS */ | 1283 | #endif /* FEATURE_USE_TERMIOS */ |
1185 | } /* end of "while (not Q)" */ | 1284 | } /* end of "while (not Q)" */ |
1186 | 1285 | ||
diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 1b0b6ab07..006d03708 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c | |||
@@ -445,6 +445,7 @@ static struct gstr get_relations_str(struct symbol **sym_arr) | |||
445 | 445 | ||
446 | pid_t pid; | 446 | pid_t pid; |
447 | 447 | ||
448 | #ifdef SIGWINCH | ||
448 | static void winch_handler(int sig) | 449 | static void winch_handler(int sig) |
449 | { | 450 | { |
450 | if (!do_resize) { | 451 | if (!do_resize) { |
@@ -452,11 +453,11 @@ static void winch_handler(int sig) | |||
452 | do_resize = 1; | 453 | do_resize = 1; |
453 | } | 454 | } |
454 | } | 455 | } |
456 | #endif | ||
455 | 457 | ||
456 | static int exec_conf(void) | 458 | static int exec_conf(void) |
457 | { | 459 | { |
458 | int pipefd[2], stat, size; | 460 | int pipefd[2], stat, size; |
459 | struct sigaction sa; | ||
460 | sigset_t sset, osset; | 461 | sigset_t sset, osset; |
461 | 462 | ||
462 | sigemptyset(&sset); | 463 | sigemptyset(&sset); |
@@ -465,10 +466,15 @@ static int exec_conf(void) | |||
465 | 466 | ||
466 | signal(SIGINT, SIG_DFL); | 467 | signal(SIGINT, SIG_DFL); |
467 | 468 | ||
468 | sa.sa_handler = winch_handler; | 469 | #ifdef SIGWINCH |
469 | sigemptyset(&sa.sa_mask); | 470 | { |
470 | sa.sa_flags = SA_RESTART; | 471 | struct sigaction sa; |
471 | sigaction(SIGWINCH, &sa, NULL); | 472 | sa.sa_handler = winch_handler; |
473 | sigemptyset(&sa.sa_mask); | ||
474 | sa.sa_flags = SA_RESTART; | ||
475 | sigaction(SIGWINCH, &sa, NULL); | ||
476 | } | ||
477 | #endif | ||
472 | 478 | ||
473 | *argptr++ = NULL; | 479 | *argptr++ = NULL; |
474 | 480 | ||
diff --git a/shell/ash.c b/shell/ash.c index 46bf6ed49..5c33bb817 100644 --- a/shell/ash.c +++ b/shell/ash.c | |||
@@ -6691,7 +6691,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6691 | IF_ASH_BASH_COMPAT(const char *repl = NULL;) | 6691 | IF_ASH_BASH_COMPAT(const char *repl = NULL;) |
6692 | IF_ASH_BASH_COMPAT(int pos, len, orig_len;) | 6692 | IF_ASH_BASH_COMPAT(int pos, len, orig_len;) |
6693 | int saveherefd = herefd; | 6693 | int saveherefd = herefd; |
6694 | int amount, workloc, resetloc; | 6694 | int amount, resetloc; |
6695 | IF_ASH_BASH_COMPAT(int workloc;) | ||
6695 | int zero; | 6696 | int zero; |
6696 | char *(*scan)(char*, char*, char*, char*, int, int); | 6697 | char *(*scan)(char*, char*, char*, char*, int, int); |
6697 | 6698 | ||
@@ -6804,9 +6805,9 @@ subevalvar(char *p, char *varname, int strloc, int subtype, | |||
6804 | rmescend--; | 6805 | rmescend--; |
6805 | str = (char *)stackblock() + strloc; | 6806 | str = (char *)stackblock() + strloc; |
6806 | preglob(str, varflags & VSQUOTE, 0); | 6807 | preglob(str, varflags & VSQUOTE, 0); |
6807 | workloc = expdest - (char *)stackblock(); | ||
6808 | 6808 | ||
6809 | #if ENABLE_ASH_BASH_COMPAT | 6809 | #if ENABLE_ASH_BASH_COMPAT |
6810 | workloc = expdest - (char *)stackblock(); | ||
6810 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { | 6811 | if (subtype == VSREPLACE || subtype == VSREPLACEALL) { |
6811 | char *idx, *end; | 6812 | char *idx, *end; |
6812 | 6813 | ||
@@ -9786,11 +9787,11 @@ evalcommand(union node *cmd, int flags) | |||
9786 | 9787 | ||
9787 | /* Now locate the command. */ | 9788 | /* Now locate the command. */ |
9788 | if (argc) { | 9789 | if (argc) { |
9789 | const char *oldpath; | ||
9790 | int cmd_flag = DO_ERR; | 9790 | int cmd_flag = DO_ERR; |
9791 | 9791 | #if ENABLE_ASH_CMDCMD | |
9792 | const char *oldpath = path + 5; | ||
9793 | #endif | ||
9792 | path += 5; | 9794 | path += 5; |
9793 | oldpath = path; | ||
9794 | for (;;) { | 9795 | for (;;) { |
9795 | find_command(argv[0], &cmdentry, cmd_flag, path); | 9796 | find_command(argv[0], &cmdentry, cmd_flag, path); |
9796 | if (cmdentry.cmdtype == CMDUNKNOWN) { | 9797 | if (cmdentry.cmdtype == CMDUNKNOWN) { |
@@ -13165,9 +13166,27 @@ exportcmd(int argc UNUSED_PARAM, char **argv) | |||
13165 | char *name; | 13166 | char *name; |
13166 | const char *p; | 13167 | const char *p; |
13167 | char **aptr; | 13168 | char **aptr; |
13168 | int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT; | 13169 | char opt; |
13170 | int flag; | ||
13171 | int flag_off; | ||
13169 | 13172 | ||
13170 | if (nextopt("p") != 'p') { | 13173 | /* "readonly" in bash accepts, but ignores -n. |
13174 | * We do the same: it saves a conditional in nextopt's param. | ||
13175 | */ | ||
13176 | flag_off = 0; | ||
13177 | while ((opt = nextopt("np")) != '\0') { | ||
13178 | if (opt == 'n') | ||
13179 | flag_off = VEXPORT; | ||
13180 | } | ||
13181 | flag = VEXPORT; | ||
13182 | if (argv[0][0] == 'r') { | ||
13183 | flag = VREADONLY; | ||
13184 | flag_off = 0; /* readonly ignores -n */ | ||
13185 | } | ||
13186 | flag_off = ~flag_off; | ||
13187 | |||
13188 | /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */ | ||
13189 | { | ||
13171 | aptr = argptr; | 13190 | aptr = argptr; |
13172 | name = *aptr; | 13191 | name = *aptr; |
13173 | if (name) { | 13192 | if (name) { |
@@ -13178,15 +13197,19 @@ exportcmd(int argc UNUSED_PARAM, char **argv) | |||
13178 | } else { | 13197 | } else { |
13179 | vp = *findvar(hashvar(name), name); | 13198 | vp = *findvar(hashvar(name), name); |
13180 | if (vp) { | 13199 | if (vp) { |
13181 | vp->flags |= flag; | 13200 | vp->flags = ((vp->flags | flag) & flag_off); |
13182 | continue; | 13201 | continue; |
13183 | } | 13202 | } |
13184 | } | 13203 | } |
13185 | setvar(name, p, flag); | 13204 | setvar(name, p, (flag & flag_off)); |
13186 | } while ((name = *++aptr) != NULL); | 13205 | } while ((name = *++aptr) != NULL); |
13187 | return 0; | 13206 | return 0; |
13188 | } | 13207 | } |
13189 | } | 13208 | } |
13209 | |||
13210 | /* No arguments. Show the list of exported or readonly vars. | ||
13211 | * -n is ignored. | ||
13212 | */ | ||
13190 | showvars(argv[0], flag, 0); | 13213 | showvars(argv[0], flag, 0); |
13191 | return 0; | 13214 | return 0; |
13192 | } | 13215 | } |