slattach: code shrink, better --help text
No binary (build failed)
—
(log yok)
| @@ -78,7 +78,7 @@ conspy - interactive, longterm | |
| cp - noexec. runner | |
| cpio - runner | |
| crond - daemon | |
| - | crontab 0 leaks: open+xasprintf |
| + | crontab - longterm (runs $EDITOR), leaks: open+xasprintf |
| cryptpw - noexec. changes state: with --password-fd=N, moves N to stdin | |
| cttyhack - noexec. spawner | |
| cut - noexec. runner | |
| @@ -311,7 +311,7 @@ setkeycodes | |
| setlogcons | |
| setpriv - spawner, changes state, let's play safe and not be noexec | |
| setserial | |
| - | setsid - spawner, uses fork_or_rexec() [not audted to work in noexec], let's play safe and not be noexec |
| + | setsid - spawner, uses fork_or_rexec() [not audited to work in noexec], let's play safe and not be noexec |
| setuidgid - noexec. spawner | |
| sha1sum - noexec. runner | |
| sha256sum - noexec. runner | |
| @@ -320,7 +320,7 @@ sha512sum - noexec. runner | |
| showkey - interactive, longterm | |
| shred - runner | |
| shuf - noexec. runner | |
| - | slattach |
| + | slattach - longterm (may sleep forever), uses bb_common_bufsiz1 |
| sleep - runner, longterm | |
| smemcap - runner | |
| softlimit - noexec. spawner | |
| @@ -313,7 +313,7 @@ int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) | |
| int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags) | |
| { | |
| - | //TODO: lineedit, microcom and less might be adapted to use this too: |
| + | //TODO: lineedit, microcom, slattach, less might be adapted to use this too: |
| // grep for "tcsetattr" | |
| struct termios newterm; | |
| @@ -17,23 +17,23 @@ | |
| //config: default y | |
| //config: select PLATFORM_LINUX | |
| //config: help | |
| - | //config: slattach is a small utility to attach network interfaces to serial |
| - | //config: lines. |
| + | //config: slattach configures serial line as SLIP network interface. |
| //applet:IF_SLATTACH(APPLET(slattach, BB_DIR_SBIN, BB_SUID_DROP)) | |
| + | /* shouldn't be NOEXEC: may sleep indefinitely */ |
| //kbuild:lib-$(CONFIG_SLATTACH) += slattach.o | |
| //usage:#define slattach_trivial_usage | |
| - | //usage: "[-cehmLF] [-s SPEED] [-p PROTOCOL] DEVICE" |
| + | //usage: "[-ehmLF] [-c SCRIPT] [-s BAUD] [-p PROTOCOL] SERIAL_DEVICE" |
| //usage:#define slattach_full_usage "\n\n" | |
| - | //usage: "Attach network interface(s) to serial line(s)\n" |
| - | //usage: "\n -p PROT Set protocol (slip, cslip, slip6, clisp6 or adaptive)" |
| - | //usage: "\n -s SPD Set line speed" |
| - | //usage: "\n -e Exit after initializing device" |
| - | //usage: "\n -h Exit when the carrier is lost" |
| - | //usage: "\n -c PROG Run PROG when the line is hung up" |
| - | //usage: "\n -m Do NOT initialize the line in raw 8 bits mode" |
| + | //usage: "Configure serial line as SLIP network interface\n" |
| + | //usage: "\n -p PROT Protocol: slip, cslip (default), slip6, clisp6, adaptive" |
| + | //usage: "\n -s BAUD Line speed" |
| + | //usage: "\n -e Exit after initialization" |
| + | //usage: "\n -h Exit if carrier is lost (else never exits)" |
| + | //usage: "\n -c PROG Run PROG on carrier loss" |
| + | //usage: "\n -m Do NOT set raw 8bit mode" |
| //usage: "\n -L Enable 3-wire operation" | |
| //usage: "\n -F Disable RTS/CTS flow control" | |
| @@ -42,103 +42,53 @@ | |
| #include "libiproute/utils.h" /* invarg_1_to_2() */ | |
| struct globals { | |
| - | int handle; |
| int saved_disc; | |
| struct termios saved_state; | |
| } FIX_ALIASING; | |
| #define G (*(struct globals*)bb_common_bufsiz1) | |
| - | #define handle (G.handle ) |
| - | #define saved_disc (G.saved_disc ) |
| - | #define saved_state (G.saved_state ) |
| #define INIT_G() do { setup_common_bufsiz(); } while (0) | |
| + | #define serial_fd 3 |
| - | /* |
| - | * Save tty state and line discipline |
| - | * |
| - | * It is fine here to bail out on errors, since we haven modified anything yet |
| - | */ |
| - | static void save_state(void) |
| - | { |
| - | /* Save line status */ |
| - | if (tcgetattr(handle, &saved_state) < 0) |
| - | bb_perror_msg_and_die("get state"); |
| - | |
| - | /* Save line discipline */ |
| - | xioctl(handle, TIOCGETD, &saved_disc); |
| - | } |
| - | |
| - | static int set_termios_state_or_warn(struct termios *state) |
| + | static int tcsetattr_serial_or_warn(struct termios *state) |
| { | |
| int ret; | |
| - | ret = tcsetattr(handle, TCSANOW, state); |
| - | if (ret < 0) { |
| - | bb_perror_msg("set state"); |
| + | ret = tcsetattr(serial_fd, TCSANOW, state); |
| + | if (ret != 0) { |
| + | bb_perror_msg("tcsetattr"); |
| return 1; /* used as exitcode */ | |
| } | |
| - | return 0; |
| + | return ret; /* 0 */ |
| } | |
| - | /* |
| - | * Restore state and line discipline for ALL managed ttys |
| - | * |
| - | * Restoring ALL managed ttys is the only way to have a single |
| - | * hangup delay. |
| - | * |
| - | * Go on after errors: we want to restore as many controlled ttys |
| - | * as possible. |
| - | */ |
| static void restore_state_and_exit(int exitcode) NORETURN; | |
| static void restore_state_and_exit(int exitcode) | |
| { | |
| struct termios state; | |
| /* Restore line discipline */ | |
| - | if (ioctl_or_warn(handle, TIOCSETD, &saved_disc) < 0) { |
| + | if (ioctl_or_warn(serial_fd, TIOCSETD, &G.saved_disc)) { |
| exitcode = 1; | |
| } | |
| /* Hangup */ | |
| - | memcpy(&state, &saved_state, sizeof(state)); |
| + | memcpy(&state, &G.saved_state, sizeof(state)); |
| cfsetispeed(&state, B0); | |
| cfsetospeed(&state, B0); | |
| - | if (set_termios_state_or_warn(&state)) |
| - | exitcode = 1; |
| + | exitcode |= tcsetattr_serial_or_warn(&state); |
| sleep(1); | |
| /* Restore line status */ | |
| - | if (set_termios_state_or_warn(&saved_state)) |
| + | if (tcsetattr_serial_or_warn(&G.saved_state)) |
| exit(EXIT_FAILURE); | |
| + | |
| if (ENABLE_FEATURE_CLEAN_UP) | |
| - | close(handle); |
| + | close(serial_fd); |
| exit(exitcode); | |
| } | |
| - | /* |
| - | * Set tty state, line discipline and encapsulation |
| - | */ |
| - | static void set_state(struct termios *state, int encap) |
| - | { |
| - | int disc; |
| - | |
| - | /* Set line status */ |
| - | if (set_termios_state_or_warn(state)) |
| - | goto bad; |
| - | /* Set line discliple (N_SLIP always) */ |
| - | disc = N_SLIP; |
| - | if (ioctl_or_warn(handle, TIOCSETD, &disc) < 0) { |
| - | goto bad; |
| - | } |
| - | |
| - | /* Set encapsulation (SLIP, CSLIP, etc) */ |
| - | if (ioctl_or_warn(handle, SIOCSIFENCAP, &encap) < 0) { |
| - | bad: |
| - | restore_state_and_exit(EXIT_FAILURE); |
| - | } |
| - | } |
| - | |
| static void sig_handler(int signo UNUSED_PARAM) | |
| { | |
| restore_state_and_exit(EXIT_SUCCESS); | |
| @@ -155,13 +105,14 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |
| "cslip6\0" /* 3 */ | |
| "adaptive\0" /* 8 */ | |
| ; | |
| + | static const int int_N_SLIP = N_SLIP; |
| - | int i, encap, opt; |
| + | int encap, opt, fd; |
| struct termios state; | |
| const char *proto = "cslip"; | |
| const char *extcmd; /* Command to execute after hangup */ | |
| const char *baud_str; | |
| - | int baud_code = -1; /* Line baud rate (system code) */ |
| + | int baud_code = baud_code; /* for compiler */ |
| enum { | |
| OPT_p_proto = 1 << 0, | |
| @@ -177,15 +128,12 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |
| INIT_G(); | |
| /* Parse command line options */ | |
| + | opt_complementary = "=1"; |
| opt = getopt32(argv, "p:s:c:ehmLF", &proto, &baud_str, &extcmd); | |
| /*argc -= optind;*/ | |
| argv += optind; | |
| - | if (!*argv) |
| - | bb_show_usage(); |
| - | |
| encap = index_in_strings(proto_names, proto); | |
| - | |
| if (encap < 0) | |
| invarg_1_to_2(proto, "protocol"); | |
| if (encap > 3) | |
| @@ -198,6 +146,22 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |
| invarg_1_to_2(baud_str, "baud rate"); | |
| } | |
| + | /* Open tty */ |
| + | fd = open(*argv, O_RDWR | O_NDELAY); |
| + | if (fd < 0) { |
| + | char *buf = concat_path_file("/dev", *argv); |
| + | fd = xopen(buf, O_RDWR | O_NDELAY); |
| + | /* maybe if (ENABLE_FEATURE_CLEAN_UP) ?? */ |
| + | free(buf); |
| + | } |
| + | xmove_fd(fd, serial_fd); |
| + | |
| + | /* Save current tty state */ |
| + | if (tcgetattr(serial_fd, &G.saved_state) != 0) |
| + | bb_perror_msg_and_die("tcgetattr"); |
| + | /* Save line discipline */ |
| + | xioctl(serial_fd, TIOCGETD, &G.saved_disc); |
| + | |
| /* Trap signals in order to restore tty states upon exit */ | |
| if (!(opt & OPT_e_quit)) { | |
| bb_signals(0 | |
| @@ -208,43 +172,37 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |
| , sig_handler); | |
| } | |
| - | /* Open tty */ |
| - | handle = open(*argv, O_RDWR | O_NDELAY); |
| - | if (handle < 0) { |
| - | char *buf = concat_path_file("/dev", *argv); |
| - | handle = xopen(buf, O_RDWR | O_NDELAY); |
| - | /* maybe if (ENABLE_FEATURE_CLEAN_UP) ?? */ |
| - | free(buf); |
| - | } |
| - | |
| - | /* Save current tty state */ |
| - | save_state(); |
| - | |
| /* Configure tty */ | |
| - | memcpy(&state, &saved_state, sizeof(state)); |
| + | memcpy(&state, &G.saved_state, sizeof(state)); |
| if (!(opt & OPT_m_nonraw)) { /* raw not suppressed */ | |
| memset(&state.c_cc, 0, sizeof(state.c_cc)); | |
| state.c_cc[VMIN] = 1; | |
| state.c_iflag = IGNBRK | IGNPAR; | |
| - | state.c_oflag = 0; |
| - | state.c_lflag = 0; |
| + | /*state.c_oflag = 0;*/ |
| + | /*state.c_lflag = 0;*/ |
| state.c_cflag = CS8 | HUPCL | CREAD | |
| | ((opt & OPT_L_local) ? CLOCAL : 0) | |
| | ((opt & OPT_F_noflow) ? 0 : CRTSCTS); | |
| - | cfsetispeed(&state, cfgetispeed(&saved_state)); |
| - | cfsetospeed(&state, cfgetospeed(&saved_state)); |
| + | cfsetispeed(&state, cfgetispeed(&G.saved_state)); |
| + | cfsetospeed(&state, cfgetospeed(&G.saved_state)); |
| } | |
| - | |
| if (opt & OPT_s_baud) { | |
| cfsetispeed(&state, baud_code); | |
| cfsetospeed(&state, baud_code); | |
| } | |
| - | |
| - | set_state(&state, encap); |
| + | /* Set line status */ |
| + | if (tcsetattr_serial_or_warn(&state)) |
| + | goto bad; |
| + | /* Set line disclipline (N_SLIP always) */ |
| + | if (ioctl_or_warn(serial_fd, TIOCSETD, (void*)&int_N_SLIP)) |
| + | goto bad; |
| + | /* Set encapsulation (SLIP, CSLIP, etc) */ |
| + | if (ioctl_or_warn(serial_fd, SIOCSIFENCAP, &encap)) |
| + | goto bad; |
| /* Exit now if option -e was passed */ | |
| if (opt & OPT_e_quit) | |
| - | return 0; |
| + | return EXIT_SUCCESS; |
| /* If we're not requested to watch, just keep descriptor open | |
| * until we are killed */ | |
| @@ -254,17 +212,20 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |
| /* Watch line for hangup */ | |
| while (1) { | |
| - | if (ioctl(handle, TIOCMGET, &i) < 0 || !(i & TIOCM_CAR)) |
| - | goto no_carrier; |
| + | int modem_stat; |
| + | if (ioctl(serial_fd, TIOCMGET, &modem_stat)) |
| + | break; |
| + | if (!(modem_stat & TIOCM_CAR)) |
| + | break; |
| sleep(15); | |
| } | |
| - | no_carrier: |
| - | |
| /* Execute command on hangup */ | |
| if (opt & OPT_c_extcmd) | |
| system(extcmd); | |
| /* Restore states and exit */ | |
| restore_state_and_exit(EXIT_SUCCESS); | |
| + | bad: |
| + | restore_state_and_exit(EXIT_FAILURE); |
| } | |