6937487be7
Back in 2007, commit 0c97c9d43707 ("'simple' error message functions by Loic Grenie") introduced bb_simple_perror_msg() to allow for a lower overhead call to bb_perror_msg() when only a string was being printed with no parameters. This saves space for some CPU architectures because it avoids the overhead of a call to a variadic function. However there has never been a simple version of bb_error_msg(), and since 2007 many new calls to bb_perror_msg() have been added that only take a single parameter and so could have been using bb_simple_perror_message(). This changeset introduces 'simple' versions of bb_info_msg(), bb_error_msg(), bb_error_msg_and_die(), bb_herror_msg() and bb_herror_msg_and_die(), and replaces all calls that only take a single parameter, or use something like ("%s", arg), with calls to the corresponding 'simple' version. Since it is likely that single parameter calls to the variadic functions may be accidentally reintroduced in the future a new debugging config option WARN_SIMPLE_MSG has been introduced. This uses some macro magic which will cause any such calls to generate a warning, but this is turned off by default to avoid use of the unpleasant macros in normal circumstances. This is a large changeset due to the number of calls that have been replaced. The only files that contain changes other than simple substitution of function calls are libbb.h, libbb/herror_msg.c, libbb/verror_msg.c and libbb/xfuncs_printf.c. In miscutils/devfsd.c, networking/udhcp/common.h and util-linux/mdev.c additonal macros have been added for logging so that single parameter and multiple parameter logging variants exist. The amount of space saved varies considerably by architecture, and was found to be as follows (for 'defconfig' using GCC 7.4): Arm: -92 bytes MIPS: -52 bytes PPC: -1836 bytes x86_64: -938 bytes Note that for the MIPS architecture only an exception had to be made disabling the 'simple' calls for 'udhcp' (in networking/udhcp/common.h) because it made these files larger on MIPS. Signed-off-by: James Byrne <james.byrne@origamienergy.com> Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
233 lines
6.0 KiB
C
233 lines
6.0 KiB
C
/* vi: set sw=4 ts=4: */
|
|
/*
|
|
* Stripped down version of net-tools for busybox.
|
|
*
|
|
* Author: Ignacio Garcia Perez (iggarpe at gmail dot com)
|
|
*
|
|
* Licensed under GPLv2 or later, see file LICENSE in this source tree.
|
|
*
|
|
* There are some differences from the standard net-tools slattach:
|
|
*
|
|
* - The -l option is not supported.
|
|
*
|
|
* - The -F options allows disabling of RTS/CTS flow control.
|
|
*/
|
|
//config:config SLATTACH
|
|
//config: bool "slattach (6.2 kb)"
|
|
//config: default y
|
|
//config: select PLATFORM_LINUX
|
|
//config: help
|
|
//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: "[-ehmLF] [-c SCRIPT] [-s BAUD] [-p PROTOCOL] SERIAL_DEVICE"
|
|
//usage:#define slattach_full_usage "\n\n"
|
|
//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"
|
|
|
|
#include "libbb.h"
|
|
#include "common_bufsiz.h"
|
|
#include "libiproute/utils.h" /* invarg_1_to_2() */
|
|
|
|
struct globals {
|
|
int saved_disc;
|
|
struct termios saved_state;
|
|
} FIX_ALIASING;
|
|
#define G (*(struct globals*)bb_common_bufsiz1)
|
|
#define INIT_G() do { setup_common_bufsiz(); } while (0)
|
|
|
|
#define serial_fd 3
|
|
|
|
static int tcsetattr_serial_or_warn(struct termios *state)
|
|
{
|
|
int ret;
|
|
|
|
ret = tcsetattr(serial_fd, TCSANOW, state);
|
|
if (ret != 0) {
|
|
bb_simple_perror_msg("tcsetattr");
|
|
return 1; /* used as exitcode */
|
|
}
|
|
return ret; /* 0 */
|
|
}
|
|
|
|
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(serial_fd, TIOCSETD, &G.saved_disc)) {
|
|
exitcode = 1;
|
|
}
|
|
|
|
/* Hangup */
|
|
memcpy(&state, &G.saved_state, sizeof(state));
|
|
cfsetispeed(&state, B0);
|
|
cfsetospeed(&state, B0);
|
|
exitcode |= tcsetattr_serial_or_warn(&state);
|
|
sleep(1);
|
|
|
|
/* Restore line status */
|
|
if (tcsetattr_serial_or_warn(&G.saved_state))
|
|
exit(EXIT_FAILURE);
|
|
|
|
if (ENABLE_FEATURE_CLEAN_UP)
|
|
close(serial_fd);
|
|
|
|
exit(exitcode);
|
|
}
|
|
|
|
static void sig_handler(int signo UNUSED_PARAM)
|
|
{
|
|
restore_state_and_exit(EXIT_SUCCESS);
|
|
}
|
|
|
|
int slattach_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
|
|
int slattach_main(int argc UNUSED_PARAM, char **argv)
|
|
{
|
|
/* Line discipline code table */
|
|
static const char proto_names[] ALIGN1 =
|
|
"slip\0" /* 0 */
|
|
"cslip\0" /* 1 */
|
|
"slip6\0" /* 2 */
|
|
"cslip6\0" /* 3 */
|
|
"adaptive\0" /* 8 */
|
|
;
|
|
static const int int_N_SLIP = N_SLIP;
|
|
|
|
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 = baud_code; /* for compiler */
|
|
|
|
enum {
|
|
OPT_p_proto = 1 << 0,
|
|
OPT_s_baud = 1 << 1,
|
|
OPT_c_extcmd = 1 << 2,
|
|
OPT_e_quit = 1 << 3,
|
|
OPT_h_watch = 1 << 4,
|
|
OPT_m_nonraw = 1 << 5,
|
|
OPT_L_local = 1 << 6,
|
|
OPT_F_noflow = 1 << 7
|
|
};
|
|
|
|
INIT_G();
|
|
|
|
/* Parse command line options */
|
|
opt = getopt32(argv, "^" "p:s:c:ehmLF" "\0" "=1",
|
|
&proto, &baud_str, &extcmd
|
|
);
|
|
/*argc -= optind;*/
|
|
argv += optind;
|
|
|
|
encap = index_in_strings(proto_names, proto);
|
|
if (encap < 0)
|
|
invarg_1_to_2(proto, "protocol");
|
|
if (encap > 3)
|
|
encap = 8;
|
|
|
|
/* We want to know if the baud rate is valid before we start touching the ttys */
|
|
if (opt & OPT_s_baud) {
|
|
baud_code = tty_value_to_baud(xatoi(baud_str));
|
|
if (baud_code < 0)
|
|
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_simple_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
|
|
+ (1 << SIGHUP)
|
|
+ (1 << SIGINT)
|
|
+ (1 << SIGQUIT)
|
|
+ (1 << SIGTERM)
|
|
, sig_handler);
|
|
}
|
|
|
|
/* Configure tty */
|
|
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_cflag = CS8 | HUPCL | CREAD
|
|
| ((opt & OPT_L_local) ? CLOCAL : 0)
|
|
| ((opt & OPT_F_noflow) ? 0 : CRTSCTS);
|
|
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 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 EXIT_SUCCESS;
|
|
|
|
/* If we're not requested to watch, just keep descriptor open
|
|
* until we are killed */
|
|
if (!(opt & OPT_h_watch))
|
|
while (1)
|
|
sleep(24*60*60);
|
|
|
|
/* Watch line for hangup */
|
|
while (1) {
|
|
int modem_stat;
|
|
if (ioctl(serial_fd, TIOCMGET, &modem_stat))
|
|
break;
|
|
if (!(modem_stat & TIOCM_CAR))
|
|
break;
|
|
sleep(15);
|
|
}
|
|
|
|
/* 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);
|
|
}
|