slattach: code shrink, better --help text
function old new delta tcsetattr_serial_or_warn - 34 +34 static.int_N_SLIP - 4 +4 restore_state_and_exit 123 117 -6 packed_usage 31774 31747 -27 set_termios_state_or_warn 42 - -42 slattach_main 673 624 -49 ------------------------------------------------------------------------------ (add/remove: 2/1 grow/shrink: 0/3 up/down: 38/-124) Total: -86 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
parent
a759b22c29
commit
2262746e2b
@ -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);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user