From d32fc647d7da1923a91750ae937bf9b517195c8f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 1 Jul 2014 13:20:22 +0200 Subject: libbb: fix bb_ask() to flush input before prompt, not after. Closes 7190 Signed-off-by: Denys Vlasenko --- libbb/bb_askpass.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libbb/bb_askpass.c b/libbb/bb_askpass.c index 77c1bcd95..1927ba9e9 100644 --- a/libbb/bb_askpass.c +++ b/libbb/bb_askpass.c @@ -30,9 +30,12 @@ char* FAST_FUNC bb_ask(const int fd, int timeout, const char *prompt) struct sigaction sa, oldsa; struct termios tio, oldtio; + tcflush(fd, TCIFLUSH); + /* Was buggy: was printing prompt *before* flushing input, + * which was upsetting "expect" based scripts of some users. + */ fputs(prompt, stdout); fflush_all(); - tcflush(fd, TCIFLUSH); tcgetattr(fd, &oldtio); tio = oldtio; -- cgit v1.2.3-55-g6feb From 98654b995bb460733d94eba9ff2ee3d746c1e344 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 1 Jul 2014 14:16:28 +0200 Subject: test: fix mishandling of "test '(' = '('" and similar function old new delta test_main 246 350 +104 Signed-off-by: Denys Vlasenko --- coreutils/test.c | 69 ++++++++++++++++++++++++++-------------------------- testsuite/test.tests | 20 +++++++++++++++ 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/coreutils/test.c b/coreutils/test.c index 4df505a05..88cc55050 100644 --- a/coreutils/test.c +++ b/coreutils/test.c @@ -826,7 +826,6 @@ int test_main(int argc, char **argv) { int res; const char *arg0; -// bool negate = 0; arg0 = bb_basename(argv[0]); if (arg0[0] == '[') { @@ -844,6 +843,7 @@ int test_main(int argc, char **argv) } argv[argc] = NULL; } + /* argc is unused after this point */ /* We must do DEINIT_S() prior to returning */ INIT_S(); @@ -862,43 +862,45 @@ int test_main(int argc, char **argv) */ /*ngroups = 0; - done by INIT_S() */ - //argc--; argv++; + args = argv; - /* Implement special cases from POSIX.2, section 4.62.4 */ - if (!argv[0]) { /* "test" */ - res = 1; - goto ret; - } -#if 0 -// Now it's fixed in the parser and should not be needed - if (LONE_CHAR(argv[0], '!') && argv[1]) { - negate = 1; - //argc--; - argv++; - } - if (!argv[1]) { /* "test [!] arg" */ - res = (*argv[0] == '\0'); - goto ret; - } - if (argv[2] && !argv[3]) { - check_operator(argv[1]); - if (last_operator->op_type == BINOP) { - /* "test [!] arg1 arg2" */ - args = argv; - res = (binop() == 0); - goto ret; + /* Implement special cases from POSIX.2, section 4.62.4. + * Testcase: "test '(' = '('" + * The general parser would misinterpret '(' as group start. + */ + if (1) { + int negate = 0; + again: + if (!argv[0]) { + /* "test" */ + res = 1; + goto ret_special; + } + if (!argv[1]) { + /* "test [!] arg" */ + res = (argv[0][0] == '\0'); + goto ret_special; + } + if (argv[2] && !argv[3]) { + check_operator(argv[1]); + if (last_operator->op_type == BINOP) { + /* "test [!] arg1 arg2" */ + args = argv; + res = (binop() == 0); + ret_special: + /* If there was leading "!" op... */ + res ^= negate; + goto ret; + } + } + if (LONE_CHAR(argv[0], '!')) { + argv++; + negate ^= 1; + goto again; } } - /* Some complex expression. Undo '!' removal */ - if (negate) { - negate = 0; - //argc++; - argv--; - } -#endif - args = argv; res = !oexpr(check_operator(*args)); if (*args != NULL && *++args != NULL) { @@ -911,6 +913,5 @@ int test_main(int argc, char **argv) } ret: DEINIT_S(); -// return negate ? !res : res; return res; } diff --git a/testsuite/test.tests b/testsuite/test.tests index 2c92e34ba..1c2edaf62 100755 --- a/testsuite/test.tests +++ b/testsuite/test.tests @@ -76,4 +76,24 @@ testing "test ! a = b -a ! c = d: should be true (0)" \ "0\n" \ "" "" +testing "test '!' = '!': should be true (0)" \ + "busybox test '!' = '!'; echo \$?" \ + "0\n" \ + "" "" + +testing "test '(' = '(': should be true (0)" \ + "busybox test '(' = '('; echo \$?" \ + "0\n" \ + "" "" + +testing "test '!' '!' = '!': should be false (1)" \ + "busybox test '!' '!' = '!'; echo \$?" \ + "1\n" \ + "" "" + +testing "test '!' '(' = '(': should be false (1)" \ + "busybox test '!' '(' = '('; echo \$?" \ + "1\n" \ + "" "" + exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From a28c1b21e1a3770b83fe9b15f26ec50f2e14e7f6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 2 Jul 2014 15:21:30 +0200 Subject: syslogd: make "-O -" log to stdout function old new delta packed_usage 29871 29908 +37 log_locally 404 440 +36 syslogd_main 1966 1956 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 73/-10) Total: 63 bytes Signed-off-by: Denys Vlasenko --- sysklogd/syslogd.c | 81 ++++++++++++++++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 36 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index f75851085..d80447bd7 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -21,31 +21,31 @@ //usage: "(this version of syslogd ignores /etc/syslog.conf)\n" //usage: ) //usage: "\n -n Run in foreground" -//usage: "\n -O FILE Log to FILE (default:/var/log/messages)" -//usage: "\n -l N Log only messages more urgent than prio N (1-8)" -//usage: "\n -S Smaller output" -//usage: IF_FEATURE_ROTATE_LOGFILE( -//usage: "\n -s SIZE Max size (KB) before rotation (default:200KB, 0=off)" -//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)" -//usage: ) //usage: IF_FEATURE_REMOTE_LOG( //usage: "\n -R HOST[:PORT] Log to HOST:PORT (default PORT:514)" //usage: "\n -L Log locally and via network (default is network only if -R)" //usage: ) -//usage: IF_FEATURE_SYSLOGD_DUP( -//usage: "\n -D Drop duplicates" -//usage: ) //usage: IF_FEATURE_IPC_SYSLOG( /* NB: -Csize shouldn't have space (because size is optional) */ //usage: "\n -C[size_kb] Log to shared mem buffer (use logread to read it)" //usage: ) +//usage: IF_FEATURE_KMSG_SYSLOG( +//usage: "\n -K Log to kernel printk buffer (use dmesg to read it)" +//usage: ) +//usage: "\n -O FILE Log to FILE (default:/var/log/messages, stdout if -)" +//usage: IF_FEATURE_ROTATE_LOGFILE( +//usage: "\n -s SIZE Max size (KB) before rotation (default:200KB, 0=off)" +//usage: "\n -b N N rotated logs to keep (default:1, max=99, 0=purge)" +//usage: ) +//usage: "\n -l N Log only messages more urgent than prio N (1-8)" +//usage: "\n -S Smaller output" +//usage: IF_FEATURE_SYSLOGD_DUP( +//usage: "\n -D Drop duplicates" +//usage: ) //usage: IF_FEATURE_SYSLOGD_CFG( //usage: "\n -f FILE Use FILE as config (default:/etc/syslog.conf)" //usage: ) /* //usage: "\n -m MIN Minutes between MARK lines (default:20, 0=off)" */ -//usage: IF_FEATURE_KMSG_SYSLOG( -//usage: "\n -K Log to kernel printk buffer (use dmesg to read it)" -//usage: ) //usage: //usage:#define syslogd_example_usage //usage: "$ syslogd -R masterlog:514\n" @@ -585,7 +585,9 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file) #endif int len = strlen(msg); - if (log_file->fd >= 0) { + /* fd can't be 0 (we connect fd 0 to /dev/log socket) */ + /* fd is 1 if "-O -" is in use */ + if (log_file->fd > 1) { /* Reopen log file every second. This allows admin * to delete the file and not worry about restarting us. * This costs almost nothing since it happens @@ -598,29 +600,38 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file) close(log_file->fd); goto reopen; } - } else { + } + else if (log_file->fd == 1) { + /* We are logging to stdout: do nothing */ + } + else { + if (LONE_DASH(log_file->path)) { + log_file->fd = 1; + /* log_file->isRegular = 0; - already is */ + } else { reopen: - log_file->fd = open(log_file->path, O_WRONLY | O_CREAT + log_file->fd = open(log_file->path, O_WRONLY | O_CREAT | O_NOCTTY | O_APPEND | O_NONBLOCK, 0666); - if (log_file->fd < 0) { - /* cannot open logfile? - print to /dev/console then */ - int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK); - if (fd < 0) - fd = 2; /* then stderr, dammit */ - full_write(fd, msg, len); - if (fd != 2) - close(fd); - return; - } + if (log_file->fd < 0) { + /* cannot open logfile? - print to /dev/console then */ + int fd = device_open(DEV_CONSOLE, O_WRONLY | O_NOCTTY | O_NONBLOCK); + if (fd < 0) + fd = 2; /* then stderr, dammit */ + full_write(fd, msg, len); + if (fd != 2) + close(fd); + return; + } #if ENABLE_FEATURE_ROTATE_LOGFILE - { - struct stat statf; - log_file->isRegular = (fstat(log_file->fd, &statf) == 0 && S_ISREG(statf.st_mode)); - /* bug (mostly harmless): can wrap around if file > 4gb */ - log_file->size = statf.st_size; - } + { + struct stat statf; + log_file->isRegular = (fstat(log_file->fd, &statf) == 0 && S_ISREG(statf.st_mode)); + /* bug (mostly harmless): can wrap around if file > 4gb */ + log_file->size = statf.st_size; + } #endif + } } #ifdef SYSLOGD_WRLOCK @@ -865,7 +876,6 @@ static int try_to_resolve_remote(remoteHost_t *rh) static void do_syslogd(void) NORETURN; static void do_syslogd(void) { - int sock_fd; #if ENABLE_FEATURE_REMOTE_LOG llist_t *item; #endif @@ -886,7 +896,7 @@ static void do_syslogd(void) signal(SIGALRM, do_mark); alarm(G.markInterval); #endif - sock_fd = create_socket(); + xmove_fd(create_socket(), STDIN_FILENO); if (option_mask32 & OPT_circularlog) ipcsyslog_init(); @@ -907,7 +917,7 @@ static void do_syslogd(void) recvbuf = G.recvbuf; #endif read_again: - sz = read(sock_fd, recvbuf, MAX_READ - 1); + sz = read(STDIN_FILENO, recvbuf, MAX_READ - 1); if (sz < 0) { if (!bb_got_signal) bb_perror_msg("read from %s", _PATH_LOG); @@ -978,7 +988,6 @@ static void do_syslogd(void) } /* while (!bb_got_signal) */ timestamp_and_log_internal("syslogd exiting"); - puts("syslogd exiting"); remove_pidfile(CONFIG_PID_FILE_PATH "/syslogd.pid"); ipcsyslog_cleanup(); if (option_mask32 & OPT_kmsg) -- cgit v1.2.3-55-g6feb From e46047aa87c9ec0b8e27d1d4ecfcb3e9798ddb8d Mon Sep 17 00:00:00 2001 From: Joshua Judson Rosen Date: Wed, 2 Jul 2014 19:41:41 +0200 Subject: syslogd: syslogd: don't *decrement* log_file->size on write failures Even if we fail to write to a log-file, and it's not growing, it's not *shrinking* either.... Signed-off-by: Joshua Judson Rosen Signed-off-by: Denys Vlasenko --- sysklogd/syslogd.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index d80447bd7..04221fc33 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -569,7 +569,7 @@ static void log_to_kmsg(int pri, const char *msg) */ pri &= G.primask; - write(G.kmsgfd, G.printbuf, sprintf(G.printbuf, "<%d>%s\n", pri, msg)); + full_write(G.kmsgfd, G.printbuf, sprintf(G.printbuf, "<%d>%s\n", pri, msg)); } #else static void kmsg_init(void) {} @@ -678,9 +678,14 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file) close(log_file->fd); goto reopen; } - log_file->size += +/* TODO: what to do on write errors ("disk full")? */ + len = full_write(log_file->fd, msg, len); + if (len > 0) + log_file->size += len; +#else + full_write(log_file->fd, msg, len); #endif - full_write(log_file->fd, msg, len); + #ifdef SYSLOGD_WRLOCK fl.l_type = F_UNLCK; fcntl(log_file->fd, F_SETLKW, &fl); -- cgit v1.2.3-55-g6feb From ae57fcad5d36dc2ba00179ef3e44154c10223862 Mon Sep 17 00:00:00 2001 From: Joshua Judson Rosen Date: Thu, 3 Jul 2014 14:51:47 +0200 Subject: syslogd: make "reopen log file every second" logic work for multiple logs Move last_log_time from a single global to *each logFile_t* so that we can actually apply the logic to every log-file in multi-file configurations, rather than working only for the first file written in each 1-second interval and then leaving the others connected to possibly wrong files. Signed-off-by: Joshua Judson Rosen Signed-off-by: Denys Vlasenko --- sysklogd/syslogd.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/sysklogd/syslogd.c b/sysklogd/syslogd.c index 04221fc33..266657f3b 100644 --- a/sysklogd/syslogd.c +++ b/sysklogd/syslogd.c @@ -110,6 +110,7 @@ typedef struct { typedef struct logFile_t { const char *path; int fd; + time_t last_log_time; #if ENABLE_FEATURE_ROTATE_LOGFILE unsigned size; uint8_t isRegular; @@ -165,7 +166,6 @@ struct globals { #if ENABLE_FEATURE_IPC_SYSLOG struct shbuf_ds *shbuf; #endif - time_t last_log_time; /* localhost's name. We print only first 64 chars */ char *hostname; @@ -588,15 +588,16 @@ static void log_locally(time_t now, char *msg, logFile_t *log_file) /* fd can't be 0 (we connect fd 0 to /dev/log socket) */ /* fd is 1 if "-O -" is in use */ if (log_file->fd > 1) { - /* Reopen log file every second. This allows admin - * to delete the file and not worry about restarting us. + /* Reopen log files every second. This allows admin + * to delete the files and not worry about restarting us. * This costs almost nothing since it happens - * _at most_ once a second. + * _at most_ once a second for each file, and happens + * only when each file is actually written. */ if (!now) now = time(NULL); - if (G.last_log_time != now) { - G.last_log_time = now; + if (log_file->last_log_time != now) { + log_file->last_log_time = now; close(log_file->fd); goto reopen; } -- cgit v1.2.3-55-g6feb From 6e17766c3378b56a130830fe23e77a444ab5b7f9 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jul 2014 13:58:57 +0200 Subject: setlogcons: fix help text Signed-off-by: Denys Vlasenko --- console-tools/setlogcons.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/console-tools/setlogcons.c b/console-tools/setlogcons.c index c76a5a42b..2a11da329 100644 --- a/console-tools/setlogcons.c +++ b/console-tools/setlogcons.c @@ -10,9 +10,9 @@ */ //usage:#define setlogcons_trivial_usage -//usage: "N" +//usage: "[N]" //usage:#define setlogcons_full_usage "\n\n" -//usage: "Redirect the kernel output to console N (0 for current)" +//usage: "Redirect the kernel output to console N. Default:0 (current console)" #include "libbb.h" -- cgit v1.2.3-55-g6feb From 03e17bfa8d71c0feca01c94a820ce2f3736a35b8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 4 Jul 2014 15:16:46 +0200 Subject: fatattr: use the standard type for 32-bit int Signed-off-by: Denys Vlasenko --- util-linux/fatattr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/util-linux/fatattr.c b/util-linux/fatattr.c index 0f8d63268..5d933874a 100644 --- a/util-linux/fatattr.c +++ b/util-linux/fatattr.c @@ -34,8 +34,8 @@ #include "libbb.h" /* linux/msdos_fs.h says: */ #ifndef FAT_IOCTL_GET_ATTRIBUTES -# define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, __u32) -# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, __u32) +# define FAT_IOCTL_GET_ATTRIBUTES _IOR('r', 0x10, uint32_t) +# define FAT_IOCTL_SET_ATTRIBUTES _IOW('r', 0x11, uint32_t) #endif /* Currently supports only the FAT flags, not the NTFS ones. -- cgit v1.2.3-55-g6feb From 7d16964c3ebb9e7beee89ad96f824470f7ab5346 Mon Sep 17 00:00:00 2001 From: David Marchand Date: Thu, 3 Jul 2014 12:24:55 +0200 Subject: modinfo: fix module parsing with kernel >= 2.6.37 display() function returns the length of the value we are displaying + 1. As a consequence, if we have field=value\0field=value\0field=value in the binary, then the second occurence will be skipped as ptr will miss the first character of the following field. Example trying to list aliases from ixgbe.ko on a 3.2 kernel. - In the module we have: alias=pci:v00008086d00001560sv*sd*bc*sc*i*\0 alias=pci:v00008086d0000154Asv*sd*bc*sc*i*\0 alias=pci:v00008086d00001557sv*sd*bc*sc*i*\0 alias=pci:v00008086d0000154Fsv*sd*bc*sc*i*\0 alias=pci:v00008086d0000154Dsv*sd*bc*sc*i*\0 ... - Using modinfo -F alias ixgbe returns: alias: pci:v00008086d00001560sv*sd*bc*sc*i* alias: pci:v00008086d00001557sv*sd*bc*sc*i* alias: pci:v00008086d0000154Dsv*sd*bc*sc*i* ... This problem appeared with kernel commit "modules: no need to align .modinfo strings" b6472776816af1ed52848c93d26e3edb3b17adab in 2.6.37. Fix this by not trusting display() return value but increment ptr by strlen(ptr) (the same way as depmod.c does). Signed-off-by: David Marchand Signed-off-by: Denys Vlasenko --- modutils/modinfo.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modutils/modinfo.c b/modutils/modinfo.c index 7c978d1da..0ab942890 100644 --- a/modutils/modinfo.c +++ b/modutils/modinfo.c @@ -34,14 +34,14 @@ struct modinfo_env { int tags; }; -static int display(const char *data, const char *pattern, int flag) +static void display(const char *data, const char *pattern, int flag) { if (flag) { int n = printf("%s:", pattern); while (n++ < 16) bb_putchar(' '); } - return printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n'); + printf("%s%c", data, (option_mask32 & OPT_0) ? '\0' : '\n'); } static void modinfo(const char *path, const char *version, @@ -104,7 +104,8 @@ static void modinfo(const char *path, const char *version, /* field prefixes are 0x80 or 0x00 */ if ((ptr[-1] & 0x7F) == '\0') { ptr += length + 1; - ptr += display(ptr, pattern, (1< Date: Tue, 15 Jul 2014 15:06:54 +0200 Subject: ntpd: add support for -I IFACE function old new delta packed_usage 29908 29947 +39 ntp_init 428 460 +32 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 71/0) Total: 71 bytes Signed-off-by: Nikolaus Froehlich Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 59607ed23..cfe695631 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -29,7 +29,7 @@ */ //usage:#define ntpd_trivial_usage -//usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l")"] [-S PROG] [-p PEER]..." +//usage: "[-dnqNw"IF_FEATURE_NTPD_SERVER("l -I IFACE")"] [-S PROG] [-p PEER]..." //usage:#define ntpd_full_usage "\n\n" //usage: "NTP client/server\n" //usage: "\n -d Verbose" @@ -39,6 +39,7 @@ //usage: "\n -w Do not set time (only query peers), implies -n" //usage: IF_FEATURE_NTPD_SERVER( //usage: "\n -l Run as server on port 123" +//usage: "\n -I IFACE Bind server to IFACE, implies -l" //usage: ) //usage: "\n -S PROG Run PROG after stepping time, stratum change, and every 11 mins" //usage: "\n -p PEER Obtain time from PEER (may be repeated)" @@ -283,6 +284,7 @@ enum { OPT_p = (1 << 5), OPT_S = (1 << 6), OPT_l = (1 << 7) * ENABLE_FEATURE_NTPD_SERVER, + OPT_I = (1 << 8) * ENABLE_FEATURE_NTPD_SERVER, /* We hijack some bits for other purposes */ OPT_qq = (1 << 31), }; @@ -301,6 +303,7 @@ struct globals { llist_t *ntp_peers; #if ENABLE_FEATURE_NTPD_SERVER int listen_fd; + char *if_name; # define G_listen_fd (G.listen_fd) #else # define G_listen_fd (-1) @@ -2092,13 +2095,19 @@ static NOINLINE void ntp_init(char **argv) /* Parse options */ peers = NULL; - opt_complementary = "dd:p::wn"; /* d: counter; p: list; -w implies -n */ + opt_complementary = "dd:p::wn" /* -d: counter; -p: list; -w implies -n */ + IF_FEATURE_NTPD_SERVER(":Il"); /* -I implies -l */ opts = getopt32(argv, "nqNx" /* compat */ "wp:S:"IF_FEATURE_NTPD_SERVER("l") /* NOT compat */ + IF_FEATURE_NTPD_SERVER("I:") /* compat */ "d" /* compat */ "46aAbgL", /* compat, ignored */ - &peers, &G.script_name, &G.verbose); + &peers,&G.script_name, +#if ENABLE_FEATURE_NTPD_SERVER + &G.if_name, +#endif + &G.verbose); // if (opts & OPT_x) /* disable stepping, only slew is allowed */ // G.time_was_stepped = 1; @@ -2130,18 +2139,22 @@ static NOINLINE void ntp_init(char **argv) /* -l but no peers: "stratum 1 server" mode */ G.stratum = 1; } - if (!(opts & OPT_n)) { - bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); - logmode = LOGMODE_NONE; - } #if ENABLE_FEATURE_NTPD_SERVER G_listen_fd = -1; if (opts & OPT_l) { G_listen_fd = create_and_bind_dgram_or_die(NULL, 123); + if (opts & OPT_I) { + if (setsockopt_bindtodevice(G_listen_fd, G.if_name)) + xfunc_die(); + } socket_want_pktinfo(G_listen_fd); setsockopt(G_listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); } #endif + if (!(opts & OPT_n)) { + bb_daemonize_or_rexec(DAEMON_DEVNULL_STDIO, argv); + logmode = LOGMODE_NONE; + } /* I hesitate to set -20 prio. -15 should be high enough for timekeeping */ if (opts & OPT_N) setpriority(PRIO_PROCESS, 0, -15); -- cgit v1.2.3-55-g6feb From b8ffd11e65734f90ebdaedb0ce32196fb150db01 Mon Sep 17 00:00:00 2001 From: Jeremy Kerr Date: Tue, 15 Jul 2014 11:03:17 +0800 Subject: udhcp: add PXELINUX path prefix option (code 210) definition Like d3092c99, this change adds support for the DHCP "path-prefix" option, as defined in RFC 5071. We use the string identifer "pxepathprefix". Adding this option makes string parsing in the hook scripts simpler. function old new delta dhcp_option_strings 255 269 +14 dhcp_optflags 72 74 +2 Signed-off-by: Jeremy Kerr Signed-off-by: Denys Vlasenko --- networking/udhcp/common.c | 2 ++ networking/udhcp/common.h | 1 + 2 files changed, 3 insertions(+) diff --git a/networking/udhcp/common.c b/networking/udhcp/common.c index fe322db4f..bc41c8d4d 100644 --- a/networking/udhcp/common.c +++ b/networking/udhcp/common.c @@ -63,6 +63,7 @@ const struct dhcp_optflag dhcp_optflags[] = { { OPTION_U8 , 0x85 }, /* DHCP_VLAN_PRIORITY */ #endif { OPTION_STRING , 0xd1 }, /* DHCP_PXE_CONF_FILE */ + { OPTION_STRING , 0xd2 }, /* DHCP_PXE_PATH_PREFIX */ { OPTION_6RD , 0xd4 }, /* DHCP_6RD */ { OPTION_STATIC_ROUTES | OPTION_LIST , 0xf9 }, /* DHCP_MS_STATIC_ROUTES */ { OPTION_STRING , 0xfc }, /* DHCP_WPAD */ @@ -130,6 +131,7 @@ const char dhcp_option_strings[] ALIGN1 = "vlanpriority" "\0"/* DHCP_VLAN_PRIORITY */ #endif "pxeconffile" "\0" /* DHCP_PXE_CONF_FILE */ + "pxepathprefix" "\0" /* DHCP_PXE_PATH_PREFIX */ "ip6rd" "\0" /* DHCP_6RD */ "msstaticroutes""\0"/* DHCP_MS_STATIC_ROUTES */ "wpad" "\0" /* DHCP_WPAD */ diff --git a/networking/udhcp/common.h b/networking/udhcp/common.h index 5e70d609f..e5e0f2599 100644 --- a/networking/udhcp/common.h +++ b/networking/udhcp/common.h @@ -152,6 +152,7 @@ enum { //#define DHCP_VLAN_ID 0x84 /* 802.1P VLAN ID */ //#define DHCP_VLAN_PRIORITY 0x85 /* 802.1Q VLAN priority */ //#define DHCP_PXE_CONF_FILE 0xd1 /* RFC 5071 Configuration File */ +//#define DHCP_PXE_PATH_PREFIX 0xd2 /* RFC 5071 Configuration File */ //#define DHCP_MS_STATIC_ROUTES 0xf9 /* Microsoft's pre-RFC 3442 code for 0x79? */ //#define DHCP_WPAD 0xfc /* MSIE's Web Proxy Autodiscovery Protocol */ #define DHCP_END 0xff -- cgit v1.2.3-55-g6feb From a4d564ad7c24df2da1d8e03a7dd016f0a3d5edbd Mon Sep 17 00:00:00 2001 From: Ken Sharp Date: Sun, 20 Jul 2014 14:01:49 +0200 Subject: zcip: fix link-local IP conflict detection During link-local IP resolution, if a regular ARP request is received during the ARP probe period, it will incorrectly cause a target IP conflict. This then leads to a new IP being picked unnecessarily. Per RFC 3927, section 2.2.1, we should flag a target IP conflict only if the source IP is null, the target IP matches our IP, and the source hw addr does not match our hw addr. function old new delta zcip_main 1354 1322 -32 Signed-off-by: Ken Sharp Signed-off-by: Ben Shelton Signed-off-by: Denys Vlasenko --- networking/zcip.c | 38 ++++++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 16 deletions(-) diff --git a/networking/zcip.c b/networking/zcip.c index 7314ff8db..45d1f7c1c 100644 --- a/networking/zcip.c +++ b/networking/zcip.c @@ -366,11 +366,11 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) nprobes++; VDBG("probe/%u %s@%s\n", nprobes, argv_intf, inet_ntoa(ip)); + timeout_ms = PROBE_MIN * 1000; + timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); arp(/* ARPOP_REQUEST, */ /* ð_addr, */ null_ip, &null_addr, ip); - timeout_ms = PROBE_MIN * 1000; - timeout_ms += random_delay_ms(PROBE_MAX - PROBE_MIN); } else { // Switch to announce state. @@ -378,10 +378,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) nclaims = 0; VDBG("announce/%u %s@%s\n", nclaims, argv_intf, inet_ntoa(ip)); + timeout_ms = ANNOUNCE_INTERVAL * 1000; arp(/* ARPOP_REQUEST, */ /* ð_addr, */ ip, ð_addr, ip); - timeout_ms = ANNOUNCE_INTERVAL * 1000; } break; case RATE_LIMIT_PROBE: @@ -391,10 +391,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) nclaims = 0; VDBG("announce/%u %s@%s\n", nclaims, argv_intf, inet_ntoa(ip)); + timeout_ms = ANNOUNCE_INTERVAL * 1000; arp(/* ARPOP_REQUEST, */ /* ð_addr, */ ip, ð_addr, ip); - timeout_ms = ANNOUNCE_INTERVAL * 1000; break; case ANNOUNCE: // timeouts in the ANNOUNCE state mean no conflicting ARP packets @@ -403,10 +403,10 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) nclaims++; VDBG("announce/%u %s@%s\n", nclaims, argv_intf, inet_ntoa(ip)); + timeout_ms = ANNOUNCE_INTERVAL * 1000; arp(/* ARPOP_REQUEST, */ /* ð_addr, */ ip, ð_addr, ip); - timeout_ms = ANNOUNCE_INTERVAL * 1000; } else { // Switch to monitor state. @@ -495,22 +495,28 @@ int zcip_main(int argc UNUSED_PARAM, char **argv) } #endif if (p.arp.arp_op != htons(ARPOP_REQUEST) - && p.arp.arp_op != htons(ARPOP_REPLY)) + && p.arp.arp_op != htons(ARPOP_REPLY) + ) { continue; + } source_ip_conflict = 0; target_ip_conflict = 0; - if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr)) == 0 - && memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0 - ) { - source_ip_conflict = 1; - } - if (p.arp.arp_op == htons(ARPOP_REQUEST) - && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 - && memcmp(&p.arp.arp_tha, ð_addr, ETH_ALEN) != 0 - ) { - target_ip_conflict = 1; + if (memcmp(&p.arp.arp_sha, ð_addr, ETH_ALEN) != 0) { + if (memcmp(p.arp.arp_spa, &ip.s_addr, sizeof(struct in_addr))) { + /* A probe or reply with source_ip == chosen ip */ + source_ip_conflict = 1; + } + if (p.arp.arp_op == htons(ARPOP_REQUEST) + && memcmp(p.arp.arp_spa, &null_ip, sizeof(struct in_addr)) == 0 + && memcmp(p.arp.arp_tpa, &ip.s_addr, sizeof(struct in_addr)) == 0 + ) { + /* A probe with source_ip == 0.0.0.0, target_ip == chosen ip: + * another host trying to claim this ip! + */ + target_ip_conflict = 1; + } } VDBG("state = %d, source ip conflict = %d, target ip conflict = %d\n", -- cgit v1.2.3-55-g6feb From 2a563ea49a16589f47ed6afe7b22eebef4e3a6d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 25 Jul 2014 17:24:13 +0200 Subject: sha3: add 32-bit optimized bit-sliced implementation It is an interesting trick, but so far I only managed to make it work correctly, not to make it faster and/or smaller. The code is ifdefed out for now. Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha.c | 256 ++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 242 insertions(+), 14 deletions(-) diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index 3f743ac75..dff583ad1 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -926,10 +926,81 @@ void FAST_FUNC sha512_end(sha512_ctx_t *ctx, void *resbuf) # define SHA3_SMALL CONFIG_SHA3_SMALL #endif +#define OPTIMIZE_SHA3_FOR_32 0 +/* + * SHA3 can be optimized for 32-bit CPUs with bit-slicing: + * every 64-bit word of state[] can be split into two 32-bit words + * by even/odd bits. In this form, all rotations of sha3 round + * are 32-bit - and there are lots of them. + * However, it requires either splitting/combining state words + * before/after sha3 round (code does this now) + * or shuffling bits before xor'ing them into state and in sha3_end. + * Without shuffling, bit-slicing results in -130 bytes of code + * and marginal speedup (but of course it gives wrong result). + * With shuffling it works, but +260 code bytes, and slower. + * Disabled for now: + */ +#if 0 /* LONG_MAX == 0x7fffffff */ +# undef OPTIMIZE_SHA3_FOR_32 +# define OPTIMIZE_SHA3_FOR_32 1 +#endif + enum { SHA3_IBLK_BYTES = 72, /* 576 bits / 8 */ }; +#if OPTIMIZE_SHA3_FOR_32 +/* This splits every 64-bit word into a pair of 32-bit words, + * even bits go into first word, odd bits go to second one. + * The conversion is done in-place. + */ +static void split_halves(uint64_t *state) +{ + /* Credit: Henry S. Warren, Hacker's Delight, Addison-Wesley, 2002 */ + uint32_t *s32 = (uint32_t*)state; + uint32_t t, x0, x1; + int i; + for (i = 24; i >= 0; --i) { + x0 = s32[0]; + t = (x0 ^ (x0 >> 1)) & 0x22222222; x0 = x0 ^ t ^ (t << 1); + t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0C; x0 = x0 ^ t ^ (t << 2); + t = (x0 ^ (x0 >> 4)) & 0x00F000F0; x0 = x0 ^ t ^ (t << 4); + t = (x0 ^ (x0 >> 8)) & 0x0000FF00; x0 = x0 ^ t ^ (t << 8); + x1 = s32[1]; + t = (x1 ^ (x1 >> 1)) & 0x22222222; x1 = x1 ^ t ^ (t << 1); + t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0C; x1 = x1 ^ t ^ (t << 2); + t = (x1 ^ (x1 >> 4)) & 0x00F000F0; x1 = x1 ^ t ^ (t << 4); + t = (x1 ^ (x1 >> 8)) & 0x0000FF00; x1 = x1 ^ t ^ (t << 8); + *s32++ = (x0 & 0x0000FFFF) | (x1 << 16); + *s32++ = (x0 >> 16) | (x1 & 0xFFFF0000); + } +} +/* The reverse operation */ +static void combine_halves(uint64_t *state) +{ + uint32_t *s32 = (uint32_t*)state; + uint32_t t, x0, x1; + int i; + for (i = 24; i >= 0; --i) { + x0 = s32[0]; + x1 = s32[1]; + t = (x0 & 0x0000FFFF) | (x1 << 16); + x1 = (x0 >> 16) | (x1 & 0xFFFF0000); + x0 = t; + t = (x0 ^ (x0 >> 8)) & 0x0000FF00; x0 = x0 ^ t ^ (t << 8); + t = (x0 ^ (x0 >> 4)) & 0x00F000F0; x0 = x0 ^ t ^ (t << 4); + t = (x0 ^ (x0 >> 2)) & 0x0C0C0C0C; x0 = x0 ^ t ^ (t << 2); + t = (x0 ^ (x0 >> 1)) & 0x22222222; x0 = x0 ^ t ^ (t << 1); + *s32++ = x0; + t = (x1 ^ (x1 >> 8)) & 0x0000FF00; x1 = x1 ^ t ^ (t << 8); + t = (x1 ^ (x1 >> 4)) & 0x00F000F0; x1 = x1 ^ t ^ (t << 4); + t = (x1 ^ (x1 >> 2)) & 0x0C0C0C0C; x1 = x1 ^ t ^ (t << 2); + t = (x1 ^ (x1 >> 1)) & 0x22222222; x1 = x1 ^ t ^ (t << 1); + *s32++ = x1; + } +} +#endif + /* * In the crypto literature this function is usually called Keccak-f(). */ @@ -937,6 +1008,164 @@ static void sha3_process_block72(uint64_t *state) { enum { NROUNDS = 24 }; +#if OPTIMIZE_SHA3_FOR_32 + /* + static const uint32_t IOTA_CONST_0[NROUNDS] = { + 0x00000001UL, + 0x00000000UL, + 0x00000000UL, + 0x00000000UL, + 0x00000001UL, + 0x00000001UL, + 0x00000001UL, + 0x00000001UL, + 0x00000000UL, + 0x00000000UL, + 0x00000001UL, + 0x00000000UL, + 0x00000001UL, + 0x00000001UL, + 0x00000001UL, + 0x00000001UL, + 0x00000000UL, + 0x00000000UL, + 0x00000000UL, + 0x00000000UL, + 0x00000001UL, + 0x00000000UL, + 0x00000001UL, + 0x00000000UL, + }; + ** bits are in lsb: 0101 0000 1111 0100 1111 0001 + */ + uint32_t IOTA_CONST_0bits = (uint32_t)(0x0050f4f1); + static const uint32_t IOTA_CONST_1[NROUNDS] = { + 0x00000000UL, + 0x00000089UL, + 0x8000008bUL, + 0x80008080UL, + 0x0000008bUL, + 0x00008000UL, + 0x80008088UL, + 0x80000082UL, + 0x0000000bUL, + 0x0000000aUL, + 0x00008082UL, + 0x00008003UL, + 0x0000808bUL, + 0x8000000bUL, + 0x8000008aUL, + 0x80000081UL, + 0x80000081UL, + 0x80000008UL, + 0x00000083UL, + 0x80008003UL, + 0x80008088UL, + 0x80000088UL, + 0x00008000UL, + 0x80008082UL, + }; + + uint32_t *const s32 = (uint32_t*)state; + unsigned round; + + split_halves(state); + + for (round = 0; round < NROUNDS; round++) { + unsigned x; + + /* Theta */ + { + uint32_t BC[20]; + for (x = 0; x < 10; ++x) { + BC[x+10] = BC[x] = s32[x]^s32[x+10]^s32[x+20]^s32[x+30]^s32[x+40]; + } + for (x = 0; x < 10; x += 2) { + uint32_t ta, tb; + ta = BC[x+8] ^ rotl32(BC[x+3], 1); + tb = BC[x+9] ^ BC[x+2]; + s32[x+0] ^= ta; + s32[x+1] ^= tb; + s32[x+10] ^= ta; + s32[x+11] ^= tb; + s32[x+20] ^= ta; + s32[x+21] ^= tb; + s32[x+30] ^= ta; + s32[x+31] ^= tb; + s32[x+40] ^= ta; + s32[x+41] ^= tb; + } + } + /* RhoPi */ + { + uint32_t t0a,t0b, t1a,t1b; + t1a = s32[1*2+0]; + t1b = s32[1*2+1]; + +#define RhoPi(PI_LANE, ROT_CONST) \ + t0a = s32[PI_LANE*2+0];\ + t0b = s32[PI_LANE*2+1];\ + if (ROT_CONST & 1) {\ + s32[PI_LANE*2+0] = rotl32(t1b, ROT_CONST/2+1);\ + s32[PI_LANE*2+1] = ROT_CONST == 1 ? t1a : rotl32(t1a, ROT_CONST/2+0);\ + } else {\ + s32[PI_LANE*2+0] = rotl32(t1a, ROT_CONST/2);\ + s32[PI_LANE*2+1] = rotl32(t1b, ROT_CONST/2);\ + }\ + t1a = t0a; t1b = t0b; + + RhoPi(10, 1) + RhoPi( 7, 3) + RhoPi(11, 6) + RhoPi(17,10) + RhoPi(18,15) + RhoPi( 3,21) + RhoPi( 5,28) + RhoPi(16,36) + RhoPi( 8,45) + RhoPi(21,55) + RhoPi(24, 2) + RhoPi( 4,14) + RhoPi(15,27) + RhoPi(23,41) + RhoPi(19,56) + RhoPi(13, 8) + RhoPi(12,25) + RhoPi( 2,43) + RhoPi(20,62) + RhoPi(14,18) + RhoPi(22,39) + RhoPi( 9,61) + RhoPi( 6,20) + RhoPi( 1,44) +#undef RhoPi + } + /* Chi */ + for (x = 0; x <= 20; x += 5) { + /* + * Can write this in terms of uint32 too, + * but why? compiler does it automatically. + */ + uint64_t BC0, BC1, BC2, BC3, BC4; + BC0 = state[x + 0]; + BC1 = state[x + 1]; + BC2 = state[x + 2]; + state[x + 0] = BC0 ^ ((~BC1) & BC2); + BC3 = state[x + 3]; + state[x + 1] = BC1 ^ ((~BC2) & BC3); + BC4 = state[x + 4]; + state[x + 2] = BC2 ^ ((~BC3) & BC4); + state[x + 3] = BC3 ^ ((~BC4) & BC0); + state[x + 4] = BC4 ^ ((~BC0) & BC1); + } + /* Iota */ + s32[0] ^= IOTA_CONST_0bits & 1; + IOTA_CONST_0bits >>= 1; + s32[1] ^= IOTA_CONST_1[round]; + } + + combine_halves(state); +#else /* Elements should be 64-bit, but top half is always zero or 0x80000000. * We encode 63rd bits in a separate word below. * Same is true for 31th bits, which lets us use 16-bit table instead of 64-bit. @@ -983,7 +1212,7 @@ static void sha3_process_block72(uint64_t *state) }; /*static const uint8_t MOD5[10] = { 0, 1, 2, 3, 4, 0, 1, 2, 3, 4, };*/ - unsigned x, y; + unsigned x; unsigned round; if (BB_BIG_ENDIAN) { @@ -1045,22 +1274,20 @@ static void sha3_process_block72(uint64_t *state) RhoPi_twice(20); RhoPi_twice(22); #undef RhoPi_twice } - /* Chi */ - for (y = 0; y <= 20; y += 5) { + for (x = 0; x <= 20; x += 5) { uint64_t BC0, BC1, BC2, BC3, BC4; - BC0 = state[y + 0]; - BC1 = state[y + 1]; - BC2 = state[y + 2]; - state[y + 0] = BC0 ^ ((~BC1) & BC2); - BC3 = state[y + 3]; - state[y + 1] = BC1 ^ ((~BC2) & BC3); - BC4 = state[y + 4]; - state[y + 2] = BC2 ^ ((~BC3) & BC4); - state[y + 3] = BC3 ^ ((~BC4) & BC0); - state[y + 4] = BC4 ^ ((~BC0) & BC1); + BC0 = state[x + 0]; + BC1 = state[x + 1]; + BC2 = state[x + 2]; + state[x + 0] = BC0 ^ ((~BC1) & BC2); + BC3 = state[x + 3]; + state[x + 1] = BC1 ^ ((~BC2) & BC3); + BC4 = state[x + 4]; + state[x + 2] = BC2 ^ ((~BC3) & BC4); + state[x + 3] = BC3 ^ ((~BC4) & BC0); + state[x + 4] = BC4 ^ ((~BC0) & BC1); } - /* Iota */ state[0] ^= IOTA_CONST[round] | (uint32_t)((IOTA_CONST_bit31 << round) & 0x80000000) @@ -1072,6 +1299,7 @@ static void sha3_process_block72(uint64_t *state) state[x] = SWAP_LE64(state[x]); } } +#endif } void FAST_FUNC sha3_begin(sha3_ctx_t *ctx) -- cgit v1.2.3-55-g6feb From 7df1f1dda1f997c44800d16a9a12cf6cae2ed7e7 Mon Sep 17 00:00:00 2001 From: Timo Teräs Date: Mon, 21 Jul 2014 14:14:24 +0300 Subject: top: fix and merge code to parse /proc/meminfo MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit display_header() code to parse meminfo as is was buggy: - uninitialized variables were used if meminfo was not as expected - meminfo parsing failed on new kernels (3.14+) as new field 'MemAvailable' was introduced between MemFree and Buffers - shared memory was handled only for ancient kernels (2.4.x and earlier) as result Buffers and shared memory fields were shown with bogus values on current kernels. The new code does not try to parse the old style summary header, as the separated fields are always present (it saves code size). Additionally, both Shmem (2.6+) and MemShared (2.4 and earlier) fields are now parsed and summed for shared memory usage; as only one of them exists depending on kernel version. display_topmem_header() parses also meminfo so this makes it use the same code for code shrink. function old new delta display_header - 681 +681 display_topmem_process_list 465 684 +219 parse_meminfo - 189 +189 static.fields - 106 +106 static.match 132 - -132 .rodata 120254 120117 -137 display_topmem_header 513 - -513 display_process_list 1705 667 -1038 ------------------------------------------------------------------------------ (add/remove: 3/2 grow/shrink: 1/2 up/down: 1195/-1820) Total: -625 bytes Signed-off-by: Timo Teräs Signed-off-by: Denys Vlasenko --- procps/top.c | 196 ++++++++++++++++++++++++++--------------------------------- 1 file changed, 86 insertions(+), 110 deletions(-) diff --git a/procps/top.c b/procps/top.c index 530f45fa1..62f9421af 100644 --- a/procps/top.c +++ b/procps/top.c @@ -499,85 +499,94 @@ static void display_cpus(int scr_width, char *scrbuf, int *lines_rem_p) # define display_cpus(scr_width, scrbuf, lines_rem) ((void)0) #endif -static unsigned long display_header(int scr_width, int *lines_rem_p) -{ - FILE *fp; - char buf[80]; - char scrbuf[80]; - unsigned long total, used, mfree, shared, buffers, cached; +enum { + MI_MEMTOTAL, + MI_MEMFREE, + MI_MEMSHARED, + MI_SHMEM, + MI_BUFFERS, + MI_CACHED, + MI_SWAPTOTAL, + MI_SWAPFREE, + MI_DIRTY, + MI_WRITEBACK, + MI_ANONPAGES, + MI_MAPPED, + MI_SLAB, + MI_MAX +}; - /* read memory info */ - fp = xfopen_for_read("meminfo"); +static void parse_meminfo(unsigned long meminfo[MI_MAX]) +{ + static const char fields[] = + "MemTotal\0" + "MemFree\0" + "MemShared\0" + "Shmem\0" + "Buffers\0" + "Cached\0" + "SwapTotal\0" + "SwapFree\0" + "Dirty\0" + "Writeback\0" + "AnonPages\0" + "Mapped\0" + "Slab\0"; + char buf[60]; /* actual lines we expect are ~30 chars or less */ + FILE *f; + int i; - /* - * Old kernels (such as 2.4.x) had a nice summary of memory info that - * we could parse, however this is gone entirely in 2.6. Try parsing - * the old way first, and if that fails, parse each field manually. - * - * First, we read in the first line. Old kernels will have bogus - * strings we don't care about, whereas new kernels will start right - * out with MemTotal: - * -- PFM. - */ - if (fscanf(fp, "MemTotal: %lu %s\n", &total, buf) != 2) { - fgets(buf, sizeof(buf), fp); /* skip first line */ - - fscanf(fp, "Mem: %lu %lu %lu %lu %lu %lu", - &total, &used, &mfree, &shared, &buffers, &cached); - /* convert to kilobytes */ - used /= 1024; - mfree /= 1024; - shared /= 1024; - buffers /= 1024; - cached /= 1024; - total /= 1024; - } else { - /* - * Revert to manual parsing, which incidentally already has the - * sizes in kilobytes. This should be safe for both 2.4 and - * 2.6. - */ - fscanf(fp, "MemFree: %lu %s\n", &mfree, buf); + memset(meminfo, 0, sizeof(meminfo)); + f = xfopen_for_read("meminfo"); + while (fgets(buf, sizeof(buf), f) != NULL) { + char *c = strchr(buf, ':'); + if (!c) + continue; + *c = '\0'; + i = index_in_strings(fields, buf); + if (i >= 0) + meminfo[i] = strtoul(c+1, NULL, 10); + } + fclose(f); +} - /* - * MemShared: is no longer present in 2.6. Report this as 0, - * to maintain consistent behavior with normal procps. - */ - if (fscanf(fp, "MemShared: %lu %s\n", &shared, buf) != 2) - shared = 0; - fscanf(fp, "Buffers: %lu %s\n", &buffers, buf); - fscanf(fp, "Cached: %lu %s\n", &cached, buf); +static unsigned long display_header(int scr_width, int *lines_rem_p) +{ + char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */ + char *buf; + unsigned long meminfo[MI_MAX]; - used = total - mfree; - } - fclose(fp); + parse_meminfo(meminfo); - /* output memory info */ + /* Output memory info */ if (scr_width > (int)sizeof(scrbuf)) scr_width = sizeof(scrbuf); snprintf(scrbuf, scr_width, "Mem: %luK used, %luK free, %luK shrd, %luK buff, %luK cached", - used, mfree, shared, buffers, cached); - /* go to top & clear to the end of screen */ + meminfo[MI_MEMTOTAL] - meminfo[MI_MEMFREE], + meminfo[MI_MEMFREE], + meminfo[MI_MEMSHARED] + meminfo[MI_SHMEM], + meminfo[MI_BUFFERS], + meminfo[MI_CACHED]); + /* Go to top & clear to the end of screen */ printf(OPT_BATCH_MODE ? "%s\n" : "\033[H\033[J%s\n", scrbuf); (*lines_rem_p)--; - /* Display CPU time split as percentage of total time - * This displays either a cumulative line or one line per CPU + /* Display CPU time split as percentage of total time. + * This displays either a cumulative line or one line per CPU. */ display_cpus(scr_width, scrbuf, lines_rem_p); - /* read load average as a string */ - buf[0] = '\0'; - open_read_close("loadavg", buf, sizeof(buf) - 1); - buf[sizeof(buf) - 1] = '\n'; - *strchr(buf, '\n') = '\0'; - snprintf(scrbuf, scr_width, "Load average: %s", buf); + /* Read load average as a string */ + buf = stpcpy(scrbuf, "Load average: "); + open_read_close("loadavg", buf, sizeof(scrbuf) - sizeof("Load average: ")); + scrbuf[scr_width - 1] = '\0'; + strchrnul(buf, '\n')[0] = '\0'; puts(scrbuf); (*lines_rem_p)--; - return total; + return meminfo[MI_MEMTOTAL]; } static NOINLINE void display_process_list(int lines_rem, int scr_width) @@ -781,64 +790,31 @@ static int topmem_sort(char *a, char *b) /* display header info (meminfo / loadavg) */ static void display_topmem_header(int scr_width, int *lines_rem_p) { - enum { - TOTAL = 0, MFREE, BUF, CACHE, - SWAPTOTAL, SWAPFREE, DIRTY, - MWRITE, ANON, MAP, SLAB, - NUM_FIELDS - }; - static const char match[NUM_FIELDS][12] = { - "\x09" "MemTotal:", // TOTAL - "\x08" "MemFree:", // MFREE - "\x08" "Buffers:", // BUF - "\x07" "Cached:", // CACHE - "\x0a" "SwapTotal:", // SWAPTOTAL - "\x09" "SwapFree:", // SWAPFREE - "\x06" "Dirty:", // DIRTY - "\x0a" "Writeback:", // MWRITE - "\x0a" "AnonPages:", // ANON - "\x07" "Mapped:", // MAP - "\x05" "Slab:", // SLAB - }; - char meminfo_buf[4 * 1024]; - const char *Z[NUM_FIELDS]; - unsigned i; - int sz; - - for (i = 0; i < NUM_FIELDS; i++) - Z[i] = "?"; - - /* read memory info */ - sz = open_read_close("meminfo", meminfo_buf, sizeof(meminfo_buf) - 1); - if (sz >= 0) { - char *p = meminfo_buf; - meminfo_buf[sz] = '\0'; - /* Note that fields always appear in the match[] order */ - for (i = 0; i < NUM_FIELDS; i++) { - char *found = strstr(p, match[i] + 1); - if (found) { - /* Cut "NNNN" out of " NNNN kb" */ - char *s = skip_whitespace(found + match[i][0]); - p = skip_non_whitespace(s); - *p++ = '\0'; - Z[i] = s; - } - } - } + unsigned long meminfo[MI_MAX]; + + parse_meminfo(meminfo); snprintf(line_buf, LINE_BUF_SIZE, - "Mem total:%s anon:%s map:%s free:%s", - Z[TOTAL], Z[ANON], Z[MAP], Z[MFREE]); + "Mem total:%lu anon:%lu map:%lu free:%lu", + meminfo[MI_MEMTOTAL], + meminfo[MI_ANONPAGES], + meminfo[MI_MAPPED], + meminfo[MI_MEMFREE]); printf(OPT_BATCH_MODE ? "%.*s\n" : "\033[H\033[J%.*s\n", scr_width, line_buf); snprintf(line_buf, LINE_BUF_SIZE, - " slab:%s buf:%s cache:%s dirty:%s write:%s", - Z[SLAB], Z[BUF], Z[CACHE], Z[DIRTY], Z[MWRITE]); + " slab:%lu buf:%lu cache:%lu dirty:%lu write:%lu", + meminfo[MI_SLAB], + meminfo[MI_BUFFERS], + meminfo[MI_CACHED], + meminfo[MI_DIRTY], + meminfo[MI_WRITEBACK]); printf("%.*s\n", scr_width, line_buf); snprintf(line_buf, LINE_BUF_SIZE, - "Swap total:%s free:%s", // TODO: % used? - Z[SWAPTOTAL], Z[SWAPFREE]); + "Swap total:%lu free:%lu", // TODO: % used? + meminfo[MI_SWAPTOTAL], + meminfo[MI_SWAPFREE]); printf("%.*s\n", scr_width, line_buf); (*lines_rem_p) -= 3; -- cgit v1.2.3-55-g6feb From 6c6d37ee4526f77fe07e46f05b0378ce43421e84 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 29 Jul 2014 17:00:30 +0200 Subject: top: fix memset length (sizeof(ptr) vs sizeof(array) problem) Signed-off-by: Denys Vlasenko --- procps/top.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/procps/top.c b/procps/top.c index 62f9421af..3d67c3cfd 100644 --- a/procps/top.c +++ b/procps/top.c @@ -536,7 +536,7 @@ static void parse_meminfo(unsigned long meminfo[MI_MAX]) FILE *f; int i; - memset(meminfo, 0, sizeof(meminfo)); + memset(meminfo, 0, sizeof(meminfo[0]) * MI_MAX); f = xfopen_for_read("meminfo"); while (fgets(buf, sizeof(buf), f) != NULL) { char *c = strchr(buf, ':'); @@ -550,7 +550,6 @@ static void parse_meminfo(unsigned long meminfo[MI_MAX]) fclose(f); } - static unsigned long display_header(int scr_width, int *lines_rem_p) { char scrbuf[100]; /* [80] was a bit too low on 8Gb ram box */ -- cgit v1.2.3-55-g6feb From 4ff933c0e7895bd1ac1fe9793117f4d69de35514 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 30 Jul 2014 14:18:57 +0200 Subject: sha3: code shrink (and speedup for SHA3_SMALL=0) function old new delta sha3_process_block72 1454 1359 -95 Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha.c | 82 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 66 insertions(+), 16 deletions(-) diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index dff583ad1..4cef2aba1 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -1141,22 +1141,30 @@ static void sha3_process_block72(uint64_t *state) #undef RhoPi } /* Chi */ - for (x = 0; x <= 20; x += 5) { - /* - * Can write this in terms of uint32 too, - * but why? compiler does it automatically. - */ - uint64_t BC0, BC1, BC2, BC3, BC4; - BC0 = state[x + 0]; - BC1 = state[x + 1]; - BC2 = state[x + 2]; - state[x + 0] = BC0 ^ ((~BC1) & BC2); - BC3 = state[x + 3]; - state[x + 1] = BC1 ^ ((~BC2) & BC3); - BC4 = state[x + 4]; - state[x + 2] = BC2 ^ ((~BC3) & BC4); - state[x + 3] = BC3 ^ ((~BC4) & BC0); - state[x + 4] = BC4 ^ ((~BC0) & BC1); + for (x = 0; x <= 40;) { + uint32_t BC0, BC1, BC2, BC3, BC4; + BC0 = s32[x + 0*2]; + BC1 = s32[x + 1*2]; + BC2 = s32[x + 2*2]; + s32[x + 0*2] = BC0 ^ ((~BC1) & BC2); + BC3 = s32[x + 3*2]; + s32[x + 1*2] = BC1 ^ ((~BC2) & BC3); + BC4 = s32[x + 4*2]; + s32[x + 2*2] = BC2 ^ ((~BC3) & BC4); + s32[x + 3*2] = BC3 ^ ((~BC4) & BC0); + s32[x + 4*2] = BC4 ^ ((~BC0) & BC1); + x++; + BC0 = s32[x + 0*2]; + BC1 = s32[x + 1*2]; + BC2 = s32[x + 2*2]; + s32[x + 0*2] = BC0 ^ ((~BC1) & BC2); + BC3 = s32[x + 3*2]; + s32[x + 1*2] = BC1 ^ ((~BC2) & BC3); + BC4 = s32[x + 4*2]; + s32[x + 2*2] = BC2 ^ ((~BC3) & BC4); + s32[x + 3*2] = BC3 ^ ((~BC4) & BC0); + s32[x + 4*2] = BC4 ^ ((~BC0) & BC1); + x += 9; } /* Iota */ s32[0] ^= IOTA_CONST_0bits & 1; @@ -1275,6 +1283,7 @@ static void sha3_process_block72(uint64_t *state) #undef RhoPi_twice } /* Chi */ +#if LONG_MAX > 0x7fffffff for (x = 0; x <= 20; x += 5) { uint64_t BC0, BC1, BC2, BC3, BC4; BC0 = state[x + 0]; @@ -1288,6 +1297,47 @@ static void sha3_process_block72(uint64_t *state) state[x + 3] = BC3 ^ ((~BC4) & BC0); state[x + 4] = BC4 ^ ((~BC0) & BC1); } +#else + /* Reduced register pressure version + * for register-starved 32-bit arches + * (i386: -95 bytes, and it is _faster_) + */ + for (x = 0; x <= 40;) { + uint32_t BC0, BC1, BC2, BC3, BC4; + uint32_t *const s32 = (uint32_t*)state; +# if SHA3_SMALL + do_half: +#endif + BC0 = s32[x + 0*2]; + BC1 = s32[x + 1*2]; + BC2 = s32[x + 2*2]; + s32[x + 0*2] = BC0 ^ ((~BC1) & BC2); + BC3 = s32[x + 3*2]; + s32[x + 1*2] = BC1 ^ ((~BC2) & BC3); + BC4 = s32[x + 4*2]; + s32[x + 2*2] = BC2 ^ ((~BC3) & BC4); + s32[x + 3*2] = BC3 ^ ((~BC4) & BC0); + s32[x + 4*2] = BC4 ^ ((~BC0) & BC1); + x++; +# if SHA3_SMALL + if (x & 1) + goto do_half; + x += 8; +# else + BC0 = s32[x + 0*2]; + BC1 = s32[x + 1*2]; + BC2 = s32[x + 2*2]; + s32[x + 0*2] = BC0 ^ ((~BC1) & BC2); + BC3 = s32[x + 3*2]; + s32[x + 1*2] = BC1 ^ ((~BC2) & BC3); + BC4 = s32[x + 4*2]; + s32[x + 2*2] = BC2 ^ ((~BC3) & BC4); + s32[x + 3*2] = BC3 ^ ((~BC4) & BC0); + s32[x + 4*2] = BC4 ^ ((~BC0) & BC1); + x += 9; +# endif + } +#endif /* Iota */ state[0] ^= IOTA_CONST[round] | (uint32_t)((IOTA_CONST_bit31 << round) & 0x80000000) -- cgit v1.2.3-55-g6feb From 09a0e2223f68a266749043bf33c84faeb5cee8a0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 30 Jul 2014 16:26:09 +0200 Subject: sha3: tweak comments and indentation Signed-off-by: Denys Vlasenko --- libbb/hash_md5_sha.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/libbb/hash_md5_sha.c b/libbb/hash_md5_sha.c index 4cef2aba1..1f63ccdee 100644 --- a/libbb/hash_md5_sha.c +++ b/libbb/hash_md5_sha.c @@ -1174,12 +1174,13 @@ static void sha3_process_block72(uint64_t *state) combine_halves(state); #else - /* Elements should be 64-bit, but top half is always zero or 0x80000000. - * We encode 63rd bits in a separate word below. - * Same is true for 31th bits, which lets us use 16-bit table instead of 64-bit. - * The speed penalty is lost in the noise. - */ + /* Native 64-bit algorithm */ static const uint16_t IOTA_CONST[NROUNDS] = { + /* Elements should be 64-bit, but top half is always zero + * or 0x80000000. We encode 63rd bits in a separate word below. + * Same is true for 31th bits, which lets us use 16-bit table + * instead of 64-bit. The speed penalty is lost in the noise. + */ 0x0001, 0x8082, 0x808a, @@ -1283,7 +1284,7 @@ static void sha3_process_block72(uint64_t *state) #undef RhoPi_twice } /* Chi */ -#if LONG_MAX > 0x7fffffff +# if LONG_MAX > 0x7fffffff for (x = 0; x <= 20; x += 5) { uint64_t BC0, BC1, BC2, BC3, BC4; BC0 = state[x + 0]; @@ -1297,7 +1298,7 @@ static void sha3_process_block72(uint64_t *state) state[x + 3] = BC3 ^ ((~BC4) & BC0); state[x + 4] = BC4 ^ ((~BC0) & BC1); } -#else +# else /* Reduced register pressure version * for register-starved 32-bit arches * (i386: -95 bytes, and it is _faster_) @@ -1305,9 +1306,9 @@ static void sha3_process_block72(uint64_t *state) for (x = 0; x <= 40;) { uint32_t BC0, BC1, BC2, BC3, BC4; uint32_t *const s32 = (uint32_t*)state; -# if SHA3_SMALL +# if SHA3_SMALL do_half: -#endif +# endif BC0 = s32[x + 0*2]; BC1 = s32[x + 1*2]; BC2 = s32[x + 2*2]; @@ -1319,11 +1320,11 @@ static void sha3_process_block72(uint64_t *state) s32[x + 3*2] = BC3 ^ ((~BC4) & BC0); s32[x + 4*2] = BC4 ^ ((~BC0) & BC1); x++; -# if SHA3_SMALL +# if SHA3_SMALL if (x & 1) goto do_half; x += 8; -# else +# else BC0 = s32[x + 0*2]; BC1 = s32[x + 1*2]; BC2 = s32[x + 2*2]; @@ -1335,9 +1336,9 @@ static void sha3_process_block72(uint64_t *state) s32[x + 3*2] = BC3 ^ ((~BC4) & BC0); s32[x + 4*2] = BC4 ^ ((~BC0) & BC1); x += 9; -# endif +# endif } -#endif +# endif /* long is 32-bit */ /* Iota */ state[0] ^= IOTA_CONST[round] | (uint32_t)((IOTA_CONST_bit31 << round) & 0x80000000) -- cgit v1.2.3-55-g6feb From feac9b607dc68ea63992a46b3b8361f00f663cdc Mon Sep 17 00:00:00 2001 From: Morten Kvistgaard Date: Tue, 5 Aug 2014 21:57:18 +0200 Subject: ftpd: add optional support for authentication function old new delta cmdio_get_cmd_and_arg - 237 +237 get_passwd - 97 +97 check_password - 82 +82 ftpd_main 2297 2178 -119 ask_and_check_password_extended 206 84 -122 ------------------------------------------------------------------------------ (add/remove: 3/0 grow/shrink: 0/2 up/down: 416/-241) Total: 175 bytes Signed-off-by: Morten Kvistgaard Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/Kbuild.src | 1 + libbb/correct_password.c | 96 +++++++++++++++++++++++++++++++++--------------- networking/Config.src | 7 ++++ networking/ftpd.c | 47 ++++++++++++------------ 5 files changed, 100 insertions(+), 52 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index 858084bc5..ff223dd0f 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1316,6 +1316,7 @@ int sd_listen_fds(void); #define SETUP_ENV_NO_CHDIR (1 << 4) void setup_environment(const char *shell, int flags, const struct passwd *pw) FAST_FUNC; void nuke_str(char *str) FAST_FUNC; +int check_password(const struct passwd *pw, const char *plaintext) FAST_FUNC; int ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) FAST_FUNC; int ask_and_check_password(const struct passwd *pw) FAST_FUNC; /* Returns a malloced string */ diff --git a/libbb/Kbuild.src b/libbb/Kbuild.src index 62680bd52..0a9e803d7 100644 --- a/libbb/Kbuild.src +++ b/libbb/Kbuild.src @@ -150,6 +150,7 @@ lib-$(CONFIG_VLOCK) += pw_encrypt.o correct_password.o lib-$(CONFIG_SU) += pw_encrypt.o correct_password.o lib-$(CONFIG_LOGIN) += pw_encrypt.o correct_password.o lib-$(CONFIG_FEATURE_HTTPD_AUTH_MD5) += pw_encrypt.o +lib-$(CONFIG_FEATURE_FTP_AUTHENTICATION) += pw_encrypt.o lib-$(CONFIG_DF) += find_mount_point.o lib-$(CONFIG_MKFS_MINIX) += find_mount_point.o diff --git a/libbb/correct_password.c b/libbb/correct_password.c index acadf3914..513c93028 100644 --- a/libbb/correct_password.c +++ b/libbb/correct_password.c @@ -30,6 +30,63 @@ #include "libbb.h" +#define SHADOW_BUFSIZE 256 + +/* Retrieve encrypted password string for pw. + * If pw == NULL, return a string which fails password check against any + * password. + */ +#if !ENABLE_FEATURE_SHADOWPASSWDS +#define get_passwd(pw, buffer) get_passwd(pw) +#endif +static const char *get_passwd(const struct passwd *pw, char buffer[SHADOW_BUFSIZE]) +{ + const char *pass; + + if (!pw) + return "aa"; /* "aa" will never match */ + + pass = pw->pw_passwd; +#if ENABLE_FEATURE_SHADOWPASSWDS + /* Using _r function to avoid pulling in static buffers */ + if ((pass[0] == 'x' || pass[0] == '*') && !pass[1]) { + struct spwd spw; + int r; + /* getspnam_r may return 0 yet set result to NULL. + * At least glibc 2.4 does this. Be extra paranoid here. */ + struct spwd *result = NULL; + r = getspnam_r(pw->pw_name, &spw, buffer, SHADOW_BUFSIZE, &result); + pass = (r || !result) ? "aa" : result->sp_pwdp; + } +#endif + return pass; +} + +/* + * Return 1 if PW has an empty password. + * Return 1 if the user gives the correct password for entry PW, + * 0 if not. + * NULL pw means "just fake it for login with bad username" + */ +int FAST_FUNC check_password(const struct passwd *pw, const char *plaintext) +{ + IF_FEATURE_SHADOWPASSWDS(char buffer[SHADOW_BUFSIZE];) + char *encrypted; + const char *pw_pass; + int r; + + pw_pass = get_passwd(pw, buffer); + if (!pw_pass[0]) { /* empty password field? */ + return 1; + } + + encrypted = pw_encrypt(plaintext, /*salt:*/ pw_pass, 1); + r = (strcmp(encrypted, pw_pass) == 0); + free(encrypted); + return r; +} + + /* Ask the user for a password. * Return 1 without asking if PW has an empty password. * Return -1 on EOF, error while reading input, or timeout. @@ -41,42 +98,23 @@ int FAST_FUNC ask_and_check_password_extended(const struct passwd *pw, int timeout, const char *prompt) { - char *unencrypted, *encrypted; - const char *correct; + IF_FEATURE_SHADOWPASSWDS(char buffer[SHADOW_BUFSIZE];) + char *plaintext; + const char *pw_pass; int r; - /* fake salt. crypt() can choke otherwise. */ - correct = "aa"; - if (!pw) { - /* "aa" will never match */ - goto fake_it; - } - correct = pw->pw_passwd; -#if ENABLE_FEATURE_SHADOWPASSWDS - /* Using _r function to avoid pulling in static buffers */ - if ((correct[0] == 'x' || correct[0] == '*') && !correct[1]) { - struct spwd spw; - char buffer[256]; - /* getspnam_r may return 0 yet set result to NULL. - * At least glibc 2.4 does this. Be extra paranoid here. */ - struct spwd *result = NULL; - r = getspnam_r(pw->pw_name, &spw, buffer, sizeof(buffer), &result); - correct = (r || !result) ? "aa" : result->sp_pwdp; - } -#endif - if (!correct[0]) /* empty password field? */ + pw_pass = get_passwd(pw, buffer); + if (!pw_pass[0]) /* empty password field? */ return 1; - fake_it: - unencrypted = bb_ask(STDIN_FILENO, timeout, prompt); - if (!unencrypted) { + plaintext = bb_ask(STDIN_FILENO, timeout, prompt); + if (!plaintext) { /* EOF (such as ^D) or error (such as ^C) or timeout */ return -1; } - encrypted = pw_encrypt(unencrypted, correct, 1); - r = (strcmp(encrypted, correct) == 0); - free(encrypted); - nuke_str(unencrypted); + + r = check_password(pw, plaintext); + nuke_str(plaintext); return r; } diff --git a/networking/Config.src b/networking/Config.src index fbad7ecb2..e56646917 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -134,6 +134,13 @@ config FEATURE_FTPD_ACCEPT_BROKEN_LIST it increases the code size by ~40 bytes. Most other ftp servers seem to behave similar to this. +config FEATURE_FTP_AUTHENTICATION + bool "Enable authentication" + default y + depends on FTPD + help + Enable basic system login as seen in telnet etc. + config FTPGET bool "ftpget" default y diff --git a/networking/ftpd.c b/networking/ftpd.c index 2d2a3a44c..9fcc3e963 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -1172,18 +1172,6 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) if (logmode) applet_name = xasprintf("%s[%u]", applet_name, (int)getpid()); -#if !BB_MMU - G.root_fd = -1; -#endif - argv += optind; - if (argv[0]) { -#if !BB_MMU - G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY); - close_on_exec_on(G.root_fd); -#endif - xchroot(argv[0]); - } - //umask(077); - admin can set umask before starting us /* Signals. We'll always take -EPIPE rather than a rude signal, thanks */ @@ -1199,23 +1187,22 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) WRITE_OK(FTP_GREET); signal(SIGALRM, timeout_handler); -#ifdef IF_WE_WANT_TO_REQUIRE_LOGIN +#if ENABLE_FEATURE_FTP_AUTHENTICATION { - smallint user_was_specified = 0; + struct passwd *pw = NULL; + while (1) { uint32_t cmdval = cmdio_get_cmd_and_arg(); if (cmdval == const_USER) { - if (G.ftp_arg == NULL || strcasecmp(G.ftp_arg, "anonymous") != 0) - cmdio_write_raw(STR(FTP_LOGINERR)" Server is anonymous only\r\n"); - else { - user_was_specified = 1; - cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify the password\r\n"); - } + pw = getpwnam(G.ftp_arg); + cmdio_write_raw(STR(FTP_GIVEPWORD)" Please specify password\r\n"); } else if (cmdval == const_PASS) { - if (user_was_specified) - break; - cmdio_write_raw(STR(FTP_NEEDUSER)" Login with USER\r\n"); + if (check_password(pw, G.ftp_arg) > 0) { + break; /* login success */ + } + cmdio_write_raw(STR(FTP_LOGINERR)" Login failed\r\n"); + pw = NULL; } else if (cmdval == const_QUIT) { WRITE_OK(FTP_GOODBYE); return 0; @@ -1223,10 +1210,24 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) cmdio_write_raw(STR(FTP_LOGINERR)" Login with USER and PASS\r\n"); } } + change_identity(pw); } WRITE_OK(FTP_LOGINOK); #endif + /* Do this after auth, else /etc/passwd is not accessible */ +#if !BB_MMU + G.root_fd = -1; +#endif + argv += optind; + if (argv[0]) { +#if !BB_MMU + G.root_fd = xopen("/", O_RDONLY | O_DIRECTORY); + close_on_exec_on(G.root_fd); +#endif + xchroot(argv[0]); + } + /* RFC-959 Section 5.1 * The following commands and options MUST be supported by every * server-FTP and user-FTP, except in cases where the underlying -- cgit v1.2.3-55-g6feb From 45b4ecc8689d1291b01793efab3ac25125e14e48 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 11 Aug 2014 20:33:18 +0200 Subject: init: if libc-based Unicode support is on, run setlocale(LC_ALL, "") at startup It is not clear why we were excluding init from this. The "getpid() != 1" clause was there from the beginning (2001) but not explained. Signed-off-by: Denys Vlasenko --- libbb/appletlib.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/libbb/appletlib.c b/libbb/appletlib.c index f7c416ece..a0150854a 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -184,8 +184,7 @@ void lbb_prepare(const char *applet #endif applet_name = applet; - /* Set locale for everybody except 'init' */ - if (ENABLE_LOCALE_SUPPORT && getpid() != 1) + if (ENABLE_LOCALE_SUPPORT) setlocale(LC_ALL, ""); #if ENABLE_FEATURE_INDIVIDUAL -- cgit v1.2.3-55-g6feb From c538d5bcc304d1ac99783de2337937c70a7013c7 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Aug 2014 09:57:44 +0200 Subject: hush: make ${#var} unicode-aware This mimics bash Signed-off-by: Denys Vlasenko --- shell/hush.c | 29 +++++++++++++++++++---------- shell/hush_test/hush-misc/unicode1.right | 3 +++ shell/hush_test/hush-misc/unicode1.tests | 13 +++++++++++++ 3 files changed, 35 insertions(+), 10 deletions(-) create mode 100644 shell/hush_test/hush-misc/unicode1.right create mode 100755 shell/hush_test/hush-misc/unicode1.tests diff --git a/shell/hush.c b/shell/hush.c index e1d0ece29..7d3547110 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1976,6 +1976,22 @@ static struct variable *set_vars_and_save_old(char **strings) } +/* + * Unicode helper + */ +static void reinit_unicode_for_hush(void) +{ + /* Unicode support should be activated even if LANG is set + * _during_ shell execution, not only if it was set when + * shell was started. Therefore, re-check LANG every time: + */ + const char *s = get_local_var_value("LC_ALL"); + if (!s) s = get_local_var_value("LC_CTYPE"); + if (!s) s = get_local_var_value("LANG"); + reinit_unicode(s); +} + + /* * in_str support */ @@ -2042,15 +2058,7 @@ static void get_user_input(struct in_str *i) /* Enable command line editing only while a command line * is actually being read */ do { - /* Unicode support should be activated even if LANG is set - * _during_ shell execution, not only if it was set when - * shell was started. Therefore, re-check LANG every time: - */ - const char *s = get_local_var_value("LC_ALL"); - if (!s) s = get_local_var_value("LC_CTYPE"); - if (!s) s = get_local_var_value("LANG"); - reinit_unicode(s); - + reinit_unicode_for_hush(); G.flag_SIGINT = 0; /* buglet: SIGINT will not make new prompt to appear _at once_, * only after . (^C will work) */ @@ -5028,8 +5036,9 @@ static NOINLINE const char *expand_one_var(char **to_be_freed_pp, char *arg, cha /* Handle any expansions */ if (exp_op == 'L') { + reinit_unicode_for_hush(); debug_printf_expand("expand: length(%s)=", val); - val = utoa(val ? strlen(val) : 0); + val = utoa(val ? unicode_strlen(val) : 0); debug_printf_expand("%s\n", val); } else if (exp_op) { if (exp_op == '%' || exp_op == '#') { diff --git a/shell/hush_test/hush-misc/unicode1.right b/shell/hush_test/hush-misc/unicode1.right new file mode 100644 index 000000000..d3bbbf697 --- /dev/null +++ b/shell/hush_test/hush-misc/unicode1.right @@ -0,0 +1,3 @@ +1 +1 +Ok diff --git a/shell/hush_test/hush-misc/unicode1.tests b/shell/hush_test/hush-misc/unicode1.tests new file mode 100755 index 000000000..8788ba910 --- /dev/null +++ b/shell/hush_test/hush-misc/unicode1.tests @@ -0,0 +1,13 @@ +LANG=en_US.UTF-8 + +# A combining character U+300 +a=`printf "\xcc\x80"` +# Should print 1 +echo ${#a} + +# A Japanese katakana charachter U+30a3 +a=`printf "\xe3\x82\xa3"` +# Should print 1 +echo ${#a} + +echo Ok -- cgit v1.2.3-55-g6feb From 841f8331d79c642b4268dae52c382fab2da9cddc Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Aug 2014 10:09:49 +0200 Subject: ash,hush: run reinit_unicode() only if makes sense With static Unicode support, no need to check $LANG et al. Signed-off-by: Denys Vlasenko --- shell/ash.c | 4 +++- shell/hush.c | 12 ++++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index dc7a9bf4f..3b8aac553 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -9661,7 +9661,9 @@ preadfd(void) * _during_ shell execution, not only if it was set when * shell was started. Therefore, re-check LANG every time: */ - { + if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV + || ENABLE_UNICODE_USING_LOCALE + ) { const char *s = lookupvar("LC_ALL"); if (!s) s = lookupvar("LC_CTYPE"); if (!s) s = lookupvar("LANG"); diff --git a/shell/hush.c b/shell/hush.c index 7d3547110..92d790180 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1985,10 +1985,14 @@ static void reinit_unicode_for_hush(void) * _during_ shell execution, not only if it was set when * shell was started. Therefore, re-check LANG every time: */ - const char *s = get_local_var_value("LC_ALL"); - if (!s) s = get_local_var_value("LC_CTYPE"); - if (!s) s = get_local_var_value("LANG"); - reinit_unicode(s); + if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV + || ENABLE_UNICODE_USING_LOCALE + ) { + const char *s = get_local_var_value("LC_ALL"); + if (!s) s = get_local_var_value("LC_CTYPE"); + if (!s) s = get_local_var_value("LANG"); + reinit_unicode(s); + } } -- cgit v1.2.3-55-g6feb From e9ab07c211b283c0f798628858eaaef93a4893aa Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 13 Aug 2014 18:00:08 +0200 Subject: ash: make ${#var} unicode-aware Signed-off-by: Denys Vlasenko --- shell/ash.c | 39 ++++++++++++++++++++++++++------------- 1 file changed, 26 insertions(+), 13 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 3b8aac553..4ead6f990 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -2121,6 +2121,22 @@ lookupvar(const char *name) return NULL; } +static void reinit_unicode_for_ash(void) +{ + /* Unicode support should be activated even if LANG is set + * _during_ shell execution, not only if it was set when + * shell was started. Therefore, re-check LANG every time: + */ + if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV + || ENABLE_UNICODE_USING_LOCALE + ) { + const char *s = lookupvar("LC_ALL"); + if (!s) s = lookupvar("LC_CTYPE"); + if (!s) s = lookupvar("LANG"); + reinit_unicode(s); + } +} + /* * Search the environment of a builtin command. */ @@ -6798,7 +6814,15 @@ evalvar(char *p, int flags, struct strlist *var_str_list) varunset(p, var, 0, 0); if (subtype == VSLENGTH) { - cvtnum(varlen > 0 ? varlen : 0); + ssize_t n = varlen; + if (n > 0) { + reinit_unicode_for_ash(); + if (unicode_status == UNICODE_ON) { + const char *val = lookupvar(var); + n = unicode_strlen(val); + } + } + cvtnum(n > 0 ? n : 0); goto record; } @@ -9657,18 +9681,7 @@ preadfd(void) # if ENABLE_FEATURE_TAB_COMPLETION line_input_state->path_lookup = pathval(); # endif - /* Unicode support should be activated even if LANG is set - * _during_ shell execution, not only if it was set when - * shell was started. Therefore, re-check LANG every time: - */ - if (ENABLE_FEATURE_CHECK_UNICODE_IN_ENV - || ENABLE_UNICODE_USING_LOCALE - ) { - const char *s = lookupvar("LC_ALL"); - if (!s) s = lookupvar("LC_CTYPE"); - if (!s) s = lookupvar("LANG"); - reinit_unicode(s); - } + reinit_unicode_for_ash(); nr = read_line_input(line_input_state, cmdedit_prompt, buf, IBUFSIZ, timeout); if (nr == 0) { /* Ctrl+C pressed */ -- cgit v1.2.3-55-g6feb From fb8d1ef2d00db013eae3cc675fc8b34fd0a7a987 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 15 Aug 2014 14:29:43 +0200 Subject: addgroup: mention -S in the help text Signed-off-by: Denys Vlasenko --- loginutils/addgroup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/loginutils/addgroup.c b/loginutils/addgroup.c index 22cd0e661..260e337f3 100644 --- a/loginutils/addgroup.c +++ b/loginutils/addgroup.c @@ -11,9 +11,9 @@ */ //usage:#define addgroup_trivial_usage -//usage: "[-g GID] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP" +//usage: "[-g GID] [-S] " IF_FEATURE_ADDUSER_TO_GROUP("[USER] ") "GROUP" //usage:#define addgroup_full_usage "\n\n" -//usage: "Add a group " IF_FEATURE_ADDUSER_TO_GROUP("or add a user to a group") "\n" +//usage: "Add a group" IF_FEATURE_ADDUSER_TO_GROUP(" or add a user to a group") "\n" //usage: "\n -g GID Group id" //usage: "\n -S Create a system group" -- cgit v1.2.3-55-g6feb From 962c4e822012a6d4c83b869eb47506881b4abc57 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 17 Aug 2014 19:36:22 +0200 Subject: taskset: support CPU masks for more than 64 CPUs function old new delta taskset_main 522 631 +109 Signed-off-by: Denys Vlasenko --- include/applets.src.h | 1 - miscutils/Config.src | 16 ---------- miscutils/Kbuild.src | 1 - miscutils/taskset.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 79 insertions(+), 25 deletions(-) diff --git a/include/applets.src.h b/include/applets.src.h index cb36628b5..b80c4f4e8 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -342,7 +342,6 @@ IF_BB_SYSCTL(APPLET(sysctl, BB_DIR_SBIN, BB_SUID_DROP)) IF_SYSLOGD(APPLET(syslogd, BB_DIR_SBIN, BB_SUID_DROP)) IF_TAC(APPLET_NOEXEC(tac, tac, BB_DIR_USR_BIN, BB_SUID_DROP, tac)) IF_TAIL(APPLET(tail, BB_DIR_USR_BIN, BB_SUID_DROP)) -IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) /* IF_TC(APPLET(tc, BB_DIR_SBIN, BB_SUID_DROP)) */ IF_TCPSVD(APPLET_ODDNAME(tcpsvd, tcpudpsvd, BB_DIR_USR_BIN, BB_SUID_DROP, tcpsvd)) IF_TEE(APPLET(tee, BB_DIR_USR_BIN, BB_SUID_DROP)) diff --git a/miscutils/Config.src b/miscutils/Config.src index 1b2a3ae9a..d69abf1a2 100644 --- a/miscutils/Config.src +++ b/miscutils/Config.src @@ -499,22 +499,6 @@ config STRINGS strings prints the printable character sequences for each file specified. -config TASKSET - bool "taskset" - default n # doesn't build on some non-x86 targets (m68k) - help - Retrieve or set a processes's CPU affinity. - This requires sched_{g,s}etaffinity support in your libc. - -config FEATURE_TASKSET_FANCY - bool "Fancy output" - default y - depends on TASKSET - help - Add code for fancy output. This merely silences a compiler-warning - and adds about 135 Bytes. May be needed for machines with alot - of CPUs. - config TIME bool "time" default y diff --git a/miscutils/Kbuild.src b/miscutils/Kbuild.src index 8eaa82de9..7b449e6e8 100644 --- a/miscutils/Kbuild.src +++ b/miscutils/Kbuild.src @@ -39,7 +39,6 @@ lib-$(CONFIG_RUNLEVEL) += runlevel.o lib-$(CONFIG_RX) += rx.o lib-$(CONFIG_SETSID) += setsid.o lib-$(CONFIG_STRINGS) += strings.o -lib-$(CONFIG_TASKSET) += taskset.o lib-$(CONFIG_TIME) += time.o lib-$(CONFIG_TIMEOUT) += timeout.o lib-$(CONFIG_TTYSIZE) += ttysize.o diff --git a/miscutils/taskset.c b/miscutils/taskset.c index 4a9e3230d..8bd32ed61 100644 --- a/miscutils/taskset.c +++ b/miscutils/taskset.c @@ -6,6 +6,25 @@ * Licensed under GPLv2 or later, see file LICENSE in this source tree. */ +//config:config TASKSET +//config: bool "taskset" +//config: default n # doesn't build on some non-x86 targets (m68k) +//config: help +//config: Retrieve or set a processes's CPU affinity. +//config: This requires sched_{g,s}etaffinity support in your libc. +//config: +//config:config FEATURE_TASKSET_FANCY +//config: bool "Fancy output" +//config: default y +//config: depends on TASKSET +//config: help +//config: Add code for fancy output. This merely silences a compiler-warning +//config: and adds about 135 Bytes. May be needed for machines with alot +//config: of CPUs. + +//applet:IF_TASKSET(APPLET(taskset, BB_DIR_USR_BIN, BB_SUID_DROP)) +//kbuild:lib-$(CONFIG_TASKSET) += taskset.o + //usage:#define taskset_trivial_usage //usage: "[-p] [MASK] [PID | PROG ARGS]" //usage:#define taskset_full_usage "\n\n" @@ -22,6 +41,11 @@ //usage: "pid 6671's new affinity mask: 1\n" //usage: "$ taskset -p 1\n" //usage: "pid 1's current affinity mask: 3\n" +/* + Not yet implemented: + * -a/--all-tasks (affect all threads) + * -c/--cpu-list (specify CPUs via "1,3,5-7") + */ #include #include "libbb.h" @@ -128,17 +152,65 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) current_new += 8; /* "new" */ } - { /* Affinity was specified, translate it into cpu_set_t */ + /* Affinity was specified, translate it into cpu_set_t */ + CPU_ZERO(&mask); + if (!ENABLE_FEATURE_TASKSET_FANCY) { unsigned i; + unsigned long long m; + /* Do not allow zero mask: */ - unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); - enum { CNT_BIT = CPU_SETSIZE < sizeof(m)*8 ? CPU_SETSIZE : sizeof(m)*8 }; + m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); + i = 0; + do { + if (m & 1) + CPU_SET(i, &mask); + i++; + m >>= 1; + } while (m != 0); + } else { + unsigned i; + char *last_byte; + char *bin; + uint8_t bit_in_byte; + + /* Cheap way to get "long enough" buffer */ + bin = xstrdup(aff); + + if (aff[0] != '0' && (aff[1]|0x20) != 'x') { +/* TODO: decimal/octal masks are still limited to 2^64 */ + unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); + bin += strlen(bin); + last_byte = bin - 1; + while (m) { + *--bin = m & 0xff; + m >>= 8; + } + } else { + /* aff is "0x.....", we accept very long masks in this form */ + last_byte = hex2bin(bin, aff + 2, INT_MAX); + if (!last_byte) { + bad_aff: + bb_error_msg_and_die("bad affinity '%s'", aff); + } + last_byte--; /* now points to the last byte */ + } - CPU_ZERO(&mask); - for (i = 0; i < CNT_BIT; i++) { - unsigned long long bit = (1ULL << i); - if (bit & m) + i = 0; + bit_in_byte = 1; + while (last_byte >= bin) { + if (bit_in_byte & *last_byte) { + if (i >= CPU_SETSIZE) + goto bad_aff; CPU_SET(i, &mask); + //bb_error_msg("bit %d set", i); + } + i++; + /* bit_in_byte is uint8_t! & 0xff is implied */ + bit_in_byte = (bit_in_byte << 1); + if (!bit_in_byte) { + bit_in_byte = 1; + last_byte--; + } } } -- cgit v1.2.3-55-g6feb From 6ff055115798166e172039284448be758b04e195 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Wed, 27 Aug 2014 16:01:25 +0200 Subject: ping: add -p to specify data pattern function old new delta common_ping_main 1788 1831 +43 sendping6 56 82 +26 sendping4 82 108 +26 packed_usage 29959 29938 -21 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/1 up/down: 95/-21) Total: 74 bytes Signed-off-by: Florian Fainelli Signed-off-by: Denys Vlasenko --- networking/ping.c | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/networking/ping.c b/networking/ping.c index 5e4771f5a..c475395e7 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -100,8 +100,9 @@ //usage: "\n (after all -c CNT packets are sent)" //usage: "\n -w SEC Seconds until ping exits (default:infinite)" //usage: "\n (can exit earlier with -c CNT)" -//usage: "\n -q Quiet, only displays output at start" +//usage: "\n -q Quiet, only display output at start" //usage: "\n and when finished" +//usage: "\n -p Pattern to use for payload" //usage: //usage:# define ping6_trivial_usage //usage: "[OPTIONS] HOST" @@ -110,8 +111,9 @@ //usage: "\n -c CNT Send only CNT pings" //usage: "\n -s SIZE Send SIZE data bytes in packets (default:56)" //usage: "\n -I IFACE/IP Use interface or IP address as source" -//usage: "\n -q Quiet, only displays output at start" +//usage: "\n -q Quiet, only display output at start" //usage: "\n and when finished" +//usage: "\n -p Pattern to use for payload" //usage: //usage:#endif //usage: @@ -330,7 +332,7 @@ static int common_ping_main(sa_family_t af, char **argv) /* Full(er) version */ -#define OPT_STRING ("qvc:s:t:w:W:I:n4" IF_PING6("6")) +#define OPT_STRING ("qvc:s:t:w:W:I:np:4" IF_PING6("6")) enum { OPT_QUIET = 1 << 0, OPT_VERBOSE = 1 << 1, @@ -341,8 +343,9 @@ enum { OPT_W = 1 << 6, OPT_I = 1 << 7, /*OPT_n = 1 << 8, - ignored */ - OPT_IPV4 = 1 << 9, - OPT_IPV6 = (1 << 10) * ENABLE_PING6, + OPT_p = 1 << 9, + OPT_IPV4 = 1 << 10, + OPT_IPV6 = (1 << 11) * ENABLE_PING6, }; @@ -355,6 +358,7 @@ struct globals { unsigned opt_ttl; unsigned long ntransmitted, nreceived, nrepeats; uint16_t myid; + uint8_t pattern; unsigned tmin, tmax; /* in us */ unsigned long long tsum; /* in us, sum of all times */ unsigned deadline; @@ -485,7 +489,7 @@ static void sendping4(int junk UNUSED_PARAM) { struct icmp *pkt = G.snd_packet; - //memset(pkt, 0, datalen + ICMP_MINLEN + 4); - G.snd_packet was xzalloced + memset(pkt, G.pattern, datalen + ICMP_MINLEN + 4); pkt->icmp_type = ICMP_ECHO; /*pkt->icmp_code = 0;*/ pkt->icmp_cksum = 0; /* cksum is calculated with this field set to 0 */ @@ -508,7 +512,7 @@ static void sendping6(int junk UNUSED_PARAM) { struct icmp6_hdr *pkt = G.snd_packet; - //memset(pkt, 0, datalen + sizeof(struct icmp6_hdr) + 4); + memset(pkt, G.pattern, datalen + sizeof(struct icmp6_hdr) + 4); pkt->icmp6_type = ICMP6_ECHO_REQUEST; /*pkt->icmp6_code = 0;*/ /*pkt->icmp6_cksum = 0;*/ @@ -850,13 +854,13 @@ static void ping(len_and_sockaddr *lsa) static int common_ping_main(int opt, char **argv) { len_and_sockaddr *lsa; - char *str_s; + char *str_s, *str_p; INIT_G(); /* exactly one argument needed; -v and -q don't mix; -c NUM, -t NUM, -w NUM, -W NUM */ opt_complementary = "=1:q--v:v--q:c+:t+:w+:W+"; - opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I); + opt |= getopt32(argv, OPT_STRING, &pingcount, &str_s, &opt_ttl, &deadline, &timeout, &str_I, &str_p); if (opt & OPT_s) datalen = xatou16(str_s); // -s if (opt & OPT_I) { // -I @@ -867,6 +871,9 @@ static int common_ping_main(int opt, char **argv) str_I = NULL; /* don't try to bind to device later */ } } + if (opt & OPT_p) + G.pattern = xstrtou_range(str_p, 16, 0, 255); + myid = (uint16_t) getpid(); hostname = argv[optind]; #if ENABLE_PING6 -- cgit v1.2.3-55-g6feb From 34cc6c91a286411a8275d9d61aa80397fe1e5fa3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 28 Aug 2014 15:50:09 +0200 Subject: grep: fix "grep -r PATTRN SYMLINK_TO_DIR" Signed-off-by: Denys Vlasenko --- findutils/grep.c | 2 +- testsuite/grep.tests | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/findutils/grep.c b/findutils/grep.c index f1b6dc694..b9621384e 100644 --- a/findutils/grep.c +++ b/findutils/grep.c @@ -668,7 +668,7 @@ static int grep_dir(const char *dir) int matched = 0; recursive_action(dir, /* recurse=yes */ ACTION_RECURSE | - /* followLinks=no */ + /* followLinks=command line only */ ACTION_FOLLOWLINKS_L0 | /* depthFirst=yes */ ACTION_DEPTHFIRST, /* fileAction= */ file_action_grep, /* dirAction= */ NULL, diff --git a/testsuite/grep.tests b/testsuite/grep.tests index 323b3849d..f6d9f2105 100755 --- a/testsuite/grep.tests +++ b/testsuite/grep.tests @@ -171,6 +171,26 @@ testing "grep -w word match second word" \ "bword,word\n""wordb,word\n""bwordb,word\n" \ "" +# -r on symlink to dir should recurse into dir +mkdir -p grep.testdir/foo +echo bar > grep.testdir/foo/file +ln -s foo grep.testdir/symfoo +testing "grep -r on symlink to dir" \ + "grep -r . grep.testdir/symfoo" \ + "grep.testdir/symfoo/file:bar\n" \ + "" "" +rm -Rf grep.testdir + +# But -r on dir/symlink_to_dir should not recurse into symlink_to_dir +mkdir -p grep.testdir/foo +echo bar > grep.testdir/foo/file +ln -s foo grep.testdir/symfoo +testing "grep -r on dir/symlink to dir" \ + "grep -r . grep.testdir" \ + "grep.testdir/foo/file:bar\n" \ + "" "" +rm -Rf grep.testdir + # testing "test name" "commands" "expected result" "file input" "stdin" # file input will be file called "input" # test can create a file "actual" instead of writing to stdout -- cgit v1.2.3-55-g6feb From f02c52bcdecc2f2859655e42f15365c0449b6ce3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 31 Aug 2014 01:35:45 +0200 Subject: taskset: fix logic error in "if it doesn't start with 0x..." Signed-off-by: Denys Vlasenko --- miscutils/taskset.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/miscutils/taskset.c b/miscutils/taskset.c index 8bd32ed61..2646e1dab 100644 --- a/miscutils/taskset.c +++ b/miscutils/taskset.c @@ -176,7 +176,7 @@ int taskset_main(int argc UNUSED_PARAM, char **argv) /* Cheap way to get "long enough" buffer */ bin = xstrdup(aff); - if (aff[0] != '0' && (aff[1]|0x20) != 'x') { + if (aff[0] != '0' || (aff[1]|0x20) != 'x') { /* TODO: decimal/octal masks are still limited to 2^64 */ unsigned long long m = xstrtoull_range(aff, 0, 1, ULLONG_MAX); bin += strlen(bin); -- cgit v1.2.3-55-g6feb From 67e01fecce5547a3d3d5695f52b375d224014b54 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 3 Sep 2014 18:35:38 +0200 Subject: tftpd: support full 512-byte requests Some HP PA-RISC firmware always sends fixed 512-byte requests, with trailing garbage. function old new delta tftpd_main 578 572 -6 Signed-off-by: Denys Vlasenko --- networking/tftp.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/networking/tftp.c b/networking/tftp.c index 630fdaf9a..8e3b0a2dc 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -119,6 +119,7 @@ struct globals { struct passwd *pw; /* used in tftpd_main(), a bit big for stack: */ char block_buf[TFTP_BLKSIZE_DEFAULT]; + char block_buf_tail[1]; #if ENABLE_FEATURE_TFTP_PROGRESS_BAR off_t pos; off_t size; @@ -793,14 +794,16 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) xchroot(argv[0]); } - result = recv_from_to(STDIN_FILENO, G.block_buf, sizeof(G.block_buf), + result = recv_from_to(STDIN_FILENO, + G.block_buf, sizeof(G.block_buf) + 1, + /* ^^^ sizeof+1 to reliably detect oversized input */ 0 /* flags */, &peer_lsa->u.sa, &our_lsa->u.sa, our_lsa->len); error_msg = "malformed packet"; opcode = ntohs(*(uint16_t*)G.block_buf); - if (result < 4 || result >= sizeof(G.block_buf) - || G.block_buf[result-1] != '\0' + if (result < 4 || result > sizeof(G.block_buf) + /*|| G.block_buf[result-1] != '\0' - bug compatibility, see below */ || (IF_FEATURE_TFTP_PUT(opcode != TFTP_RRQ) /* not download */ IF_GETPUT(&&) IF_FEATURE_TFTP_GET(opcode != TFTP_WRQ) /* not upload */ @@ -808,6 +811,13 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) ) { goto err; } + /* Some HP PA-RISC firmware always sends fixed 512-byte requests, + * with trailing garbage. + * Support that by not requiring NUL to be the last byte (see above). + * To make strXYZ() ops safe, force NUL termination: + */ + G.block_buf_tail[0] = '\0'; + local_file = G.block_buf + 2; if (local_file[0] == '.' || strstr(local_file, "/.")) { error_msg = "dot in file name"; -- cgit v1.2.3-55-g6feb From 4eb1e425fec4cf0eecd3fd33dc838f9332af5e44 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 4 Sep 2014 12:24:03 +0200 Subject: tftpd: tweak HP PA-RISC firmware bug compatibility Signed-off-by: Denys Vlasenko --- networking/tftp.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/networking/tftp.c b/networking/tftp.c index 8e3b0a2dc..7c0ee58d7 100644 --- a/networking/tftp.c +++ b/networking/tftp.c @@ -117,8 +117,9 @@ struct globals { /* u16 TFTP_ERROR; u16 reason; both network-endian, then error text: */ uint8_t error_pkt[4 + 32]; struct passwd *pw; - /* used in tftpd_main(), a bit big for stack: */ - char block_buf[TFTP_BLKSIZE_DEFAULT]; + /* Used in tftpd_main() for initial packet */ + /* Some HP PA-RISC firmware always sends fixed 516-byte requests */ + char block_buf[516]; char block_buf_tail[1]; #if ENABLE_FEATURE_TFTP_PROGRESS_BAR off_t pos; @@ -811,7 +812,7 @@ int tftpd_main(int argc UNUSED_PARAM, char **argv) ) { goto err; } - /* Some HP PA-RISC firmware always sends fixed 512-byte requests, + /* Some HP PA-RISC firmware always sends fixed 516-byte requests, * with trailing garbage. * Support that by not requiring NUL to be the last byte (see above). * To make strXYZ() ops safe, force NUL termination: -- cgit v1.2.3-55-g6feb From 3e9b13e4c572d97468bef029f9c6e72271297fcb Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 5 Sep 2014 12:16:15 +0200 Subject: find: support -perm /BITS. Closes 7340 function old new delta parse_params 1487 1497 +10 func_perm 57 61 +4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 14/0) Total: 14 bytes Signed-off-by: Denys Vlasenko --- findutils/find.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/findutils/find.c b/findutils/find.c index 56a7ed3ab..83aa63f92 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -558,8 +558,8 @@ ACTF(type) #if ENABLE_FEATURE_FIND_PERM ACTF(perm) { - /* -perm +mode: at least one of perm_mask bits are set */ - if (ap->perm_char == '+') + /* -perm [+/]mode: at least one of perm_mask bits are set */ + if (ap->perm_char == '+' || ap->perm_char == '/') return (statbuf->st_mode & ap->perm_mask) != 0; /* -perm -mode: all of perm_mask are set */ if (ap->perm_char == '-') @@ -1252,14 +1252,14 @@ static action*** parse_params(char **argv) /* -perm BITS File's mode bits are exactly BITS (octal or symbolic). * Symbolic modes use mode 0 as a point of departure. * -perm -BITS All of the BITS are set in file's mode. - * -perm +BITS At least one of the BITS is set in file's mode. + * -perm [+/]BITS At least one of the BITS is set in file's mode. */ else if (parm == PARM_perm) { action_perm *ap; dbg("%d", __LINE__); ap = ALLOC_ACTION(perm); ap->perm_char = arg1[0]; - arg1 = plus_minus_num(arg1); + arg1 = (arg1[0] == '/' ? arg1+1 : plus_minus_num(arg1)); /*ap->perm_mask = 0; - ALLOC_ACTION did it */ if (!bb_parse_mode(arg1, &ap->perm_mask)) bb_error_msg_and_die("invalid mode '%s'", arg1); -- cgit v1.2.3-55-g6feb From 2ec34969e73c5262e20d3b4599196ff03913e66e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Sep 2014 16:52:39 +0200 Subject: ash: factor out ASH_HELP config option It used to be aliased to !FEATURE_SH_EXTRA_QUIET for ash, while hush had it separate from FEATURE_SH_EXTRA_QUIET. Bring ash in line with hush. Signed-off-by: Denys Vlasenko --- shell/ash.c | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 4ead6f990..293f15147 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -143,6 +143,13 @@ //config: help //config: Enable support for test builtin in ash. //config: +//config:config ASH_HELP +//config: bool "help builtin" +//config: default y +//config: depends on ASH +//config: help +//config: Enable help builtin in ash. +//config: //config:config ASH_CMDCMD //config: bool "'command' command to override shell builtins" //config: default y @@ -8804,8 +8811,8 @@ setinteractive(int on) if (!did_banner) { /* note: ash and hush share this string */ out1fmt("\n\n%s %s\n" - "Enter 'help' for a list of built-in commands." - "\n\n", + IF_ASH_HELP("Enter 'help' for a list of built-in commands.\n") + "\n", bb_banner, "built-in shell (ash)" ); @@ -9058,7 +9065,7 @@ static int exportcmd(int, char **) FAST_FUNC; #if ENABLE_ASH_GETOPTS static int getoptscmd(int, char **) FAST_FUNC; #endif -#if !ENABLE_FEATURE_SH_EXTRA_QUIET +#if ENABLE_ASH_HELP static int helpcmd(int, char **) FAST_FUNC; #endif #if MAX_HISTORY @@ -9134,7 +9141,7 @@ static const struct builtincmd builtintab[] = { { BUILTIN_REGULAR "getopts" , getoptscmd }, #endif { BUILTIN_NOSPEC "hash" , hashcmd }, -#if !ENABLE_FEATURE_SH_EXTRA_QUIET +#if ENABLE_ASH_HELP { BUILTIN_NOSPEC "help" , helpcmd }, #endif #if MAX_HISTORY @@ -12611,10 +12618,7 @@ trapcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) /* ============ Builtins */ -#if !ENABLE_FEATURE_SH_EXTRA_QUIET -/* - * Lists available builtins - */ +#if ENABLE_ASH_HELP static int FAST_FUNC helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) { @@ -12632,7 +12636,7 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) col = 0; } } -#if ENABLE_FEATURE_SH_STANDALONE +# if ENABLE_FEATURE_SH_STANDALONE { const char *a = applet_names; while (*a) { @@ -12644,11 +12648,11 @@ helpcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) a += strlen(a) + 1; } } -#endif +# endif out1fmt("\n\n"); return EXIT_SUCCESS; } -#endif /* FEATURE_SH_EXTRA_QUIET */ +#endif #if MAX_HISTORY static int FAST_FUNC -- cgit v1.2.3-55-g6feb From 07f7ea70edd0fdc7ad7da36df3f487111e14d0d1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Sep 2014 17:21:52 +0200 Subject: ash: fix off-by-one in "jobs %4" handling. closes 7310 Signed-off-by: Denys Vlasenko --- shell/ash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/ash.c b/shell/ash.c index 293f15147..705fe9fa4 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -3647,7 +3647,7 @@ getjob(const char *name, int getctl) if (is_number(p)) { num = atoi(p); - if (num < njobs) { + if (num <= njobs) { jp = jobtab + num - 1; if (jp->used) goto gotit; -- cgit v1.2.3-55-g6feb From 26a8b9f1967d910033c516462c101100e041a9b4 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 8 Sep 2014 18:19:15 +0200 Subject: mdev: treat zero-length /dev/mdev.seq the same as "\n" one. Closes 7334 Signed-off-by: Denys Vlasenko --- util-linux/mdev.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/util-linux/mdev.c b/util-linux/mdev.c index e80b58f2e..b2d56575f 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -972,7 +972,7 @@ wait_for_seqfile(const char *seq) break; } seqbuf[seqlen] = '\0'; - if (seqbuf[0] == '\n') { + if (seqbuf[0] == '\n' || seqbuf[0] == '\0') { /* seed file: write out seq ASAP */ xwrite_str(seq_fd, seq); xlseek(seq_fd, 0, SEEK_SET); -- cgit v1.2.3-55-g6feb From 05399fc53dc0b812727e44189882181ecaf3b6d6 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 15 Sep 2014 17:06:10 +0200 Subject: vi: fix incorrect memory access on brace matching. Closes 7256 While at it, fix brace matching to actually show the match (missed fflush was causing cursor positioning to be buffered); shorten brace matching code; remove unused macro indirection in indicate_error(). Custom linker script 'busybox_ldscript' found, using it function old new delta indicate_error - 61 +61 mysleep 43 56 +13 char_insert 483 486 +3 find_pair 167 124 -43 Indicate_Error 61 - -61 ------------------------------------------------------------------------------ (add/remove: 1/1 grow/shrink: 2/1 up/down: 77/-104) Total: -27 bytes Signed-off-by: Denys Vlasenko --- editors/vi.c | 79 +++++++++++++++++++++++++++--------------------------------- 1 file changed, 36 insertions(+), 43 deletions(-) diff --git a/editors/vi.c b/editors/vi.c index 24a9f60a8..70bdbab07 100644 --- a/editors/vi.c +++ b/editors/vi.c @@ -566,8 +566,7 @@ static void redraw(int); // force a full screen refresh static char* format_line(char* /*, int*/); static void refresh(int); // update the terminal from screen[] -static void Indicate_Error(void); // use flash or beep to indicate error -#define indicate_error(c) Indicate_Error() +static void indicate_error(void); // use flash or beep to indicate error static void Hit_Return(void); #if ENABLE_FEATURE_VI_SEARCH @@ -1840,11 +1839,11 @@ static char *bound_dot(char *p) // make sure text[0] <= P < "end" { if (p >= end && end > text) { p = end - 1; - indicate_error('1'); + indicate_error(); } if (p < text) { p = text; - indicate_error('2'); + indicate_error(); } return p; } @@ -2023,16 +2022,9 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' p = text_hole_delete(p, p, ALLOW_UNDO_QUEUED); // shrink buffer 1 char } } else { -#if ENABLE_FEATURE_VI_SETOPTS // insert a char into text[] - char *sp; // "save p" -#endif - if (c == 13) c = '\n'; // translate \r to \n -#if ENABLE_FEATURE_VI_SETOPTS - sp = p; // remember addr of insert -#endif #if ENABLE_FEATURE_VI_UNDO # if ENABLE_FEATURE_VI_UNDO_QUEUE if (c == '\n') @@ -2056,8 +2048,8 @@ static char *char_insert(char *p, char c, int undo) // insert the char c at 'p' #endif /* ENABLE_FEATURE_VI_UNDO */ p += 1 + stupid_insert(p, c); // insert the char #if ENABLE_FEATURE_VI_SETOPTS - if (showmatch && strchr(")]}", *sp) != NULL) { - showmatching(sp); + if (showmatch && strchr(")]}", c) != NULL) { + showmatching(p - 1); } if (autoindent && c == '\n') { // auto indent the new line char *q; @@ -2217,34 +2209,32 @@ static char *skip_thing(char *p, int linecnt, int dir, int type) } // find matching char of pair () [] {} +// will crash if c is not one of these static char *find_pair(char *p, const char c) { - char match, *q; + const char *braces = "()[]{}"; + char match; int dir, level; - match = ')'; + dir = strchr(braces, c) - braces; + dir ^= 1; + match = braces[dir]; + dir = ((dir & 1) << 1) - 1; /* 1 for ([{, -1 for )\} */ + + // look for match, count levels of pairs (( )) level = 1; - dir = 1; // assume forward - switch (c) { - case '(': match = ')'; break; - case '[': match = ']'; break; - case '{': match = '}'; break; - case ')': match = '('; dir = -1; break; - case ']': match = '['; dir = -1; break; - case '}': match = '{'; dir = -1; break; - } - for (q = p + dir; text <= q && q < end; q += dir) { - // look for match, count levels of pairs (( )) - if (*q == c) + for (;;) { + p += dir; + if (p < text || p >= end) + return NULL; + if (*p == c) level++; // increase pair levels - if (*q == match) + if (*p == match) { level--; // reduce pair level - if (level == 0) - break; // found matching pair + if (level == 0) + return p; // found matching pair + } } - if (level != 0) - q = NULL; // indicate no match - return q; } #if ENABLE_FEATURE_VI_SETOPTS @@ -2256,7 +2246,7 @@ static void showmatching(char *p) // we found half of a pair q = find_pair(p, *p); // get loc of matching char if (q == NULL) { - indicate_error('3'); // no matching char + indicate_error(); // no matching char } else { // "q" now points to matching pair save_dot = dot; // remember where we are @@ -2815,6 +2805,9 @@ static int mysleep(int hund) // sleep for 'hund' 1/100 seconds or stdin ready { struct pollfd pfd[1]; + if (hund != 0) + fflush_all(); + pfd[0].fd = STDIN_FILENO; pfd[0].events = POLLIN; return safe_poll(pfd, 1, hund*10) > 0; @@ -3059,7 +3052,7 @@ static void flash(int h) redraw(TRUE); } -static void Indicate_Error(void) +static void indicate_error(void) { #if ENABLE_FEATURE_VI_CRASHME if (crashme > 0) @@ -3602,7 +3595,7 @@ static void do_cmd(int c) break; case 27: // esc if (cmd_mode == 0) - indicate_error(c); + indicate_error(); cmd_mode = 0; // stop insrting undo_queue_commit(); end_cmd_q(); @@ -3621,7 +3614,7 @@ static void do_cmd(int c) if ((unsigned)c1 <= 25) { // a-z? YDreg = c1; } else { - indicate_error(c); + indicate_error(); } break; case '\'': // '- goto a specific mark @@ -3639,7 +3632,7 @@ static void do_cmd(int c) dot_begin(); // go to B-o-l dot_skip_over_ws(); } else { - indicate_error(c); + indicate_error(); } break; case 'm': // m- Mark a line @@ -3652,7 +3645,7 @@ static void do_cmd(int c) // remember the line mark[c1] = dot; } else { - indicate_error(c); + indicate_error(); } break; case 'P': // P- Put register before @@ -3713,7 +3706,7 @@ static void do_cmd(int c) // we found half of a pair p = find_pair(q, *q); if (p == NULL) { - indicate_error(c); + indicate_error(); } else { dot = p; } @@ -3721,7 +3714,7 @@ static void do_cmd(int c) } } if (*q == '\n') - indicate_error(c); + indicate_error(); break; case 'f': // f- forward to a user specified char last_forward_char = get_one_char(); // get the search char @@ -4054,7 +4047,7 @@ static void do_cmd(int c) // ZZ means to save file (if necessary), then exit c1 = get_one_char(); if (c1 != 'Z') { - indicate_error(c); + indicate_error(); break; } if (modified_count) { @@ -4138,7 +4131,7 @@ static void do_cmd(int c) // could not recognize object c = c1 = 27; // error- ml = 0; - indicate_error(c); + indicate_error(); } if (ml && whole) { if (c == 'c') { -- cgit v1.2.3-55-g6feb From 7666fa1d02b4e7e74a83833881caef09b475b88b Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 15 Sep 2014 23:35:58 +0200 Subject: ftpd: make LIST command show dotfiles too Signed-off-by: Denys Vlasenko --- networking/ftpd.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/networking/ftpd.c b/networking/ftpd.c index 9fcc3e963..6adcb1dee 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -622,7 +622,7 @@ popen_ls(const char *opt) pid_t pid; argv[0] = "ftpd"; - argv[1] = opt; /* "-l" or "-1" */ + argv[1] = opt; /* "-lA" or "-1A" */ argv[2] = "--"; argv[3] = G.ftp_arg; argv[4] = NULL; @@ -699,7 +699,7 @@ handle_dir_common(int opts) if (!(opts & USE_CTRL_CONN) && !port_or_pasv_was_seen()) return; /* port_or_pasv_was_seen emitted error response */ - ls_fd = popen_ls((opts & LONG_LISTING) ? "-l" : "-1"); + ls_fd = popen_ls((opts & LONG_LISTING) ? "-lA" : "-1A"); ls_fp = xfdopen_for_read(ls_fd); /* FIXME: filenames with embedded newlines are mishandled */ @@ -1102,10 +1102,11 @@ enum { #if !BB_MMU OPT_l = (1 << 0), OPT_1 = (1 << 1), + OPT_A = (1 << 2), #endif - OPT_v = (1 << ((!BB_MMU) * 2 + 0)), - OPT_S = (1 << ((!BB_MMU) * 2 + 1)), - OPT_w = (1 << ((!BB_MMU) * 2 + 2)) * ENABLE_FEATURE_FTP_WRITE, + OPT_v = (1 << ((!BB_MMU) * 3 + 0)), + OPT_S = (1 << ((!BB_MMU) * 3 + 1)), + OPT_w = (1 << ((!BB_MMU) * 3 + 2)) * ENABLE_FEATURE_FTP_WRITE, }; int ftpd_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; @@ -1126,12 +1127,11 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) G.timeout = 2 * 60; opt_complementary = "t+:T+:vv:SS"; #if BB_MMU - opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); + opts = getopt32(argv, "vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); #else - opts = getopt32(argv, "l1vS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); + opts = getopt32(argv, "l1AvS" IF_FEATURE_FTP_WRITE("w") "t:T:", &G.timeout, &abs_timeout, &G.verbose, &verbose_S); if (opts & (OPT_l|OPT_1)) { /* Our secret backdoor to ls */ -/* TODO: pass -A? It shows dot files */ /* TODO: pass --group-directories-first? would be nice, but ls doesn't do that yet */ if (fchdir(3) != 0) _exit(127); -- cgit v1.2.3-55-g6feb From 9caea2448e168560de306a1496574dd58c645fea Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 16 Sep 2014 01:11:13 +0200 Subject: sed: fix a buglet in s///NUM handling Signed-off-by: Denys Vlasenko --- editors/sed.c | 5 ++++- testsuite/sed.tests | 4 ++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/editors/sed.c b/editors/sed.c index e18e48ab5..e1b8352fd 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -395,7 +395,9 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) /* process the flags */ sed_cmd->which_match = 1; + dbg("s flags:'%s'", substr + idx + 1); while (substr[++idx]) { + dbg("s flag:'%c'", substr[idx]); /* Parse match number */ if (isdigit(substr[idx])) { if (match[0] != '^') { @@ -403,7 +405,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) const char *pos = substr + idx; /* FIXME: error check? */ sed_cmd->which_match = (unsigned)strtol(substr+idx, (char**) &pos, 10); - idx = pos - substr; + idx = pos - substr - 1; } continue; } @@ -443,6 +445,7 @@ static int parse_subst_cmd(sed_cmd_t *sed_cmd, const char *substr) case '}': goto out; default: + dbg("s bad flags:'%s'", substr + idx); bb_error_msg_and_die("bad option in substitution expression"); } } diff --git a/testsuite/sed.tests b/testsuite/sed.tests index 9494ac2de..19f2915ce 100755 --- a/testsuite/sed.tests +++ b/testsuite/sed.tests @@ -329,6 +329,10 @@ line with \\ continuation " +testing "sed s///NUM test" \ + "sed -e 's/a/b/2; s/a/c/g'" \ + "cb\n" "" "aa\n" + # testing "description" "commands" "result" "infile" "stdin" exit $FAILCOUNT -- cgit v1.2.3-55-g6feb From d0cdacafa98ec0e73e58c2e5a8ba9dded18006df Mon Sep 17 00:00:00 2001 From: Ari Sundholm Date: Wed, 17 Sep 2014 20:53:58 +0200 Subject: df: implement -T option function old new delta df_main 863 998 +135 packed_usage 29827 29861 +34 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 169/0) Total: 169 bytes Signed-off-by: Ari Sundholm Signed-off-by: Denys Vlasenko --- coreutils/df.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/coreutils/df.c b/coreutils/df.c index 5e9a8670f..7a82fee83 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -25,6 +25,7 @@ //usage:#define df_trivial_usage //usage: "[-Pk" //usage: IF_FEATURE_HUMAN_READABLE("mh") +//usage: "T" //usage: IF_FEATURE_DF_FANCY("ai] [-B SIZE") //usage: "] [FILESYSTEM]..." //usage:#define df_full_usage "\n\n" @@ -35,6 +36,7 @@ //usage: "\n -m 1M-byte blocks" //usage: "\n -h Human readable (e.g. 1K 243M 2G)" //usage: ) +//usage: "\n -T Print filesystem type" //usage: IF_FEATURE_DF_FANCY( //usage: "\n -a Show all filesystems" //usage: "\n -i Inodes" @@ -88,6 +90,7 @@ int df_main(int argc UNUSED_PARAM, char **argv) OPT_BSIZE = (1 << 4) * ENABLE_FEATURE_DF_FANCY, OPT_HUMAN = (1 << (2 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, OPT_MEGA = (1 << (3 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, + OPT_FSTYPE = (1 << (4 + 3*ENABLE_FEATURE_DF_FANCY)), }; const char *disp_units_hdr = NULL; char *chp; @@ -102,6 +105,7 @@ int df_main(int argc UNUSED_PARAM, char **argv) opt = getopt32(argv, "kP" IF_FEATURE_DF_FANCY("aiB:") IF_FEATURE_HUMAN_READABLE("hm") + "T" IF_FEATURE_DF_FANCY(, &chp)); if (opt & OPT_MEGA) df_disp_hr = 1024*1024; @@ -134,8 +138,11 @@ int df_main(int argc UNUSED_PARAM, char **argv) disp_units_hdr = xasprintf("%lu-blocks", df_disp_hr); #endif } - printf("Filesystem %-15sUsed Available %s Mounted on\n", - disp_units_hdr, (opt & OPT_POSIX) ? "Capacity" : "Use%"); + + printf("Filesystem %s%-15sUsed Available %s Mounted on\n", + (opt & OPT_FSTYPE) ? "Type " : "", + disp_units_hdr, + (opt & OPT_POSIX) ? "Capacity" : "Use%"); mount_table = NULL; argv += optind; @@ -148,6 +155,7 @@ int df_main(int argc UNUSED_PARAM, char **argv) while (1) { const char *device; const char *mount_point; + const char *fs_type; if (mount_table) { mount_entry = getmntent(mount_table); @@ -170,6 +178,7 @@ int df_main(int argc UNUSED_PARAM, char **argv) device = mount_entry->mnt_fsname; mount_point = mount_entry->mnt_dir; + fs_type = mount_entry->mnt_type; if (statfs(mount_point, &s) != 0) { bb_simple_perror_msg(mount_point); @@ -218,10 +227,22 @@ int df_main(int argc UNUSED_PARAM, char **argv) printf("%s%*s", uni_dev, 20 - (int)uni_stat.unicode_width, ""); } free(uni_dev); + if (opt & OPT_FSTYPE) { + char *uni_type = unicode_conv_to_printable(&uni_stat, fs_type); + if (uni_stat.unicode_width > 10 && !(opt & OPT_POSIX)) + printf(" %s\n%31s", uni_type, ""); + else + printf(" %s%*s", uni_type, 10 - (int)uni_stat.unicode_width, ""); + free(uni_type); + } } #else if (printf("\n%-20s" + 1, device) > 20 && !(opt & OPT_POSIX)) printf("\n%-20s", ""); + if (opt & OPT_FSTYPE) { + if (printf(" %-10s", fs_type) > 11 && !(opt & OPT_POSIX)) + printf("\n%-30s", ""); + } #endif #if ENABLE_FEATURE_HUMAN_READABLE -- cgit v1.2.3-55-g6feb From cd7a38a87d54f5421b379870ff866676f31923b2 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 18 Sep 2014 00:47:05 +0200 Subject: false: make "false --help" exit with 1 function old new delta run_applet_no_and_exit 447 445 -2 Signed-off-by: Denys Vlasenko --- applets/applet_tables.c | 17 +++++++++++++++++ libbb/appletlib.c | 26 ++++++++++++++++++-------- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/applets/applet_tables.c b/applets/applet_tables.c index 94b974e09..92bf1e447 100644 --- a/applets/applet_tables.c +++ b/applets/applet_tables.c @@ -14,6 +14,7 @@ #include #include #include +#include #undef ARRAY_SIZE #define ARRAY_SIZE(x) ((unsigned)(sizeof(x) / sizeof((x)[0]))) @@ -49,6 +50,16 @@ static int cmp_name(const void *a, const void *b) return strcmp(aa->name, bb->name); } +static int str_isalnum_(const char *s) +{ + while (*s) { + if (!isalnum(*s) && *s != '_') + return 0; + s++; + } + return 1; +} + int main(int argc, char **argv) { int i; @@ -94,6 +105,12 @@ int main(int argc, char **argv) } printf(";\n\n"); + for (i = 0; i < NUM_APPLETS; i++) { + if (str_isalnum_(applets[i].name)) + printf("#define APPLET_NO_%s %d\n", applets[i].name, i); + } + printf("\n"); + printf("#ifndef SKIP_applet_main\n"); printf("int (*const applet_main[])(int argc, char **argv) = {\n"); for (i = 0; i < NUM_APPLETS; i++) { diff --git a/libbb/appletlib.c b/libbb/appletlib.c index a0150854a..cb16e310f 100644 --- a/libbb/appletlib.c +++ b/libbb/appletlib.c @@ -745,15 +745,25 @@ void FAST_FUNC run_applet_no_and_exit(int applet_no, char **argv) /* Reinit some shared global data */ xfunc_error_retval = EXIT_FAILURE; - applet_name = APPLET_NAME(applet_no); - if (argc == 2 && strcmp(argv[1], "--help") == 0) { - /* Special case. POSIX says "test --help" - * should be no different from e.g. "test --foo". */ -//TODO: just compare applet_no with APPLET_NO_test - if (!ENABLE_TEST || strcmp(applet_name, "test") != 0) { - /* If you want "foo --help" to return 0: */ - xfunc_error_retval = 0; + +#if defined APPLET_NO_test + /* Special case. POSIX says "test --help" + * should be no different from e.g. "test --foo". + * Thus for "test", we skip --help check. + */ + if (applet_no != APPLET_NO_test) +#endif + { + if (argc == 2 && strcmp(argv[1], "--help") == 0) { +#if defined APPLET_NO_false + /* Someone insisted that "false --help" must exit 1. Sigh */ + if (applet_no != APPLET_NO_false) +#endif + { + /* Make "foo --help" exit with 0: */ + xfunc_error_retval = 0; + } bb_show_usage(); } } -- cgit v1.2.3-55-g6feb From fbdc167f27193fd7e00f85537af122eba674fe95 Mon Sep 17 00:00:00 2001 From: Ari Sundholm Date: Thu, 18 Sep 2014 15:41:57 +0300 Subject: df: fix -T option when ENABLE_FEATURE_HUMAN_READABLE=0 Signed-off-by: Ari Sundholm Signed-off-by: Denys Vlasenko --- coreutils/df.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/coreutils/df.c b/coreutils/df.c index 7a82fee83..d79c11a6c 100644 --- a/coreutils/df.c +++ b/coreutils/df.c @@ -85,12 +85,12 @@ int df_main(int argc UNUSED_PARAM, char **argv) enum { OPT_KILO = (1 << 0), OPT_POSIX = (1 << 1), - OPT_ALL = (1 << 2) * ENABLE_FEATURE_DF_FANCY, - OPT_INODE = (1 << 3) * ENABLE_FEATURE_DF_FANCY, - OPT_BSIZE = (1 << 4) * ENABLE_FEATURE_DF_FANCY, - OPT_HUMAN = (1 << (2 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, - OPT_MEGA = (1 << (3 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, - OPT_FSTYPE = (1 << (4 + 3*ENABLE_FEATURE_DF_FANCY)), + OPT_FSTYPE = (1 << 2), + OPT_ALL = (1 << 3) * ENABLE_FEATURE_DF_FANCY, + OPT_INODE = (1 << 4) * ENABLE_FEATURE_DF_FANCY, + OPT_BSIZE = (1 << 5) * ENABLE_FEATURE_DF_FANCY, + OPT_HUMAN = (1 << (3 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, + OPT_MEGA = (1 << (4 + 3*ENABLE_FEATURE_DF_FANCY)) * ENABLE_FEATURE_HUMAN_READABLE, }; const char *disp_units_hdr = NULL; char *chp; @@ -102,10 +102,9 @@ int df_main(int argc UNUSED_PARAM, char **argv) #elif ENABLE_FEATURE_HUMAN_READABLE opt_complementary = "k-m:m-k"; #endif - opt = getopt32(argv, "kP" + opt = getopt32(argv, "kPT" IF_FEATURE_DF_FANCY("aiB:") IF_FEATURE_HUMAN_READABLE("hm") - "T" IF_FEATURE_DF_FANCY(, &chp)); if (opt & OPT_MEGA) df_disp_hr = 1024*1024; -- cgit v1.2.3-55-g6feb From 15943c886d6e1929b90db9bc6077c849cbaa187e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 21 Sep 2014 22:10:55 +0200 Subject: less: disable "suppress empty wraparound" optimization It is buggy wrt another use case... Signed-off-by: Denys Vlasenko --- miscutils/less.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/miscutils/less.c b/miscutils/less.c index d84df469c..719af5a0d 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -491,6 +491,11 @@ static void read_lines(void) *p++ = c; *p = '\0'; } /* end of "read chars until we have a line" loop */ +#if 0 +//BUG: also triggers on this: +// { printf "\nfoo\n"; sleep 1; printf "\nbar\n"; } | less +// (resulting in lost empty line between "foo" and "bar" lines) +// the "terminated" logic needs fixing (or explaining) /* Corner case: linewrap with only "" wrapping to next line */ /* Looks ugly on screen, so we do not store this empty line */ if (!last_terminated && !current_line[0]) { @@ -498,6 +503,7 @@ static void read_lines(void) max_lineno++; continue; } +#endif reached_eof: last_terminated = terminated; flines = xrealloc_vector(flines, 8, max_fline); -- cgit v1.2.3-55-g6feb From d6e7672545c717497490c0b0f54f64594f374f9d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Sep 2014 21:14:02 +0200 Subject: less: move "retry-on-EAGAIN" logic closer to read ops This makes "G" (goto end of input) command work as well as /search_for_nonexistent_string: both will read to EOF now even from somewhat slow input (such as kernel's "git log"). function old new delta ndelay_on 35 43 +8 ndelay_off 35 43 +8 read_lines 695 691 -4 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 16/-4) Total: 12 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 4 ++-- libbb/xfuncs.c | 10 ++++++---- miscutils/less.c | 47 +++++++++++++++++++++-------------------------- 3 files changed, 29 insertions(+), 32 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index ff223dd0f..d57f00e0e 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -390,8 +390,8 @@ const char *bb_basename(const char *name) FAST_FUNC; char *last_char_is(const char *s, int c) FAST_FUNC; const char* endofname(const char *name) FAST_FUNC; -void ndelay_on(int fd) FAST_FUNC; -void ndelay_off(int fd) FAST_FUNC; +int ndelay_on(int fd) FAST_FUNC; +int ndelay_off(int fd) FAST_FUNC; void close_on_exec_on(int fd) FAST_FUNC; void xdup2(int, int) FAST_FUNC; void xmove_fd(int, int) FAST_FUNC; diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 23f27516f..f25ce9446 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c @@ -25,20 +25,22 @@ #include "libbb.h" /* Turn on nonblocking I/O on a fd */ -void FAST_FUNC ndelay_on(int fd) +int FAST_FUNC ndelay_on(int fd) { int flags = fcntl(fd, F_GETFL); if (flags & O_NONBLOCK) - return; + return flags; fcntl(fd, F_SETFL, flags | O_NONBLOCK); + return flags; } -void FAST_FUNC ndelay_off(int fd) +int FAST_FUNC ndelay_off(int fd) { int flags = fcntl(fd, F_GETFL); if (!(flags & O_NONBLOCK)) - return; + return flags; fcntl(fd, F_SETFL, flags & ~O_NONBLOCK); + return flags; } void FAST_FUNC close_on_exec_on(int fd) diff --git a/miscutils/less.c b/miscutils/less.c index 719af5a0d..3016c5b47 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -414,10 +414,10 @@ static void read_lines(void) char *current_line, *p; int w = width; char last_terminated = terminated; + time_t last_time = 0; + int retry_EAGAIN = 2; #if ENABLE_FEATURE_LESS_REGEXP unsigned old_max_fline = max_fline; - time_t last_time = 0; - int had_progress = 2; #endif /* (careful: max_fline can be -1) */ @@ -427,8 +427,6 @@ static void read_lines(void) if (option_mask32 & FLAG_N) w -= 8; - IF_FEATURE_LESS_REGEXP(again0:) - p = current_line = ((char*)xmalloc(w + 4)) + 4; max_fline += last_terminated; if (!last_terminated) { @@ -448,15 +446,29 @@ static void read_lines(void) char c; /* if no unprocessed chars left, eat more */ if (readpos >= readeof) { - errno = 0; - ndelay_on(0); - eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf)); - ndelay_off(0); + int flags = ndelay_on(0); + + while (1) { + time_t t; + + errno = 0; + eof_error = safe_read(STDIN_FILENO, readbuf, sizeof(readbuf)); + if (errno != EAGAIN) + break; + t = time(NULL); + if (t != last_time) { + last_time = t; + if (--retry_EAGAIN < 0) + break; + } + sched_yield(); + } + fcntl(0, F_SETFL, flags); /* ndelay_off(0) */ readpos = 0; readeof = eof_error; if (eof_error <= 0) goto reached_eof; - IF_FEATURE_LESS_REGEXP(had_progress = 1;) + retry_EAGAIN = 1; } c = readbuf[readpos]; /* backspace? [needed for manpages] */ @@ -534,24 +546,7 @@ static void read_lines(void) #endif } if (eof_error <= 0) { -#if !ENABLE_FEATURE_LESS_REGEXP break; -#else - if (wanted_match < num_matches) { - break; - } /* else: goto_match() called us */ - if (errno == EAGAIN) { - time_t t = time(NULL); - if (t != last_time) { - last_time = t; - if (--had_progress < 0) - break; - } - sched_yield(); - goto again0; - } - break; -#endif } max_fline++; current_line = ((char*)xmalloc(w + 4)) + 4; -- cgit v1.2.3-55-g6feb From 865814a617cc2b197ef0ad12ee331a7a01d30e1a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 22 Sep 2014 21:17:24 +0200 Subject: less: trivial code shrink function old new delta read_lines 715 695 -20 Signed-off-by: Denys Vlasenko --- miscutils/less.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/miscutils/less.c b/miscutils/less.c index 3016c5b47..c5820d325 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -428,14 +428,13 @@ static void read_lines(void) w -= 8; p = current_line = ((char*)xmalloc(w + 4)) + 4; - max_fline += last_terminated; if (!last_terminated) { const char *cp = flines[max_fline]; - strcpy(p, cp); - p += strlen(current_line); - free(MEMPTR(flines[max_fline])); + p = stpcpy(p, cp); + free(MEMPTR(cp)); /* last_line_pos is still valid from previous read_lines() */ } else { + max_fline++; last_line_pos = 0; } -- cgit v1.2.3-55-g6feb From 307d26c0ebfb0d22a81070379675f6287f6e9d95 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Tue, 23 Sep 2014 22:58:18 +0200 Subject: less: make -E work function old new delta buffer_print 71 104 +33 Signed-off-by: Aaro Koskinen Signed-off-by: Denys Vlasenko --- miscutils/less.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/miscutils/less.c b/miscutils/less.c index c5820d325..554e54687 100644 --- a/miscutils/less.c +++ b/miscutils/less.c @@ -802,11 +802,18 @@ static void buffer_print(void) unsigned i; move_cursor(0, 0); - for (i = 0; i <= max_displayed_line; i++) + for (i = 0; i <= max_displayed_line; i++) { if (pattern_valid) print_found(buffer[i]); else print_ascii(buffer[i]); + } + if ((option_mask32 & FLAG_E) + && eof_error <= 0 + && (max_fline - cur_fline) <= max_displayed_line + ) { + less_exit(EXIT_SUCCESS); + } status_print(); } -- cgit v1.2.3-55-g6feb From 0f78d616cb394925d8b9511d370643ddd445adc3 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Wed, 24 Sep 2014 02:52:08 +0200 Subject: install: implement -t DIR Some packages want to install themselves using "-t" to specify the directory (as supported by GNU coreutils). Add support for the option for compatibility reasons. function old new delta install_longopts 76 95 +19 install_main 769 777 +8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 27/0) Total: 27 bytes Signed-off-by: Aaro Koskinen Signed-off-by: Denys Vlasenko --- coreutils/install.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/coreutils/install.c b/coreutils/install.c index 6c88ae11c..6e199941e 100644 --- a/coreutils/install.c +++ b/coreutils/install.c @@ -8,7 +8,7 @@ /* -v, -b, -c are ignored */ //usage:#define install_trivial_usage -//usage: "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [SOURCE]... DEST" +//usage: "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [-d DIR] [SOURCE]... DEST" //usage:#define install_full_usage "\n\n" //usage: "Copy files and set attributes\n" //usage: "\n -c Just copy (default)" @@ -19,6 +19,7 @@ //usage: "\n -o USER Set ownership" //usage: "\n -g GRP Set group ownership" //usage: "\n -m MODE Set permissions" +//usage: "\n -t DIR Install to DIR" //usage: IF_SELINUX( //usage: "\n -Z Set security context" //usage: ) @@ -37,6 +38,7 @@ static const char install_longopts[] ALIGN1 = "group\0" Required_argument "g" "mode\0" Required_argument "m" "owner\0" Required_argument "o" + "target-directory\0" Required_argument "t" /* autofs build insists of using -b --suffix=.orig */ /* TODO? (short option for --suffix is -S) */ #if ENABLE_SELINUX @@ -95,9 +97,8 @@ int install_main(int argc, char **argv) int mkdir_flags = FILEUTILS_RECUR; int copy_flags = FILEUTILS_DEREFERENCE | FILEUTILS_FORCE; int opts; - int min_args = 1; int ret = EXIT_SUCCESS; - int isdir = 0; + int isdir; #if ENABLE_SELINUX security_context_t scontext; bool use_default_selinux_context = 1; @@ -113,20 +114,22 @@ int install_main(int argc, char **argv) OPT_GROUP = 1 << 7, OPT_MODE = 1 << 8, OPT_OWNER = 1 << 9, + OPT_TARGET = 1 << 10, #if ENABLE_SELINUX - OPT_SET_SECURITY_CONTEXT = 1 << 10, - OPT_PRESERVE_SECURITY_CONTEXT = 1 << 11, + OPT_SET_SECURITY_CONTEXT = 1 << 11, + OPT_PRESERVE_SECURITY_CONTEXT = 1 << 12, #endif }; #if ENABLE_FEATURE_INSTALL_LONG_OPTIONS applet_long_options = install_longopts; #endif - opt_complementary = "s--d:d--s" IF_FEATURE_INSTALL_LONG_OPTIONS(IF_SELINUX(":Z--\xff:\xff--Z")); + opt_complementary = "t--d:d--t:s--d:d--s" IF_FEATURE_INSTALL_LONG_OPTIONS(IF_SELINUX(":Z--\xff:\xff--Z")); /* -c exists for backwards compatibility, it's needed */ /* -b is ignored ("make a backup of each existing destination file") */ - opts = getopt32(argv, "cvb" "Ddpsg:m:o:" IF_SELINUX("Z:"), - &gid_str, &mode_str, &uid_str IF_SELINUX(, &scontext)); + opts = getopt32(argv, "cvb" "Ddpsg:m:o:t:" IF_SELINUX("Z:"), + &gid_str, &mode_str, &uid_str, &last + IF_SELINUX(, &scontext)); argc -= optind; argv += optind; @@ -160,20 +163,23 @@ int install_main(int argc, char **argv) uid = (opts & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid(); gid = (opts & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid(); - last = argv[argc - 1]; - if (!(opts & OPT_DIRECTORY)) { - argv[argc - 1] = NULL; - min_args++; - + /* If -t DIR is in use, then isdir=true, last="DIR" */ + isdir = (opts & OPT_TARGET); + if (!(opts & (OPT_TARGET|OPT_DIRECTORY))) { + /* Neither -t DIR nor -d is in use */ + argc--; + last = argv[argc]; + argv[argc] = NULL; /* coreutils install resolves link in this case, don't use lstat */ isdir = stat(last, &statbuf) < 0 ? 0 : S_ISDIR(statbuf.st_mode); } - if (argc < min_args) + if (argc < 1) bb_show_usage(); while ((arg = *argv++) != NULL) { - char *dest = last; + char *dest; + if (opts & OPT_DIRECTORY) { dest = arg; /* GNU coreutils 6.9 does not set uid:gid @@ -184,6 +190,7 @@ int install_main(int argc, char **argv) goto next; } } else { + dest = last; if (opts & OPT_MKDIR_LEADING) { char *ddir = xstrdup(dest); bb_make_directory(dirname(ddir), 0755, mkdir_flags); -- cgit v1.2.3-55-g6feb From fb143f783da8a3b13ae7a35f6750c2d0c86081e6 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 18 Sep 2014 16:19:03 +0200 Subject: ntpd: don't wait for good offset before disabling burst mode The burst mode needs to be stopped even when no replies are received. Signed-off-by: Miroslav Lichvar Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index cfe695631..3c708c1c5 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1472,12 +1472,6 @@ update_local_clock(peer_t *p) } else { /* abs_offset <= STEP_THRESHOLD */ - if (G.poll_exp < MINPOLL && G.initial_poll_complete) { - VERB4 bb_error_msg("small offset:%+f, disabling burst mode", offset); - G.polladj_count = 0; - G.poll_exp = MINPOLL; - } - /* Compute the clock jitter as the RMS of exponentially * weighted offset differences. Used by the poll adjust code. */ @@ -2242,6 +2236,9 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) if (p->p_fd == -1) { /* Time to send new req */ if (--cnt == 0) { + VERB4 bb_error_msg("disabling burst mode"); + G.polladj_count = 0; + G.poll_exp = MINPOLL; G.initial_poll_complete = 1; } send_query_to_peer(p); -- cgit v1.2.3-55-g6feb From 590a22cf8d100edc968aa5d691c1ca3000654350 Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 18 Sep 2014 16:19:05 +0200 Subject: ntpd: split out poll adjusting code Signed-off-by: Miroslav Lichvar Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 76 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 3c708c1c5..2d1ad69a0 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1679,6 +1679,41 @@ poll_interval(int exponent) return interval; } static NOINLINE void +adjust_poll(int count) +{ + G.polladj_count += count; + if (G.polladj_count > POLLADJ_LIMIT) { + G.polladj_count = 0; + if (G.poll_exp < MAXPOLL) { + G.poll_exp++; + VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d", + G.discipline_jitter, G.poll_exp); + } + } else if (G.polladj_count < -POLLADJ_LIMIT || (count < 0 && G.poll_exp >= BIGPOLL)) { + G.polladj_count = 0; + if (G.poll_exp > MINPOLL) { + llist_t *item; + + G.poll_exp--; + /* Correct p->next_action_time in each peer + * which waits for sending, so that they send earlier. + * Old pp->next_action_time are on the order + * of t + (1 << old_poll_exp) + small_random, + * we simply need to subtract ~half of that. + */ + for (item = G.ntp_peers; item != NULL; item = item->link) { + peer_t *pp = (peer_t *) item->data; + if (pp->p_fd < 0) + pp->next_action_time -= (1 << G.poll_exp); + } + VERB4 bb_error_msg("polladj: discipline_jitter:%f --poll_exp=%d", + G.discipline_jitter, G.poll_exp); + } + } else { + VERB4 bb_error_msg("polladj: count:%d", G.polladj_count); + } +} +static NOINLINE void recv_and_process_peer_pkt(peer_t *p) { int rc; @@ -1837,7 +1872,8 @@ recv_and_process_peer_pkt(peer_t *p) */ if (fabs(q->filter_offset) >= POLLDOWN_OFFSET) { VERB4 bb_error_msg("offset:%+f > POLLDOWN_OFFSET", q->filter_offset); - goto poll_down; + adjust_poll(-POLLADJ_LIMIT * 3); + rc = 0; } } } @@ -1853,43 +1889,9 @@ recv_and_process_peer_pkt(peer_t *p) if (rc > 0 && G.offset_to_jitter_ratio <= POLLADJ_GATE) { /* was += G.poll_exp but it is a bit * too optimistic for my taste at high poll_exp's */ - G.polladj_count += MINPOLL; - if (G.polladj_count > POLLADJ_LIMIT) { - G.polladj_count = 0; - if (G.poll_exp < MAXPOLL) { - G.poll_exp++; - VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d", - G.discipline_jitter, G.poll_exp); - } - } else { - VERB4 bb_error_msg("polladj: incr:%d", G.polladj_count); - } + adjust_poll(MINPOLL); } else { - G.polladj_count -= G.poll_exp * 2; - if (G.polladj_count < -POLLADJ_LIMIT || G.poll_exp >= BIGPOLL) { - poll_down: - G.polladj_count = 0; - if (G.poll_exp > MINPOLL) { - llist_t *item; - - G.poll_exp--; - /* Correct p->next_action_time in each peer - * which waits for sending, so that they send earlier. - * Old pp->next_action_time are on the order - * of t + (1 << old_poll_exp) + small_random, - * we simply need to subtract ~half of that. - */ - for (item = G.ntp_peers; item != NULL; item = item->link) { - peer_t *pp = (peer_t *) item->data; - if (pp->p_fd < 0) - pp->next_action_time -= (1 << G.poll_exp); - } - VERB4 bb_error_msg("polladj: discipline_jitter:%f --poll_exp=%d", - G.discipline_jitter, G.poll_exp); - } - } else { - VERB4 bb_error_msg("polladj: decr:%d", G.polladj_count); - } + adjust_poll(-G.poll_exp * 2); } } -- cgit v1.2.3-55-g6feb From 054f5a5b0d383904e450ca718b1e758ed16baa66 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 24 Sep 2014 22:16:24 +0200 Subject: install: fix help text Signed-off-by: Denys Vlasenko --- coreutils/install.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/coreutils/install.c b/coreutils/install.c index 6e199941e..73f9c70d5 100644 --- a/coreutils/install.c +++ b/coreutils/install.c @@ -8,7 +8,7 @@ /* -v, -b, -c are ignored */ //usage:#define install_trivial_usage -//usage: "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [-d DIR] [SOURCE]... DEST" +//usage: "[-cdDsp] [-o USER] [-g GRP] [-m MODE] [-t DIR] [SOURCE]... DEST" //usage:#define install_full_usage "\n\n" //usage: "Copy files and set attributes\n" //usage: "\n -c Just copy (default)" -- cgit v1.2.3-55-g6feb From 186b98a86f069bb65bf4110e324d75fef98857c0 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 25 Sep 2014 22:10:32 +0200 Subject: ubiupdatevol: fix -t to not require an option. Closes 7466 Signed-off-by: Denys Vlasenko --- miscutils/ubi_tools.c | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/miscutils/ubi_tools.c b/miscutils/ubi_tools.c index b71393532..6c09fe534 100644 --- a/miscutils/ubi_tools.c +++ b/miscutils/ubi_tools.c @@ -125,12 +125,24 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv) strcpy(path, "/sys/class/ubi/ubi"); memset(&req_structs, 0, sizeof(req_structs)); +#define OPTION_m (1 << 0) +#define OPTION_d (1 << 1) +#define OPTION_n (1 << 2) +#define OPTION_N (1 << 3) +#define OPTION_s (1 << 4) +#define OPTION_a (1 << 5) +#define OPTION_t (1 << 6) if (do_mkvol) { opt_complementary = "-1:d+:n+:a+"; opts = getopt32(argv, "md:n:N:s:a:t:", &dev_num, &vol_id, &vol_name, &size_bytes_str, &alignment, &type ); + } else + if (do_update) { + opt_complementary = "-1"; + opts = getopt32(argv, "s:at", &size_bytes_str); + opts *= OPTION_s; } else { opt_complementary = "-1:m+:d+:n+:a+"; opts = getopt32(argv, "m:d:n:N:s:a:t:", @@ -138,13 +150,6 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv) &vol_name, &size_bytes_str, &alignment, &type ); } -#define OPTION_m (1 << 0) -#define OPTION_d (1 << 1) -#define OPTION_n (1 << 2) -#define OPTION_N (1 << 3) -#define OPTION_s (1 << 4) -#define OPTION_a (1 << 5) -#define OPTION_t (1 << 6) if (opts & OPTION_s) size_bytes = xatoull_sfx(size_bytes_str, size_suffixes); @@ -302,9 +307,9 @@ int ubi_tools_main(int argc UNUSED_PARAM, char **argv) if (!(opts & OPTION_s)) { if (!*argv) bb_show_usage(); - xstat(*argv, &st); - size_bytes = st.st_size; xmove_fd(xopen(*argv, O_RDONLY), STDIN_FILENO); + xfstat(STDIN_FILENO, &st, *argv); + size_bytes = st.st_size; } bytes64 = size_bytes; -- cgit v1.2.3-55-g6feb From d3fe9602714e01b228fa0c625901e748912a7775 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sat, 27 Sep 2014 22:56:09 +0200 Subject: ntpd: be less eager to use shorter poll intervals * on step, poll interval drops to 8.5 mins instead of 32 seconds * on total loss of all replies (no replies from any peer for last 8 requests), also drop poll interval to 8.5 mins instead of 32 seconds * on send abd recv errors, RETRY_INTERVAL is now 32 seconds, not 5 seconds * on timing out listening to reply, instead of unconditional shortening poll interval by x4, clamp it to NOREPLY_INTERVAL (512 seconds) * if a largish offset is seen, clamp nexp poll interval to 128 seconds, not 64 seconds function old new delta clamp_pollexp_and_set_MAXSTRAT - 37 +37 recv_and_process_peer_pkt 861 869 +8 poll_interval 52 48 -4 update_local_clock 762 752 -10 ntpd_main 1063 1050 -13 ------------------------------------------------------------------------------ (add/remove: 1/0 grow/shrink: 1/3 up/down: 45/-27) Total: 18 bytes Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 80 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 39 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 2d1ad69a0..b2b2791a8 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -109,35 +109,43 @@ * datapoints after the step. */ -#define RETRY_INTERVAL 5 /* on error, retry in N secs */ -#define RESPONSE_INTERVAL 15 /* wait for reply up to N secs */ #define INITIAL_SAMPLES 4 /* how many samples do we want for init */ #define BAD_DELAY_GROWTH 4 /* drop packet if its delay grew by more than this */ -/* Clock discipline parameters and constants */ +#define RETRY_INTERVAL 32 /* on send/recv error, retry in N secs (need to be power of 2) */ +#define NOREPLY_INTERVAL 512 /* sent, but got no reply: cap next query by this many seconds */ +#define RESPONSE_INTERVAL 16 /* wait for reply up to N secs */ /* Step threshold (sec). std ntpd uses 0.128. - * Using exact power of 2 (1/8) results in smaller code */ + * Using exact power of 2 (1/8) results in smaller code + */ #define STEP_THRESHOLD 0.125 -#define WATCH_THRESHOLD 128 /* stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ +/* Stepout threshold (sec). std ntpd uses 900 (11 mins (!)) */ +#define WATCH_THRESHOLD 128 /* NB: set WATCH_THRESHOLD to ~60 when debugging to save time) */ //UNUSED: #define PANIC_THRESHOLD 1000 /* panic threshold (sec) */ +/* + * If we got |offset| > BIGOFF from a peer, cap next query interval + * for this peer by this many seconds: + */ +#define BIGOFF (STEP_THRESHOLD * 8) +#define BIGOFF_INTERVAL (1 << 7) /* 128 s */ + #define FREQ_TOLERANCE 0.000015 /* frequency tolerance (15 PPM) */ #define BURSTPOLL 0 /* initial poll */ #define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */ -/* If we got largish offset from a peer, cap next query interval - * for this peer by this many seconds: - */ -#define BIGOFF_INTERVAL (1 << 6) -/* If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL, +/* + * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL, * then it is decreased _at once_. (If < 2^BIGPOLL, it will be decreased _eventually_). */ #define BIGPOLL 10 /* 2^10 sec ~= 17 min */ #define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ -/* Actively lower poll when we see such big offsets. +/* + * Actively lower poll when we see such big offsets. * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively - * if offset increases over ~0.04 sec */ + * if offset increases over ~0.04 sec + */ #define POLLDOWN_OFFSET (STEP_THRESHOLD / 3) #define MINDISP 0.01 /* minimum dispersion (sec) */ #define MAXDISP 16 /* maximum dispersion (sec) */ @@ -972,6 +980,16 @@ step_time(double offset) } } +static void clamp_pollexp_and_set_MAXSTRAT(void) +{ + if (G.poll_exp < MINPOLL) + G.poll_exp = MINPOLL; + if (G.poll_exp >= BIGPOLL) + G.poll_exp = BIGPOLL - 1; + G.polladj_count = 0; + G.stratum = MAXSTRAT; +} + /* * Selection and clustering, and their helpers @@ -1453,9 +1471,7 @@ update_local_clock(peer_t *p) exit(0); } - G.polladj_count = 0; - G.poll_exp = MINPOLL; - G.stratum = MAXSTRAT; + clamp_pollexp_and_set_MAXSTRAT(); run_script("step", offset); @@ -1654,28 +1670,16 @@ update_local_clock(peer_t *p) * (helpers first) */ static unsigned -retry_interval(void) -{ - /* Local problem, want to retry soon */ - unsigned interval, r; - interval = RETRY_INTERVAL; - r = rand(); - interval += r % (unsigned)(RETRY_INTERVAL / 4); - VERB4 bb_error_msg("chose retry interval:%u", interval); - return interval; -} -static unsigned -poll_interval(int exponent) +poll_interval(int upper_bound) { unsigned interval, r, mask; - exponent = G.poll_exp + exponent; - if (exponent < 0) - exponent = 0; - interval = 1 << exponent; + interval = 1 << G.poll_exp; + if (interval > upper_bound) + interval = upper_bound; mask = ((interval-1) >> 4) | 1; r = rand(); interval += r & mask; /* ~ random(0..1) * interval/16 */ - VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d exp:%d)", interval, G.poll_exp, exponent); + VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d)", interval, G.poll_exp); return interval; } static NOINLINE void @@ -1741,7 +1745,7 @@ recv_and_process_peer_pkt(peer_t *p) || errno == EAGAIN ) { //TODO: always do this? - interval = retry_interval(); + interval = poll_interval(RETRY_INTERVAL); goto set_next_and_ret; } xfunc_die(); @@ -1897,8 +1901,8 @@ recv_and_process_peer_pkt(peer_t *p) /* Decide when to send new query for this peer */ pick_normal_interval: - interval = poll_interval(0); - if (fabs(offset) >= STEP_THRESHOLD * 8 && interval > BIGOFF_INTERVAL) { + interval = poll_interval(INT_MAX); + if (fabs(offset) >= BIGOFF && interval > BIGOFF_INTERVAL) { /* If we are synced, offsets are less than STEP_THRESHOLD, * or at the very least not much larger than it. * Now we see a largish one. @@ -2248,7 +2252,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) /* Timed out waiting for reply */ close(p->p_fd); p->p_fd = -1; - timeout = poll_interval(-2); /* -2: try a bit sooner */ + timeout = poll_interval(NOREPLY_INTERVAL); bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us", p->p_dotted, p->reachable_bits, timeout); set_next(p, timeout); @@ -2339,9 +2343,7 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) goto have_reachable_peer; } /* No peer responded for last 8 packets, panic */ - G.polladj_count = 0; - G.poll_exp = MINPOLL; - G.stratum = MAXSTRAT; + clamp_pollexp_and_set_MAXSTRAT(); run_script("unsync", 0.0); have_reachable_peer: ; } -- cgit v1.2.3-55-g6feb From cf76b5ce12a685b0c0a8ea53fa95cb0f0922a4f1 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 2 Oct 2014 13:45:21 +0200 Subject: getty: set tty attrs so that control chars are shown as ^c Signed-off-by: Denys Vlasenko --- loginutils/getty.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/loginutils/getty.c b/loginutils/getty.c index 4b1b73bef..174542841 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c @@ -334,18 +334,19 @@ static void finalize_tty_attrs(void) * observed to improve backspacing through Unicode chars */ - /* line buffered input (NL or EOL or EOF chars end a line); - * recognize INT/QUIT/SUSP chars; - * echo input chars; - * echo BS-SP-BS on erase character; - * echo kill char specially, not as ^c (ECHOKE controls how exactly); - * erase all input via BS-SP-BS on kill char (else go to next line) + /* ICANON line buffered input (NL or EOL or EOF chars end a line); + * ISIG recognize INT/QUIT/SUSP chars; + * ECHO echo input chars; + * ECHOE echo BS-SP-BS on erase character; + * ECHOK echo kill char specially, not as ^c (ECHOKE controls how exactly); + * ECHOKE erase all input via BS-SP-BS on kill char (else go to next line) + * ECHOCTL Echo ctrl chars as ^c (else echo verbatim: + * e.g. up arrow emits "ESC-something" and thus moves cursor up!) */ - G.tty_attrs.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE; + G.tty_attrs.c_lflag |= ICANON | ISIG | ECHO | ECHOE | ECHOK | ECHOKE | ECHOCTL; /* Other bits in c_lflag: * XCASE Map uppercase to \lowercase [tried, doesn't work] * ECHONL Echo NL even if ECHO is not set - * ECHOCTL Echo ctrl chars as ^c (else don't echo) - maybe set this? * ECHOPRT On erase, echo erased chars * [qwe input looks like "qwe\ewq/" on screen] * NOFLSH Don't flush input buffer after interrupt or quit chars -- cgit v1.2.3-55-g6feb From b434ce70696879aad066fff67253e44e5f5b238e Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Thu, 2 Oct 2014 17:18:43 +0200 Subject: ntpd: don't stay at short polling interval To avoid polling servers frequently slowly increase the interval up to BIGPOLL when - no replies are received from a peer - no source can be selected - peer claims to be unsynchronized (e.g. we are polling it too frequently) When recv() returns with an error, drop code to try to continue on network errors: I'm not convinced those cases happen in real life. function old new delta recv_and_process_peer_pkt 919 838 -81 Signed-off-by: Miroslav Lichvar Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 80 ++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 53 insertions(+), 27 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index b2b2791a8..838a367fe 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -136,17 +136,17 @@ #define BURSTPOLL 0 /* initial poll */ #define MINPOLL 5 /* minimum poll interval. std ntpd uses 6 (6: 64 sec) */ /* - * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is >= 2^BIGPOLL, - * then it is decreased _at once_. (If < 2^BIGPOLL, it will be decreased _eventually_). + * If offset > discipline_jitter * POLLADJ_GATE, and poll interval is > 2^BIGPOLL, + * then it is decreased _at once_. (If <= 2^BIGPOLL, it will be decreased _eventually_). */ -#define BIGPOLL 10 /* 2^10 sec ~= 17 min */ +#define BIGPOLL 9 /* 2^9 sec ~= 8.5 min */ #define MAXPOLL 12 /* maximum poll interval (12: 1.1h, 17: 36.4h). std ntpd uses 17 */ /* * Actively lower poll when we see such big offsets. * With STEP_THRESHOLD = 0.125, it means we try to sync more aggressively * if offset increases over ~0.04 sec */ -#define POLLDOWN_OFFSET (STEP_THRESHOLD / 3) +//#define POLLDOWN_OFFSET (STEP_THRESHOLD / 3) #define MINDISP 0.01 /* minimum dispersion (sec) */ #define MAXDISP 16 /* maximum dispersion (sec) */ #define MAXSTRAT 16 /* maximum stratum (infinity metric) */ @@ -984,8 +984,8 @@ static void clamp_pollexp_and_set_MAXSTRAT(void) { if (G.poll_exp < MINPOLL) G.poll_exp = MINPOLL; - if (G.poll_exp >= BIGPOLL) - G.poll_exp = BIGPOLL - 1; + if (G.poll_exp > BIGPOLL) + G.poll_exp = BIGPOLL; G.polladj_count = 0; G.stratum = MAXSTRAT; } @@ -1682,7 +1682,7 @@ poll_interval(int upper_bound) VERB4 bb_error_msg("chose poll interval:%u (poll_exp:%d)", interval, G.poll_exp); return interval; } -static NOINLINE void +static void adjust_poll(int count) { G.polladj_count += count; @@ -1693,7 +1693,7 @@ adjust_poll(int count) VERB4 bb_error_msg("polladj: discipline_jitter:%f ++poll_exp=%d", G.discipline_jitter, G.poll_exp); } - } else if (G.polladj_count < -POLLADJ_LIMIT || (count < 0 && G.poll_exp >= BIGPOLL)) { + } else if (G.polladj_count < -POLLADJ_LIMIT || (count < 0 && G.poll_exp > BIGPOLL)) { G.polladj_count = 0; if (G.poll_exp > MINPOLL) { llist_t *item; @@ -1736,19 +1736,23 @@ recv_and_process_peer_pkt(peer_t *p) * ntp servers reply from their *other IP*. * TODO: maybe we should check at least what we can: from.port == 123? */ + recv_again: size = recv(p->p_fd, &msg, sizeof(msg), MSG_DONTWAIT); - if (size == -1) { - bb_perror_msg("recv(%s) error", p->p_dotted); - if (errno == EHOSTUNREACH || errno == EHOSTDOWN - || errno == ENETUNREACH || errno == ENETDOWN - || errno == ECONNREFUSED || errno == EADDRNOTAVAIL - || errno == EAGAIN - ) { -//TODO: always do this? - interval = poll_interval(RETRY_INTERVAL); - goto set_next_and_ret; - } - xfunc_die(); + if (size < 0) { + if (errno == EINTR) + /* Signal caught */ + goto recv_again; + if (errno == EAGAIN) + /* There was no packet after all + * (poll() returning POLLIN for a fd + * is not a ironclad guarantee that data is there) + */ + return; + /* + * If you need a different handling for a specific + * errno, always explain it in comment. + */ + bb_perror_msg_and_die("recv(%s) error", p->p_dotted); } if (size != NTP_MSGSIZE_NOAUTH && size != NTP_MSGSIZE) { @@ -1774,10 +1778,15 @@ recv_and_process_peer_pkt(peer_t *p) || msg.m_stratum == 0 || msg.m_stratum > NTP_MAXSTRATUM ) { -// TODO: stratum 0 responses may have commands in 32-bit m_refid field: -// "DENY", "RSTR" - peer does not like us at all -// "RATE" - peer is overloaded, reduce polling freq bb_error_msg("reply from %s: peer is unsynced", p->p_dotted); + /* + * Stratum 0 responses may have commands in 32-bit m_refid field: + * "DENY", "RSTR" - peer does not like us at all, + * "RATE" - peer is overloaded, reduce polling freq. + * If poll interval is small, increase it. + */ + if (G.poll_exp < BIGPOLL) + goto increase_interval; goto pick_normal_interval; } @@ -1866,11 +1875,19 @@ recv_and_process_peer_pkt(peer_t *p) /* Muck with statictics and update the clock */ filter_datapoints(p); q = select_and_cluster(); - rc = -1; + rc = 0; if (q) { - rc = 0; if (!(option_mask32 & OPT_w)) { rc = update_local_clock(q); +#if 0 +//Disabled this because there is a case where largish offsets +//are unavoidable: if network round-trip delay is, say, ~0.6s, +//error in offset estimation would be ~delay/2 ~= 0.3s. +//Thus, offsets will be usually in -0.3...0.3s range. +//In this case, this code would keep poll interval small, +//but it won't be helping. +//BIGOFF check below deals with a case of seeing multi-second offsets. + /* If drift is dangerously large, immediately * drop poll interval one step down. */ @@ -1879,9 +1896,15 @@ recv_and_process_peer_pkt(peer_t *p) adjust_poll(-POLLADJ_LIMIT * 3); rc = 0; } +#endif } + } else { + /* No peer selected. + * If poll interval is small, increase it. + */ + if (G.poll_exp < BIGPOLL) + goto increase_interval; } - /* else: no peer selected, rc = -1: we want to poll more often */ if (rc != 0) { /* Adjust the poll interval by comparing the current offset @@ -1893,6 +1916,7 @@ recv_and_process_peer_pkt(peer_t *p) if (rc > 0 && G.offset_to_jitter_ratio <= POLLADJ_GATE) { /* was += G.poll_exp but it is a bit * too optimistic for my taste at high poll_exp's */ + increase_interval: adjust_poll(MINPOLL); } else { adjust_poll(-G.poll_exp * 2); @@ -1917,7 +1941,6 @@ recv_and_process_peer_pkt(peer_t *p) interval = BIGOFF_INTERVAL; } - set_next_and_ret: set_next(p, interval); } @@ -2252,6 +2275,9 @@ int ntpd_main(int argc UNUSED_PARAM, char **argv) /* Timed out waiting for reply */ close(p->p_fd); p->p_fd = -1; + /* If poll interval is small, increase it */ + if (G.poll_exp < BIGPOLL) + adjust_poll(MINPOLL); timeout = poll_interval(NOREPLY_INTERVAL); bb_error_msg("timed out waiting for %s, reach 0x%02x, next query in %us", p->p_dotted, p->reachable_bits, timeout); -- cgit v1.2.3-55-g6feb From cd738711782d5860eeab4e7cefdd1f72dfb83810 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Sun, 5 Oct 2014 02:44:34 +0200 Subject: sed: fix "sed CMD -i nonexistent_file". Closes 7484 function old new delta sed_main 643 676 +33 Signed-off-by: Denys Vlasenko --- editors/sed.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/editors/sed.c b/editors/sed.c index e1b8352fd..2c64ad500 100644 --- a/editors/sed.c +++ b/editors/sed.c @@ -1522,12 +1522,16 @@ int sed_main(int argc UNUSED_PARAM, char **argv) /* -i: process each FILE separately: */ + if (stat(*argv, &statbuf) != 0) { + bb_simple_perror_msg(*argv); + G.exitcode = EXIT_FAILURE; + G.current_input_file++; + continue; + } G.outname = xasprintf("%sXXXXXX", *argv); nonstdoutfd = xmkstemp(G.outname); G.nonstdout = xfdopen_for_write(nonstdoutfd); - /* Set permissions/owner of output file */ - stat(*argv, &statbuf); /* chmod'ing AFTER chown would preserve suid/sgid bits, * but GNU sed 4.2.1 does not preserve them either */ fchmod(nonstdoutfd, statbuf.st_mode); -- cgit v1.2.3-55-g6feb From 760d035699c4a878f9109544c1d35ea0d5f6b76c Mon Sep 17 00:00:00 2001 From: Miroslav Lichvar Date: Sun, 5 Oct 2014 03:10:15 +0200 Subject: ntpd: calculate offset to jitter ratio before updating jitter The offset to jitter ratio is now calculated before updating jitter to make the test more sensitive. function old new delta ntp_init 460 474 +14 update_local_clock 752 764 +12 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 26/0) Total: 26 bytes Signed-off-by: Miroslav Lichvar Signed-off-by: Denys Vlasenko --- networking/ntpd.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/networking/ntpd.c b/networking/ntpd.c index 838a367fe..2d4f076d9 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -1488,12 +1488,19 @@ update_local_clock(peer_t *p) } else { /* abs_offset <= STEP_THRESHOLD */ + /* The ratio is calculated before jitter is updated to make + * poll adjust code more sensitive to large offsets. + */ + G.offset_to_jitter_ratio = abs_offset / G.discipline_jitter; + /* Compute the clock jitter as the RMS of exponentially * weighted offset differences. Used by the poll adjust code. */ etemp = SQUARE(G.discipline_jitter); dtemp = SQUARE(offset - G.last_update_offset); G.discipline_jitter = SQRT(etemp + (dtemp - etemp) / AVG); + if (G.discipline_jitter < G_precision_sec) + G.discipline_jitter = G_precision_sec; switch (G.discipline_state) { case STATE_NSET: @@ -1570,10 +1577,6 @@ update_local_clock(peer_t *p) } } - if (G.discipline_jitter < G_precision_sec) - G.discipline_jitter = G_precision_sec; - G.offset_to_jitter_ratio = abs_offset / G.discipline_jitter; - G.reftime = G.cur_time; G.ntp_status = p->lastpkt_status; G.refid = p->lastpkt_refid; @@ -2111,6 +2114,7 @@ static NOINLINE void ntp_init(char **argv) bb_error_msg_and_die(bb_msg_you_must_be_root); /* Set some globals */ + G.discipline_jitter = G_precision_sec; G.stratum = MAXSTRAT; if (BURSTPOLL != 0) G.poll_exp = BURSTPOLL; /* speeds up initial sync */ -- cgit v1.2.3-55-g6feb