From d077565bb27966c47ea6f0e9de092133954b5807 Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Thu, 13 Aug 2015 15:57:21 +0200 Subject: unit-tests: remove unnecesary field from struct bbunit_listelem In the initial submission struct bbunit_listelem was manipulated by custom list functions implemented in bbunit.c. Since the tests are now added to the list by llist_add_to_end(), which allocates the llist_t objects behind the scenes, there's no need for the *next field. function old new delta unit_main 142 141 -1 bbunit_strrstr_elem 24 16 -8 bbunit_obscure_weak_pass_elem 24 16 -8 bbunit_obscure_strong_pass_elem 24 16 -8 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 0/4 up/down: 0/-25) Total: -25 bytes Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 - 1 file changed, 1 deletion(-) (limited to 'include') diff --git a/include/libbb.h b/include/libbb.h index 54d01b75a..136d4fd87 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1983,7 +1983,6 @@ static ALWAYS_INLINE unsigned char bb_ascii_tolower(unsigned char a) typedef void (*bbunit_testfunc)(void); struct bbunit_listelem { - struct bbunit_listelem* next; const char* name; bbunit_testfunc testfunc; }; -- cgit v1.2.3-55-g6feb From c52cbea2bba6582b44facb424a15dc544b54fb28 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Mon, 24 Aug 2015 19:48:03 +0200 Subject: libbb: add setsockopt_foo helpers function old new delta setsockopt_int - 23 +23 do_load 918 934 +16 setsockopt_SOL_SOCKET_int - 14 +14 setsockopt_keepalive - 10 +10 setsockopt_SOL_SOCKET_1 - 10 +10 buffer_fill_and_print 169 178 +9 setsockopt_1 - 8 +8 nfsmount 3560 3566 +6 redirect 1277 1282 +5 tcpudpsvd_main 1782 1786 +4 d6_send_kernel_packet 272 275 +3 i2cget_main 380 382 +2 ed_main 2544 2545 +1 scan_recursive 380 378 -2 nbdclient_main 492 490 -2 hash_find 235 233 -2 cmdputs 334 332 -2 parse_command 1443 1440 -3 static.two 4 - -4 ntpd_main 1039 1035 -4 const_int_1 4 - -4 const_IPTOS_LOWDELAY 4 - -4 RCVBUF 4 - -4 ntp_init 474 469 -5 change_listen_mode 316 310 -6 uevent_main 416 409 -7 arping_main 1697 1690 -7 telnet_main 1612 1603 -9 socket_want_pktinfo 42 33 -9 setsockopt_reuseaddr 21 10 -11 setsockopt_broadcast 21 10 -11 httpd_main 772 757 -15 get_remote_transfer_fd 109 94 -15 make_new_session 503 487 -16 ftpd_main 2177 2160 -17 read_bunzip 1896 1866 -30 common_traceroute_main 4099 4058 -41 common_ping_main 1836 1783 -53 ------------------------------------------------------------------------------ (add/remove: 5/4 grow/shrink: 8/21 up/down: 111/-283) Total: -172 bytes Signed-off-by: Denys Vlasenko --- include/libbb.h | 8 +++++++- libbb/messages.c | 2 +- libbb/udp_io.c | 4 ++-- libbb/xconnect.c | 25 +++++++++++++++++++++++-- networking/arping.c | 2 +- networking/ftpd.c | 8 ++++---- networking/httpd.c | 4 ++-- networking/nbd-client.c | 2 +- networking/nc_bloaty.c | 4 ++-- networking/ntpd.c | 6 ++---- networking/ping.c | 16 ++++++++-------- networking/telnet.c | 2 +- networking/telnetd.c | 2 +- networking/traceroute.c | 41 ++++++++++++++++------------------------- networking/udhcp/dhcpc.c | 4 +--- util-linux/uevent.c | 6 +++--- 16 files changed, 75 insertions(+), 61 deletions(-) (limited to 'include') diff --git a/include/libbb.h b/include/libbb.h index 136d4fd87..2e20706e7 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -561,6 +561,11 @@ void xlisten(int s, int backlog) FAST_FUNC; void xconnect(int s, const struct sockaddr *s_addr, socklen_t addrlen) FAST_FUNC; ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, socklen_t tolen) FAST_FUNC; + +int setsockopt_int(int fd, int level, int optname, int optval) FAST_FUNC; +int setsockopt_1(int fd, int level, int optname) FAST_FUNC; +int setsockopt_SOL_SOCKET_int(int fd, int optname, int optval) FAST_FUNC; +int setsockopt_SOL_SOCKET_1(int fd, int optname) FAST_FUNC; /* SO_REUSEADDR allows a server to rebind to an address that is already * "in use" by old connections to e.g. previous server instance which is * killed or crashed. Without it bind will fail until all such connections @@ -568,6 +573,7 @@ ssize_t xsendto(int s, const void *buf, size_t len, const struct sockaddr *to, * regardless of SO_REUSEADDR (unlike some other flavors of Unix). * Turn it on before you call bind(). */ void setsockopt_reuseaddr(int fd) FAST_FUNC; /* On Linux this never fails. */ +int setsockopt_keepalive(int fd) FAST_FUNC; int setsockopt_broadcast(int fd) FAST_FUNC; int setsockopt_bindtodevice(int fd, const char *iface) FAST_FUNC; /* NB: returns port in host byte order */ @@ -1807,7 +1813,7 @@ extern const char bb_PATH_root_path[] ALIGN1; /* "PATH=/sbin:/usr/sbin:/bin:/usr #define bb_default_path (bb_PATH_root_path + sizeof("PATH=/sbin:/usr/sbin")) extern const int const_int_0; -extern const int const_int_1; +//extern const int const_int_1; /* Providing hard guarantee on minimum size (think of BUFSIZ == 128) */ diff --git a/libbb/messages.c b/libbb/messages.c index fad82c9da..c1b7ba252 100644 --- a/libbb/messages.c +++ b/libbb/messages.c @@ -43,7 +43,7 @@ const char bb_PATH_root_path[] ALIGN1 = "PATH=/sbin:/usr/sbin:/bin:/usr/bin" BB_ADDITIONAL_PATH; -const int const_int_1 = 1; +//const int const_int_1 = 1; /* explicitly = 0, otherwise gcc may make it a common variable * and it will end up in bss */ const int const_int_0 = 0; diff --git a/libbb/udp_io.c b/libbb/udp_io.c index 7985a9723..a32af9bd2 100644 --- a/libbb/udp_io.c +++ b/libbb/udp_io.c @@ -16,10 +16,10 @@ void FAST_FUNC socket_want_pktinfo(int fd UNUSED_PARAM) { #ifdef IP_PKTINFO - setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &const_int_1, sizeof(int)); + setsockopt_1(fd, IPPROTO_IP, IP_PKTINFO); #endif #if ENABLE_FEATURE_IPV6 && defined(IPV6_PKTINFO) - setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &const_int_1, sizeof(int)); + setsockopt_1(fd, IPPROTO_IPV6, IPV6_PKTINFO); #endif } diff --git a/libbb/xconnect.c b/libbb/xconnect.c index 2a96e03dc..6e78e6363 100644 --- a/libbb/xconnect.c +++ b/libbb/xconnect.c @@ -14,13 +14,34 @@ #include #include "libbb.h" +int FAST_FUNC setsockopt_int(int fd, int level, int optname, int optval) +{ + return setsockopt(fd, level, optname, &optval, sizeof(int)); +} +int FAST_FUNC setsockopt_1(int fd, int level, int optname) +{ + return setsockopt_int(fd, level, optname, 1); +} +int FAST_FUNC setsockopt_SOL_SOCKET_int(int fd, int optname, int optval) +{ + return setsockopt_int(fd, SOL_SOCKET, optname, optval); +} +int FAST_FUNC setsockopt_SOL_SOCKET_1(int fd, int optname) +{ + return setsockopt_SOL_SOCKET_int(fd, optname, 1); +} + void FAST_FUNC setsockopt_reuseaddr(int fd) { - setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &const_int_1, sizeof(const_int_1)); + setsockopt_SOL_SOCKET_1(fd, SO_REUSEADDR); } int FAST_FUNC setsockopt_broadcast(int fd) { - return setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &const_int_1, sizeof(const_int_1)); + return setsockopt_SOL_SOCKET_1(fd, SO_BROADCAST); +} +int FAST_FUNC setsockopt_keepalive(int fd) +{ + return setsockopt_SOL_SOCKET_1(fd, SO_KEEPALIVE); } #ifdef SO_BINDTODEVICE diff --git a/networking/arping.c b/networking/arping.c index 9ac4a7cee..ce7fa299c 100644 --- a/networking/arping.c +++ b/networking/arping.c @@ -357,7 +357,7 @@ int arping_main(int argc UNUSED_PARAM, char **argv) saddr.sin_port = htons(1025); saddr.sin_addr = dst; - if (setsockopt(probe_fd, SOL_SOCKET, SO_DONTROUTE, &const_int_1, sizeof(const_int_1)) == -1) + if (setsockopt_SOL_SOCKET_1(probe_fd, SO_DONTROUTE) != 0) bb_perror_msg("setsockopt(%s)", "SO_DONTROUTE"); xconnect(probe_fd, (struct sockaddr *) &saddr, sizeof(saddr)); getsockname(probe_fd, (struct sockaddr *) &saddr, &alen); diff --git a/networking/ftpd.c b/networking/ftpd.c index 2351d6dd3..7735b7233 100644 --- a/networking/ftpd.c +++ b/networking/ftpd.c @@ -377,7 +377,7 @@ ftpdataio_get_pasv_fd(void) return remote_fd; } - setsockopt(remote_fd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); + setsockopt_keepalive(remote_fd); return remote_fd; } @@ -1186,11 +1186,11 @@ int ftpd_main(int argc UNUSED_PARAM, char **argv) , SIG_IGN); /* Set up options on the command socket (do we need these all? why?) */ - setsockopt(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1)); - setsockopt(STDIN_FILENO, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); + setsockopt_1(STDIN_FILENO, IPPROTO_TCP, TCP_NODELAY); + setsockopt_keepalive(STDIN_FILENO); /* Telnet protocol over command link may send "urgent" data, * we prefer it to be received in the "normal" data stream: */ - setsockopt(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE, &const_int_1, sizeof(const_int_1)); + setsockopt_1(STDIN_FILENO, SOL_SOCKET, SO_OOBINLINE); WRITE_OK(FTP_GREET); signal(SIGALRM, timeout_handler); diff --git a/networking/httpd.c b/networking/httpd.c index 7a9065fcc..feaaa94d5 100644 --- a/networking/httpd.c +++ b/networking/httpd.c @@ -2352,7 +2352,7 @@ static void mini_httpd(int server_socket) continue; /* set the KEEPALIVE option to cull dead connections */ - setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); + setsockopt_keepalive(n); if (fork() == 0) { /* child */ @@ -2395,7 +2395,7 @@ static void mini_httpd_nommu(int server_socket, int argc, char **argv) continue; /* set the KEEPALIVE option to cull dead connections */ - setsockopt(n, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); + setsockopt_keepalive(n); if (vfork() == 0) { /* child */ diff --git a/networking/nbd-client.c b/networking/nbd-client.c index cadda5261..a601430b6 100644 --- a/networking/nbd-client.c +++ b/networking/nbd-client.c @@ -83,7 +83,7 @@ int nbdclient_main(int argc, char **argv) // Find and connect to server sock = create_and_connect_stream_or_die(host, xatou16(port)); - setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &const_int_1, sizeof(const_int_1)); + setsockopt_1(sock, IPPROTO_TCP, TCP_NODELAY); // Log on to the server xread(sock, &nbd_header, 8+8+8+4 + 124); diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index b28d05f51..471ae1a12 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c @@ -863,8 +863,8 @@ int nc_main(int argc UNUSED_PARAM, char **argv) xbind(netfd, &ouraddr->u.sa, ouraddr->len); } #if 0 - setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf); - setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf); + setsockopt_SOL_SOCKET_int(netfd, SO_RCVBUF, o_rcvbuf); + setsockopt_SOL_SOCKET_int(netfd, SO_SNDBUF, o_sndbuf); #endif #ifdef BLOAT diff --git a/networking/ntpd.c b/networking/ntpd.c index b5120a70d..9732c9b1a 100644 --- a/networking/ntpd.c +++ b/networking/ntpd.c @@ -405,8 +405,6 @@ struct globals { }; #define G (*ptr_to_globals) -static const int const_IPTOS_LOWDELAY = IPTOS_LOWDELAY; - #define VERB1 if (MAX_VERBOSE && G.verbose) #define VERB2 if (MAX_VERBOSE >= 2 && G.verbose >= 2) @@ -837,7 +835,7 @@ send_query_to_peer(peer_t *p) #if ENABLE_FEATURE_IPV6 if (family == AF_INET) #endif - setsockopt(fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); + setsockopt_int(fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); free(local_lsa); } @@ -2186,7 +2184,7 @@ static NOINLINE void ntp_init(char **argv) xfunc_die(); } socket_want_pktinfo(G_listen_fd); - setsockopt(G_listen_fd, IPPROTO_IP, IP_TOS, &const_IPTOS_LOWDELAY, sizeof(const_IPTOS_LOWDELAY)); + setsockopt_int(G_listen_fd, IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY); } #endif if (!(opts & OPT_n)) { diff --git a/networking/ping.c b/networking/ping.c index 20489a070..e1f9ebc3a 100644 --- a/networking/ping.c +++ b/networking/ping.c @@ -247,7 +247,7 @@ static void ping6(len_and_sockaddr *lsa) pkt->icmp6_type = ICMP6_ECHO_REQUEST; sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); - setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt)); + setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); xsendto(pingsock, G.packet, DEFDATALEN + sizeof(struct icmp6_hdr), &lsa->u.sa, lsa->len); @@ -700,12 +700,12 @@ static void ping4(len_and_sockaddr *lsa) /* set recv buf (needed if we can get lots of responses: flood ping, * broadcast ping etc) */ sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */ - setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)); + setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt); if (opt_ttl != 0) { - setsockopt(pingsock, IPPROTO_IP, IP_TTL, &opt_ttl, sizeof(opt_ttl)); + setsockopt_int(pingsock, IPPROTO_IP, IP_TTL, opt_ttl); /* above doesnt affect packets sent to bcast IP, so... */ - setsockopt(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, &opt_ttl, sizeof(opt_ttl)); + setsockopt_int(pingsock, IPPROTO_IP, IP_MULTICAST_TTL, opt_ttl); } signal(SIGINT, print_stats_and_exit); @@ -766,15 +766,15 @@ static void ping6(len_and_sockaddr *lsa) /* set recv buf (needed if we can get lots of responses: flood ping, * broadcast ping etc) */ sockopt = (datalen * 2) + 7 * 1024; /* giving it a bit of extra room */ - setsockopt(pingsock, SOL_SOCKET, SO_RCVBUF, &sockopt, sizeof(sockopt)); + setsockopt_SOL_SOCKET_int(pingsock, SO_RCVBUF, sockopt); sockopt = offsetof(struct icmp6_hdr, icmp6_cksum); - if (offsetof(struct icmp6_hdr, icmp6_cksum) != 2) + if (sockopt != 2) BUG_bad_offsetof_icmp6_cksum(); - setsockopt(pingsock, SOL_RAW, IPV6_CHECKSUM, &sockopt, sizeof(sockopt)); + setsockopt_int(pingsock, SOL_RAW, IPV6_CHECKSUM, sockopt); /* request ttl info to be returned in ancillary data */ - setsockopt(pingsock, SOL_IPV6, IPV6_HOPLIMIT, &const_int_1, sizeof(const_int_1)); + setsockopt_1(pingsock, SOL_IPV6, IPV6_HOPLIMIT); if (if_index) pingaddr.sin6.sin6_scope_id = if_index; diff --git a/networking/telnet.c b/networking/telnet.c index a25579773..3bb6fb1ba 100644 --- a/networking/telnet.c +++ b/networking/telnet.c @@ -623,7 +623,7 @@ int telnet_main(int argc UNUSED_PARAM, char **argv) xmove_fd(create_and_connect_stream_or_die(host, port), netfd); - setsockopt(netfd, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); + setsockopt_keepalive(netfd); signal(SIGINT, record_signo); diff --git a/networking/telnetd.c b/networking/telnetd.c index 6aee95871..25d05fe7a 100644 --- a/networking/telnetd.c +++ b/networking/telnetd.c @@ -265,7 +265,7 @@ make_new_session( close_on_exec_on(fd); /* SO_KEEPALIVE by popular demand */ - setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &const_int_1, sizeof(const_int_1)); + setsockopt_keepalive(sock); #if ENABLE_FEATURE_TELNETD_STANDALONE ts->sockfd_read = sock; ndelay_on(sock); diff --git a/networking/traceroute.c b/networking/traceroute.c index e41d89e9f..642110c54 100644 --- a/networking/traceroute.c +++ b/networking/traceroute.c @@ -473,8 +473,8 @@ send_probe(int seq, int ttl) #if ENABLE_TRACEROUTE6 if (dest_lsa->u.sa.sa_family == AF_INET6) { - res = setsockopt(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof(ttl)); - if (res < 0) + res = setsockopt_int(sndsock, SOL_IPV6, IPV6_UNICAST_HOPS, ttl); + if (res != 0) bb_perror_msg_and_die("setsockopt(%s) %d", "UNICAST_HOPS", ttl); out = outip; len = packlen; @@ -482,8 +482,8 @@ send_probe(int seq, int ttl) #endif { #if defined IP_TTL - res = setsockopt(sndsock, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)); - if (res < 0) + res = setsockopt_int(sndsock, IPPROTO_IP, IP_TTL, ttl); + if (res != 0) bb_perror_msg_and_die("setsockopt(%s) %d", "TTL", ttl); #endif out = outicmp; @@ -902,13 +902,10 @@ common_traceroute_main(int op, char **argv) if (af == AF_INET6) { xmove_fd(xsocket(AF_INET6, SOCK_RAW, IPPROTO_ICMPV6), rcvsock); # ifdef IPV6_RECVPKTINFO - setsockopt(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO, - &const_int_1, sizeof(const_int_1)); - setsockopt(rcvsock, SOL_IPV6, IPV6_2292PKTINFO, - &const_int_1, sizeof(const_int_1)); + setsockopt_1(rcvsock, SOL_IPV6, IPV6_RECVPKTINFO); + setsockopt_1(rcvsock, SOL_IPV6, IPV6_2292PKTINFO); # else - setsockopt(rcvsock, SOL_IPV6, IPV6_PKTINFO, - &const_int_1, sizeof(const_int_1)); + setsockopt_1(rcvsock, SOL_IPV6, IPV6_PKTINFO); # endif } else #endif @@ -918,17 +915,14 @@ common_traceroute_main(int op, char **argv) #if TRACEROUTE_SO_DEBUG if (op & OPT_DEBUG) - setsockopt(rcvsock, SOL_SOCKET, SO_DEBUG, - &const_int_1, sizeof(const_int_1)); + setsockopt_SOL_SOCKET_1(rcvsock, SO_DEBUG); #endif if (op & OPT_BYPASS_ROUTE) - setsockopt(rcvsock, SOL_SOCKET, SO_DONTROUTE, - &const_int_1, sizeof(const_int_1)); + setsockopt_SOL_SOCKET_1(rcvsock, SO_DONTROUTE); #if ENABLE_TRACEROUTE6 if (af == AF_INET6) { - static const int two = 2; - if (setsockopt(rcvsock, SOL_RAW, IPV6_CHECKSUM, &two, sizeof(two)) < 0) + if (setsockopt_int(rcvsock, SOL_RAW, IPV6_CHECKSUM, 2) != 0) bb_perror_msg_and_die("setsockopt(%s)", "IPV6_CHECKSUM"); xmove_fd(xsocket(af, SOCK_DGRAM, 0), sndsock); } else @@ -966,28 +960,25 @@ common_traceroute_main(int op, char **argv) } #ifdef SO_SNDBUF - if (setsockopt(sndsock, SOL_SOCKET, SO_SNDBUF, &packlen, sizeof(packlen)) < 0) { - bb_perror_msg_and_die("SO_SNDBUF"); + if (setsockopt_SOL_SOCKET_int(sndsock, SO_SNDBUF, packlen) != 0) { + bb_perror_msg_and_die("setsockopt(%s)", "SO_SNDBUF"); } #endif #ifdef IP_TOS - if ((op & OPT_TOS) && setsockopt(sndsock, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0) { + if ((op & OPT_TOS) && setsockopt_int(sndsock, IPPROTO_IP, IP_TOS, tos) != 0) { bb_perror_msg_and_die("setsockopt(%s) %d", "TOS", tos); } #endif #ifdef IP_DONTFRAG if (op & OPT_DONT_FRAGMNT) - setsockopt(sndsock, IPPROTO_IP, IP_DONTFRAG, - &const_int_1, sizeof(const_int_1)); + setsockopt_1(sndsock, IPPROTO_IP, IP_DONTFRAG); #endif #if TRACEROUTE_SO_DEBUG if (op & OPT_DEBUG) - setsockopt(sndsock, SOL_SOCKET, SO_DEBUG, - &const_int_1, sizeof(const_int_1)); + setsockopt_SOL_SOCKET_1(sndsock, SO_DEBUG); #endif if (op & OPT_BYPASS_ROUTE) - setsockopt(sndsock, SOL_SOCKET, SO_DONTROUTE, - &const_int_1, sizeof(const_int_1)); + setsockopt_SOL_SOCKET_1(sndsock, SO_DONTROUTE); outip = xzalloc(packlen); diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c index 811a1a1ee..11f7b2d49 100644 --- a/networking/udhcp/dhcpc.c +++ b/networking/udhcp/dhcpc.c @@ -1043,9 +1043,7 @@ static int udhcp_raw_socket(int ifindex) } #endif - if (setsockopt(fd, SOL_PACKET, PACKET_AUXDATA, - &const_int_1, sizeof(int)) < 0 - ) { + if (setsockopt_1(fd, SOL_PACKET, PACKET_AUXDATA) != 0) { if (errno != ENOPROTOOPT) log1("Can't set PACKET_AUXDATA on raw socket"); } diff --git a/util-linux/uevent.c b/util-linux/uevent.c index fb98b4845..514a9e934 100644 --- a/util-linux/uevent.c +++ b/util-linux/uevent.c @@ -37,7 +37,7 @@ enum { #ifndef SO_RCVBUFFORCE #define SO_RCVBUFFORCE 33 #endif -static const int RCVBUF = 2 * 1024 * 1024; +enum { RCVBUF = 2 * 1024 * 1024 }; int uevent_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int uevent_main(int argc UNUSED_PARAM, char **argv) @@ -63,8 +63,8 @@ int uevent_main(int argc UNUSED_PARAM, char **argv) // find /sys -name uevent -exec sh -c 'echo add >"{}"' ';' // // SO_RCVBUFFORCE (root only) can go above net.core.rmem_max sysctl - setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &RCVBUF, sizeof(RCVBUF)); - setsockopt(fd, SOL_SOCKET, SO_RCVBUFFORCE, &RCVBUF, sizeof(RCVBUF)); + setsockopt_SOL_SOCKET_int(fd, SO_RCVBUF, RCVBUF); + setsockopt_SOL_SOCKET_int(fd, SO_RCVBUFFORCE, RCVBUF); if (0) { int z; socklen_t zl = sizeof(z); -- cgit v1.2.3-55-g6feb From 7448b513c84feb3fd06fc57b39f5ab450970c01e Mon Sep 17 00:00:00 2001 From: Bartosz Golaszewski Date: Tue, 25 Aug 2015 16:36:43 +0200 Subject: libbb: add is_suffixed_with() function Signed-off-by: Bartosz Golaszewski Signed-off-by: Denys Vlasenko --- include/libbb.h | 1 + libbb/compare_string_array.c | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) (limited to 'include') diff --git a/include/libbb.h b/include/libbb.h index 2e20706e7..543214ea4 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -413,6 +413,7 @@ 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; char *is_prefixed_with(const char *string, const char *key) FAST_FUNC; +char *is_suffixed_with(const char *string, const char *key) FAST_FUNC; int ndelay_on(int fd) FAST_FUNC; int ndelay_off(int fd) FAST_FUNC; diff --git a/libbb/compare_string_array.c b/libbb/compare_string_array.c index cdcb2718d..e0d8e421b 100644 --- a/libbb/compare_string_array.c +++ b/libbb/compare_string_array.c @@ -28,6 +28,25 @@ char* FAST_FUNC is_prefixed_with(const char *string, const char *key) #endif } +/* + * Return NULL if string is not suffixed with key. Return pointer to the + * beginning of prefix key in string. If key is an empty string return pointer + * to the end of string. + */ +char* FAST_FUNC is_suffixed_with(const char *string, const char *key) +{ + size_t key_len = strlen(key); + ssize_t len_diff = strlen(string) - key_len; + + if (len_diff >= 0) { + if (strcmp(string + len_diff, key) == 0) { + return (char*)key; + } + } + + return NULL; +} + /* returns the array index of the string */ /* (index of first match is returned, or -1) */ int FAST_FUNC index_in_str_array(const char *const string_array[], const char *key) @@ -133,4 +152,18 @@ BBUNIT_DEFINE_TEST(is_prefixed_with) BBUNIT_ENDTEST; } +BBUNIT_DEFINE_TEST(is_suffixed_with) +{ + BBUNIT_ASSERT_STREQ("bar", is_suffixed_with("foo bar", "bar")); + BBUNIT_ASSERT_STREQ("foo", is_suffixed_with("foo", "foo")); + BBUNIT_ASSERT_STREQ("", is_suffixed_with("foo", "")); + BBUNIT_ASSERT_STREQ("", is_suffixed_with("", "")); + + BBUNIT_ASSERT_NULL(is_suffixed_with("foo", "bar foo")); + BBUNIT_ASSERT_NULL(is_suffixed_with("foo foo", "bar")); + BBUNIT_ASSERT_NULL(is_suffixed_with("", "foo")); + + BBUNIT_ENDTEST; +} + #endif /* ENABLE_UNIT_TEST */ -- cgit v1.2.3-55-g6feb From 1c6c670ed44a77ab4784ea0d4ac5411d7b0648d8 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Oct 2015 01:39:40 +0200 Subject: wget: make openssl/ssl_helper choice configurable I got sick of not being able to wget a https file... Signed-off-by: Denys Vlasenko --- include/applets.src.h | 1 - networking/Config.src | 42 -- networking/Kbuild.src | 1 - networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8 | 22 + networking/ssl_helper-wolfssl/README | 15 + networking/ssl_helper-wolfssl/ssl_helper.c | 480 ++++++++++++++++++++++ networking/ssl_helper-wolfssl/ssl_helper.sh | 11 + networking/wget.c | 105 ++++- 8 files changed, 623 insertions(+), 54 deletions(-) create mode 100755 networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8 create mode 100644 networking/ssl_helper-wolfssl/README create mode 100644 networking/ssl_helper-wolfssl/ssl_helper.c create mode 100755 networking/ssl_helper-wolfssl/ssl_helper.sh (limited to 'include') diff --git a/include/applets.src.h b/include/applets.src.h index 9f3ac78cb..dac83e7fb 100644 --- a/include/applets.src.h +++ b/include/applets.src.h @@ -382,7 +382,6 @@ IF_VOLNAME(APPLET(volname, BB_DIR_USR_BIN, BB_SUID_DROP)) IF_WATCH(APPLET(watch, BB_DIR_BIN, BB_SUID_DROP)) IF_WATCHDOG(APPLET(watchdog, BB_DIR_SBIN, BB_SUID_DROP)) IF_WC(APPLET(wc, BB_DIR_USR_BIN, BB_SUID_DROP)) -IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) IF_WHICH(APPLET(which, BB_DIR_USR_BIN, BB_SUID_DROP)) IF_WHOAMI(APPLET_NOFORK(whoami, whoami, BB_DIR_USR_BIN, BB_SUID_DROP, whoami)) IF_YES(APPLET_NOFORK(yes, yes, BB_DIR_USR_BIN, BB_SUID_DROP, yes)) diff --git a/networking/Config.src b/networking/Config.src index da36e8627..76cbccf4a 100644 --- a/networking/Config.src +++ b/networking/Config.src @@ -947,48 +947,6 @@ config VCONFIG help Creates, removes, and configures VLAN interfaces -config WGET - bool "wget" - default y - help - wget is a utility for non-interactive download of files from HTTP - and FTP servers. - -config FEATURE_WGET_STATUSBAR - bool "Enable a nifty process meter (+2k)" - default y - depends on WGET - help - Enable the transfer progress bar for wget transfers. - -config FEATURE_WGET_AUTHENTICATION - bool "Enable HTTP authentication" - default y - depends on WGET - help - Support authenticated HTTP transfers. - -config FEATURE_WGET_LONG_OPTIONS - bool "Enable long options" - default y - depends on WGET && LONG_OPTS - help - Support long options for the wget applet. - -config FEATURE_WGET_TIMEOUT - bool "Enable timeout option -T SEC" - default y - depends on WGET - help - Supports network read and connect timeouts for wget, - so that wget will give up and timeout, through the -T - command line option. - - Currently only connect and network data read timeout are - supported (i.e., timeout is not applied to the DNS query). When - FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option - will work in addition to -T. - config ZCIP bool "zcip" default y diff --git a/networking/Kbuild.src b/networking/Kbuild.src index 944f27be1..79f54824b 100644 --- a/networking/Kbuild.src +++ b/networking/Kbuild.src @@ -41,7 +41,6 @@ lib-$(CONFIG_TFTPD) += tftp.o lib-$(CONFIG_TRACEROUTE) += traceroute.o lib-$(CONFIG_TUNCTL) += tunctl.o lib-$(CONFIG_VCONFIG) += vconfig.o -lib-$(CONFIG_WGET) += wget.o lib-$(CONFIG_ZCIP) += zcip.o lib-$(CONFIG_TCPSVD) += tcpudp.o tcpudp_perhost.o diff --git a/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8 b/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8 new file mode 100755 index 000000000..27d0c41ee --- /dev/null +++ b/networking/ssl_helper-wolfssl/00cfg-wolfssl-3.6.8 @@ -0,0 +1,22 @@ +#!/bin/sh + +# How to configure & build a static wolfssl-3.6.8 library +# suitable for static build of ssl_helper. + +export CC="x86_64-gcc" +export CFLAGS="\ +-Os \ +-static \ +-fomit-frame-pointer \ +-falign-functions=1 -falign-labels=1 -falign-loops=1 -falign-jumps=1 \ +-ffunction-sections -fdata-sections \ +" + +./configure \ + --enable-static \ + --enable-singlethreaded \ + --disable-shared \ +|| exit $? + +make +exit $? diff --git a/networking/ssl_helper-wolfssl/README b/networking/ssl_helper-wolfssl/README new file mode 100644 index 000000000..17437606d --- /dev/null +++ b/networking/ssl_helper-wolfssl/README @@ -0,0 +1,15 @@ +Build instructions: + +* Unpack wolfssl-3.6.8.zip +* Build it: + ./configure --enable-static --disable-shared && make +* Drop this directory into wolfssl-3.6.8/ssl_helper +* Run ssl_helper.sh to compile and link the helper + +Usage: "ssl_helper -d FILE_DESCRIPTOR" where FILE_DESCRIPTOR is open to the peer. + +In bash, you can do it this way: +$ ssl_helper -d3 3<>/dev/tcp/HOST/PORT + +Stdin will be SSL-encrypted and sent to FILE_DESCRIPTOR. +Data from FILE_DESCRIPTOR will be decrypted and sent to stdout. diff --git a/networking/ssl_helper-wolfssl/ssl_helper.c b/networking/ssl_helper-wolfssl/ssl_helper.c new file mode 100644 index 000000000..38b7b56c6 --- /dev/null +++ b/networking/ssl_helper-wolfssl/ssl_helper.c @@ -0,0 +1,480 @@ +/* + * Adapted from: + * + * client.c + * + * Copyright (C) 2006-2015 wolfSSL Inc. + * + * This file is part of wolfSSL. (formerly known as CyaSSL) + * + * wolfSSL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * wolfSSL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#if 0 +# define dbg(...) say(__VA_ARGS__) +#else +# define dbg(...) ((void)0) +#endif + +static ssize_t safe_write(int fd, const void *buf, size_t count) +{ + ssize_t n; + + do { + n = write(fd, buf, count); + } while (n < 0 && errno == EINTR); + + return n; +} + +static ssize_t full_write(int fd, const void *buf, size_t len) +{ + ssize_t cc; + ssize_t total; + + total = 0; + + while (len) { + cc = safe_write(fd, buf, len); + + if (cc < 0) { + if (total) { + /* we already wrote some! */ + /* user can do another write to know the error code */ + return total; + } + return cc; /* write() returns -1 on failure. */ + } + + total += cc; + buf = ((const char *)buf) + cc; + len -= cc; + } + + return total; +} + +static void say(const char *s, ...) +{ + char buf[256]; + va_list p; + int sz; + + va_start(p, s); + sz = vsnprintf(buf, sizeof(buf), s, p); + full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf)); + va_end(p); +} + +static void die(const char *s, ...) +{ + char buf[256]; + va_list p; + int sz; + + va_start(p, s); + sz = vsnprintf(buf, sizeof(buf), s, p); + full_write(STDERR_FILENO, buf, sz >= 0 && sz < sizeof(buf) ? sz : strlen(buf)); + exit(1); + va_end(p); +} + +static void err_sys(const char *msg) +{ + die("%s\n", msg); +} + +/* ==== */ + +#if 0 +static void showPeer(WOLFSSL* ssl) +{ + WOLFSSL_CIPHER* cipher; + WOLFSSL_X509* peer = wolfSSL_get_peer_certificate(ssl); + if (peer) + ShowX509(peer, "peer's cert info:"); + else + say("peer has no cert!\n"); + say("SSL version is %s\n", wolfSSL_get_version(ssl)); + + cipher = wolfSSL_get_current_cipher(ssl); + say("SSL cipher suite is %s\n", wolfSSL_CIPHER_get_name(cipher)); + + { + WOLFSSL_X509_CHAIN* chain = wolfSSL_get_peer_chain(ssl); + int count = wolfSSL_get_chain_count(chain); + int i; + + for (i = 0; i < count; i++) { + int length; + unsigned char buffer[3072]; + WOLFSSL_X509* chainX509; + + wolfSSL_get_chain_cert_pem(chain, i, buffer, sizeof(buffer), &length); + buffer[length] = 0; + say("cert %d has length %d data = \n%s\n", i, length, buffer); + + chainX509 = wolfSSL_get_chain_X509(chain, i); + if (chainX509) + ShowX509(chainX509, "session cert info:"); + else + say("get_chain_X509 failed\n"); + wolfSSL_FreeX509(chainX509); + } + } +} +#endif + +WOLFSSL *prepare(int sockfd) +{ + WOLFSSL_METHOD* method; + WOLFSSL_CTX* ctx; + WOLFSSL* ssl; + + wolfSSL_Init(); + + method = wolfTLSv1_1_client_method(); + if (method == NULL) + err_sys("out of memory"); + ctx = wolfSSL_CTX_new(method); + if (ctx == NULL) + err_sys("out of memory"); +// if (cipherList) +// if (wolfSSL_CTX_set_cipher_list(ctx, cipherList) != SSL_SUCCESS) +// err_sys("client can't set cipher list 1"); + +// if (fewerPackets) +// wolfSSL_CTX_set_group_messages(ctx); + +//#ifndef NO_DH +// wolfSSL_CTX_SetMinDhKey_Sz(ctx, (word16)minDhKeyBits); +//#endif + +// if (usePsk) { +// wolfSSL_CTX_set_psk_client_callback(ctx, my_psk_client_cb); +// if (cipherList == NULL) { +// const char *defaultCipherList; +//#if defined(HAVE_AESGCM) && !defined(NO_DH) +// defaultCipherList = "DHE-PSK-AES128-GCM-SHA256"; +//#elif defined(HAVE_NULL_CIPHER) +// defaultCipherList = "PSK-NULL-SHA256"; +//#else +// defaultCipherList = "PSK-AES128-CBC-SHA256"; +//#endif +// if (wolfSSL_CTX_set_cipher_list(ctx,defaultCipherList) != SSL_SUCCESS) +// err_sys("client can't set cipher list 2"); +// } +// useClientCert = 0; +// } + +// if (useAnon) { +// if (cipherList == NULL) { +// wolfSSL_CTX_allow_anon_cipher(ctx); +// if (wolfSSL_CTX_set_cipher_list(ctx,"ADH-AES128-SHA") != SSL_SUCCESS) +// err_sys("client can't set cipher list 4"); +// } +// useClientCert = 0; +// } + +//#if defined(OPENSSL_EXTRA) || defined(HAVE_WEBSERVER) +// wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack); +//#endif + +// if (useOcsp) { +// if (ocspUrl != NULL) { +// wolfSSL_CTX_SetOCSP_OverrideURL(ctx, ocspUrl); +// wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE +// | WOLFSSL_OCSP_URL_OVERRIDE); +// } +// else +// wolfSSL_CTX_EnableOCSP(ctx, WOLFSSL_OCSP_NO_NONCE); +// } +// +//#ifdef USER_CA_CB +// wolfSSL_CTX_SetCACb(ctx, CaCb); +//#endif +// +//#ifdef VERIFY_CALLBACK +// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myVerify); +//#endif +//#if !defined(NO_FILESYSTEM) && !defined(NO_CERTS) +// if (useClientCert) { +// if (wolfSSL_CTX_use_certificate_chain_file(ctx, ourCert) != SSL_SUCCESS) +// err_sys("can't load client cert file, check file and run from" +// " wolfSSL home dir"); +// if (wolfSSL_CTX_use_PrivateKey_file(ctx, ourKey, SSL_FILETYPE_PEM) != SSL_SUCCESS) +// err_sys("can't load client private key file, check file and run " +// "from wolfSSL home dir"); +// } +// +// if (!usePsk && !useAnon) { +// if (wolfSSL_CTX_load_verify_locations(ctx, verifyCert,0) != SSL_SUCCESS) +// err_sys("can't load ca file, Please run from wolfSSL home dir"); +//#ifdef HAVE_ECC +// /* load ecc verify too, echoserver uses it by default w/ ecc */ +// if (wolfSSL_CTX_load_verify_locations(ctx, eccCert, 0) != SSL_SUCCESS) +// err_sys("can't load ecc ca file, Please run from wolfSSL home dir"); +//#endif +// } +//#endif /* !NO_FILESYSTEM && !NO_CERTS */ + +//#if !defined(NO_CERTS) +// if (!usePsk && !useAnon && doPeerCheck == 0) +// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); +// if (!usePsk && !useAnon && overrideDateErrors == 1) +// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, myDateCb); +//#endif + + wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); + +//#ifdef HAVE_SNI +// if (sniHostName) +// if (wolfSSL_CTX_UseSNI(ctx, 0, sniHostName, XSTRLEN(sniHostName)) != SSL_SUCCESS) +// err_sys("UseSNI failed"); +//#endif + +//#ifdef HAVE_MAX_FRAGMENT +// if (maxFragment) +// if (wolfSSL_CTX_UseMaxFragment(ctx, maxFragment) != SSL_SUCCESS) +// err_sys("UseMaxFragment failed"); +//#endif +//#ifdef HAVE_TRUNCATED_HMAC +// if (truncatedHMAC) +// if (wolfSSL_CTX_UseTruncatedHMAC(ctx) != SSL_SUCCESS) +// err_sys("UseTruncatedHMAC failed"); +//#endif +//#ifdef HAVE_SESSION_TICKET +// if (wolfSSL_CTX_UseSessionTicket(ctx) != SSL_SUCCESS) +// err_sys("UseSessionTicket failed"); +//#endif + +//#if defined(WOLFSSL_MDK_ARM) +// wolfSSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, 0); +//#endif + + ssl = wolfSSL_new(ctx); + if (ssl == NULL) + err_sys("out of memory"); + +//#ifdef HAVE_SESSION_TICKET +// wolfSSL_set_SessionTicket_cb(ssl, sessionTicketCB, (void*)"initial session"); +//#endif + +// if (doDTLS) { +// SOCKADDR_IN_T addr; +// build_addr(&addr, host, port, 1); +// wolfSSL_dtls_set_peer(ssl, &addr, sizeof(addr)); +// tcp_socket(&sockfd, 1); +// } wlse { +// tcp_connect(&sockfd, host, port, 0); +// } + +//#ifdef HAVE_POLY1305 +// /* use old poly to connect with google server */ +// if (!XSTRNCMP(domain, "www.google.com", 14)) { +// if (wolfSSL_use_old_poly(ssl, 1) != 0) +// err_sys("unable to set to old poly"); +// } +//#endif + + wolfSSL_set_fd(ssl, sockfd); + +//#ifdef HAVE_CRL +// if (disableCRL == 0) { +// if (wolfSSL_EnableCRL(ssl, WOLFSSL_CRL_CHECKALL) != SSL_SUCCESS) +// err_sys("can't enable crl check"); +// if (wolfSSL_LoadCRL(ssl, crlPemDir, SSL_FILETYPE_PEM, 0) != SSL_SUCCESS) +// err_sys("can't load crl, check crlfile and date validity"); +// if (wolfSSL_SetCRL_Cb(ssl, CRL_CallBack) != SSL_SUCCESS) +// err_sys("can't set crl callback"); +// } +//#endif +//#ifdef HAVE_SECURE_RENEGOTIATION +// if (scr) { +// if (wolfSSL_UseSecureRenegotiation(ssl) != SSL_SUCCESS) +// err_sys("can't enable secure renegotiation"); +// } +//#endif +//#ifdef ATOMIC_USER +// if (atomicUser) +// SetupAtomicUser(ctx, ssl); +//#endif +//#ifdef HAVE_PK_CALLBACKS +// if (pkCallbacks) +// SetupPkCallbacks(ctx, ssl); +//#endif +// if (matchName && doPeerCheck) +// wolfSSL_check_domain_name(ssl, domain); + + if (wolfSSL_connect(ssl) != SSL_SUCCESS) { +// /* see note at top of README */ +// int err = wolfSSL_get_error(ssl, 0); +// char buffer[WOLFSSL_MAX_ERROR_SZ]; +// say("err = %d, %s\n", err, +// wolfSSL_ERR_error_string(err, buffer)); + err_sys("SSL_connect failed"); + } +// showPeer(ssl); + +//#ifdef HAVE_SECURE_RENEGOTIATION +// if (scr && forceScr) { +// if (wolfSSL_Rehandshake(ssl) != SSL_SUCCESS) { +// int err = wolfSSL_get_error(ssl, 0); +// char buffer[WOLFSSL_MAX_ERROR_SZ]; +// say("err = %d, %s\n", err, +// wolfSSL_ERR_error_string(err, buffer)); +// err_sys("wolfSSL_Rehandshake failed"); +// } +// } +//#endif + + return ssl; +} + +static struct pollfd pfd[2] = { + { -1, POLLIN|POLLERR|POLLHUP, 0 }, + { -1, POLLIN|POLLERR|POLLHUP, 0 }, +}; +#define STDIN pfd[0] +#define NETWORK pfd[1] +#define STDIN_READY() (pfd[0].revents & (POLLIN|POLLERR|POLLHUP)) +#define NETWORK_READY() (pfd[1].revents & (POLLIN|POLLERR|POLLHUP)) + +static void wait_for_input(void) +{ + if (STDIN.fd == NETWORK.fd) /* means both are -1 */ + exit(0); + dbg("polling\n"); + STDIN.revents = NETWORK.revents = 0; + while (poll(pfd, 2, -1) < 0 && errno == EINTR) + continue; +} + +static void do_io_until_eof_and_exit(WOLFSSL *ssl, int fd) +{ + int len; + char ibuf[4 * 1024]; + + NETWORK.fd = fd; + STDIN.fd = 0; + + len = 0; /* only to suppress compiler warning */ + for (;;) { + wait_for_input(); + + if (STDIN_READY()) { + dbg("reading stdin\n"); + len = read(STDIN_FILENO, ibuf, sizeof(ibuf)); + if (len < 0) + die("read error on stdin\n"); + if (len == 0) { + dbg("read len = 0, stdin not polled anymore\n"); + STDIN.fd = -1; + } else { + int n = wolfSSL_write(ssl, ibuf, len); + if (n != len) + die("SSL_write(%d) failed (returned %d)\n", len, n); + } + } + + if (NETWORK_READY()) { + dbg("%s%s%s\n", + (pfd[1].revents & POLLIN) ? "POLLIN" : "", + (pfd[1].revents & POLLERR) ? "|POLLERR" : "", + (pfd[1].revents & POLLHUP) ? "|POLLHUP" : "" + ); +/* We are using blocking socket here. + * (Nonblocking socket would complicate writing to it). + * Therefore, SSL_read _can block_ here. + * This is not what wget expects (it wants to see short reads). + * Therefore, we use smallish buffer here, to approximate that. + */ + len = wolfSSL_read(ssl, ibuf, + sizeof(ibuf) < 1024 ? sizeof(ibuf) : 1024 + ); + if (len < 0) + die("SSL_read error on network (%d)\n", len); + if (len > 0) { + int n; + n = full_write(STDOUT_FILENO, ibuf, len); + if (n != len) + die("write(%d) to stdout returned %d\n", len, n); + continue; + } +/* Blocking reads are easier wtr EOF detection (no EAGAIN error to check for) */ + dbg("read len = 0, network not polled anymore\n"); + NETWORK.fd = -1; + /* saw EOF on network, and we processed + * and wrote out all ssl data. Signal it: + */ + close(STDOUT_FILENO); + } + } +} + +int main(int argc, char **argv) +{ + WOLFSSL *ssl; + int fd; + char *fd_str; + + if (!argv[1]) + die("Syntax error\n"); + if (argv[1][0] != '-') + die("Syntax error\n"); + if (argv[1][1] != 'd') + die("Syntax error\n"); + fd_str = argv[1] + 2; + if (!fd_str[0]) + fd_str = argv[2]; + if (!fd_str || fd_str[0] < '0' || fd_str[0] > '9') + die("Syntax error\n"); + + fd = atoi(fd_str); + if (fd < 3) + die("Syntax error\n"); + + ssl = prepare(fd); + do_io_until_eof_and_exit(ssl, fd); + /* does not return */ + +// if (doDTLS == 0) { /* don't send alert after "break" command */ +// ret = wolfSSL_shutdown(ssl); +// if (wc_shutdown && ret == SSL_SHUTDOWN_NOT_DONE) +// wolfSSL_shutdown(ssl); /* bidirectional shutdown */ +// } +//#ifdef ATOMIC_USER +// if (atomicUser) +// FreeAtomicUser(ssl); +//#endif +// wolfSSL_free(ssl); +// CloseSocket(sockfd); +// wolfSSL_CTX_free(ctx); + + return 0; +} diff --git a/networking/ssl_helper-wolfssl/ssl_helper.sh b/networking/ssl_helper-wolfssl/ssl_helper.sh new file mode 100755 index 000000000..ddb4536c7 --- /dev/null +++ b/networking/ssl_helper-wolfssl/ssl_helper.sh @@ -0,0 +1,11 @@ +#!/bin/sh + +# I use this to build static uclibc based binary using Aboriginal Linux toolchain: +PREFIX=x86_64- +STATIC=-static +# Standard build: +#PREFIX="" +#STATIC="" + +${PREFIX}gcc -Os -Wall -I.. -c ssl_helper.c -o ssl_helper.o +${PREFIX}gcc $STATIC --start-group ssl_helper.o -lm ../src/.libs/libwolfssl.a --end-group -o ssl_helper diff --git a/networking/wget.c b/networking/wget.c index f744ea2de..baa7e0e78 100644 --- a/networking/wget.c +++ b/networking/wget.c @@ -9,6 +9,89 @@ * Kuhn's copyrights are licensed GPLv2-or-later. File as a whole remains GPLv2. */ +//config:config WGET +//config: bool "wget" +//config: default y +//config: help +//config: wget is a utility for non-interactive download of files from HTTP +//config: and FTP servers. +//config: +//config:config FEATURE_WGET_STATUSBAR +//config: bool "Enable a nifty process meter (+2k)" +//config: default y +//config: depends on WGET +//config: help +//config: Enable the transfer progress bar for wget transfers. +//config: +//config:config FEATURE_WGET_AUTHENTICATION +//config: bool "Enable HTTP authentication" +//config: default y +//config: depends on WGET +//config: help +//config: Support authenticated HTTP transfers. +//config: +//config:config FEATURE_WGET_LONG_OPTIONS +//config: bool "Enable long options" +//config: default y +//config: depends on WGET && LONG_OPTS +//config: help +//config: Support long options for the wget applet. +//config: +//config:config FEATURE_WGET_TIMEOUT +//config: bool "Enable timeout option -T SEC" +//config: default y +//config: depends on WGET +//config: help +//config: Supports network read and connect timeouts for wget, +//config: so that wget will give up and timeout, through the -T +//config: command line option. +//config: +//config: Currently only connect and network data read timeout are +//config: supported (i.e., timeout is not applied to the DNS query). When +//config: FEATURE_WGET_LONG_OPTIONS is also enabled, the --timeout option +//config: will work in addition to -T. +//config: +//config:choice +//config: prompt "Choose how to handle https:// URLs" +//config: depends on WGET +//config: default FEATURE_WGET_OPENSSL +//config: help +//config: Choose how wget establishes SSL connection for https:// URLs. +//config: +//config: Busybox itself contains no SSL code. wget will spawn +//config: a helper program to talk over HTTPS. +//config: +//config: OpenSSL has a simple SSL client for debug purposes. +//config: If you select "openssl" helper, wget will effectively call +//config: "openssl s_client -quiet -connect IP:443 2>/dev/null" +//config: and pipe its data through it. +//config: Note inconvenient API: host resolution is done twice, +//config: and there is no guarantee openssl's idea of IPv6 address +//config: format is the same as ours. +//config: Another problem is that s_client prints debug information +//config: to stderr, and it needs to be suppressed. This means +//config: all error messages get suppressed too. +//config: openssl is also a big binary, often dynamically linked +//config: against ~15 libraries. +//config: +//config: ssl_helper is a tool which can be built statically +//config: from busybox sources against a small embedded SSL library. +//config: Please see networking/ssl_helper/README. +//config: It does not require double host resolution and emits +//config: error messages to stderr. +//config: +//config:config FEATURE_WGET_OPENSSL +//config: bool "openssl" +//config: +//config:config FEATURE_WGET_SSL_HELPER +//config: bool "ssl_helper" +//config: +//config:endchoice + +//applet:IF_WGET(APPLET(wget, BB_DIR_USR_BIN, BB_SUID_DROP)) + +//kbuild:lib-$(CONFIG_WGET) += wget.o + //usage:#define wget_trivial_usage //usage: IF_FEATURE_WGET_LONG_OPTIONS( //usage: "[-c|--continue] [-s|--spider] [-q|--quiet] [-O|--output-document FILE]\n" @@ -520,6 +603,7 @@ static FILE* prepare_ftp_session(FILE **dfpp, struct host_info *target, len_and_ return sfp; } +#if ENABLE_FEATURE_WGET_OPENSSL static int spawn_https_helper(const char *host, unsigned port) { char *allocated = NULL; @@ -569,12 +653,11 @@ static int spawn_https_helper(const char *host, unsigned port) close(sp[1]); return sp[0]; } +#endif -/* See networking/ssl_helper/README */ -#define SSL_HELPER 0 - -#if SSL_HELPER -static void spawn_https_helper1(int network_fd) +/* See networking/ssl_helper/README how to build one */ +#if ENABLE_FEATURE_WGET_SSL_HELPER +static void spawn_https_helper(int network_fd) { int sp[2]; int pid; @@ -851,19 +934,21 @@ static void download_one_url(const char *url) int status; /* Open socket to http(s) server */ +#if ENABLE_FEATURE_WGET_OPENSSL if (target.protocol == P_HTTPS) { -/* openssl-based helper - * Inconvenient API since we can't give it an open fd - */ + /* openssl-based helper + * Inconvenient API since we can't give it an open fd + */ int fd = spawn_https_helper(server.host, server.port); sfp = fdopen(fd, "r+"); if (!sfp) bb_perror_msg_and_die(bb_msg_memory_exhausted); } else +#endif sfp = open_socket(lsa); -#if SSL_HELPER +#if ENABLE_FEATURE_WGET_SSL_HELPER if (target.protocol == P_HTTPS) - spawn_https_helper1(fileno(sfp)); + spawn_https_helper(fileno(sfp)); #endif /* Send HTTP request */ if (use_proxy) { -- cgit v1.2.3-55-g6feb From 5711a2a4ad51ad203a2ed4ffc72593e83920b36a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Wed, 7 Oct 2015 17:55:33 +0200 Subject: libbb: more compact API for bb_parse_mode() function old new delta make_device 2182 2188 +6 parse_command 1440 1443 +3 parse_params 1497 1499 +2 install_main 773 769 -4 mkdir_main 168 160 -8 getoptscmd 641 632 -9 builtin_umask 158 147 -11 bb_parse_mode 431 410 -21 umaskcmd 286 258 -28 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 3/6 up/down: 11/-81) Total: -70 bytes Signed-off-by: Denys Vlasenko --- coreutils/chmod.c | 4 ++-- coreutils/install.c | 2 +- coreutils/libcoreutils/getopt_mk_fifo_nod.c | 4 +++- coreutils/mkdir.c | 4 ++-- findutils/find.c | 3 ++- include/libbb.h | 3 ++- libbb/parse_mode.c | 16 +++++++--------- shell/ash.c | 3 ++- shell/hush.c | 7 ++++--- util-linux/mdev.c | 2 +- 10 files changed, 26 insertions(+), 22 deletions(-) (limited to 'include') diff --git a/coreutils/chmod.c b/coreutils/chmod.c index 5ee45b942..a21c6d501 100644 --- a/coreutils/chmod.c +++ b/coreutils/chmod.c @@ -69,9 +69,9 @@ static int FAST_FUNC fileAction(const char *fileName, struct stat *statbuf, void if (S_ISLNK(statbuf->st_mode)) return TRUE; } - newmode = statbuf->st_mode; - if (!bb_parse_mode((char *)param, &newmode)) + newmode = bb_parse_mode((char *)param, statbuf->st_mode); + if (newmode == (mode_t)-1) bb_error_msg_and_die("invalid mode '%s'", (char *)param); if (chmod(fileName, newmode) == 0) { diff --git a/coreutils/install.c b/coreutils/install.c index 73f9c70d5..8aa51cc34 100644 --- a/coreutils/install.c +++ b/coreutils/install.c @@ -159,7 +159,7 @@ int install_main(int argc, char **argv) } mode = 0755; /* GNU coreutils 6.10 compat */ if (opts & OPT_MODE) - bb_parse_mode(mode_str, &mode); + mode = bb_parse_mode(mode_str, mode); uid = (opts & OPT_OWNER) ? get_ug_id(uid_str, xuname2uid) : getuid(); gid = (opts & OPT_GROUP) ? get_ug_id(gid_str, xgroup2gid) : getgid(); diff --git a/coreutils/libcoreutils/getopt_mk_fifo_nod.c b/coreutils/libcoreutils/getopt_mk_fifo_nod.c index 222717149..47375ff91 100644 --- a/coreutils/libcoreutils/getopt_mk_fifo_nod.c +++ b/coreutils/libcoreutils/getopt_mk_fifo_nod.c @@ -33,7 +33,9 @@ mode_t FAST_FUNC getopt_mk_fifo_nod(char **argv) int opt; opt = getopt32(argv, "m:" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext)); if (opt & 1) { - if (bb_parse_mode(smode, &mode)) + mode = bb_parse_mode(smode, mode); + if (mode != (mode_t)-1) /* if mode is valid */ + /* make future mknod/mkfifo set mode bits exactly */ umask(0); } diff --git a/coreutils/mkdir.c b/coreutils/mkdir.c index 864edfb0a..6f7b004dd 100644 --- a/coreutils/mkdir.c +++ b/coreutils/mkdir.c @@ -71,8 +71,8 @@ int mkdir_main(int argc UNUSED_PARAM, char **argv) #endif opt = getopt32(argv, "m:pv" IF_SELINUX("Z:"), &smode IF_SELINUX(,&scontext)); if (opt & 1) { - mode_t mmode = 0777; - if (!bb_parse_mode(smode, &mmode)) { + mode_t mmode = bb_parse_mode(smode, 0777); + if (mmode == (mode_t)-1) { bb_error_msg_and_die("invalid mode '%s'", smode); } mode = mmode; diff --git a/findutils/find.c b/findutils/find.c index ced8922e7..f72cad7d1 100644 --- a/findutils/find.c +++ b/findutils/find.c @@ -1261,7 +1261,8 @@ static action*** parse_params(char **argv) ap->perm_char = arg1[0]; 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)) + ap->perm_mask = bb_parse_mode(arg1, ap->perm_mask); + if (ap->perm_mask == (mode_t)-1) bb_error_msg_and_die("invalid mode '%s'", arg1); } #endif diff --git a/include/libbb.h b/include/libbb.h index 543214ea4..d79843a2d 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1251,7 +1251,8 @@ char *bb_ask_stdin(const char * prompt) FAST_FUNC; char *bb_ask(const int fd, int timeout, const char * prompt) FAST_FUNC; int bb_ask_confirmation(void) FAST_FUNC; -int bb_parse_mode(const char* s, mode_t* theMode) FAST_FUNC; +/* Returns -1 if input is invalid. current_mode is a base for e.g. "u+rw" */ +int bb_parse_mode(const char* s, unsigned cur_mode) FAST_FUNC; /* * Config file parser diff --git a/libbb/parse_mode.c b/libbb/parse_mode.c index 5a4e1c579..bddd39bca 100644 --- a/libbb/parse_mode.c +++ b/libbb/parse_mode.c @@ -15,7 +15,7 @@ #define FILEMODEBITS (S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO) -int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode) +int FAST_FUNC bb_parse_mode(const char *s, unsigned current_mode) { static const mode_t who_mask[] = { S_ISUID | S_ISGID | S_ISVTX | S_IRWXU | S_IRWXG | S_IRWXO, /* a */ @@ -46,13 +46,12 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode) tmp = strtoul(s, &e, 8); if (*e || (tmp > 07777U)) { /* Check range and trailing chars. */ - return 0; + return -1; } - *current_mode = tmp; - return 1; + return tmp; } - new_mode = *current_mode; + new_mode = current_mode; /* Note: we allow empty clauses, and hence empty modes. * We treat an empty mode as no change to perms. */ @@ -71,7 +70,7 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode) if (*p == *s) { wholist |= who_mask[(int)(p-who_chars)]; if (!*++s) { - return 0; + return -1; } goto WHO_LIST; } @@ -80,7 +79,7 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode) do { /* Process action list. */ if ((*s != '+') && (*s != '-')) { if (*s != '=') { - return 0; + return -1; } /* Since op is '=', clear all bits corresponding to the * wholist, or all file bits if wholist is empty. */ @@ -145,6 +144,5 @@ int FAST_FUNC bb_parse_mode(const char *s, mode_t *current_mode) } while (*s && (*s != ',')); } - *current_mode = new_mode; - return 1; + return new_mode; } diff --git a/shell/ash.c b/shell/ash.c index 80dfc1d6a..ab8ec006f 100644 --- a/shell/ash.c +++ b/shell/ash.c @@ -12862,7 +12862,8 @@ umaskcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM) /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */ if (!isdigit(modestr[0])) mask ^= 0777; - if (!bb_parse_mode(modestr, &mask) || (unsigned)mask > 0777) { + mask = bb_parse_mode(modestr, mask); + if ((unsigned)mask > 0777) { ash_msg_and_raise_error("illegal mode: %s", modestr); } if (!isdigit(modestr[0])) diff --git a/shell/hush.c b/shell/hush.c index 8b8d5fc8b..bccd9c1e9 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -8965,6 +8965,7 @@ static int FAST_FUNC builtin_umask(char **argv) int rc; mode_t mask; + rc = 1; mask = umask(0); argv = skip_dash_dash(argv); if (argv[0]) { @@ -8974,19 +8975,19 @@ static int FAST_FUNC builtin_umask(char **argv) /* symbolic umasks are inverted: "umask a=rx" calls umask(222) */ if (!isdigit(argv[0][0])) mask ^= 0777; - rc = bb_parse_mode(argv[0], &mask); + mask = bb_parse_mode(argv[0], mask); if (!isdigit(argv[0][0])) mask ^= 0777; - if (rc == 0 || (unsigned)mask > 0777) { + if ((unsigned)mask > 0777) { mask = old_mask; /* bash messages: * bash: umask: 'q': invalid symbolic mode operator * bash: umask: 999: octal number out of range */ bb_error_msg("%s: invalid mode '%s'", "umask", argv[0]); + rc = 0; } } else { - rc = 1; /* Mimic bash */ printf("%04o\n", (unsigned) mask); /* fall through and restore mask which we set to 0 */ diff --git a/util-linux/mdev.c b/util-linux/mdev.c index 662e8ab38..51781d597 100644 --- a/util-linux/mdev.c +++ b/util-linux/mdev.c @@ -406,7 +406,7 @@ static void parse_next_rule(void) } /* 3rd field: mode - device permissions */ - bb_parse_mode(tokens[2], &G.cur_rule.mode); + G.cur_rule.mode = bb_parse_mode(tokens[2], G.cur_rule.mode); /* 4th field (opt): ">|=alias" or "!" to not create the node */ val = tokens[3]; -- cgit v1.2.3-55-g6feb From 550bf5b4a418378cd8f9fbbf5252fe57acdacb5a Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 9 Oct 2015 16:42:57 +0200 Subject: remove global "jmp_buf die_jmp" from !FEATURE_PREFER_APPLETS builds function old new delta xfunc_has_died - 21 +21 sleep_much - 12 +12 sleep10 - 9 +9 die_func - 4 +4 fflush_stdout_and_exit 35 36 +1 builtin_type 121 119 -2 die_sleep 4 - -4 xfunc_die 60 24 -36 hush_main 1128 1011 -117 die_jmp 156 - -156 ------------------------------------------------------------------------------ (add/remove: 4/2 grow/shrink: 1/3 up/down: 47/-315) Total: -268 bytes text data bss dec hex filename 939992 992 17652 958636 ea0ac busybox_old 939880 992 17496 958368 e9fa0 busybox_unstripped Signed-off-by: Denys Vlasenko --- include/libbb.h | 3 +-- init/init.c | 9 +++++++-- libbb/fflush_stdout_and_exit.c | 13 ++++--------- libbb/vfork_daemon_rexec.c | 39 +++++++++++++++++++++++++-------------- libbb/xfunc_die.c | 26 ++++---------------------- loginutils/getty.c | 7 ++++++- shell/hush.c | 25 ++++++++++++++----------- 7 files changed, 61 insertions(+), 61 deletions(-) (limited to 'include') diff --git a/include/libbb.h b/include/libbb.h index d79843a2d..2f24ecbc3 100644 --- a/include/libbb.h +++ b/include/libbb.h @@ -1127,9 +1127,8 @@ enum { extern const char *msg_eol; extern smallint syslog_level; extern smallint logmode; -extern int die_sleep; extern uint8_t xfunc_error_retval; -extern jmp_buf die_jmp; +extern void (*die_func)(void); extern void xfunc_die(void) NORETURN FAST_FUNC; extern void bb_show_usage(void) NORETURN FAST_FUNC; extern void bb_error_msg(const char *s, ...) __attribute__ ((format (printf, 1, 2))) FAST_FUNC; diff --git a/init/init.c b/init/init.c index b2fe85635..80c5d0f74 100644 --- a/init/init.c +++ b/init/init.c @@ -1015,6 +1015,11 @@ void handle_sigsegv(int sig, siginfo_t *info, void *ucontext) } #endif +static void sleep_much(void) +{ + sleep(30 * 24*60*60); +} + int init_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int init_main(int argc UNUSED_PARAM, char **argv) { @@ -1051,12 +1056,12 @@ int init_main(int argc UNUSED_PARAM, char **argv) /* If, say, xmalloc would ever die, we don't want to oops kernel * by exiting. - * NB: we set die_sleep *after* PID 1 check and bb_show_usage. + * NB: we set die_func *after* PID 1 check and bb_show_usage. * Otherwise, for example, "init u" ("please rexec yourself" * command for sysvinit) will show help text (which isn't too bad), * *and sleep forever* (which is bad!) */ - die_sleep = 30 * 24*60*60; + die_func = sleep_much; /* Figure out where the default console should be */ console_init(); diff --git a/libbb/fflush_stdout_and_exit.c b/libbb/fflush_stdout_and_exit.c index 9ad5dbf96..b4bed865f 100644 --- a/libbb/fflush_stdout_and_exit.c +++ b/libbb/fflush_stdout_and_exit.c @@ -15,15 +15,10 @@ void FAST_FUNC fflush_stdout_and_exit(int retval) { + xfunc_error_retval = retval; if (fflush(stdout)) bb_perror_msg_and_die(bb_msg_standard_output); - - if (ENABLE_FEATURE_PREFER_APPLETS && die_sleep < 0) { - /* We are in NOFORK applet. Do not exit() directly, - * but use xfunc_die() */ - xfunc_error_retval = retval; - xfunc_die(); - } - - exit(retval); + /* In case we are in NOFORK applet. Do not exit() directly, + * but use xfunc_die() */ + xfunc_die(); } diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c index ed1f86f0c..d6ca7b263 100644 --- a/libbb/vfork_daemon_rexec.c +++ b/libbb/vfork_daemon_rexec.c @@ -69,28 +69,44 @@ pid_t FAST_FUNC xspawn(char **argv) } #if ENABLE_FEATURE_PREFER_APPLETS +static jmp_buf die_jmp; +static void jump(void) +{ + /* Special case. We arrive here if NOFORK applet + * calls xfunc, which then decides to die. + * We don't die, but jump instead back to caller. + * NOFORK applets still cannot carelessly call xfuncs: + * p = xmalloc(10); + * q = xmalloc(10); // BUG! if this dies, we leak p! + */ + /* | 0x100 allows to pass zero exitcode (longjmp can't pass 0). + * This works because exitcodes are bytes, + * run_nofork_applet() ensures that by "& 0xff" */ + longjmp(die_jmp, xfunc_error_retval | 0x100); +} + struct nofork_save_area { jmp_buf die_jmp; + void (*die_func)(void); const char *applet_name; uint32_t option_mask32; - int die_sleep; uint8_t xfunc_error_retval; }; static void save_nofork_data(struct nofork_save_area *save) { memcpy(&save->die_jmp, &die_jmp, sizeof(die_jmp)); + save->die_func = die_func; save->applet_name = applet_name; - save->xfunc_error_retval = xfunc_error_retval; save->option_mask32 = option_mask32; - save->die_sleep = die_sleep; + save->xfunc_error_retval = xfunc_error_retval; } static void restore_nofork_data(struct nofork_save_area *save) { memcpy(&die_jmp, &save->die_jmp, sizeof(die_jmp)); + die_func = save->die_func; applet_name = save->applet_name; - xfunc_error_retval = save->xfunc_error_retval; option_mask32 = save->option_mask32; - die_sleep = save->die_sleep; + xfunc_error_retval = save->xfunc_error_retval; } int FAST_FUNC run_nofork_applet(int applet_no, char **argv) @@ -133,11 +149,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) while (argv[argc]) argc++; - /* Special flag for xfunc_die(). If xfunc will "die" - * in NOFORK applet, xfunc_die() sees negative - * die_sleep and longjmp here instead. */ - die_sleep = -1; - + /* If xfunc "dies" in NOFORK applet, die_func longjmp's here instead */ + die_func = jump; rc = setjmp(die_jmp); if (!rc) { /* Some callers (xargs) @@ -146,10 +159,8 @@ int FAST_FUNC run_nofork_applet(int applet_no, char **argv) memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); /* Finally we can call NOFORK applet's main() */ rc = applet_main[applet_no](argc, tmp_argv); - } else { /* xfunc died in NOFORK applet */ - /* in case they meant to return 0... */ - if (rc == -2222) - rc = 0; + } else { + /* xfunc died in NOFORK applet */ } /* Restoring some globals */ diff --git a/libbb/xfunc_die.c b/libbb/xfunc_die.c index 204e5e49d..73f7998e5 100644 --- a/libbb/xfunc_die.c +++ b/libbb/xfunc_die.c @@ -7,34 +7,16 @@ * Licensed under GPLv2, see file LICENSE in this source tree. */ -/* Keeping it separate allows to NOT suck in stdio for VERY small applets. +/* Keeping it separate allows to NOT pull in stdio for VERY small applets. * Try building busybox with only "true" enabled... */ #include "libbb.h" -int die_sleep; -#if ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH -jmp_buf die_jmp; -#endif +void (*die_func)(void); void FAST_FUNC xfunc_die(void) { - if (die_sleep) { - if ((ENABLE_FEATURE_PREFER_APPLETS || ENABLE_HUSH) - && die_sleep < 0 - ) { - /* Special case. We arrive here if NOFORK applet - * calls xfunc, which then decides to die. - * We don't die, but jump instead back to caller. - * NOFORK applets still cannot carelessly call xfuncs: - * p = xmalloc(10); - * q = xmalloc(10); // BUG! if this dies, we leak p! - */ - /* -2222 means "zero" (longjmp can't pass 0) - * run_nofork_applet() catches -2222. */ - longjmp(die_jmp, xfunc_error_retval ? xfunc_error_retval : -2222); - } - sleep(die_sleep); - } + if (die_func) + die_func(); exit(xfunc_error_retval); } diff --git a/loginutils/getty.c b/loginutils/getty.c index 174542841..762d5c773 100644 --- a/loginutils/getty.c +++ b/loginutils/getty.c @@ -520,6 +520,11 @@ static void alarm_handler(int sig UNUSED_PARAM) _exit(EXIT_SUCCESS); } +static void sleep10(void) +{ + sleep(10); +} + int getty_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; int getty_main(int argc UNUSED_PARAM, char **argv) { @@ -599,7 +604,7 @@ int getty_main(int argc UNUSED_PARAM, char **argv) close(n--); /* Logging. We want special flavor of error_msg_and_die */ - die_sleep = 10; + die_func = sleep10; msg_eol = "\r\n"; /* most likely will internally use fd #3 in CLOEXEC mode: */ openlog(applet_name, LOG_PID, LOG_AUTH); diff --git a/shell/hush.c b/shell/hush.c index f085ed3eb..0d107715f 100644 --- a/shell/hush.c +++ b/shell/hush.c @@ -1479,10 +1479,11 @@ static sighandler_t install_sighandler(int sig, sighandler_t handler) #if ENABLE_HUSH_JOB +static void xfunc_has_died(void); /* After [v]fork, in child: do not restore tty pgrp on xfunc death */ -# define disable_restore_tty_pgrp_on_exit() (die_sleep = 0) +# define disable_restore_tty_pgrp_on_exit() (die_func = NULL) /* After [v]fork, in parent: restore tty pgrp on xfunc death */ -# define enable_restore_tty_pgrp_on_exit() (die_sleep = -1) +# define enable_restore_tty_pgrp_on_exit() (die_func = xfunc_has_died) /* Restores tty foreground process group, and exits. * May be called as signal handler for fatal signal @@ -1587,6 +1588,15 @@ static void hush_exit(int exitcode) #endif } +static void xfunc_has_died(void) NORETURN; +static void xfunc_has_died(void) +{ + /* xfunc has failed! die die die */ + /* no EXIT traps, this is an escape hatch! */ + G.exiting = 1; + hush_exit(xfunc_error_retval); +} + //TODO: return a mask of ALL handled sigs? static int check_and_run_traps(void) @@ -7866,12 +7876,7 @@ int hush_main(int argc, char **argv) /* Initialize some more globals to non-zero values */ cmdedit_update_prompt(); - if (setjmp(die_jmp)) { - /* xfunc has failed! die die die */ - /* no EXIT traps, this is an escape hatch! */ - G.exiting = 1; - hush_exit(xfunc_error_retval); - } + die_func = xfunc_has_died; /* Shell is non-interactive at first. We need to call * install_special_sighandlers() if we are going to execute "sh