[PATCH] slattach applet for busybox 1.4.1 (this is the GOOD one)

Bernhard Fischer rep.dot.nop at gmail.com
Fri Feb 16 05:23:28 PST 2007


On Fri, Feb 16, 2007 at 12:21:57PM +0100, Ignacio García Pérez wrote:
>Sorry, attached the wrong patch in previous message. This is the good one.
>
>As I already said, would be nice to rewrite the option parsing code to 
>make use of the libbb functions.
>
>Regards.
>
>
>

>diff -urN busybox-1.4.1/include/applets.h busybox-1.4.1-modified/include/applets.h
>--- busybox-1.4.1/include/applets.h	2007-01-24 22:34:48.000000000 +0100
>+++ busybox-1.4.1-modified/include/applets.h	2007-02-16 11:45:33.000000000 +0100
>@@ -262,6 +262,7 @@
> USE_FEATURE_SH_IS_LASH(APPLET_NOUSAGE(sh, lash, _BB_DIR_BIN, _BB_SUID_NEVER))
> USE_FEATURE_SH_IS_MSH(APPLET_NOUSAGE(sh, msh, _BB_DIR_BIN, _BB_SUID_NEVER))
> USE_SHA1SUM(APPLET_ODDNAME(sha1sum, md5_sha1_sum, _BB_DIR_USR_BIN, _BB_SUID_NEVER, sha1sum))
>+USE_SLATTACH(APPLET(slattach, _BB_DIR_SBIN, _BB_SUID_NEVER))
> USE_SLEEP(APPLET(sleep, _BB_DIR_BIN, _BB_SUID_NEVER))
> USE_SOFTLIMIT(APPLET_ODDNAME(softlimit, chpst, _BB_DIR_USR_BIN, _BB_SUID_NEVER, softlimit))
> USE_SORT(APPLET(sort, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
>diff -urN busybox-1.4.1/include/usage.h busybox-1.4.1-modified/include/usage.h
>--- busybox-1.4.1/include/usage.h	2007-01-24 22:34:48.000000000 +0100
>+++ busybox-1.4.1-modified/include/usage.h	2007-02-16 11:44:10.000000000 +0100
>@@ -2788,6 +2788,20 @@
>        "	-s	Don't output anything, status code shows success\n" \
>        "	-w	Warn about improperly formatted SHA1 checksum lines")
> 
>+#define slattach_trivial_usage \
>+	"[-cehmLF] [-s speed] [-p protocol] DEVICEs"
>+#define slattach_full_usage \
>+	"Attach network interface(s) to serial line(s).\n" \
>+	"Options:\n" \
>+	"\t-p\tset a specific kind of protocol (slip, cslip, slip6, clisp6 or adaptive).\n" \
>+	"\t-s\tset a specific line speed.\n"
>+	"\t-c\texecute a command when the line is hung up\n" \
>+	"\t-e\texit right after initializing device.\n" \
>+	"\t-h\texit when the carrier is lost.\n" \
>+	"\t-m\tdo NOT initialize the line in raw 8 bits mode.\n" \
>+	"\t-L\tenable 3-wire operation.\n" \
>+	"\t-F\tdisable RTS/CTS flow control.\n" \
>+ 
> #define sleep_trivial_usage \
> 	USE_FEATURE_FANCY_SLEEP("[") "N" USE_FEATURE_FANCY_SLEEP("]...")
> #define sleep_full_usage \
>diff -urN busybox-1.4.1/networking/Config.in busybox-1.4.1-modified/networking/Config.in
>--- busybox-1.4.1/networking/Config.in	2007-01-24 22:34:34.000000000 +0100
>+++ busybox-1.4.1-modified/networking/Config.in	2007-02-16 11:47:50.000000000 +0100
>@@ -523,6 +523,12 @@
> 	help
> 	  Route displays or manipulates the kernel's IP routing tables.
> 
>+config SLATTACH
>+	bool "slattach"
>+	default n
>+	help
>+	  Slattach is a small utility to attach network interfaces to serial lines.
>+
> config TELNET
> 	bool "telnet"
> 	default n
>diff -urN busybox-1.4.1/networking/Kbuild busybox-1.4.1-modified/networking/Kbuild
>--- busybox-1.4.1/networking/Kbuild	2007-01-24 22:34:34.000000000 +0100
>+++ busybox-1.4.1-modified/networking/Kbuild	2007-02-16 11:38:37.000000000 +0100
>@@ -32,6 +32,7 @@
> lib-$(CONFIG_PING)         += ping.o
> lib-$(CONFIG_PING6)        += ping6.o
> lib-$(CONFIG_ROUTE)        += route.o
>+lib-$(CONFIG_SLATTACH)     += slattach.o
> lib-$(CONFIG_TELNET)       += telnet.o
> lib-$(CONFIG_TELNETD)      += telnetd.o
> lib-$(CONFIG_TFTP)         += tftp.o
>diff -urN busybox-1.4.1/networking/slattach.c busybox-1.4.1-modified/networking/slattach.c
>--- busybox-1.4.1/networking/slattach.c	1970-01-01 01:00:00.000000000 +0100
>+++ busybox-1.4.1-modified/networking/slattach.c	2007-02-16 12:03:18.000000000 +0100
>@@ -0,0 +1,266 @@
>+/*
>+ *		Stripped down version of net-tools for busybox.
>+ *
>+ *		Author: Ignacio Garcia Perez (iggarpe at gmail dot com)
>+ *
>+ *		License: GPLv2 or later, see LICENSE file in this tarball.
>+ *
>+ *		There are some differences from the standard net-tools slattach:
>+ *
>+ *		- The -l option is not supported.
>+ *
>+ *		- Several devices can be specified in the command line. This is
>+ *		  very useful if you are handling many identical serial lines since
>+ *		  only one process is necessary to configure them all.
>+ *
>+ *		- The -F options allows disabling of RTS/CTS flow control.
>+ *
>+ */
>+
>+#include <unistd.h>
>+#include <stdlib.h>
>+#include <string.h>
>+#include <stdio.h>
>+#include <signal.h>
>+#include <errno.h>
>+#include <sys/socket.h>
>+#include <sys/types.h>
>+#include <sys/stat.h>
>+#include <fcntl.h>
>+#include <termios.h>
>+#include <sys/ioctl.h>
>+
>+#include "libbb.h"
>+
>+struct tty {
>+	const char *	device;
>+	int				handle;
>+	int				saved_disc;
>+	struct termios	saved_state;
>+	struct tty *	next;
>+};
>+
>+static struct tty *_tty_head = NULL;
>+static struct tty *_tty_tail = NULL;
>+
>+/* Line discipline code table */
>+
>+static struct { const char *name; int code; } _proto [] = {
>+	{ "slip",		0 },
>+	{ "cslip",		1 },
>+	{ "slip6",		2 },
>+	{ "cslip6",		3 },
>+	{ "adaptive",	8 },
>+	{ NULL }
>+};
>+
>+/*
>+ * Save tty state and line discipline
>+ */
>+
>+static int _save_state (struct tty *t) {
>+
>+	if (t->handle < 0) return 0;
>+
>+	if (tcgetattr(t->handle, &t->saved_state) < 0)			/* Save line status */
>+		{ bb_perror_msg("get state"); return -1; }
>+
>+	if (ioctl(t->handle, TIOCGETD, &t->saved_disc) < 0)		/* Save line discipline */
>+		{ bb_perror_msg("get discipline"); return -1; }
>+
>+	return 0;
>+}
>+
>+/*
>+ * Set tty state, line discipline and encapsulation
>+ */
>+
>+static int _set_state (struct tty *t, struct termios *state, int encap) {
>+
>+	int disc = N_SLIP;
>+
>+	if (t->handle < 0) return 0;
>+
>+	if (tcsetattr(t->handle, TCSANOW, state) < 0)			/* Set line status */
>+		{ bb_perror_msg("set state"); return -1; }
>+
>+	if (ioctl(t->handle, TIOCSETD, &disc) < 0)				/* Set line discliple (N_SLIP always) */
>+		{ bb_perror_msg("set discipline"); return -1; }
>+
>+	if (ioctl(t->handle, SIOCSIFENCAP, &encap) < 0)			/* Set encapsulation (SLIP, CSLIP, etc) */
>+		{ bb_perror_msg("set encapsulation"); return -1; }
>+
>+	return 0;
>+}
>+
>+/*
>+ * Restore state and line discipline for ALL managed ttys
>+ *
>+ * Restoring ALL managed ttys is the only way to have a single
>+ * hangup delay.
>+ *
>+ */
>+
>+static int _restore_state_and_close (void) {
>+
>+	struct tty *t;
>+	struct termios state;
>+
>+	for (t = _tty_head; t != NULL; t = t->next) if (t->handle >= 0) {
>+
>+		if (ioctl(t->handle, TIOCSETD, &t->saved_disc) < 0)			/* Restore line discipline */
>+			{ bb_perror_msg("set discipline"); return -1; }
>+
>+		memcpy(&state, &t->saved_state, sizeof(state));				/* Hangup */
>+		cfsetispeed(&state, B0);
>+		cfsetospeed(&state, B0);
>+		if (tcsetattr(t->handle, TCSANOW, &state) < 0)
>+			{ bb_perror_msg("set state"); return -1; }
>+	}
>+
>+	sleep(1);	/* The sleep time does not depend on the number of managed ttys */
>+
>+	for (t = _tty_head; t != NULL; t = t->next) if (t->handle >= 0) {
>+
>+		if (tcsetattr(t->handle, TCSANOW, &t->saved_state) < 0)		/* Restore line status */
>+			{ perror("set state"); return -1; }
>+
>+		close(t->handle); t->handle = -1;
>+	}
>+
>+	return 0;
>+}
>+
>+static void _sig_handler (int signo) {
>+	if (_restore_state_and_close() < 0) sleep_and_die();
>+	exit(0);
>+}
>+
>+int slattach_main (int argc, char **argv) {
>+
>+	int i, encap;
>+	struct tty *t;
>+	struct termios state;
>+	char buf [PATH_MAX];

That's a large buffer, imho. xmalloc() or make it
RESERVE_CONFIG_BUFFER(buf,PATH_MAX)

>+
>+	const char *proto = "cslip";	/* Protocol */
>+	const char *extcmd = NULL;		/* Command to execute after hangup */
>+
>+	int baud = -1;		/* Line baud rate (value) */
>+	int baud_code = -1;	/* Line baud rate (system code) */
>+	int local = 0;		/* Local mode (disable carrier watch) */
>+	int quit = 0;		/* Initialize and exit */
>+	int watch = 0;		/* watch for line hangup */
>+	int raw = 1;		/* Initialize line in raw 8 bit mode */
>+	int flow = 1;		/* Disable RTS/CTS flow control (not in net-tools slattach !!!) */

most of these should use one variable and mask their bits in.
>+
>+	/* Parse command line options */
>+	/* TODO: use bb lib getopt_whatever? */

getopt32, yes.

The block below is just too bloated.
>+
>+	for (i = 1; i < argc; i++) {
>+
>+		if (argv[i][0] == '-') switch (argv[i][1]) {
>+			case 'p': proto = argv[++i]; break;
>+			case 's': baud = atoi(argv[++i]); break;
>+			case 'c': extcmd = argv[++i]; break;
>+			case 'e': quit = 1; break;
>+			case 'h': watch = 1; break;
>+			case 'm': raw = 0; break;
>+			case 'L': local = 1; break;
>+			case 'F': flow = 0; break;
>+			default: bb_error_msg_and_die("invalid option %s", argv[i]);
>+		}
>+
>+		else {
>+			t = (struct tty *)malloc(sizeof(struct tty));
>+			if (t == NULL) bb_error_msg_and_die("not enough memory");

No. xmalloc() instead

>+
>+			t->device = argv[i];
>+			t->handle = -1;
>+			t->next = NULL;
>+
>+			if (_tty_head == NULL) _tty_head = _tty_tail = t;
>+			else { _tty_tail->next = t; _tty_tail = t; }
>+		}
>+	}
>+
>+	if (_tty_head == NULL) bb_show_usage();
>+
>+	for (i = 0; _proto[i].name != NULL; i++)
>+		if (!strcmp(_proto[i].name, proto)) break;

index_in_str_array() instead

>+	if (_proto[i].name == NULL) bb_error_msg_and_die("invalid protocol %s", proto);
>+	encap = _proto[i].code;
>+
>+	baud_code = tty_value_to_baud(baud);
>+	if (baud_code < 0) bb_error_msg_and_die("invalid baud rate %i", baud);
>+
>+	/* Trap signals in order to restore tty states upon exit */
>+
>+	if (!quit) {
>+		signal(SIGHUP, _sig_handler);
>+		signal(SIGINT, _sig_handler);
>+		signal(SIGQUIT, _sig_handler);
>+		signal(SIGTERM, _sig_handler);
>+	}
>+
>+	/* Configure ttys */
>+
>+	for (t = _tty_head; t != NULL; t = t->next) {
>+
>+		t->handle = open(t->device, O_RDWR | O_NDELAY);
>+		if (t->handle < 0) {
>+			snprintf(buf, sizeof(buf), "/dev/%s", t->device);

concat_path_file() instead. Should make that huge buf from above
superfluous.

>+			t->handle = open(buf, O_RDWR | O_NDELAY);
>+			if (t->handle < 0) bb_perror_msg_and_die("open %s", t->device);
>+		}
>+
>+		if (_save_state(t) < 0) sleep_and_die();
>+
>+		memcpy(&state, &t->saved_state, sizeof(state));
>+
>+		if (raw) {
>+			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
>+								| (local ? CLOCAL : 0) | (flow ? CRTSCTS : 0);
>+		}
>+
>+		if (baud_code >= 0) {

Didn't we check above that boud_rate not is < 0 above? drop it then.

>+			cfsetispeed(&state, baud_code);
>+			cfsetospeed(&state, baud_code);
>+		}
>+
>+		if (_set_state(t, &state, encap) < 0)
>+			{ _restore_state_and_close(); sleep_and_die(); }
>+	}
>+
>+	/* Exit now if option -e was passed */
>+
>+	if (quit) exit(0);
>+
>+	/* Watch line for hangup */
>+
>+	for (;;) {
>+
>+		if (watch)
>+			for (t = _tty_head; t != NULL; t = t->next)
>+				if (ioctl(t->handle, TIOCMGET, &i) < 0 || !(i & TIOCM_CAR))
>+					quit = 1;
>+
>+		if (quit) break;

would a while (!option_mask32 & QUIT) be smaller?

>+		sleep(15);
>+	}
>+
>+	/* Execute command on hangup */
>+
>+	if (extcmd != NULL) system(extcmd);
>+
>+	/* Restore states and exit */
>+
>+	_restore_state_and_close();
>+	return 0;
>+}
>+


More information about the busybox mailing list