From aca464ddac4b86211f138203c4a1d1e3c69a2230 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 13 Sep 2012 13:00:49 +0200 Subject: telnet: convert CR -> CR LF, not CR -> CR NUL when sending data to server Signed-off-by: Denys Vlasenko --- networking/telnet.c | 22 +++++----------------- networking/telnetd.c | 1 + 2 files changed, 6 insertions(+), 17 deletions(-) diff --git a/networking/telnet.c b/networking/telnet.c index e8e51dce4..7081a6a41 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -186,22 +186,6 @@ static void con_escape(void) static void handle_net_output(int len) { - /* here we could do smart tricks how to handle 0xFF:s in output - * stream like writing twice every sequence of FF:s (thus doing - * many write()s. But I think interactive telnet application does - * not need to be 100% 8-bit clean, so changing every 0xff:s to - * 0x7f:s - * - * 2002-mar-21, Przemyslaw Czerpak (druzus@polbox.com) - * I don't agree. - * first - I cannot use programs like sz/rz - * second - the 0x0D is sent as one character and if the next - * char is 0x0A then it's eaten by a server side. - * third - why do you have to make 'many write()s'? - * I don't understand. - * So I implemented it. It's really useful for me. I hope that - * other people will find it interesting too. - */ byte outbuf[2 * DATABUFSIZE]; byte *p = (byte*)G.buf; int j = 0; @@ -216,7 +200,11 @@ static void handle_net_output(int len) if (c == IAC) outbuf[j++] = c; /* IAC -> IAC IAC */ else if (c == '\r') - outbuf[j++] = '\0'; /* CR -> CR NUL */ + /* See RFC 1123 3.3.1 Telnet End-of-Line Convention. + * Using CR LF instead of other allowed possibilities + * like CR NUL - easier to talk to HTTP/SMTP servers. + */ + outbuf[j++] = '\n'; /* CR -> CR LF */ } if (j > 0) full_write(netfd, outbuf, j); diff --git a/networking/telnetd.c b/networking/telnetd.c index 33020f1b4..9e7a84cce 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c @@ -125,6 +125,7 @@ remove_iacs(struct tsession *ts, int *pnum_totty) /* We map \r\n ==> \r for pragmatic reasons. * Many client implementations send \r\n when * the user hits the CarriageReturn key. + * See RFC 1123 3.3.1 Telnet End-of-Line Convention. */ if (c == '\r' && ptr < end && (*ptr == '\n' || *ptr == '\0')) ptr++; -- cgit v1.2.3-55-g6feb From 57f07bfcb276777f9ea85df7d09ae005a0231464 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Sep 2012 11:53:09 +0200 Subject: telnet: shrink literal string size text data bss dec hex filename 888483 497 7584 896564 dae34 busybox_old 888450 497 7584 896531 dae13 busybox_unstripped Signed-off-by: Denys Vlasenko --- networking/telnet.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/telnet.c b/networking/telnet.c index 7081a6a41..b700fbed9 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -386,20 +386,20 @@ static void put_iac_naws(byte c, int x, int y) } #endif -static char const escapecharis[] ALIGN1 = "\r\nEscape character is "; - static void setConMode(void) { if (G.telflags & UF_ECHO) { if (G.charmode == CHM_TRY) { G.charmode = CHM_ON; - printf("\r\nEntering character mode%s'^]'.\r\n", escapecharis); + printf("\r\nEntering %s mode" + "\r\nEscape character is '^%c'.\r\n", "character", ']'); rawmode(); } } else { if (G.charmode != CHM_OFF) { G.charmode = CHM_OFF; - printf("\r\nEntering line mode%s'^C'.\r\n", escapecharis); + printf("\r\nEntering %s mode" + "\r\nEscape character is '^%c'.\r\n", "line", 'C'); cookmode(); } } -- cgit v1.2.3-55-g6feb From 0ffd63ca9a46d1e9112e12702e4337195eade25d Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 17 Sep 2012 11:54:35 +0200 Subject: telnet: convert Enter -> CR LF in line mode too function old new delta handle_net_output 87 98 +11 Signed-off-by: Denys Vlasenko --- networking/telnet.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/networking/telnet.c b/networking/telnet.c index b700fbed9..58a691916 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -187,27 +187,34 @@ static void con_escape(void) static void handle_net_output(int len) { byte outbuf[2 * DATABUFSIZE]; - byte *p = (byte*)G.buf; - int j = 0; + byte *dst = outbuf; + byte *src = (byte*)G.buf; + byte *end = src + len; - for (; len > 0; len--, p++) { - byte c = *p; + while (src < end) { + byte c = *src++; if (c == 0x1d) { con_escape(); return; } - outbuf[j++] = c; + *dst = c; if (c == IAC) - outbuf[j++] = c; /* IAC -> IAC IAC */ - else if (c == '\r') - /* See RFC 1123 3.3.1 Telnet End-of-Line Convention. + *++dst = c; /* IAC -> IAC IAC */ + else + if (c == '\r' || c == '\n') { + /* Enter key sends '\r' in raw mode and '\n' in cooked one. + * + * See RFC 1123 3.3.1 Telnet End-of-Line Convention. * Using CR LF instead of other allowed possibilities * like CR NUL - easier to talk to HTTP/SMTP servers. */ - outbuf[j++] = '\n'; /* CR -> CR LF */ + *dst = '\r'; /* Enter -> CR LF */ + *++dst = '\n'; + } + dst++; } - if (j > 0) - full_write(netfd, outbuf, j); + if (dst - outbuf != 0) + full_write(netfd, outbuf, dst - outbuf); } static void handle_net_input(int len) -- cgit v1.2.3-55-g6feb From 3c62bbae94642e6d05bc9f900bbdb5173d26cc51 Mon Sep 17 00:00:00 2001 From: Alexey Froloff Date: Mon, 17 Sep 2012 16:02:44 +0200 Subject: ushcpc: gracefully handle packets with CHECKSUM_PARTIAL function old new delta udhcp_recv_raw_packet 415 579 +164 change_listen_mode 317 370 +53 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/0 up/down: 217/0) Total: 217 bytes Signed-off-by: Alexey Froloff Signed-off-by: Denys Vlasenko --- networking/udhcp/dhcpc.c | 57 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index bc1db7087..dcb7d42dc 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -26,8 +26,8 @@ #include "dhcpc.h" #include -#include #include +#include /* "struct client_config_t client_config" is in bb_common_bufsiz1 */ @@ -836,12 +836,31 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) int bytes; struct ip_udp_dhcp_packet packet; uint16_t check; + unsigned char cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))]; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; - bytes = safe_read(fd, &packet, sizeof(packet)); - if (bytes < 0) { - log1("Packet read error, ignoring"); - /* NB: possible down interface, etc. Caller should pause. */ - return bytes; /* returns -1 */ + /* used to use just safe_read(fd, &packet, sizeof(packet)) + * but we need to check for TP_STATUS_CSUMNOTREADY :( + */ + iov.iov_base = &packet; + iov.iov_len = sizeof(packet); + memset(&msg, 0, sizeof(msg)); + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); + for (;;) { + bytes = recvmsg(fd, &msg, 0); + if (bytes < 0) { + if (errno == EINTR) + continue; + log1("Packet read error, ignoring"); + /* NB: possible down interface, etc. Caller should pause. */ + return bytes; /* returns -1 */ + } + break; } if (bytes < (int) (sizeof(packet.ip) + sizeof(packet.udp))) { @@ -878,6 +897,20 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) return -2; } + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + if (cmsg->cmsg_level == SOL_PACKET + && cmsg->cmsg_type == PACKET_AUXDATA + ) { + /* some VMs don't checksum UDP and TCP data + * they send to the same physical machine, + * here we detect this case: + */ + struct tpacket_auxdata *aux = (void *)CMSG_DATA(cmsg); + if (aux->tp_status & TP_STATUS_CSUMNOTREADY) + goto skip_udp_sum_check; + } + } + /* verify UDP checksum. IP header has to be modified for this */ memset(&packet.ip, 0, offsetof(struct iphdr, protocol)); /* ip.xx fields which are not memset: protocol, check, saddr, daddr */ @@ -888,6 +921,7 @@ static NOINLINE int udhcp_recv_raw_packet(struct dhcp_packet *dhcp_pkt, int fd) log1("Packet with bad UDP checksum received, ignoring"); return -2; } + skip_udp_sum_check: if (packet.data.cookie != htonl(DHCP_MAGIC)) { bb_info_msg("Packet with bad magic, ignoring"); @@ -983,7 +1017,7 @@ static int udhcp_raw_socket(int ifindex) log1("Opening raw socket on ifindex %d", ifindex); //log2? fd = xsocket(PF_PACKET, SOCK_DGRAM, htons(ETH_P_IP)); - log1("Got raw socket fd %d", fd); //log2? + log1("Got raw socket fd"); //log2? sock.sll_family = AF_PACKET; sock.sll_protocol = htons(ETH_P_IP); @@ -995,7 +1029,14 @@ static int udhcp_raw_socket(int ifindex) /* Ignoring error (kernel may lack support for this) */ if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &filter_prog, sizeof(filter_prog)) >= 0) - log1("Attached filter to raw socket fd %d", fd); // log? + log1("Attached filter to raw socket fd"); // log? + } + + if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, + &const_int_1, sizeof(int)) < 0 + ) { + if (errno != ENOPROTOOPT) + log1("Can't set PACKET_AUXDATA on raw socket"); } log1("Created raw socket"); -- cgit v1.2.3-55-g6feb From 2fb8d0dee974622c52e446a02d066cccc4768bbf Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 21 Sep 2012 13:04:37 +0200 Subject: top: implement scrolling up/down (_very_ useful) function old new delta handle_input 494 564 +70 top_main 928 947 +19 display_topmem_process_list 363 381 +18 display_process_list 1442 1453 +11 clearmems 38 28 -10 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 4/1 up/down: 118/-10) Total: 108 bytes Signed-off-by: Denys Vlasenko --- procps/Config.src | 54 ----------------------- procps/top.c | 130 +++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 110 insertions(+), 74 deletions(-) diff --git a/procps/Config.src b/procps/Config.src index 5cd47c84f..527d9ee0c 100644 --- a/procps/Config.src +++ b/procps/Config.src @@ -140,60 +140,6 @@ config BB_SYSCTL help Configure kernel parameters at runtime. -config TOP - bool "top" - default y - help - The top program provides a dynamic real-time view of a running - system. - -config FEATURE_TOP_CPU_USAGE_PERCENTAGE - bool "Show CPU per-process usage percentage" - default y - depends on TOP - help - Make top display CPU usage for each process. - This adds about 2k. - -config FEATURE_TOP_CPU_GLOBAL_PERCENTS - bool "Show CPU global usage percentage" - default y - depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE - help - Makes top display "CPU: NN% usr NN% sys..." line. - This adds about 0.5k. - -config FEATURE_TOP_SMP_CPU - bool "SMP CPU usage display ('c' key)" - default y - depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS - help - Allow 'c' key to switch between individual/cumulative CPU stats - This adds about 0.5k. - -config FEATURE_TOP_DECIMALS - bool "Show 1/10th of a percent in CPU/mem statistics" - default y - depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE - help - Show 1/10th of a percent in CPU/mem statistics. - This adds about 0.3k. - -config FEATURE_TOP_SMP_PROCESS - bool "Show CPU process runs on ('j' field)" - default y - depends on TOP - help - Show CPU where process was last found running on. - This is the 'j' field. - -config FEATURE_TOPMEM - bool "Topmem command ('s' key)" - default y - depends on TOP - help - Enable 's' in top (gives lots of memory info). - config FEATURE_SHOW_THREADS bool "Support for showing threads in ps/pstree/top" default y diff --git a/procps/top.c b/procps/top.c index 15eb624cc..00cb44896 100644 --- a/procps/top.c +++ b/procps/top.c @@ -50,6 +50,60 @@ * chroot . ./top -bn1 >top1.out */ +//config:config TOP +//config: bool "top" +//config: default y +//config: help +//config: The top program provides a dynamic real-time view of a running +//config: system. +//config: +//config:config FEATURE_TOP_CPU_USAGE_PERCENTAGE +//config: bool "Show CPU per-process usage percentage" +//config: default y +//config: depends on TOP +//config: help +//config: Make top display CPU usage for each process. +//config: This adds about 2k. +//config: +//config:config FEATURE_TOP_CPU_GLOBAL_PERCENTS +//config: bool "Show CPU global usage percentage" +//config: default y +//config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE +//config: help +//config: Makes top display "CPU: NN% usr NN% sys..." line. +//config: This adds about 0.5k. +//config: +//config:config FEATURE_TOP_SMP_CPU +//config: bool "SMP CPU usage display ('c' key)" +//config: default y +//config: depends on FEATURE_TOP_CPU_GLOBAL_PERCENTS +//config: help +//config: Allow 'c' key to switch between individual/cumulative CPU stats +//config: This adds about 0.5k. +//config: +//config:config FEATURE_TOP_DECIMALS +//config: bool "Show 1/10th of a percent in CPU/mem statistics" +//config: default y +//config: depends on FEATURE_TOP_CPU_USAGE_PERCENTAGE +//config: help +//config: Show 1/10th of a percent in CPU/mem statistics. +//config: This adds about 0.3k. +//config: +//config:config FEATURE_TOP_SMP_PROCESS +//config: bool "Show CPU process runs on ('j' field)" +//config: default y +//config: depends on TOP +//config: help +//config: Show CPU where process was last found running on. +//config: This is the 'j' field. +//config: +//config:config FEATURE_TOPMEM +//config: bool "Topmem command ('s' key)" +//config: default y +//config: depends on TOP +//config: help +//config: Enable 's' in top (gives lots of memory info). + #include "libbb.h" @@ -101,6 +155,8 @@ struct globals { #endif #if ENABLE_FEATURE_USE_TERMIOS struct termios initial_settings; + unsigned lines; /* screen height */ + int scroll_ofs; #endif #if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE cmp_funcp sort_function[1]; @@ -117,6 +173,9 @@ struct globals { /* Per CPU samples: current and last */ jiffy_counts_t *cpu_jif, *cpu_prev_jif; int num_cpus; +#endif +#if ENABLE_FEATURE_USE_TERMIOS + char kbd_input[KEYCODE_BUFFER_SIZE]; #endif char line_buf[80]; }; //FIX_ALIASING; - large code growth @@ -602,9 +661,9 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) /* Ok, all preliminary data is ready, go through the list */ scr_width += 2; /* account for leading '\n' and trailing NUL */ - if (lines_rem > ntop) - lines_rem = ntop; - s = top; + if (lines_rem > ntop - G.scroll_ofs) + lines_rem = ntop - G.scroll_ofs; + s = top + G.scroll_ofs; while (--lines_rem >= 0) { unsigned col; CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); @@ -649,7 +708,6 @@ static void clearmems(void) clear_username_cache(); free(top); top = NULL; - ntop = 0; } #if ENABLE_FEATURE_USE_TERMIOS @@ -793,7 +851,7 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width) { #define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" #define MIN_WIDTH sizeof(HDR_STR) - const topmem_status_t *s = topmem; + const topmem_status_t *s = topmem + G.scroll_ofs; display_topmem_header(scr_width, &lines_rem); strcpy(line_buf, HDR_STR " COMMAND"); @@ -801,8 +859,8 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width) printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf); lines_rem--; - if (lines_rem > ntop) - lines_rem = ntop; + if (lines_rem > ntop - G.scroll_ofs) + lines_rem = ntop - G.scroll_ofs; while (--lines_rem >= 0) { /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */ ulltoa6_and_space(s->pid , &line_buf[0*6]); @@ -856,26 +914,57 @@ enum { #if ENABLE_FEATURE_USE_TERMIOS static unsigned handle_input(unsigned scan_mask, unsigned interval) { - unsigned char c; struct pollfd pfd[1]; pfd[0].fd = 0; pfd[0].events = POLLIN; while (1) { - if (safe_poll(pfd, 1, interval * 1000) <= 0) - return scan_mask; - interval = 0; + int32_t c; - if (safe_read(STDIN_FILENO, &c, 1) != 1) { /* error/EOF? */ + c = read_key(STDIN_FILENO, G.kbd_input, interval * 1000); + if (c == -1 && errno != EAGAIN) { + /* error/EOF */ option_mask32 |= OPT_EOF; - return scan_mask; + break; } + interval = 0; if (c == initial_settings.c_cc[VINTR]) return EXIT_MASK; if (c == initial_settings.c_cc[VEOF]) return EXIT_MASK; + + if (c == KEYCODE_UP) { + G.scroll_ofs--; + goto normalize_ofs; + } + if (c == KEYCODE_DOWN) { + G.scroll_ofs++; + goto normalize_ofs; + } + if (c == KEYCODE_HOME) { + G.scroll_ofs = 0; + break; + } + if (c == KEYCODE_END) { + G.scroll_ofs = ntop - G.lines / 2; + goto normalize_ofs; + } + if (c == KEYCODE_PAGEUP) { + G.scroll_ofs -= G.lines / 2; + goto normalize_ofs; + } + if (c == KEYCODE_PAGEDOWN) { + G.scroll_ofs += G.lines / 2; + normalize_ofs: + if (G.scroll_ofs >= ntop) + G.scroll_ofs = ntop - 1; + if (G.scroll_ofs < 0) + G.scroll_ofs = 0; + break; + } + c |= 0x20; /* lowercase */ if (c == 'q') return EXIT_MASK; @@ -1011,7 +1100,7 @@ int top_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int top_main(int argc UNUSED_PARAM, char **argv) { int iterations; - unsigned lines, col; + unsigned col; unsigned interval; char *str_interval, *str_iterations; unsigned scan_mask = TOP_MASK; @@ -1081,15 +1170,15 @@ int top_main(int argc UNUSED_PARAM, char **argv) procps_status_t *p = NULL; if (OPT_BATCH_MODE) { - lines = INT_MAX; + G.lines = INT_MAX; col = LINE_BUF_SIZE - 2; /* +2 bytes for '\n', NUL */ } else { - lines = 24; /* default */ + G.lines = 24; /* default */ col = 79; #if ENABLE_FEATURE_USE_TERMIOS /* We output to stdout, we need size of stdout (not stdin)! */ - get_terminal_width_height(STDOUT_FILENO, &col, &lines); - if (lines < 5 || col < 10) { + get_terminal_width_height(STDOUT_FILENO, &col, &G.lines); + if (G.lines < 5 || col < 10) { sleep(interval); continue; } @@ -1099,6 +1188,7 @@ int top_main(int argc UNUSED_PARAM, char **argv) } /* read process IDs & status for all the processes */ + ntop = 0; while ((p = procps_scan(p, scan_mask)) != NULL) { int n; #if ENABLE_FEATURE_TOPMEM @@ -1165,10 +1255,10 @@ int top_main(int argc UNUSED_PARAM, char **argv) } #endif if (scan_mask != TOPMEM_MASK) - display_process_list(lines, col); + display_process_list(G.lines, col); #if ENABLE_FEATURE_TOPMEM else - display_topmem_process_list(lines, col); + display_topmem_process_list(G.lines, col); #endif clearmems(); if (iterations >= 0 && !--iterations) -- cgit v1.2.3-55-g6feb From 42be921d486ee0fb43e982341cd54c41f15f55ee Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Sep 2012 12:48:10 +0200 Subject: ps: fix build failure in !DESKTOP case Signed-off-by: Denys Vlasenko --- procps/ps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/procps/ps.c b/procps/ps.c index 3a5af7c18..efc087ee5 100644 --- a/procps/ps.c +++ b/procps/ps.c @@ -655,9 +655,9 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) time_t now = now; long uptime; #endif - int opts = 0; /* If we support any options, parse argv */ #if ENABLE_SELINUX || ENABLE_FEATURE_SHOW_THREADS || ENABLE_FEATURE_PS_WIDE || ENABLE_FEATURE_PS_LONG + int opts = 0; # if ENABLE_FEATURE_PS_WIDE /* -w is a bit complicated */ int w_count = 0; @@ -711,10 +711,10 @@ int ps_main(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) * We also show STIME (standard says that -f shows it, -l doesn't). */ puts("S UID PID PPID VSZ RSS TTY STIME TIME CMD"); -#if ENABLE_FEATURE_PS_LONG +# if ENABLE_FEATURE_PS_LONG now = time(NULL); uptime = get_uptime(); -#endif +# endif } else { puts(" PID USER VSZ STAT COMMAND"); -- cgit v1.2.3-55-g6feb From ffe03f04cb44f1ef606de4997c3032995b20518f Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Sep 2012 12:48:46 +0200 Subject: top: fix build failure in !USE_TERMIOS case Signed-off-by: Denys Vlasenko --- procps/top.c | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/procps/top.c b/procps/top.c index 00cb44896..dc5ea7360 100644 --- a/procps/top.c +++ b/procps/top.c @@ -153,10 +153,13 @@ struct globals { #if ENABLE_FEATURE_TOP_SMP_CPU smallint smp_cpu_info; /* one/many cpu info lines? */ #endif + unsigned lines; /* screen height */ #if ENABLE_FEATURE_USE_TERMIOS struct termios initial_settings; - unsigned lines; /* screen height */ int scroll_ofs; +#define G_scroll_ofs G.scroll_ofs +#else +#define G_scroll_ofs 0 #endif #if !ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE cmp_funcp sort_function[1]; @@ -661,9 +664,9 @@ static NOINLINE void display_process_list(int lines_rem, int scr_width) /* Ok, all preliminary data is ready, go through the list */ scr_width += 2; /* account for leading '\n' and trailing NUL */ - if (lines_rem > ntop - G.scroll_ofs) - lines_rem = ntop - G.scroll_ofs; - s = top + G.scroll_ofs; + if (lines_rem > ntop - G_scroll_ofs) + lines_rem = ntop - G_scroll_ofs; + s = top + G_scroll_ofs; while (--lines_rem >= 0) { unsigned col; CALC_STAT(pmem, (s->vsz*pmem_scale + pmem_half) >> pmem_shift); @@ -851,7 +854,7 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width) { #define HDR_STR " PID VSZ VSZRW RSS (SHR) DIRTY (SHR) STACK" #define MIN_WIDTH sizeof(HDR_STR) - const topmem_status_t *s = topmem + G.scroll_ofs; + const topmem_status_t *s = topmem + G_scroll_ofs; display_topmem_header(scr_width, &lines_rem); strcpy(line_buf, HDR_STR " COMMAND"); @@ -859,8 +862,8 @@ static NOINLINE void display_topmem_process_list(int lines_rem, int scr_width) printf(OPT_BATCH_MODE ? "%.*s" : "\e[7m%.*s\e[0m", scr_width, line_buf); lines_rem--; - if (lines_rem > ntop - G.scroll_ofs) - lines_rem = ntop - G.scroll_ofs; + if (lines_rem > ntop - G_scroll_ofs) + lines_rem = ntop - G_scroll_ofs; while (--lines_rem >= 0) { /* PID VSZ VSZRW RSS (SHR) DIRTY (SHR) COMMAND */ ulltoa6_and_space(s->pid , &line_buf[0*6]); @@ -936,32 +939,32 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval) return EXIT_MASK; if (c == KEYCODE_UP) { - G.scroll_ofs--; + G_scroll_ofs--; goto normalize_ofs; } if (c == KEYCODE_DOWN) { - G.scroll_ofs++; + G_scroll_ofs++; goto normalize_ofs; } if (c == KEYCODE_HOME) { - G.scroll_ofs = 0; + G_scroll_ofs = 0; break; } if (c == KEYCODE_END) { - G.scroll_ofs = ntop - G.lines / 2; + G_scroll_ofs = ntop - G.lines / 2; goto normalize_ofs; } if (c == KEYCODE_PAGEUP) { - G.scroll_ofs -= G.lines / 2; + G_scroll_ofs -= G.lines / 2; goto normalize_ofs; } if (c == KEYCODE_PAGEDOWN) { - G.scroll_ofs += G.lines / 2; + G_scroll_ofs += G.lines / 2; normalize_ofs: - if (G.scroll_ofs >= ntop) - G.scroll_ofs = ntop - 1; - if (G.scroll_ofs < 0) - G.scroll_ofs = 0; + if (G_scroll_ofs >= ntop) + G_scroll_ofs = ntop - 1; + if (G_scroll_ofs < 0) + G_scroll_ofs = 0; break; } -- cgit v1.2.3-55-g6feb From 0b4980c2527552594d4f540ebc6e6cfb398895b3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Sep 2012 12:49:29 +0200 Subject: ash: trivial fixes for compile failures Signed-off-by: Denys Vlasenko --- shell/ash.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index 153bcc057..d42316a88 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -6338,7 +6338,8 @@ subevalvar(char *p, char *varname, int strloc, int subtype, IF_ASH_BASH_COMPAT(const char *repl = NULL;) IF_ASH_BASH_COMPAT(int pos, len, orig_len;) int saveherefd = herefd; - int amount, workloc, resetloc; + int amount, resetloc; + IF_ASH_BASH_COMPAT(int workloc;) int zero; char *(*scan)(char*, char*, char*, char*, int, int); @@ -6451,9 +6452,9 @@ subevalvar(char *p, char *varname, int strloc, int subtype, rmescend--; str = (char *)stackblock() + strloc; preglob(str, varflags & VSQUOTE, 0); - workloc = expdest - (char *)stackblock(); #if ENABLE_ASH_BASH_COMPAT + workloc = expdest - (char *)stackblock(); if (subtype == VSREPLACE || subtype == VSREPLACEALL) { char *idx, *end; @@ -9310,11 +9311,11 @@ evalcommand(union node *cmd, int flags) /* Now locate the command. */ if (argc) { - const char *oldpath; int cmd_flag = DO_ERR; - +#if ENABLE_ASH_CMDCMD + const char *oldpath = path + 5; +#endif path += 5; - oldpath = path; for (;;) { find_command(argv[0], &cmdentry, cmd_flag, path); if (cmdentry.cmdtype == CMDUNKNOWN) { -- cgit v1.2.3-55-g6feb From 06a98e32ae930a4e332281b42b6bb769dcadc04e Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 25 Sep 2012 20:37:38 +0200 Subject: modprobe_small: make rmmod to NOT remove dependencies. Closes 5162 Signed-off-by: Denys Vlasenko --- modutils/modprobe-small.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/modutils/modprobe-small.c b/modutils/modprobe-small.c index bd855f628..5b7836344 100644 --- a/modutils/modprobe-small.c +++ b/modutils/modprobe-small.c @@ -594,11 +594,18 @@ static void process_module(char *name, const char *cmdline_options) bb_perror_msg("remove '%s'", name); goto ret; } - /* N.B. we do not stop here - + + if (applet_name[0] == 'r') { + /* rmmod: do not remove dependencies, exit */ + goto ret; + } + + /* modprobe -r: we do not stop here - * continue to unload modules on which the module depends: * "-r --remove: option causes modprobe to remove a module. * If the modules it depends on are also unused, modprobe - * will try to remove them, too." */ + * will try to remove them, too." + */ } if (!info) { -- cgit v1.2.3-55-g6feb From 73a19908975948154d1a07c3550592059238e9ef Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 26 Sep 2012 16:58:25 +0200 Subject: top: do not touch stdin if -b Signed-off-by: Denys Vlasenko --- procps/top.c | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/procps/top.c b/procps/top.c index dc5ea7360..1977fcafc 100644 --- a/procps/top.c +++ b/procps/top.c @@ -717,7 +717,8 @@ static void clearmems(void) static void reset_term(void) { - tcsetattr_stdin_TCSANOW(&initial_settings); + if (!OPT_BATCH_MODE) + tcsetattr_stdin_TCSANOW(&initial_settings); if (ENABLE_FEATURE_CLEAN_UP) { clearmems(); # if ENABLE_FEATURE_TOP_CPU_USAGE_PERCENTAGE @@ -729,7 +730,7 @@ static void reset_term(void) static void sig_catcher(int sig UNUSED_PARAM) { reset_term(); - _exit(EXIT_FAILURE); + kill_myself_with_sig(sig); } #endif /* FEATURE_USE_TERMIOS */ @@ -919,6 +920,12 @@ static unsigned handle_input(unsigned scan_mask, unsigned interval) { struct pollfd pfd[1]; + if (option_mask32 & OPT_EOF) { + /* EOF on stdin ("top Date: Thu, 27 Sep 2012 13:20:34 +0200 Subject: libbb: correctness/size tweaks in signal-related helpers Signed-off-by: Denys Vlasenko --- libbb/signals.c | 6 +++--- procps/top.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/libbb/signals.c b/libbb/signals.c index cdc37b1ef..56512473a 100644 --- a/libbb/signals.c +++ b/libbb/signals.c @@ -39,7 +39,7 @@ void FAST_FUNC bb_signals(int sigs, void (*f)(int)) while (sigs) { if (sigs & bit) { - sigs &= ~bit; + sigs -= bit; signal(sig_no, f); } sig_no++; @@ -60,7 +60,7 @@ void FAST_FUNC bb_signals_recursive_norestart(int sigs, void (*f)(int)) while (sigs) { if (sigs & bit) { - sigs &= ~bit; + sigs -= bit; sigaction_set(sig_no, &sa); } sig_no++; @@ -97,7 +97,7 @@ void FAST_FUNC kill_myself_with_sig(int sig) signal(sig, SIG_DFL); sig_unblock(sig); raise(sig); - _exit(EXIT_FAILURE); /* Should not reach it */ + _exit(sig | 128); /* Should not reach it */ } void FAST_FUNC signal_SA_RESTART_empty_mask(int sig, void (*handler)(int)) diff --git a/procps/top.c b/procps/top.c index 1977fcafc..b08444a76 100644 --- a/procps/top.c +++ b/procps/top.c @@ -727,7 +727,7 @@ static void reset_term(void) } } -static void sig_catcher(int sig UNUSED_PARAM) +static void sig_catcher(int sig) { reset_term(); kill_myself_with_sig(sig); -- cgit v1.2.3-55-g6feb From 225cc1327a9a3786d0c5317ea1a8342f8c04f0d8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Sep 2012 15:26:40 +0200 Subject: scripts/kconfig/mconf: work on systems w/o SIGWINCH Signed-off-by: Denys Vlasenko --- scripts/kconfig/mconf.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/scripts/kconfig/mconf.c b/scripts/kconfig/mconf.c index 1b0b6ab07..006d03708 100644 --- a/scripts/kconfig/mconf.c +++ b/scripts/kconfig/mconf.c @@ -445,6 +445,7 @@ static struct gstr get_relations_str(struct symbol **sym_arr) pid_t pid; +#ifdef SIGWINCH static void winch_handler(int sig) { if (!do_resize) { @@ -452,11 +453,11 @@ static void winch_handler(int sig) do_resize = 1; } } +#endif static int exec_conf(void) { int pipefd[2], stat, size; - struct sigaction sa; sigset_t sset, osset; sigemptyset(&sset); @@ -465,10 +466,15 @@ static int exec_conf(void) signal(SIGINT, SIG_DFL); - sa.sa_handler = winch_handler; - sigemptyset(&sa.sa_mask); - sa.sa_flags = SA_RESTART; - sigaction(SIGWINCH, &sa, NULL); +#ifdef SIGWINCH + { + struct sigaction sa; + sa.sa_handler = winch_handler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + sigaction(SIGWINCH, &sa, NULL); + } +#endif *argptr++ = NULL; -- cgit v1.2.3-55-g6feb From 9371043698933452bb69566f279a6e40af961c8c Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Sep 2012 15:35:10 +0200 Subject: fix unsafe bb_perror_msg(filename) calls Signed-off-by: Denys Vlasenko --- coreutils/stat.c | 4 ++-- e2fsprogs/old_e2fsprogs/lsattr.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/coreutils/stat.c b/coreutils/stat.c index 3fb212f0f..e38c8f6b0 100644 --- a/coreutils/stat.c +++ b/coreutils/stat.c @@ -442,7 +442,7 @@ static bool do_statfs(const char *filename, const char *format) : getfilecon(filename, &scontext) ) < 0 ) { - bb_perror_msg(filename); + bb_simple_perror_msg(filename); return 0; } } @@ -555,7 +555,7 @@ static bool do_stat(const char *filename, const char *format) : getfilecon(filename, &scontext) ) < 0 ) { - bb_perror_msg(filename); + bb_simple_perror_msg(filename); return 0; } } diff --git a/e2fsprogs/old_e2fsprogs/lsattr.c b/e2fsprogs/old_e2fsprogs/lsattr.c index 9e0e4cb60..9eab68b5b 100644 --- a/e2fsprogs/old_e2fsprogs/lsattr.c +++ b/e2fsprogs/old_e2fsprogs/lsattr.c @@ -93,7 +93,7 @@ static int lsattr_dir_proc(const char *dir_name, struct dirent *de, path = concat_path_file(dir_name, de->d_name); if (lstat(path, &st) == -1) - bb_perror_msg(path); + bb_simple_perror_msg(path); else { if (de->d_name[0] != '.' || (flags & OPT_ALL)) { list_attributes(path); -- cgit v1.2.3-55-g6feb From b2320370be14811459718b9fe418efed75ea3615 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Thu, 27 Sep 2012 16:03:49 +0200 Subject: lineedit: in !EDITING config, return -1 on fgets error Signed-off-by: Denys Vlasenko --- libbb/lineedit.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libbb/lineedit.c b/libbb/lineedit.c index 92bea856e..dbe616466 100644 --- a/libbb/lineedit.c +++ b/libbb/lineedit.c @@ -2729,7 +2729,8 @@ int FAST_FUNC read_line_input(const char* prompt, char* command, int maxsize) { fputs(prompt, stdout); fflush_all(); - fgets(command, maxsize, stdin); + if (!fgets(command, maxsize, stdin)) + return -1; return strlen(command); } -- cgit v1.2.3-55-g6feb From d1097988825aeec1706d86cc4941d6812735f868 Mon Sep 17 00:00:00 2001 From: Manuel Zerpies Date: Thu, 27 Sep 2012 16:06:34 +0200 Subject: flashcp: remove unused variable opts Signed-off-by: Manuel Zerpies Signed-off-by: Denys Vlasenko --- miscutils/flashcp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/miscutils/flashcp.c b/miscutils/flashcp.c index 790f9c01f..81cde9072 100644 --- a/miscutils/flashcp.c +++ b/miscutils/flashcp.c @@ -50,7 +50,6 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv) int fd_f, fd_d; /* input file and mtd device file descriptors */ int i; uoff_t erase_count; - unsigned opts; struct mtd_info_user mtd; struct erase_info_user e; struct stat statb; @@ -59,7 +58,7 @@ int flashcp_main(int argc UNUSED_PARAM, char **argv) RESERVE_CONFIG_UBUFFER(buf2, BUFSIZE); opt_complementary = "=2"; /* exactly 2 non-option args: file, dev */ - opts = getopt32(argv, "v"); + /*opts =*/ getopt32(argv, "v"); argv += optind; // filename = *argv++; // devicename = *argv; -- cgit v1.2.3-55-g6feb From 1c7a58dfb82ea04c525e0c19f94f2d800dee99e3 Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Thu, 27 Sep 2012 16:22:24 +0200 Subject: udhcpc[6]: allow discover_retries == 0 (infinite) Signed-off-by: Felix Fietkau Signed-off-by: Denys Vlasenko --- networking/udhcp/d6_dhcpc.c | 4 ++-- networking/udhcp/dhcpc.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/udhcp/d6_dhcpc.c b/networking/udhcp/d6_dhcpc.c index dda4a9112..c44220bf9 100644 --- a/networking/udhcp/d6_dhcpc.c +++ b/networking/udhcp/d6_dhcpc.c @@ -1111,7 +1111,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) switch (state) { case INIT_SELECTING: - if (packet_num < discover_retries) { + if (!discover_retries || packet_num < discover_retries) { if (packet_num == 0) xid = random_xid(); /* multicast */ @@ -1140,7 +1140,7 @@ int udhcpc6_main(int argc UNUSED_PARAM, char **argv) packet_num = 0; continue; case REQUESTING: - if (packet_num < discover_retries) { + if (!discover_retries || packet_num < discover_retries) { /* send multicast select packet */ send_d6_select(xid); timeout = discover_timeout; diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index dcb7d42dc..f72217c84 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1442,7 +1442,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) switch (state) { case INIT_SELECTING: - if (packet_num < discover_retries) { + if (!discover_retries || packet_num < discover_retries) { if (packet_num == 0) xid = random_xid(); /* broadcast */ @@ -1471,7 +1471,7 @@ int udhcpc_main(int argc UNUSED_PARAM, char **argv) packet_num = 0; continue; case REQUESTING: - if (packet_num < discover_retries) { + if (!discover_retries || packet_num < discover_retries) { /* send broadcast select packet */ send_select(xid, server_addr, requested_ip); timeout = discover_timeout; -- cgit v1.2.3-55-g6feb From f47ce07b2699134d94dae9320dabc4a91c3c6b83 Mon Sep 17 00:00:00 2001 From: Nicolas Thill Date: Tue, 25 Sep 2012 14:06:01 +0200 Subject: brctl: fix description and usage brctl uncorrectly displays the "showmacs" command as being supported while it is not, remove it from the usage and Config.src file. Signed-off-by: Nicolas Thill Signed-off-by: Denys Vlasenko --- networking/Config.src | 4 ++-- networking/brctl.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/networking/Config.src b/networking/Config.src index e2376d548..e1ae0c9d5 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -82,12 +82,12 @@ config FEATURE_BRCTL_FANCY This adds about 600 bytes. config FEATURE_BRCTL_SHOW - bool "Support show, showmac and showstp" + bool "Support show" default y depends on BRCTL && FEATURE_BRCTL_FANCY help Add support for option which prints the current config: - showmacs, showstp, show + show config DNSD bool "dnsd" diff --git a/networking/brctl.c b/networking/brctl.c index 7289e641f..b4f5809df 100644 --- a/networking/brctl.c +++ b/networking/brctl.c @@ -129,7 +129,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) "setageing\0" "setfd\0" "sethello\0" "setmaxage\0" "setpathcost\0" "setportprio\0" "setbridgeprio\0" ) - IF_FEATURE_BRCTL_SHOW("showmacs\0" "show\0"); + IF_FEATURE_BRCTL_SHOW("show\0"); enum { ARG_addbr = 0, ARG_delbr, ARG_addif, ARG_delif IF_FEATURE_BRCTL_FANCY(, @@ -137,7 +137,7 @@ int brctl_main(int argc UNUSED_PARAM, char **argv) ARG_setageing, ARG_setfd, ARG_sethello, ARG_setmaxage, ARG_setpathcost, ARG_setportprio, ARG_setbridgeprio ) - IF_FEATURE_BRCTL_SHOW(, ARG_showmacs, ARG_show) + IF_FEATURE_BRCTL_SHOW(, ARG_show) }; int fd; -- cgit v1.2.3-55-g6feb From d5275888821a8382e7a493d90cebb7b23d975795 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 1 Oct 2012 13:41:17 +0200 Subject: ash: implement export -n function old new delta exportcmd 129 175 +46 Signed-off-by: Denys Vlasenko --- shell/ash.c | 30 ++++++++++++++++++++++++++---- 1 file changed, 26 insertions(+), 4 deletions(-) diff --git a/shell/ash.c b/shell/ash.c index d42316a88..010924db4 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12630,9 +12630,27 @@ exportcmd(int argc UNUSED_PARAM, char **argv) char *name; const char *p; char **aptr; - int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT; + char opt; + int flag; + int flag_off; + + /* "readonly" in bash accepts, but ignores -n. + * We do the same: it saves a conditional in nextopt's param. + */ + flag_off = 0; + while ((opt = nextopt("np")) != '\0') { + if (opt == 'n') + flag_off = VEXPORT; + } + flag = VEXPORT; + if (argv[0][0] == 'r') { + flag = VREADONLY; + flag_off = 0; /* readonly ignores -n */ + } + flag_off = ~flag_off; - if (nextopt("p") != 'p') { + /*if (opt_p_not_specified) - bash doesnt check this. Try "export -p NAME" */ + { aptr = argptr; name = *aptr; if (name) { @@ -12643,15 +12661,19 @@ exportcmd(int argc UNUSED_PARAM, char **argv) } else { vp = *findvar(hashvar(name), name); if (vp) { - vp->flags |= flag; + vp->flags = ((vp->flags | flag) & flag_off); continue; } } - setvar(name, p, flag); + setvar(name, p, (flag & flag_off)); } while ((name = *++aptr) != NULL); return 0; } } + + /* No arguments. Show the list of exported or readonly vars. + * -n is ignored. + */ showvars(argv[0], flag, 0); return 0; } -- cgit v1.2.3-55-g6feb From 32711c414193b81f215aee060ae8138675572280 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Tue, 2 Oct 2012 11:31:37 +0200 Subject: top/ps: argv0:"gdm-session-worker [pam/gdm-password]" == comm:"gdm-session-wor" Signed-off-by: Denys Vlasenko --- libbb/procps.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libbb/procps.c b/libbb/procps.c index 295048c46..b4557e797 100644 --- a/libbb/procps.c +++ b/libbb/procps.c @@ -583,6 +583,8 @@ void FAST_FUNC read_cmdline(char *buf, int col, unsigned pid, const char *comm) buf[sz] = '\0'; while (--sz >= 0 && buf[sz] == '\0') continue; + /* Prevent basename("process foo/bar") = "bar" */ + strchrnul(buf, ' ')[0] = '\0'; base = bb_basename(buf); /* before we replace argv0's NUL with space */ while (sz >= 0) { if ((unsigned char)(buf[sz]) < ' ') -- cgit v1.2.3-55-g6feb From fd77ea505ed1eb15161585a6e3b6ea7ae95ed6b3 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 3 Oct 2012 09:42:21 +0200 Subject: mark get_shell_name FAST_FUNC Signed-off-by: Denys Vlasenko --- include/libbb.h | 2 +- libbb/get_shell_name.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/include/libbb.h b/include/libbb.h index f22e58e27..2059567e0 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1248,7 +1248,7 @@ extern void run_shell(const char *shell, int loginshell, const char *command, co * Note that getpwuid result might need xstrdup'ing * if there is a possibility of intervening getpwxxx() calls. */ -const char *get_shell_name(void); +const char *get_shell_name(void) FAST_FUNC; #if ENABLE_SELINUX extern void renew_current_security_context(void) FAST_FUNC; diff --git a/libbb/get_shell_name.c b/libbb/get_shell_name.c index c930afd94..5aebe9cdc 100644 --- a/libbb/get_shell_name.c +++ b/libbb/get_shell_name.c @@ -8,7 +8,7 @@ #include "libbb.h" -const char *get_shell_name(void) +const char* FAST_FUNC get_shell_name(void) { struct passwd *pw; char *shell; -- cgit v1.2.3-55-g6feb From 8dc6d1a813e2be33ecfcf3fa97a1b5aae05a8631 Mon Sep 17 00:00:00 2001 From: Tito Ragusa Date: Mon, 8 Oct 2012 11:18:08 +0200 Subject: adduser: make it accept "adduser USER GROUP" form Signed-off-by: Tito Ragusa Signed-off-by: Denys Vlasenko Signed-off-by: Denys Vlasenko --- loginutils/adduser.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/loginutils/adduser.c b/loginutils/adduser.c index 1d082c876..dc0244476 100644 --- a/loginutils/adduser.c +++ b/loginutils/adduser.c @@ -9,9 +9,9 @@ */ //usage:#define adduser_trivial_usage -//usage: "[OPTIONS] USER" +//usage: "[OPTIONS] USER [GROUP]" //usage:#define adduser_full_usage "\n\n" -//usage: "Add a user\n" +//usage: "Create new user, or add USER to GROUP\n" //usage: "\n -h DIR Home directory" //usage: "\n -g GECOS GECOS field" //usage: "\n -s SHELL Login shell" @@ -80,7 +80,7 @@ static void passwd_study(struct passwd *p) } } -static void addgroup_wrapper(struct passwd *p, const char *group_name) +static int addgroup_wrapper(struct passwd *p, const char *group_name) { char *argv[6]; @@ -110,7 +110,7 @@ static void addgroup_wrapper(struct passwd *p, const char *group_name) argv[5] = NULL; } - spawn_and_wait(argv); + return spawn_and_wait(argv); } static void passwd_wrapper(const char *login_name) NORETURN; @@ -162,9 +162,9 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) pw.pw_shell = (char *)get_shell_name(); pw.pw_dir = NULL; - /* exactly one non-option arg */ + /* at most two non-option args */ /* disable interactive passwd for system accounts */ - opt_complementary = "=1:SD:u+"; + opt_complementary = "?2:SD:u+"; if (sizeof(pw.pw_uid) == sizeof(int)) { opts = getopt32(argv, "h:g:s:G:DSHu:", &pw.pw_dir, &pw.pw_gecos, &pw.pw_shell, &usegroup, &pw.pw_uid); } else { @@ -175,9 +175,16 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) } } argv += optind; + pw.pw_name = argv[0]; + + if (!opts && argv[1]) { + /* if called with two non-option arguments, adduser + * will add an existing user to an existing group. + */ + return addgroup_wrapper(&pw, argv[1]); + } /* fill in the passwd struct */ - pw.pw_name = argv[0]; die_if_bad_username(pw.pw_name); if (!pw.pw_dir) { /* create string for $HOME if not specified already */ @@ -205,7 +212,6 @@ int adduser_main(int argc UNUSED_PARAM, char **argv) } if (ENABLE_FEATURE_CLEAN_UP) free(p); - #if ENABLE_FEATURE_SHADOWPASSWDS /* /etc/shadow fields: * 1. username -- cgit v1.2.3-55-g6feb From eab343e7e1e5331df833aa69f14584e4a6c738f1 Mon Sep 17 00:00:00 2001 From: Ron Yorston Date: Mon, 8 Oct 2012 11:47:22 +0200 Subject: mktemp: fix mktemp -u temp.XXXXXX returning garbage when TMPDIR is set Use mktemp instead of tempnam for compatibility with real mktemp. Don't let mktemp fail silently, print some simple error messages. Don't ignore -q. Signed-off-by: Tito Ragusa Signed-off-by: Ron Yorston Signed-off-by: Denys Vlasenko --- debianutils/mktemp.c | 40 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/debianutils/mktemp.c b/debianutils/mktemp.c index dbe430955..983d7a246 100644 --- a/debianutils/mktemp.c +++ b/debianutils/mktemp.c @@ -38,7 +38,7 @@ //usage: "TEMPLATE must end with XXXXXX (e.g. [/dir/]nameXXXXXX).\n" //usage: "Without TEMPLATE, -t tmp.XXXXXX is assumed.\n" //usage: "\n -d Make directory, not file" -////usage: "\n -q Fail silently on errors" - we ignore this opt +//usage: "\n -q Fail silently on errors" //usage: "\n -t Prepend base directory name to TEMPLATE" //usage: "\n -p DIR Use DIR as a base directory (implies -t)" //usage: "\n -u Do not create anything; print a name" @@ -71,7 +71,6 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv) if (!path || path[0] == '\0') path = "/tmp"; - /* -q is ignored */ opt_complementary = "?1"; /* 1 argument max */ opts = getopt32(argv, "dqtp:u", &path); @@ -83,33 +82,32 @@ int mktemp_main(int argc UNUSED_PARAM, char **argv) chp = xstrdup("tmp.XXXXXX"); opts |= OPT_t; } - - if (opts & OPT_u) { - /* Remove (up to) 6 X's */ - unsigned len = strlen(chp); - int cnt = len > 6 ? 6 : len; - while (--cnt >= 0 && chp[--len] == 'X') - chp[len] = '\0'; - - chp = tempnam(opts & (OPT_t|OPT_p) ? path : "./", chp); - if (!chp) - return EXIT_FAILURE; - if (!(opts & (OPT_t|OPT_p))) - chp += 2; - goto ret; +#if 0 + /* Don't allow directory separator in template */ + if ((opts & OPT_t) && bb_basename(chp) != chp) { + errno = EINVAL; + goto error; } - +#endif if (opts & (OPT_t|OPT_p)) chp = concat_path_file(path, chp); - if (opts & OPT_d) { + if (opts & OPT_u) { + chp = mktemp(chp); + if (chp[0] == '\0') + goto error; + } else if (opts & OPT_d) { if (mkdtemp(chp) == NULL) - return EXIT_FAILURE; + goto error; } else { if (mkstemp(chp) < 0) - return EXIT_FAILURE; + goto error; } - ret: puts(chp); return EXIT_SUCCESS; + error: + if (opts & OPT_q) + return EXIT_FAILURE; + /* don't use chp as it gets mangled in case of error */ + bb_perror_nomsg_and_die(); } -- cgit v1.2.3-55-g6feb