aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRon Yorston <rmy@pobox.com>2012-10-10 12:56:24 +0100
committerRon Yorston <rmy@pobox.com>2012-10-10 12:56:24 +0100
commit981a6fcd1323a77d5829c7d574bb40fd1b96dc4d (patch)
treea1e3aadf4de65d7a525c7dd6172546ff577777d5
parent19436cc0ee509a5e356c04f0026919abd417bec4 (diff)
parenteab343e7e1e5331df833aa69f14584e4a6c738f1 (diff)
downloadbusybox-w32-981a6fcd1323a77d5829c7d574bb40fd1b96dc4d.tar.gz
busybox-w32-981a6fcd1323a77d5829c7d574bb40fd1b96dc4d.tar.bz2
busybox-w32-981a6fcd1323a77d5829c7d574bb40fd1b96dc4d.zip
Merge branch 'busybox' into merge
-rw-r--r--coreutils/stat.c4
-rw-r--r--debianutils/mktemp.c40
-rw-r--r--e2fsprogs/old_e2fsprogs/lsattr.c2
-rw-r--r--include/libbb.h2
-rw-r--r--libbb/get_shell_name.c2
-rw-r--r--libbb/lineedit.c3
-rw-r--r--libbb/procps.c2
-rw-r--r--libbb/signals.c6
-rw-r--r--loginutils/adduser.c22
-rw-r--r--miscutils/flashcp.c3
-rw-r--r--modutils/modprobe-small.c11
-rw-r--r--networking/Config.src4
-rw-r--r--networking/brctl.c4
-rw-r--r--networking/telnet.c55
-rw-r--r--networking/telnetd.c1
-rw-r--r--networking/udhcp/d6_dhcpc.c4
-rw-r--r--networking/udhcp/dhcpc.c61
-rw-r--r--procps/Config.src54
-rw-r--r--procps/ps.c6
-rw-r--r--procps/top.c161
-rw-r--r--scripts/kconfig/mconf.c16
-rw-r--r--shell/ash.c41
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 */
1267const char *get_shell_name(void); 1267const char *get_shell_name(void) FAST_FUNC;
1268 1268
1269#if ENABLE_SELINUX 1269#if ENABLE_SELINUX
1270extern void renew_current_security_context(void) FAST_FUNC; 1270extern 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
11const char *get_shell_name(void) 11const 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
103void FAST_FUNC signal_SA_RESTART_empty_mask(int sig, void (*handler)(int)) 103void 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
83static void addgroup_wrapper(struct passwd *p, const char *group_name) 83static 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
116static void passwd_wrapper(const char *login_name) NORETURN; 116static 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
84config FEATURE_BRCTL_SHOW 84config 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
92config DNSD 92config 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
187static void handle_net_output(int len) 187static 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
225static void handle_net_input(int len) 220static 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
401static char const escapecharis[] ALIGN1 = "\r\nEscape character is ";
402
403static void setConMode(void) 396static 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
143config 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
150config 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
158config 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
166config 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
174config 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
182config 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
190config 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
197config FEATURE_SHOW_THREADS 143config 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
123enum { LINE_BUF_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line_buf) }; 185enum { 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
657static void reset_term(void) 718static 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
668static void sig_catcher(int sig UNUSED_PARAM) 730static 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
857static unsigned handle_input(unsigned scan_mask, unsigned interval) 919static 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;
1011int top_main(int argc UNUSED_PARAM, char **argv) 1110int 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
446pid_t pid; 446pid_t pid;
447 447
448#ifdef SIGWINCH
448static void winch_handler(int sig) 449static 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
456static int exec_conf(void) 458static 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}