diff options
| author | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-12 23:13:50 +0000 |
|---|---|---|
| committer | Denis Vlasenko <vda.linux@googlemail.com> | 2008-03-12 23:13:50 +0000 |
| commit | 4cf1d08fc2e50f9abda999d468c5e972ff4995c2 (patch) | |
| tree | 58dd8efdd7d0f0990d30d8b5f5f53cf2ee35d444 | |
| parent | 4e6d5117b839cef41cd3919966f95bf25d24d8d9 (diff) | |
| download | busybox-w32-4cf1d08fc2e50f9abda999d468c5e972ff4995c2.tar.gz busybox-w32-4cf1d08fc2e50f9abda999d468c5e972ff4995c2.tar.bz2 busybox-w32-4cf1d08fc2e50f9abda999d468c5e972ff4995c2.zip | |
nc: remove a bit of bloat
inetd: more NOMMU fixes
rx: shrink
devfsd: minor shrink
vlock: shrink
tcpudp: narrow down window where we have no wildcard socket
parse_one_line 1015 1102 +87
init_ring - 53 +53
xzalloc_lsa - 48 +48
read_byte 51 50 -1
rearm_alarm 28 25 -3
nc_main 1028 1000 -28
initring 53 - -53
vlock_main 583 496 -87
reread_config_file 1089 991 -98
rx_main 1046 912 -134
------------------------------------------------------------------------------
(add/remove: 2/1 grow/shrink: 1/6 up/down: 188/-404) Total: -216 bytes
text data bss dec hex filename
800120 661 7428 808209 c5511 busybox_old
799796 661 7428 807885 c53cd busybox_unstripped
| -rw-r--r-- | ipsvd/tcpudp.c | 12 | ||||
| -rw-r--r-- | libbb/signals.c | 7 | ||||
| -rw-r--r-- | loginutils/vlock.c | 84 | ||||
| -rw-r--r-- | miscutils/devfsd.c | 9 | ||||
| -rw-r--r-- | miscutils/rx.c | 232 | ||||
| -rw-r--r-- | networking/inetd.c | 258 | ||||
| -rw-r--r-- | networking/nc_bloaty.c | 7 |
7 files changed, 308 insertions, 301 deletions
diff --git a/ipsvd/tcpudp.c b/ipsvd/tcpudp.c index cb57e598a..8b4ae88f4 100644 --- a/ipsvd/tcpudp.c +++ b/ipsvd/tcpudp.c | |||
| @@ -339,16 +339,17 @@ int tcpudpsvd_main(int argc, char **argv) | |||
| 339 | * 1) we have to do it before fork() | 339 | * 1) we have to do it before fork() |
| 340 | * 2) order is important - is it right now? */ | 340 | * 2) order is important - is it right now? */ |
| 341 | 341 | ||
| 342 | /* Make plain write/send work for this socket by supplying default | 342 | /* Open new non-connected UDP socket for further clients... */ |
| 343 | sock = xsocket(lsa->u.sa.sa_family, SOCK_DGRAM, 0); | ||
| 344 | setsockopt_reuseaddr(sock); | ||
| 345 | /* Make plain write/send work for old socket by supplying default | ||
| 343 | * destination address. This also restricts incoming packets | 346 | * destination address. This also restricts incoming packets |
| 344 | * to ones coming from this remote IP. */ | 347 | * to ones coming from this remote IP. */ |
| 345 | xconnect(0, &remote.u.sa, sa_len); | 348 | xconnect(0, &remote.u.sa, sa_len); |
| 346 | /* hole? at this point we have no wildcard udp socket... | 349 | /* hole? at this point we have no wildcard udp socket... |
| 347 | * can this cause clients to get "port unreachable" icmp? | 350 | * can this cause clients to get "port unreachable" icmp? |
| 348 | * Yup, time window is very small, but it exists (is it?) */ | 351 | * Yup, time window is very small, but it exists (is it?) */ |
| 349 | /* Open new non-connected UDP socket for further clients */ | 352 | /* ..."open new socket", continued */ |
| 350 | sock = xsocket(lsa->u.sa.sa_family, tcp ? SOCK_STREAM : SOCK_DGRAM, 0); | ||
| 351 | setsockopt_reuseaddr(sock); | ||
| 352 | xbind(sock, &lsa->u.sa, sa_len); | 353 | xbind(sock, &lsa->u.sa, sa_len); |
| 353 | socket_want_pktinfo(sock); | 354 | socket_want_pktinfo(sock); |
| 354 | 355 | ||
| @@ -377,7 +378,6 @@ int tcpudpsvd_main(int argc, char **argv) | |||
| 377 | goto again; | 378 | goto again; |
| 378 | } | 379 | } |
| 379 | 380 | ||
| 380 | |||
| 381 | if (pid != 0) { | 381 | if (pid != 0) { |
| 382 | /* parent */ | 382 | /* parent */ |
| 383 | cnum++; | 383 | cnum++; |
| @@ -467,7 +467,7 @@ int tcpudpsvd_main(int argc, char **argv) | |||
| 467 | 467 | ||
| 468 | argv += 2; | 468 | argv += 2; |
| 469 | #ifdef SSLSVD | 469 | #ifdef SSLSVD |
| 470 | strcpy(id, utoa(pid); | 470 | strcpy(id, utoa(pid)); |
| 471 | ssl_io(0, argv); | 471 | ssl_io(0, argv); |
| 472 | #else | 472 | #else |
| 473 | BB_EXECVP(argv[0], argv); | 473 | BB_EXECVP(argv[0], argv); |
diff --git a/libbb/signals.c b/libbb/signals.c index 1929cb88e..a327e87c8 100644 --- a/libbb/signals.c +++ b/libbb/signals.c | |||
| @@ -82,13 +82,8 @@ void sig_pause(void) | |||
| 82 | /* Assuming the sig is fatal */ | 82 | /* Assuming the sig is fatal */ |
| 83 | void kill_myself_with_sig(int sig) | 83 | void kill_myself_with_sig(int sig) |
| 84 | { | 84 | { |
| 85 | sigset_t set; | ||
| 86 | |||
| 87 | signal(sig, SIG_DFL); | 85 | signal(sig, SIG_DFL); |
| 88 | 86 | sig_unblock(sig); | |
| 89 | sigemptyset(&set); | ||
| 90 | sigaddset(&set, sig); | ||
| 91 | sigprocmask(SIG_UNBLOCK, &set, NULL); | ||
| 92 | raise(sig); | 87 | raise(sig); |
| 93 | _exit(1); /* Should not reach it */ | 88 | _exit(1); /* Should not reach it */ |
| 94 | } | 89 | } |
diff --git a/loginutils/vlock.c b/loginutils/vlock.c index 6e928e239..846733ea8 100644 --- a/loginutils/vlock.c +++ b/loginutils/vlock.c | |||
| @@ -1,5 +1,4 @@ | |||
| 1 | /* vi: set sw=4 ts=4: */ | 1 | /* vi: set sw=4 ts=4: */ |
| 2 | |||
| 3 | /* | 2 | /* |
| 4 | * vlock implementation for busybox | 3 | * vlock implementation for busybox |
| 5 | * | 4 | * |
| @@ -16,27 +15,25 @@ | |||
| 16 | /* Fixed by Erik Andersen to do passwords the tinylogin way... | 15 | /* Fixed by Erik Andersen to do passwords the tinylogin way... |
| 17 | * It now works with md5, sha1, etc passwords. */ | 16 | * It now works with md5, sha1, etc passwords. */ |
| 18 | 17 | ||
| 19 | #include "libbb.h" | ||
| 20 | #include <sys/vt.h> | 18 | #include <sys/vt.h> |
| 21 | 19 | #include "libbb.h" | |
| 22 | enum { vfd = 3 }; | ||
| 23 | |||
| 24 | /* static unsigned long o_lock_all; */ | ||
| 25 | 20 | ||
| 26 | static void release_vt(int signo) | 21 | static void release_vt(int signo) |
| 27 | { | 22 | { |
| 28 | ioctl(vfd, VT_RELDISP, (unsigned long) !option_mask32 /*!o_lock_all*/); | 23 | /* If -a, param is 0, which means: |
| 24 | * "no, kernel, we don't allow console switch away from us!" */ | ||
| 25 | ioctl(STDIN_FILENO, VT_RELDISP, (unsigned long) !option_mask32); | ||
| 29 | } | 26 | } |
| 30 | 27 | ||
| 31 | static void acquire_vt(int signo) | 28 | static void acquire_vt(int signo) |
| 32 | { | 29 | { |
| 33 | ioctl(vfd, VT_RELDISP, VT_ACKACQ); | 30 | /* ACK to kernel that switch to console is successful */ |
| 31 | ioctl(STDIN_FILENO, VT_RELDISP, VT_ACKACQ); | ||
| 34 | } | 32 | } |
| 35 | 33 | ||
| 36 | int vlock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 34 | int vlock_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 37 | int vlock_main(int argc, char **argv) | 35 | int vlock_main(int argc, char **argv) |
| 38 | { | 36 | { |
| 39 | sigset_t sig; | ||
| 40 | struct sigaction sa; | 37 | struct sigaction sa; |
| 41 | struct vt_mode vtm; | 38 | struct vt_mode vtm; |
| 42 | struct termios term; | 39 | struct termios term; |
| @@ -48,49 +45,48 @@ int vlock_main(int argc, char **argv) | |||
| 48 | uid = getuid(); | 45 | uid = getuid(); |
| 49 | pw = getpwuid(uid); | 46 | pw = getpwuid(uid); |
| 50 | if (pw == NULL) | 47 | if (pw == NULL) |
| 51 | bb_error_msg_and_die("unknown uid %d", uid); | 48 | bb_error_msg_and_die("unknown uid %d", (int)uid); |
| 52 | 49 | ||
| 53 | if (argc > 2) { | 50 | opt_complementary = "=0"; /* no params! */ |
| 54 | bb_show_usage(); | 51 | getopt32(argv, "a"); |
| 55 | } | 52 | |
| 56 | 53 | /* Ignore some signals so that we don't get killed by them */ | |
| 57 | /*o_lock_all = */getopt32(argv, "a"); | 54 | bb_signals(0 |
| 58 | 55 | + (1 << SIGTSTP) | |
| 59 | /* Avoid using statics - use constant fd */ | 56 | + (1 << SIGTTIN) |
| 60 | xmove_fd(xopen(CURRENT_TTY, O_RDWR), vfd); | 57 | + (1 << SIGTTOU) |
| 61 | xioctl(vfd, VT_GETMODE, &vtm); | 58 | + (1 << SIGHUP ) |
| 62 | 59 | + (1 << SIGCHLD) /* paranoia :) */ | |
| 63 | /* mask a bunch of signals */ | 60 | + (1 << SIGQUIT) |
| 64 | sigprocmask(SIG_SETMASK, NULL, &sig); | 61 | + (1 << SIGINT ) |
| 65 | sigdelset(&sig, SIGUSR1); | 62 | , SIG_IGN); |
| 66 | sigdelset(&sig, SIGUSR2); | 63 | |
| 67 | sigaddset(&sig, SIGTSTP); | 64 | /* We will use SIGUSRx for console switch control: */ |
| 68 | sigaddset(&sig, SIGTTIN); | 65 | /* 1: set handlers */ |
| 69 | sigaddset(&sig, SIGTTOU); | 66 | sigemptyset(&sa.sa_mask); |
| 70 | sigaddset(&sig, SIGHUP); | ||
| 71 | sigaddset(&sig, SIGCHLD); | ||
| 72 | sigaddset(&sig, SIGQUIT); | ||
| 73 | sigaddset(&sig, SIGINT); | ||
| 74 | |||
| 75 | sigemptyset(&(sa.sa_mask)); | ||
| 76 | sa.sa_flags = SA_RESTART; | 67 | sa.sa_flags = SA_RESTART; |
| 77 | sa.sa_handler = release_vt; | 68 | sa.sa_handler = release_vt; |
| 78 | sigaction(SIGUSR1, &sa, NULL); | 69 | sigaction(SIGUSR1, &sa, NULL); |
| 79 | sa.sa_handler = acquire_vt; | 70 | sa.sa_handler = acquire_vt; |
| 80 | sigaction(SIGUSR2, &sa, NULL); | 71 | sigaction(SIGUSR2, &sa, NULL); |
| 81 | 72 | /* 2: unmask them */ | |
| 82 | /* need to handle some signals so that we don't get killed by them */ | 73 | sigprocmask(SIG_SETMASK, NULL, &sa.sa_mask); |
| 83 | sa.sa_handler = SIG_IGN; | 74 | sigdelset(&sa.sa_mask, SIGUSR1); |
| 84 | sigaction(SIGHUP, &sa, NULL); | 75 | sigdelset(&sa.sa_mask, SIGUSR2); |
| 85 | sigaction(SIGQUIT, &sa, NULL); | 76 | sigprocmask(SIG_SETMASK, &sa.sa_mask, NULL); |
| 86 | sigaction(SIGINT, &sa, NULL); | 77 | |
| 87 | sigaction(SIGTSTP, &sa, NULL); | 78 | /* Revert stdin/out to our controlling tty |
| 88 | 79 | * (or die if we have none) */ | |
| 80 | xmove_fd(xopen(CURRENT_TTY, O_RDWR), STDIN_FILENO); | ||
| 81 | xdup2(STDIN_FILENO, STDOUT_FILENO); | ||
| 82 | |||
| 83 | xioctl(STDIN_FILENO, VT_GETMODE, &vtm); | ||
| 89 | ovtm = vtm; | 84 | ovtm = vtm; |
| 85 | /* "console switches are controlled by us, not kernel!" */ | ||
| 90 | vtm.mode = VT_PROCESS; | 86 | vtm.mode = VT_PROCESS; |
| 91 | vtm.relsig = SIGUSR1; | 87 | vtm.relsig = SIGUSR1; |
| 92 | vtm.acqsig = SIGUSR2; | 88 | vtm.acqsig = SIGUSR2; |
| 93 | ioctl(vfd, VT_SETMODE, &vtm); | 89 | ioctl(STDIN_FILENO, VT_SETMODE, &vtm); |
| 94 | 90 | ||
| 95 | tcgetattr(STDIN_FILENO, &oterm); | 91 | tcgetattr(STDIN_FILENO, &oterm); |
| 96 | term = oterm; | 92 | term = oterm; |
| @@ -111,7 +107,7 @@ int vlock_main(int argc, char **argv) | |||
| 111 | puts("Password incorrect"); | 107 | puts("Password incorrect"); |
| 112 | } while (1); | 108 | } while (1); |
| 113 | 109 | ||
| 114 | ioctl(vfd, VT_SETMODE, &ovtm); | 110 | ioctl(STDIN_FILENO, VT_SETMODE, &ovtm); |
| 115 | tcsetattr(STDIN_FILENO, TCSANOW, &oterm); | 111 | tcsetattr(STDIN_FILENO, TCSANOW, &oterm); |
| 116 | fflush_stdout_and_exit(0); | 112 | fflush_stdout_and_exit(0); |
| 117 | } | 113 | } |
diff --git a/miscutils/devfsd.c b/miscutils/devfsd.c index 286f00fd8..50c8203cb 100644 --- a/miscutils/devfsd.c +++ b/miscutils/devfsd.c | |||
| @@ -386,15 +386,14 @@ int devfsd_main(int argc, char **argv) | |||
| 386 | /* Tell kernel we are special(i.e. we get to see hidden entries) */ | 386 | /* Tell kernel we are special(i.e. we get to see hidden entries) */ |
| 387 | xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, 0); | 387 | xioctl(fd, DEVFSDIOC_SET_EVENT_MASK, 0); |
| 388 | 388 | ||
| 389 | /* Set up SIGHUP and SIGUSR1 handlers */ | ||
| 389 | sigemptyset(&new_action.sa_mask); | 390 | sigemptyset(&new_action.sa_mask); |
| 390 | new_action.sa_flags = 0; | 391 | new_action.sa_flags = 0; |
| 391 | |||
| 392 | /* Set up SIGHUP and SIGUSR1 handlers */ | ||
| 393 | new_action.sa_handler = signal_handler; | 392 | new_action.sa_handler = signal_handler; |
| 394 | if (sigaction(SIGHUP, &new_action, NULL) != 0 || sigaction(SIGUSR1, &new_action, NULL) != 0) | 393 | sigaction(SIGHUP, &new_action, NULL); |
| 395 | bb_error_msg_and_die("sigaction"); | 394 | sigaction(SIGUSR1, &new_action, NULL); |
| 396 | 395 | ||
| 397 | printf("%s v%s started for %s\n",applet_name, DEVFSD_VERSION, mount_point); | 396 | printf("%s v%s started for %s\n", applet_name, DEVFSD_VERSION, mount_point); |
| 398 | 397 | ||
| 399 | /* Set umask so that mknod(2), open(2) and mkdir(2) have complete control over permissions */ | 398 | /* Set umask so that mknod(2), open(2) and mkdir(2) have complete control over permissions */ |
| 400 | umask(0); | 399 | umask(0); |
diff --git a/miscutils/rx.c b/miscutils/rx.c index 8ccea4974..9a8fcaa20 100644 --- a/miscutils/rx.c +++ b/miscutils/rx.c | |||
| @@ -16,7 +16,6 @@ | |||
| 16 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. | 16 | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
| 17 | * | 17 | * |
| 18 | * This was originally written for blob and then adapted for busybox. | 18 | * This was originally written for blob and then adapted for busybox. |
| 19 | * | ||
| 20 | */ | 19 | */ |
| 21 | 20 | ||
| 22 | #include "libbb.h" | 21 | #include "libbb.h" |
| @@ -29,66 +28,59 @@ | |||
| 29 | #define BS 0x08 | 28 | #define BS 0x08 |
| 30 | 29 | ||
| 31 | /* | 30 | /* |
| 32 | |||
| 33 | Cf: | 31 | Cf: |
| 34 | |||
| 35 | http://www.textfiles.com/apple/xmodem | 32 | http://www.textfiles.com/apple/xmodem |
| 36 | http://www.phys.washington.edu/~belonis/xmodem/docxmodem.txt | 33 | http://www.phys.washington.edu/~belonis/xmodem/docxmodem.txt |
| 37 | http://www.phys.washington.edu/~belonis/xmodem/docymodem.txt | 34 | http://www.phys.washington.edu/~belonis/xmodem/docymodem.txt |
| 38 | http://www.phys.washington.edu/~belonis/xmodem/modmprot.col | 35 | http://www.phys.washington.edu/~belonis/xmodem/modmprot.col |
| 39 | |||
| 40 | */ | 36 | */ |
| 41 | 37 | ||
| 42 | #define TIMEOUT 1 | 38 | #define TIMEOUT 1 |
| 43 | #define TIMEOUT_LONG 10 | 39 | #define TIMEOUT_LONG 10 |
| 44 | #define MAXERRORS 10 | 40 | #define MAXERRORS 10 |
| 45 | 41 | ||
| 46 | static int read_byte(int fd, unsigned timeout) | 42 | #define read_fd STDIN_FILENO |
| 43 | #define write_fd STDOUT_FILENO | ||
| 44 | |||
| 45 | static int read_byte(unsigned timeout) | ||
| 47 | { | 46 | { |
| 48 | char buf[1]; | 47 | char buf[1]; |
| 49 | int n; | 48 | int n; |
| 50 | 49 | ||
| 51 | alarm(timeout); | 50 | alarm(timeout); |
| 52 | 51 | /* NOT safe_read! We want ALRM to interrupt us */ | |
| 53 | n = read(fd, &buf, 1); | 52 | n = read(read_fd, buf, 1); |
| 54 | |||
| 55 | alarm(0); | 53 | alarm(0); |
| 56 | |||
| 57 | if (n == 1) | 54 | if (n == 1) |
| 58 | return buf[0] & 0xff; | 55 | return (unsigned char)buf[0]; |
| 59 | else | 56 | return -1; |
| 60 | return -1; | ||
| 61 | } | 57 | } |
| 62 | 58 | ||
| 63 | static int receive(char *error_buf, size_t error_buf_size, | 59 | static int receive(/*int read_fd, */int file_fd) |
| 64 | int ttyfd, int filefd) | ||
| 65 | { | 60 | { |
| 66 | char blockBuf[1024]; | 61 | unsigned char blockBuf[1024]; |
| 67 | unsigned int errors = 0; | 62 | unsigned errors = 0; |
| 68 | unsigned int wantBlockNo = 1; | 63 | unsigned wantBlockNo = 1; |
| 69 | unsigned int length = 0; | 64 | unsigned length = 0; |
| 70 | int docrc = 1; | 65 | int do_crc = 1; |
| 71 | char nak = 'C'; | 66 | char nak = 'C'; |
| 72 | unsigned int timeout = TIMEOUT_LONG; | 67 | unsigned timeout = TIMEOUT_LONG; |
| 73 | |||
| 74 | #define note_error(fmt,args...) \ | ||
| 75 | snprintf(error_buf, error_buf_size, fmt,##args) | ||
| 76 | 68 | ||
| 77 | /* Flush pending input */ | 69 | /* Flush pending input */ |
| 78 | tcflush(ttyfd, TCIFLUSH); | 70 | tcflush(read_fd, TCIFLUSH); |
| 79 | 71 | ||
| 80 | /* Ask for CRC; if we get errors, we will go with checksum */ | 72 | /* Ask for CRC; if we get errors, we will go with checksum */ |
| 81 | write(ttyfd, &nak, 1); | 73 | full_write(write_fd, &nak, 1); |
| 82 | 74 | ||
| 83 | for (;;) { | 75 | for (;;) { |
| 84 | int blockBegin; | 76 | int blockBegin; |
| 85 | int blockNo, blockNoOnesCompl; | 77 | int blockNo, blockNoOnesCompl; |
| 86 | int blockLength; | 78 | int blockLength; |
| 87 | int cksum = 0; | 79 | int cksum_crc; /* cksum OR crc */ |
| 88 | int crcHi = 0; | 80 | int expected; |
| 89 | int crcLo = 0; | 81 | int i,j; |
| 90 | 82 | ||
| 91 | blockBegin = read_byte(ttyfd, timeout); | 83 | blockBegin = read_byte(timeout); |
| 92 | if (blockBegin < 0) | 84 | if (blockBegin < 0) |
| 93 | goto timeout; | 85 | goto timeout; |
| 94 | 86 | ||
| @@ -102,52 +94,47 @@ static int receive(char *error_buf, size_t error_buf_size, | |||
| 102 | 94 | ||
| 103 | case EOT: | 95 | case EOT: |
| 104 | nak = ACK; | 96 | nak = ACK; |
| 105 | write(ttyfd, &nak, 1); | 97 | full_write(write_fd, &nak, 1); |
| 106 | goto done; | 98 | return length; |
| 107 | 99 | ||
| 108 | default: | 100 | default: |
| 109 | goto error; | 101 | goto error; |
| 110 | } | 102 | } |
| 111 | 103 | ||
| 112 | /* block no */ | 104 | /* block no */ |
| 113 | blockNo = read_byte(ttyfd, TIMEOUT); | 105 | blockNo = read_byte(TIMEOUT); |
| 114 | if (blockNo < 0) | 106 | if (blockNo < 0) |
| 115 | goto timeout; | 107 | goto timeout; |
| 116 | 108 | ||
| 117 | /* block no one's compliment */ | 109 | /* block no one's compliment */ |
| 118 | blockNoOnesCompl = read_byte(ttyfd, TIMEOUT); | 110 | blockNoOnesCompl = read_byte(TIMEOUT); |
| 119 | if (blockNoOnesCompl < 0) | 111 | if (blockNoOnesCompl < 0) |
| 120 | goto timeout; | 112 | goto timeout; |
| 121 | 113 | ||
| 122 | if (blockNo != (255 - blockNoOnesCompl)) { | 114 | if (blockNo != (255 - blockNoOnesCompl)) { |
| 123 | note_error("bad block ones compl"); | 115 | bb_error_msg("bad block ones compl"); |
| 124 | goto error; | 116 | goto error; |
| 125 | } | 117 | } |
| 126 | 118 | ||
| 127 | blockLength = (blockBegin == SOH) ? 128 : 1024; | 119 | blockLength = (blockBegin == SOH) ? 128 : 1024; |
| 128 | 120 | ||
| 129 | { | 121 | for (i = 0; i < blockLength; i++) { |
| 130 | int i; | 122 | int cc = read_byte(TIMEOUT); |
| 131 | 123 | if (cc < 0) | |
| 132 | for (i = 0; i < blockLength; i++) { | 124 | goto timeout; |
| 133 | int cc = read_byte(ttyfd, TIMEOUT); | 125 | blockBuf[i] = cc; |
| 134 | if (cc < 0) | ||
| 135 | goto timeout; | ||
| 136 | blockBuf[i] = cc; | ||
| 137 | } | ||
| 138 | } | 126 | } |
| 139 | 127 | ||
| 140 | if (docrc) { | 128 | if (do_crc) { |
| 141 | crcHi = read_byte(ttyfd, TIMEOUT); | 129 | cksum_crc = read_byte(TIMEOUT); |
| 142 | if (crcHi < 0) | 130 | if (cksum_crc < 0) |
| 143 | goto timeout; | 131 | goto timeout; |
| 144 | 132 | cksum_crc = (cksum_crc << 8) | read_byte(TIMEOUT); | |
| 145 | crcLo = read_byte(ttyfd, TIMEOUT); | 133 | if (cksum_crc < 0) |
| 146 | if (crcLo < 0) | ||
| 147 | goto timeout; | 134 | goto timeout; |
| 148 | } else { | 135 | } else { |
| 149 | cksum = read_byte(ttyfd, TIMEOUT); | 136 | cksum_crc = read_byte(TIMEOUT); |
| 150 | if (cksum < 0) | 137 | if (cksum_crc < 0) |
| 151 | goto timeout; | 138 | goto timeout; |
| 152 | } | 139 | } |
| 153 | 140 | ||
| @@ -156,93 +143,74 @@ static int receive(char *error_buf, size_t error_buf_size, | |||
| 156 | /* this also ignores the initial block 0 which is */ | 143 | /* this also ignores the initial block 0 which is */ |
| 157 | /* meta data. */ | 144 | /* meta data. */ |
| 158 | goto next; | 145 | goto next; |
| 159 | } else if (blockNo != (wantBlockNo & 0xff)) { | 146 | } |
| 160 | note_error("unexpected block no, 0x%08x, expecting 0x%08x", blockNo, wantBlockNo); | 147 | if (blockNo != (wantBlockNo & 0xff)) { |
| 148 | bb_error_msg("unexpected block no, 0x%08x, expecting 0x%08x", blockNo, wantBlockNo); | ||
| 161 | goto error; | 149 | goto error; |
| 162 | } | 150 | } |
| 163 | 151 | ||
| 164 | if (docrc) { | 152 | expected = 0; |
| 165 | int crc = 0; | 153 | if (do_crc) { |
| 166 | int i, j; | ||
| 167 | int expectedCrcHi; | ||
| 168 | int expectedCrcLo; | ||
| 169 | |||
| 170 | for (i = 0; i < blockLength; i++) { | 154 | for (i = 0; i < blockLength; i++) { |
| 171 | crc = crc ^ (int) blockBuf[i] << 8; | 155 | expected = expected ^ blockBuf[i] << 8; |
| 172 | for (j = 0; j < 8; j++) | 156 | for (j = 0; j < 8; j++) { |
| 173 | if (crc & 0x8000) | 157 | if (expected & 0x8000) |
| 174 | crc = crc << 1 ^ 0x1021; | 158 | expected = expected << 1 ^ 0x1021; |
| 175 | else | 159 | else |
| 176 | crc = crc << 1; | 160 | expected = expected << 1; |
| 177 | } | 161 | } |
| 178 | |||
| 179 | expectedCrcHi = (crc >> 8) & 0xff; | ||
| 180 | expectedCrcLo = crc & 0xff; | ||
| 181 | |||
| 182 | if ((crcHi != expectedCrcHi) || | ||
| 183 | (crcLo != expectedCrcLo)) { | ||
| 184 | note_error("crc error, expected 0x%02x 0x%02x, got 0x%02x 0x%02x", expectedCrcHi, expectedCrcLo, crcHi, crcLo); | ||
| 185 | goto error; | ||
| 186 | } | 162 | } |
| 163 | expected &= 0xffff; | ||
| 187 | } else { | 164 | } else { |
| 188 | unsigned char expectedCksum = 0; | ||
| 189 | int i; | ||
| 190 | |||
| 191 | for (i = 0; i < blockLength; i++) | 165 | for (i = 0; i < blockLength; i++) |
| 192 | expectedCksum += blockBuf[i]; | 166 | expected += blockBuf[i]; |
| 193 | 167 | expected &= 0xff; | |
| 194 | if (cksum != expectedCksum) { | 168 | } |
| 195 | note_error("checksum error, expected 0x%02x, got 0x%02x", expectedCksum, cksum); | 169 | if (cksum_crc != expected) { |
| 196 | goto error; | 170 | bb_error_msg(do_crc ? "crc error, expected 0x%04x, got 0x%04x" |
| 197 | } | 171 | : "checksum error, expected 0x%02x, got 0x%02x", |
| 172 | expected, cksum_crc); | ||
| 173 | goto error; | ||
| 198 | } | 174 | } |
| 199 | 175 | ||
| 200 | wantBlockNo++; | 176 | wantBlockNo++; |
| 201 | length += blockLength; | 177 | length += blockLength; |
| 202 | 178 | ||
| 203 | if (full_write(filefd, blockBuf, blockLength) < 0) { | 179 | errno = 0; |
| 204 | note_error("write to file failed: %m"); | 180 | if (full_write(file_fd, blockBuf, blockLength) != blockLength) { |
| 181 | bb_perror_msg("can't write to file"); | ||
| 205 | goto fatal; | 182 | goto fatal; |
| 206 | } | 183 | } |
| 207 | 184 | next: | |
| 208 | next: | ||
| 209 | errors = 0; | 185 | errors = 0; |
| 210 | nak = ACK; | 186 | nak = ACK; |
| 211 | write(ttyfd, &nak, 1); | 187 | full_write(write_fd, &nak, 1); |
| 212 | continue; | 188 | continue; |
| 213 | 189 | error: | |
| 214 | error: | 190 | timeout: |
| 215 | timeout: | ||
| 216 | errors++; | 191 | errors++; |
| 217 | if (errors == MAXERRORS) { | 192 | if (errors == MAXERRORS) { |
| 218 | /* Abort */ | 193 | /* Abort */ |
| 219 | 194 | ||
| 220 | // if using crc, try again w/o crc | 195 | /* if were asking for crc, try again w/o crc */ |
| 221 | if (nak == 'C') { | 196 | if (nak == 'C') { |
| 222 | nak = NAK; | 197 | nak = NAK; |
| 223 | errors = 0; | 198 | errors = 0; |
| 224 | docrc = 0; | 199 | do_crc = 0; |
| 225 | goto timeout; | 200 | goto timeout; |
| 226 | } | 201 | } |
| 227 | 202 | bb_error_msg("too many errors; giving up"); | |
| 228 | note_error("too many errors; giving up"); | 203 | fatal: |
| 229 | 204 | /* 5 CAN followed by 5 BS. Don't try too hard... */ | |
| 230 | fatal: | 205 | safe_write(write_fd, "\030\030\030\030\030\010\010\010\010\010", 10); |
| 231 | /* 5 CAN followed by 5 BS */ | ||
| 232 | write(ttyfd, "\030\030\030\030\030\010\010\010\010\010", 10); | ||
| 233 | return -1; | 206 | return -1; |
| 234 | } | 207 | } |
| 235 | 208 | ||
| 236 | /* Flush pending input */ | 209 | /* Flush pending input */ |
| 237 | tcflush(ttyfd, TCIFLUSH); | 210 | tcflush(read_fd, TCIFLUSH); |
| 238 | |||
| 239 | write(ttyfd, &nak, 1); | ||
| 240 | } | ||
| 241 | |||
| 242 | done: | ||
| 243 | return length; | ||
| 244 | 211 | ||
| 245 | #undef note_error | 212 | full_write(write_fd, &nak, 1); |
| 213 | } /* for (;;) */ | ||
| 246 | } | 214 | } |
| 247 | 215 | ||
| 248 | static void sigalrm_handler(int ATTRIBUTE_UNUSED signum) | 216 | static void sigalrm_handler(int ATTRIBUTE_UNUSED signum) |
| @@ -252,40 +220,38 @@ static void sigalrm_handler(int ATTRIBUTE_UNUSED signum) | |||
| 252 | int rx_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 220 | int rx_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
| 253 | int rx_main(int argc, char **argv) | 221 | int rx_main(int argc, char **argv) |
| 254 | { | 222 | { |
| 255 | char *fn; | ||
| 256 | int ttyfd, filefd; | ||
| 257 | struct termios tty, orig_tty; | ||
| 258 | struct sigaction act; | 223 | struct sigaction act; |
| 224 | struct termios tty, orig_tty; | ||
| 225 | int termios_err; | ||
| 226 | int file_fd; | ||
| 259 | int n; | 227 | int n; |
| 260 | char error_buf[256]; | ||
| 261 | 228 | ||
| 262 | if (argc != 2) | 229 | if (argc != 2) |
| 263 | bb_show_usage(); | 230 | bb_show_usage(); |
| 264 | 231 | ||
| 265 | fn = argv[1]; | 232 | /* Disabled by vda: |
| 266 | ttyfd = xopen(CURRENT_TTY, O_RDWR); | 233 | * why we can't receive from stdin? Why we *require* |
| 267 | filefd = xopen(fn, O_RDWR|O_CREAT|O_TRUNC); | 234 | * controlling tty?? */ |
| 268 | 235 | /*read_fd = xopen(CURRENT_TTY, O_RDWR);*/ | |
| 269 | if (tcgetattr(ttyfd, &tty) < 0) | 236 | file_fd = xopen(argv[1], O_RDWR|O_CREAT|O_TRUNC); |
| 270 | bb_perror_msg_and_die("tcgetattr"); | 237 | |
| 271 | 238 | termios_err = tcgetattr(read_fd, &tty); | |
| 272 | orig_tty = tty; | 239 | if (termios_err == 0) { |
| 273 | 240 | orig_tty = tty; | |
| 274 | cfmakeraw(&tty); | 241 | cfmakeraw(&tty); |
| 275 | tcsetattr(ttyfd, TCSAFLUSH, &tty); | 242 | tcsetattr(read_fd, TCSAFLUSH, &tty); |
| 243 | } | ||
| 276 | 244 | ||
| 245 | /* No SA_RESTART: we want ALRM to interrupt read() */ | ||
| 277 | memset(&act, 0, sizeof(act)); | 246 | memset(&act, 0, sizeof(act)); |
| 278 | act.sa_handler = sigalrm_handler; | 247 | act.sa_handler = sigalrm_handler; |
| 279 | sigaction(SIGALRM, &act, 0); | 248 | sigaction(SIGALRM, &act, NULL); |
| 280 | |||
| 281 | n = receive(error_buf, sizeof(error_buf), ttyfd, filefd); | ||
| 282 | |||
| 283 | close(filefd); | ||
| 284 | |||
| 285 | tcsetattr(ttyfd, TCSAFLUSH, &orig_tty); | ||
| 286 | 249 | ||
| 287 | if (n < 0) | 250 | n = receive(file_fd); |
| 288 | bb_error_msg_and_die("\nreceive failed:\n %s", error_buf); | ||
| 289 | 251 | ||
| 290 | fflush_stdout_and_exit(EXIT_SUCCESS); | 252 | if (termios_err == 0) |
| 253 | tcsetattr(read_fd, TCSAFLUSH, &orig_tty); | ||
| 254 | if (ENABLE_FEATURE_CLEAN_UP) | ||
| 255 | close(file_fd); | ||
| 256 | fflush_stdout_and_exit(n >= 0); | ||
| 291 | } | 257 | } |
diff --git a/networking/inetd.c b/networking/inetd.c index 8a4c9fbf6..463c7cfcf 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
| @@ -3,6 +3,7 @@ | |||
| 3 | /* $OpenBSD: inetd.c,v 1.79 2001/01/30 08:30:57 deraadt Exp $ */ | 3 | /* $OpenBSD: inetd.c,v 1.79 2001/01/30 08:30:57 deraadt Exp $ */ |
| 4 | /* $NetBSD: inetd.c,v 1.11 1996/02/22 11:14:41 mycroft Exp $ */ | 4 | /* $NetBSD: inetd.c,v 1.11 1996/02/22 11:14:41 mycroft Exp $ */ |
| 5 | /* Busybox port by Vladimir Oleynik (C) 2001-2005 <dzo@simtreas.ru> */ | 5 | /* Busybox port by Vladimir Oleynik (C) 2001-2005 <dzo@simtreas.ru> */ |
| 6 | /* IPv6 support, many bug fixes by Denys Vlasenko (c) 2008 */ | ||
| 6 | /* | 7 | /* |
| 7 | * Copyright (c) 1983,1991 The Regents of the University of California. | 8 | * Copyright (c) 1983,1991 The Regents of the University of California. |
| 8 | * All rights reserved. | 9 | * All rights reserved. |
| @@ -38,21 +39,17 @@ | |||
| 38 | 39 | ||
| 39 | /* Inetd - Internet super-server | 40 | /* Inetd - Internet super-server |
| 40 | * | 41 | * |
| 41 | * This program invokes all internet services as needed. | 42 | * This program invokes configured services when a connection |
| 42 | * connection-oriented services are invoked each time a | 43 | * from a peer is established or a datagram arrives. |
| 44 | * Connection-oriented services are invoked each time a | ||
| 43 | * connection is made, by creating a process. This process | 45 | * connection is made, by creating a process. This process |
| 44 | * is passed the connection as file descriptor 0 and is | 46 | * is passed the connection as file descriptor 0 and is |
| 45 | * expected to do a getpeername to find out the source host | 47 | * expected to do a getpeername to find out peer's host |
| 46 | * and port. | 48 | * and port. |
| 47 | * | ||
| 48 | * Datagram oriented services are invoked when a datagram | 49 | * Datagram oriented services are invoked when a datagram |
| 49 | * arrives; a process is created and passed a pending message | 50 | * arrives; a process is created and passed a pending message |
| 50 | * on file descriptor 0. Datagram servers may either connect | 51 | * on file descriptor 0. peer's address can be obtained |
| 51 | * to their peer, freeing up the original socket for inetd | 52 | * using recvfrom. |
| 52 | * to receive further messages on, or "take over the socket", | ||
| 53 | * processing all arriving datagrams and, eventually, timing | ||
| 54 | * out. The first type of server is said to be "multi-threaded"; | ||
| 55 | * the second type of server "single-threaded". | ||
| 56 | * | 53 | * |
| 57 | * Inetd uses a configuration file which is read at startup | 54 | * Inetd uses a configuration file which is read at startup |
| 58 | * and, possibly, at some later time in response to a hangup signal. | 55 | * and, possibly, at some later time in response to a hangup signal. |
| @@ -60,28 +57,28 @@ | |||
| 60 | * order shown below. Continuation lines for an entry must begin with | 57 | * order shown below. Continuation lines for an entry must begin with |
| 61 | * a space or tab. All fields must be present in each entry. | 58 | * a space or tab. All fields must be present in each entry. |
| 62 | * | 59 | * |
| 63 | * service name must be in /etc/services | 60 | * service_name must be in /etc/services |
| 64 | * socket type stream/dgram/raw/rdm/seqpacket | 61 | * socket_type stream/dgram/raw/rdm/seqpacket |
| 65 | * protocol must be in /etc/protocols | 62 | * protocol must be in /etc/protocols |
| 66 | * (usually "tcp" or "udp") | 63 | * (usually "tcp" or "udp") |
| 67 | * wait/nowait[.max] single-threaded/multi-threaded, max # | 64 | * wait/nowait[.max] single-threaded/multi-threaded, max # |
| 68 | * user[.group] or user[:group] user/group to run daemon as | 65 | * user[.group] or user[:group] user/group to run daemon as |
| 69 | * server program full path name | 66 | * server_program full path name |
| 70 | * server program arguments maximum of MAXARGS (20) | 67 | * server_program_arguments maximum of MAXARGS (20) |
| 71 | * | 68 | * |
| 72 | * For RPC services | 69 | * For RPC services |
| 73 | * service name/version must be in /etc/rpc | 70 | * service_name/version must be in /etc/rpc |
| 74 | * socket type stream/dgram/raw/rdm/seqpacket | 71 | * socket_type stream/dgram/raw/rdm/seqpacket |
| 75 | * rpc/protocol "rpc/tcp" etc | 72 | * rpc/protocol "rpc/tcp" etc |
| 76 | * wait/nowait[.max] single-threaded/multi-threaded | 73 | * wait/nowait[.max] single-threaded/multi-threaded |
| 77 | * user[.group] or user[:group] user to run daemon as | 74 | * user[.group] or user[:group] user to run daemon as |
| 78 | * server program full path name | 75 | * server_program full path name |
| 79 | * server program arguments maximum of MAXARGS (20) | 76 | * server_program_arguments maximum of MAXARGS (20) |
| 80 | * | 77 | * |
| 81 | * For non-RPC services, the "service name" can be of the form | 78 | * For non-RPC services, the "service name" can be of the form |
| 82 | * hostaddress:servicename, in which case the hostaddress is used | 79 | * hostaddress:servicename, in which case the hostaddress is used |
| 83 | * as the host portion of the address to listen on. If hostaddress | 80 | * as the host portion of the address to listen on. If hostaddress |
| 84 | * consists of a single `*' character, INADDR_ANY is used. | 81 | * consists of a single '*' character, INADDR_ANY is used. |
| 85 | * | 82 | * |
| 86 | * A line can also consist of just | 83 | * A line can also consist of just |
| 87 | * hostaddress: | 84 | * hostaddress: |
| @@ -102,7 +99,7 @@ | |||
| 102 | * one line for any given RPC service, even if the host-address | 99 | * one line for any given RPC service, even if the host-address |
| 103 | * specifiers are different. | 100 | * specifiers are different. |
| 104 | * | 101 | * |
| 105 | * Comment lines are indicated by a `#' in column 1. | 102 | * Comment lines are indicated by a '#' in column 1. |
| 106 | */ | 103 | */ |
| 107 | 104 | ||
| 108 | /* inetd rules for passing file descriptors to children | 105 | /* inetd rules for passing file descriptors to children |
| @@ -133,6 +130,8 @@ | |||
| 133 | * tening service socket, and must accept at least one connection request | 130 | * tening service socket, and must accept at least one connection request |
| 134 | * before exiting. Such a server would normally accept and process incoming | 131 | * before exiting. Such a server would normally accept and process incoming |
| 135 | * connection requests until a timeout. | 132 | * connection requests until a timeout. |
| 133 | * | ||
| 134 | * In short: "stream" can be "wait" or "nowait"; "dgram" must be "wait". | ||
| 136 | */ | 135 | */ |
| 137 | 136 | ||
| 138 | /* Here's the scoop concerning the user[:group] feature: | 137 | /* Here's the scoop concerning the user[:group] feature: |
| @@ -152,26 +151,27 @@ | |||
| 152 | 151 | ||
| 153 | #include <syslog.h> | 152 | #include <syslog.h> |
| 154 | #include <sys/un.h> | 153 | #include <sys/un.h> |
| 154 | |||
| 155 | #include "libbb.h" | 155 | #include "libbb.h" |
| 156 | 156 | ||
| 157 | #if ENABLE_FEATURE_INETD_RPC | ||
| 158 | #include <rpc/rpc.h> | ||
| 159 | #include <rpc/pmap_clnt.h> | ||
| 160 | #endif | ||
| 161 | |||
| 157 | #if !BB_MMU | 162 | #if !BB_MMU |
| 158 | /* stream versions of these builtins are forking, | 163 | /* stream version of chargen is forking but not execing, |
| 159 | * can't do that (easily) on NOMMU */ | 164 | * can't do that (easily) on NOMMU */ |
| 160 | #undef ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | ||
| 161 | #define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD 0 | ||
| 162 | #undef ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 165 | #undef ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
| 163 | #define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN 0 | 166 | #define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN 0 |
| 164 | #endif | 167 | #endif |
| 165 | 168 | ||
| 166 | #if ENABLE_FEATURE_INETD_RPC | ||
| 167 | #include <rpc/rpc.h> | ||
| 168 | #include <rpc/pmap_clnt.h> | ||
| 169 | #endif | ||
| 170 | |||
| 171 | #define _PATH_INETDPID "/var/run/inetd.pid" | 169 | #define _PATH_INETDPID "/var/run/inetd.pid" |
| 172 | 170 | ||
| 173 | #define CNT_INTERVAL 60 /* servers in CNT_INTERVAL sec. */ | 171 | #define CNT_INTERVAL 60 /* servers in CNT_INTERVAL sec. */ |
| 174 | #define RETRYTIME (60*10) /* retry after bind or server fail */ | 172 | #define RETRYTIME 60 /* retry after bind or server fail */ |
| 173 | |||
| 174 | // TODO: explain, or get rid of setrlimit games | ||
| 175 | 175 | ||
| 176 | #ifndef RLIMIT_NOFILE | 176 | #ifndef RLIMIT_NOFILE |
| 177 | #define RLIMIT_NOFILE RLIMIT_OFILE | 177 | #define RLIMIT_NOFILE RLIMIT_OFILE |
| @@ -209,20 +209,21 @@ typedef struct servtab_t { | |||
| 209 | #else | 209 | #else |
| 210 | #define is_rpc_service(sep) 0 | 210 | #define is_rpc_service(sep) 0 |
| 211 | #endif | 211 | #endif |
| 212 | pid_t se_wait; /* 0:"nowait", 1:"wait" */ | 212 | pid_t se_wait; /* 0:"nowait", 1:"wait", >1:"wait" */ |
| 213 | /* and waiting for this pid */ | ||
| 213 | socktype_t se_socktype; /* SOCK_STREAM/DGRAM/RDM/... */ | 214 | socktype_t se_socktype; /* SOCK_STREAM/DGRAM/RDM/... */ |
| 214 | family_t se_family; /* AF_UNIX/INET[6] */ | 215 | family_t se_family; /* AF_UNIX/INET[6] */ |
| 215 | smallint se_proto_no; /* almost "getprotobyname(se_proto)" */ | 216 | /* se_proto_no is used by RPC code only... hmm */ |
| 217 | smallint se_proto_no; /* IPPROTO_TCP/UDP, n/a for AF_UNIX */ | ||
| 216 | smallint se_checked; /* looked at during merge */ | 218 | smallint se_checked; /* looked at during merge */ |
| 219 | unsigned se_max; /* allowed instances per minute */ | ||
| 220 | unsigned se_count; /* number started since se_time */ | ||
| 221 | unsigned se_time; /* whem we started counting */ | ||
| 217 | char *se_user; /* user name to run as */ | 222 | char *se_user; /* user name to run as */ |
| 218 | char *se_group; /* group name to run as, can be NULL */ | 223 | char *se_group; /* group name to run as, can be NULL */ |
| 219 | #ifdef INETD_BUILTINS_ENABLED | 224 | #ifdef INETD_BUILTINS_ENABLED |
| 220 | const struct builtin *se_builtin; /* if built-in, description */ | 225 | const struct builtin *se_builtin; /* if built-in, description */ |
| 221 | #endif | 226 | #endif |
| 222 | // TODO: wrong algorithm!!! | ||
| 223 | unsigned se_max; /* max # of instances of this service */ | ||
| 224 | unsigned se_count; /* number started since se_time */ | ||
| 225 | unsigned se_time; /* start of se_count */ | ||
| 226 | struct servtab_t *se_next; | 227 | struct servtab_t *se_next; |
| 227 | len_and_sockaddr *se_lsa; | 228 | len_and_sockaddr *se_lsa; |
| 228 | char *se_program; /* server program */ | 229 | char *se_program; /* server program */ |
| @@ -231,60 +232,54 @@ typedef struct servtab_t { | |||
| 231 | } servtab_t; | 232 | } servtab_t; |
| 232 | 233 | ||
| 233 | #ifdef INETD_BUILTINS_ENABLED | 234 | #ifdef INETD_BUILTINS_ENABLED |
| 234 | /* Echo received data */ | 235 | /* Echo received data */ |
| 235 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 236 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
| 236 | static void echo_stream(int, servtab_t *); | 237 | static void echo_stream(int, servtab_t *); |
| 237 | static void echo_dg(int, servtab_t *); | 238 | static void echo_dg(int, servtab_t *); |
| 238 | #endif | 239 | #endif |
| 239 | /* Internet /dev/null */ | 240 | /* Internet /dev/null */ |
| 240 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | 241 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD |
| 241 | static void discard_stream(int, servtab_t *); | 242 | static void discard_stream(int, servtab_t *); |
| 242 | static void discard_dg(int, servtab_t *); | 243 | static void discard_dg(int, servtab_t *); |
| 243 | #endif | 244 | #endif |
| 244 | /* Return 32 bit time since 1900 */ | 245 | /* Return 32 bit time since 1900 */ |
| 245 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME | 246 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME |
| 246 | static void machtime_stream(int, servtab_t *); | 247 | static void machtime_stream(int, servtab_t *); |
| 247 | static void machtime_dg(int, servtab_t *); | 248 | static void machtime_dg(int, servtab_t *); |
| 248 | #endif | 249 | #endif |
| 249 | /* Return human-readable time */ | 250 | /* Return human-readable time */ |
| 250 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME | 251 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME |
| 251 | static void daytime_stream(int, servtab_t *); | 252 | static void daytime_stream(int, servtab_t *); |
| 252 | static void daytime_dg(int, servtab_t *); | 253 | static void daytime_dg(int, servtab_t *); |
| 253 | #endif | 254 | #endif |
| 254 | /* Familiar character generator */ | 255 | /* Familiar character generator */ |
| 255 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 256 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
| 256 | static void chargen_stream(int, servtab_t *); | 257 | static void chargen_stream(int, servtab_t *); |
| 257 | static void chargen_dg(int, servtab_t *); | 258 | static void chargen_dg(int, servtab_t *); |
| 258 | #endif | 259 | #endif |
| 259 | 260 | ||
| 260 | struct builtin { | 261 | struct builtin { |
| 261 | const char *bi_service; /* internally provided service name */ | 262 | /* NB: not necessarily NUL terminated */ |
| 262 | uint8_t bi_fork; /* 1 if stream fn should run in child */ | 263 | char bi_service7[7]; /* internally provided service name */ |
| 263 | /* All builtins are "nowait" */ | 264 | uint8_t bi_fork; /* 1 if stream fn should run in child */ |
| 264 | /* uint8_t bi_wait; */ /* 1 if should wait for child */ | ||
| 265 | void (*bi_stream_fn)(int, servtab_t *); | 265 | void (*bi_stream_fn)(int, servtab_t *); |
| 266 | void (*bi_dgram_fn)(int, servtab_t *); | 266 | void (*bi_dgram_fn)(int, servtab_t *); |
| 267 | }; | 267 | }; |
| 268 | 268 | ||
| 269 | static const struct builtin builtins[] = { | 269 | static const struct builtin builtins[] = { |
| 270 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 270 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
| 271 | /* Echo received data */ | ||
| 272 | { "echo", 1, echo_stream, echo_dg }, | 271 | { "echo", 1, echo_stream, echo_dg }, |
| 273 | #endif | 272 | #endif |
| 274 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | 273 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD |
| 275 | /* Internet /dev/null */ | ||
| 276 | { "discard", 1, discard_stream, discard_dg }, | 274 | { "discard", 1, discard_stream, discard_dg }, |
| 277 | #endif | 275 | #endif |
| 278 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 276 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
| 279 | /* Familiar character generator */ | ||
| 280 | { "chargen", 1, chargen_stream, chargen_dg }, | 277 | { "chargen", 1, chargen_stream, chargen_dg }, |
| 281 | #endif | 278 | #endif |
| 282 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME | 279 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME |
| 283 | /* Return 32 bit time since 1900 */ | ||
| 284 | { "time", 0, machtime_stream, machtime_dg }, | 280 | { "time", 0, machtime_stream, machtime_dg }, |
| 285 | #endif | 281 | #endif |
| 286 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME | 282 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME |
| 287 | /* Return human-readable time */ | ||
| 288 | { "daytime", 0, daytime_stream, daytime_dg }, | 283 | { "daytime", 0, daytime_stream, daytime_dg }, |
| 289 | #endif | 284 | #endif |
| 290 | }; | 285 | }; |
| @@ -305,8 +300,8 @@ struct globals { | |||
| 305 | FILE *fconfig; | 300 | FILE *fconfig; |
| 306 | char *default_local_hostname; | 301 | char *default_local_hostname; |
| 307 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 302 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
| 308 | char *endring; | 303 | char *end_ring; |
| 309 | char *ringpos; | 304 | char *ring_pos; |
| 310 | char ring[128]; | 305 | char ring[128]; |
| 311 | #endif | 306 | #endif |
| 312 | fd_set allsock; | 307 | fd_set allsock; |
| @@ -333,8 +328,8 @@ struct BUG_G_too_big { | |||
| 333 | #define default_local_hostname (G.default_local_hostname) | 328 | #define default_local_hostname (G.default_local_hostname) |
| 334 | #define first_ps_byte (G.first_ps_byte ) | 329 | #define first_ps_byte (G.first_ps_byte ) |
| 335 | #define last_ps_byte (G.last_ps_byte ) | 330 | #define last_ps_byte (G.last_ps_byte ) |
| 336 | #define endring (G.endring ) | 331 | #define end_ring (G.end_ring ) |
| 337 | #define ringpos (G.ringpos ) | 332 | #define ring_pos (G.ring_pos ) |
| 338 | #define ring (G.ring ) | 333 | #define ring (G.ring ) |
| 339 | #define allsock (G.allsock ) | 334 | #define allsock (G.allsock ) |
| 340 | #define line (G.line ) | 335 | #define line (G.line ) |
| @@ -357,6 +352,8 @@ static len_and_sockaddr *xzalloc_lsa(int family) | |||
| 357 | int sz; | 352 | int sz; |
| 358 | 353 | ||
| 359 | sz = sizeof(struct sockaddr_in); | 354 | sz = sizeof(struct sockaddr_in); |
| 355 | if (family == AF_UNIX) | ||
| 356 | sz = sizeof(struct sockaddr_un); | ||
| 360 | #if ENABLE_FEATURE_IPV6 | 357 | #if ENABLE_FEATURE_IPV6 |
| 361 | if (family == AF_INET6) | 358 | if (family == AF_INET6) |
| 362 | sz = sizeof(struct sockaddr_in6); | 359 | sz = sizeof(struct sockaddr_in6); |
| @@ -367,7 +364,6 @@ static len_and_sockaddr *xzalloc_lsa(int family) | |||
| 367 | return lsa; | 364 | return lsa; |
| 368 | } | 365 | } |
| 369 | 366 | ||
| 370 | |||
| 371 | static void rearm_alarm(void) | 367 | static void rearm_alarm(void) |
| 372 | { | 368 | { |
| 373 | if (!alarm_armed) { | 369 | if (!alarm_armed) { |
| @@ -660,10 +656,8 @@ static NOINLINE servtab_t *parse_one_line(void) | |||
| 660 | } | 656 | } |
| 661 | 657 | ||
| 662 | arg = next_word(&cp); | 658 | arg = next_word(&cp); |
| 663 | if (arg == NULL) { | 659 | if (arg == NULL) /* a blank line. */ |
| 664 | /* A blank line. */ | ||
| 665 | goto more; | 660 | goto more; |
| 666 | } | ||
| 667 | 661 | ||
| 668 | /* [host:]service socktype proto wait user[:group] prog [args] */ | 662 | /* [host:]service socktype proto wait user[:group] prog [args] */ |
| 669 | /* Check for "host:...." line */ | 663 | /* Check for "host:...." line */ |
| @@ -764,9 +758,9 @@ static NOINLINE servtab_t *parse_one_line(void) | |||
| 764 | } | 758 | } |
| 765 | /* we don't really need getprotobyname()! */ | 759 | /* we don't really need getprotobyname()! */ |
| 766 | if (strcmp(arg, "tcp") == 0) | 760 | if (strcmp(arg, "tcp") == 0) |
| 767 | sep->se_proto_no = 6; | 761 | sep->se_proto_no = IPPROTO_TCP; /* = 6 */ |
| 768 | if (strcmp(arg, "udp") == 0) | 762 | if (strcmp(arg, "udp") == 0) |
| 769 | sep->se_proto_no = 17; | 763 | sep->se_proto_no = IPPROTO_UDP; /* = 17 */ |
| 770 | if (six) | 764 | if (six) |
| 771 | *six = '6'; | 765 | *six = '6'; |
| 772 | if (!sep->se_proto_no) /* not tcp/udp?? */ | 766 | if (!sep->se_proto_no) /* not tcp/udp?? */ |
| @@ -785,7 +779,11 @@ static NOINLINE servtab_t *parse_one_line(void) | |||
| 785 | if (errno) | 779 | if (errno) |
| 786 | goto parse_err; | 780 | goto parse_err; |
| 787 | } | 781 | } |
| 788 | sep->se_wait = (strcmp(arg, "wait") == 0); | 782 | sep->se_wait = (arg[0] != 'n' || arg[1] != 'o'); |
| 783 | if (!sep->se_wait) /* "no" seen */ | ||
| 784 | arg += 2; | ||
| 785 | if (strcmp(arg, "wait") != 0) | ||
| 786 | goto parse_err; | ||
| 789 | 787 | ||
| 790 | /* user[:group] prog [args] */ | 788 | /* user[:group] prog [args] */ |
| 791 | sep->se_user = xstrdup(next_word(&cp)); | 789 | sep->se_user = xstrdup(next_word(&cp)); |
| @@ -804,48 +802,56 @@ static NOINLINE servtab_t *parse_one_line(void) | |||
| 804 | if (sep->se_program == NULL) | 802 | if (sep->se_program == NULL) |
| 805 | goto parse_err; | 803 | goto parse_err; |
| 806 | #ifdef INETD_BUILTINS_ENABLED | 804 | #ifdef INETD_BUILTINS_ENABLED |
| 807 | /* sep->se_builtin = NULL; - done by new_servtab() */ | ||
| 808 | if (strcmp(sep->se_program, "internal") == 0 | 805 | if (strcmp(sep->se_program, "internal") == 0 |
| 806 | && strlen(sep->se_service) <= 7 | ||
| 809 | && (sep->se_socktype == SOCK_STREAM | 807 | && (sep->se_socktype == SOCK_STREAM |
| 810 | || sep->se_socktype == SOCK_DGRAM) | 808 | || sep->se_socktype == SOCK_DGRAM) |
| 811 | ) { | 809 | ) { |
| 812 | int i; | 810 | int i; |
| 813 | for (i = 0; i < ARRAY_SIZE(builtins); i++) | 811 | for (i = 0; i < ARRAY_SIZE(builtins); i++) |
| 814 | if (strcmp(builtins[i].bi_service, sep->se_service) == 0) | 812 | if (strncmp(builtins[i].bi_service7, sep->se_service, 7) == 0) |
| 815 | goto found_bi; | 813 | goto found_bi; |
| 816 | bb_error_msg("unknown internal service %s", sep->se_service); | 814 | bb_error_msg("unknown internal service %s", sep->se_service); |
| 817 | goto parse_err; | 815 | goto parse_err; |
| 818 | found_bi: | 816 | found_bi: |
| 819 | sep->se_builtin = &builtins[i]; | 817 | sep->se_builtin = &builtins[i]; |
| 820 | sep->se_wait = 0; /* = builtins[i].bi_wait; - always 0 */ | 818 | /* stream builtins must be "nowait", dgram must be "wait" */ |
| 819 | if (sep->se_wait != (sep->se_socktype == SOCK_DGRAM)) | ||
| 820 | goto parse_err; | ||
| 821 | } | 821 | } |
| 822 | #endif | 822 | #endif |
| 823 | argc = 0; | 823 | argc = 0; |
| 824 | while ((arg = next_word(&cp)) != NULL && argc < MAXARGV) { | 824 | while ((arg = next_word(&cp)) != NULL && argc < MAXARGV) |
| 825 | sep->se_argv[argc++] = xstrdup(arg); | 825 | sep->se_argv[argc++] = xstrdup(arg); |
| 826 | |||
| 827 | /* catch mixups. "<service> stream udp ..." == wtf */ | ||
| 828 | if (sep->se_socktype == SOCK_STREAM) { | ||
| 829 | if (sep->se_proto_no == IPPROTO_UDP) | ||
| 830 | goto parse_err; | ||
| 831 | } | ||
| 832 | if (sep->se_socktype == SOCK_DGRAM) { | ||
| 833 | if (sep->se_proto_no == IPPROTO_TCP) | ||
| 834 | goto parse_err; | ||
| 835 | /* "udp nowait" is a small fork bomb :) */ | ||
| 836 | if (!sep->se_wait) | ||
| 837 | goto parse_err; | ||
| 826 | } | 838 | } |
| 827 | /* while (argc <= MAXARGV) */ | 839 | |
| 828 | /* sep->se_argv[argc++] = NULL; - done by new_servtab() */ | 840 | /* check if the hostname specifier is a comma separated list |
| 829 | 841 | * of hostnames. we'll make new entries for each address. */ | |
| 830 | /* | ||
| 831 | * Now that we've processed the entire line, check if the hostname | ||
| 832 | * specifier was a comma separated list of hostnames. If so | ||
| 833 | * we'll make new entries for each address. | ||
| 834 | */ | ||
| 835 | while ((hostdelim = strrchr(sep->se_local_hostname, ',')) != NULL) { | 842 | while ((hostdelim = strrchr(sep->se_local_hostname, ',')) != NULL) { |
| 836 | nsep = dup_servtab(sep); | 843 | nsep = dup_servtab(sep); |
| 837 | /* | 844 | /* NUL terminate the hostname field of the existing entry, |
| 838 | * NUL terminate the hostname field of the existing entry, | 845 | * and make a dup for the new entry. */ |
| 839 | * and make a dup for the new entry. | ||
| 840 | */ | ||
| 841 | *hostdelim++ = '\0'; | 846 | *hostdelim++ = '\0'; |
| 842 | nsep->se_local_hostname = xstrdup(hostdelim); | 847 | nsep->se_local_hostname = xstrdup(hostdelim); |
| 843 | nsep->se_next = sep->se_next; | 848 | nsep->se_next = sep->se_next; |
| 844 | sep->se_next = nsep; | 849 | sep->se_next = nsep; |
| 845 | } | 850 | } |
| 846 | 851 | ||
| 847 | /* Was doing it here: */ | 852 | /* was doing it here: */ |
| 848 | /* DNS resolution, create copies for each IP address */ | 853 | /* DNS resolution, create copies for each IP address */ |
| 854 | /* IPv6-ization destroyed it :( */ | ||
| 849 | 855 | ||
| 850 | return sep; | 856 | return sep; |
| 851 | } | 857 | } |
| @@ -947,15 +953,9 @@ static void reread_config_file(int sig ATTRIBUTE_UNUSED) | |||
| 947 | switch (sep->se_family) { | 953 | switch (sep->se_family) { |
| 948 | struct sockaddr_un *sun; | 954 | struct sockaddr_un *sun; |
| 949 | case AF_UNIX: | 955 | case AF_UNIX: |
| 950 | /* we have poor infrastructure for AF_UNIX... */ | 956 | lsa = xzalloc_lsa(AF_UNIX); |
| 951 | n = strlen(sep->se_service); | ||
| 952 | if (n > sizeof(sun->sun_path) - 1) | ||
| 953 | n = sizeof(sun->sun_path) - 1; | ||
| 954 | lsa = xzalloc(LSA_LEN_SIZE + sizeof(struct sockaddr_un)); | ||
| 955 | lsa->len = sizeof(struct sockaddr_un); | ||
| 956 | sun = (struct sockaddr_un*)&lsa->u.sa; | 957 | sun = (struct sockaddr_un*)&lsa->u.sa; |
| 957 | sun->sun_family = AF_UNIX; | 958 | safe_strncpy(sun->sun_path, sep->se_service, sizeof(sun->sun_path)); |
| 958 | strncpy(sun->sun_path, sep->se_service, n); | ||
| 959 | break; | 959 | break; |
| 960 | 960 | ||
| 961 | default: /* case AF_INET, case AF_INET6 */ | 961 | default: /* case AF_INET, case AF_INET6 */ |
| @@ -1259,8 +1259,8 @@ int inetd_main(int argc, char **argv) | |||
| 1259 | sep->se_count = 0; | 1259 | sep->se_count = 0; |
| 1260 | } | 1260 | } |
| 1261 | } | 1261 | } |
| 1262 | /* on NOMMU, streamed echo, chargen and discard | 1262 | /* on NOMMU, streamed chargen |
| 1263 | * builtins wouldn't work, but they are | 1263 | * builtin wouldn't work, but it is |
| 1264 | * not allowed on NOMMU (ifdefed out) */ | 1264 | * not allowed on NOMMU (ifdefed out) */ |
| 1265 | #ifdef INETD_BUILTINS_ENABLED | 1265 | #ifdef INETD_BUILTINS_ENABLED |
| 1266 | if (BB_MMU && sep->se_builtin) | 1266 | if (BB_MMU && sep->se_builtin) |
| @@ -1311,8 +1311,42 @@ int inetd_main(int argc, char **argv) | |||
| 1311 | continue; /* -> check next fd in fd set */ | 1311 | continue; /* -> check next fd in fd set */ |
| 1312 | } | 1312 | } |
| 1313 | #endif | 1313 | #endif |
| 1314 | /* child. prepare env and exec program */ | 1314 | /* child */ |
| 1315 | setsid(); | 1315 | setsid(); |
| 1316 | #if 0 | ||
| 1317 | /* This does not work. | ||
| 1318 | * Actually, it _almost_ works. The idea behind it is: child | ||
| 1319 | * can peek at (already received and buffered by kernel) UDP packet, | ||
| 1320 | * and perform connect() on the socket so that it is linked only | ||
| 1321 | * to this peer. But this also affects parent, because descriptors | ||
| 1322 | * are shared after fork() a-la dup(). When parent returns to | ||
| 1323 | * select(), it will see this descriptor attached to the peer (!) | ||
| 1324 | * and likely still readable, will act on it and mess things up | ||
| 1325 | * (can create many copies of same child, etc). | ||
| 1326 | * If child will create new socket instead, then bind() and | ||
| 1327 | * connect() it to peer's address, descriptor aliasing problem | ||
| 1328 | * is solved, but first packet cannot be "transferred" to the new | ||
| 1329 | * socket. It is not a problem if child can account for this, | ||
| 1330 | * but our child will exec - and exec'ed program does not know | ||
| 1331 | * about this "lost packet" problem! Pity... */ | ||
| 1332 | /* "nowait" udp[6]. Hmmm... */ | ||
| 1333 | if (!sep->se_wait | ||
| 1334 | && sep->se_socktype == SOCK_DGRAM | ||
| 1335 | && sep->se_family != AF_UNIX | ||
| 1336 | ) { | ||
| 1337 | len_and_sockaddr *lsa = xzalloc_lsa(sep->se_family); | ||
| 1338 | /* peek at the packet and remember peer addr */ | ||
| 1339 | int r = recvfrom(ctrl, NULL, 0, MSG_PEEK|MSG_DONTWAIT, | ||
| 1340 | &lsa->u.sa, &lsa->len); | ||
| 1341 | if (r >= 0) | ||
| 1342 | /* make this socket "connected" to peer addr: | ||
| 1343 | * only packets from this peer will be recv'ed, | ||
| 1344 | * and bare write()/send() will work on it */ | ||
| 1345 | connect(ctrl, &lsa->u.sa, lsa->len); | ||
| 1346 | free(lsa); | ||
| 1347 | } | ||
| 1348 | #endif | ||
| 1349 | /* prepare env and exec program */ | ||
| 1316 | pwd = getpwnam(sep->se_user); | 1350 | pwd = getpwnam(sep->se_user); |
| 1317 | if (pwd == NULL) { | 1351 | if (pwd == NULL) { |
| 1318 | bb_error_msg("%s: no such user", sep->se_user); | 1352 | bb_error_msg("%s: no such user", sep->se_user); |
| @@ -1342,8 +1376,8 @@ int inetd_main(int argc, char **argv) | |||
| 1342 | bb_perror_msg("setrlimit"); | 1376 | bb_perror_msg("setrlimit"); |
| 1343 | closelog(); | 1377 | closelog(); |
| 1344 | xmove_fd(ctrl, 0); | 1378 | xmove_fd(ctrl, 0); |
| 1345 | dup2(0, 1); | 1379 | xdup2(0, 1); |
| 1346 | dup2(0, 2); | 1380 | xdup2(0, 2); |
| 1347 | /* NB: among others, this loop closes listening socket | 1381 | /* NB: among others, this loop closes listening socket |
| 1348 | * for nowait stream children */ | 1382 | * for nowait stream children */ |
| 1349 | for (sep2 = serv_list; sep2; sep2 = sep2->se_next) | 1383 | for (sep2 = serv_list; sep2; sep2 = sep2->se_next) |
| @@ -1378,6 +1412,8 @@ static void echo_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
| 1378 | } | 1412 | } |
| 1379 | #else | 1413 | #else |
| 1380 | static const char *const args[] = { "cat", NULL }; | 1414 | static const char *const args[] = { "cat", NULL }; |
| 1415 | /* no error messages */ | ||
| 1416 | xmove_fd(xopen("/dev/null", O_WRONLY), STDERR_FILENO); | ||
| 1381 | BB_EXECVP("cat", (char**)args); | 1417 | BB_EXECVP("cat", (char**)args); |
| 1382 | _exit(1); | 1418 | _exit(1); |
| 1383 | #endif | 1419 | #endif |
| @@ -1404,8 +1440,16 @@ static void echo_dg(int s, servtab_t *sep) | |||
| 1404 | /* ARGSUSED */ | 1440 | /* ARGSUSED */ |
| 1405 | static void discard_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1441 | static void discard_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
| 1406 | { | 1442 | { |
| 1443 | #if BB_MMU | ||
| 1407 | while (safe_read(s, line, LINE_SIZE) > 0) | 1444 | while (safe_read(s, line, LINE_SIZE) > 0) |
| 1408 | continue; | 1445 | continue; |
| 1446 | #else | ||
| 1447 | static const char *const args[] = { "dd", "of=/dev/null", NULL }; | ||
| 1448 | /* no error messages */ | ||
| 1449 | xmove_fd(xopen("/dev/null", O_WRONLY), STDERR_FILENO); | ||
| 1450 | BB_EXECVP("dd", (char**)args); | ||
| 1451 | _exit(1); | ||
| 1452 | #endif | ||
| 1409 | } | 1453 | } |
| 1410 | /* ARGSUSED */ | 1454 | /* ARGSUSED */ |
| 1411 | static void discard_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1455 | static void discard_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
| @@ -1418,14 +1462,14 @@ static void discard_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
| 1418 | 1462 | ||
| 1419 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 1463 | #if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
| 1420 | #define LINESIZ 72 | 1464 | #define LINESIZ 72 |
| 1421 | static void initring(void) | 1465 | static void init_ring(void) |
| 1422 | { | 1466 | { |
| 1423 | int i; | 1467 | int i; |
| 1424 | 1468 | ||
| 1425 | endring = ring; | 1469 | end_ring = ring; |
| 1426 | for (i = 0; i <= 128; ++i) | 1470 | for (i = 0; i <= 128; ++i) |
| 1427 | if (isprint(i)) | 1471 | if (isprint(i)) |
| 1428 | *endring++ = i; | 1472 | *end_ring++ = i; |
| 1429 | } | 1473 | } |
| 1430 | /* Character generator. MMU arches only. */ | 1474 | /* Character generator. MMU arches only. */ |
| 1431 | /* ARGSUSED */ | 1475 | /* ARGSUSED */ |
| @@ -1435,8 +1479,8 @@ static void chargen_stream(int s, servtab_t *sep) | |||
| 1435 | int len; | 1479 | int len; |
| 1436 | char text[LINESIZ + 2]; | 1480 | char text[LINESIZ + 2]; |
| 1437 | 1481 | ||
| 1438 | if (!endring) { | 1482 | if (!end_ring) { |
| 1439 | initring(); | 1483 | init_ring(); |
| 1440 | rs = ring; | 1484 | rs = ring; |
| 1441 | } | 1485 | } |
| 1442 | 1486 | ||
| @@ -1444,14 +1488,14 @@ static void chargen_stream(int s, servtab_t *sep) | |||
| 1444 | text[LINESIZ + 1] = '\n'; | 1488 | text[LINESIZ + 1] = '\n'; |
| 1445 | rs = ring; | 1489 | rs = ring; |
| 1446 | for (;;) { | 1490 | for (;;) { |
| 1447 | len = endring - rs; | 1491 | len = end_ring - rs; |
| 1448 | if (len >= LINESIZ) | 1492 | if (len >= LINESIZ) |
| 1449 | memmove(text, rs, LINESIZ); | 1493 | memmove(text, rs, LINESIZ); |
| 1450 | else { | 1494 | else { |
| 1451 | memmove(text, rs, len); | 1495 | memmove(text, rs, len); |
| 1452 | memmove(text + len, ring, LINESIZ - len); | 1496 | memmove(text + len, ring, LINESIZ - len); |
| 1453 | } | 1497 | } |
| 1454 | if (++rs == endring) | 1498 | if (++rs == end_ring) |
| 1455 | rs = ring; | 1499 | rs = ring; |
| 1456 | xwrite(s, text, sizeof(text)); | 1500 | xwrite(s, text, sizeof(text)); |
| 1457 | } | 1501 | } |
| @@ -1469,20 +1513,20 @@ static void chargen_dg(int s, servtab_t *sep) | |||
| 1469 | if (recvfrom(s, text, sizeof(text), MSG_DONTWAIT, &lsa->u.sa, &lsa->len) < 0) | 1513 | if (recvfrom(s, text, sizeof(text), MSG_DONTWAIT, &lsa->u.sa, &lsa->len) < 0) |
| 1470 | return; | 1514 | return; |
| 1471 | 1515 | ||
| 1472 | if (!endring) { | 1516 | if (!end_ring) { |
| 1473 | initring(); | 1517 | init_ring(); |
| 1474 | ringpos = ring; | 1518 | ring_pos = ring; |
| 1475 | } | 1519 | } |
| 1476 | 1520 | ||
| 1477 | len = endring - ringpos; | 1521 | len = end_ring - ring_pos; |
| 1478 | if (len >= LINESIZ) | 1522 | if (len >= LINESIZ) |
| 1479 | memmove(text, ringpos, LINESIZ); | 1523 | memmove(text, ring_pos, LINESIZ); |
| 1480 | else { | 1524 | else { |
| 1481 | memmove(text, ringpos, len); | 1525 | memmove(text, ring_pos, len); |
| 1482 | memmove(text + len, ring, LINESIZ - len); | 1526 | memmove(text + len, ring, LINESIZ - len); |
| 1483 | } | 1527 | } |
| 1484 | if (++ringpos == endring) | 1528 | if (++ring_pos == end_ring) |
| 1485 | ringpos = ring; | 1529 | ring_pos = ring; |
| 1486 | text[LINESIZ] = '\r'; | 1530 | text[LINESIZ] = '\r'; |
| 1487 | text[LINESIZ + 1] = '\n'; | 1531 | text[LINESIZ + 1] = '\n'; |
| 1488 | sendto(s, text, sizeof(text), 0, &lsa->u.sa, lsa->len); | 1532 | sendto(s, text, sizeof(text), 0, &lsa->u.sa, lsa->len); |
| @@ -1498,7 +1542,7 @@ static void chargen_dg(int s, servtab_t *sep) | |||
| 1498 | * we must add 2208988800 seconds to this figure to make up for | 1542 | * we must add 2208988800 seconds to this figure to make up for |
| 1499 | * some seventy years Bell Labs was asleep. | 1543 | * some seventy years Bell Labs was asleep. |
| 1500 | */ | 1544 | */ |
| 1501 | static unsigned machtime(void) | 1545 | static uint32_t machtime(void) |
| 1502 | { | 1546 | { |
| 1503 | struct timeval tv; | 1547 | struct timeval tv; |
| 1504 | 1548 | ||
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 2ee833e3f..ce4829584 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
| @@ -751,6 +751,11 @@ int nc_main(int argc, char **argv) | |||
| 751 | if (option_mask32 & OPT_s) { /* local address */ | 751 | if (option_mask32 & OPT_s) { /* local address */ |
| 752 | /* if o_lport is still 0, then we will use random port */ | 752 | /* if o_lport is still 0, then we will use random port */ |
| 753 | ouraddr = xhost2sockaddr(str_s, o_lport); | 753 | ouraddr = xhost2sockaddr(str_s, o_lport); |
| 754 | #ifdef BLOAT | ||
| 755 | /* prevent spurious "UDP listen needs !0 port" */ | ||
| 756 | o_lport = get_nport(ouraddr); | ||
| 757 | o_lport = ntohs(o_lport); | ||
| 758 | #endif | ||
| 754 | x = xsocket(ouraddr->u.sa.sa_family, x, 0); | 759 | x = xsocket(ouraddr->u.sa.sa_family, x, 0); |
| 755 | } else { | 760 | } else { |
| 756 | /* We try IPv6, then IPv4, unless addr family is | 761 | /* We try IPv6, then IPv4, unless addr family is |
| @@ -771,12 +776,14 @@ int nc_main(int argc, char **argv) | |||
| 771 | setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf); | 776 | setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf); |
| 772 | #endif | 777 | #endif |
| 773 | 778 | ||
| 779 | #ifdef BLOAT | ||
| 774 | if (OPT_l && (option_mask32 & (OPT_u|OPT_l)) == (OPT_u|OPT_l)) { | 780 | if (OPT_l && (option_mask32 & (OPT_u|OPT_l)) == (OPT_u|OPT_l)) { |
| 775 | /* apparently UDP can listen ON "port 0", | 781 | /* apparently UDP can listen ON "port 0", |
| 776 | but that's not useful */ | 782 | but that's not useful */ |
| 777 | if (!o_lport) | 783 | if (!o_lport) |
| 778 | bb_error_msg_and_die("UDP listen needs nonzero -p port"); | 784 | bb_error_msg_and_die("UDP listen needs nonzero -p port"); |
| 779 | } | 785 | } |
| 786 | #endif | ||
| 780 | 787 | ||
| 781 | FD_SET(0, &ding1); /* stdin *is* initially open */ | 788 | FD_SET(0, &ding1); /* stdin *is* initially open */ |
| 782 | if (proggie) { | 789 | if (proggie) { |
