diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2017-08-06 17:14:09 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2017-08-06 17:14:09 +0200 |
commit | 2262746e2b798361a9c293e02f76cb4f06b7b100 (patch) | |
tree | 76ecf71510faa55363085869ad5fa2aa361d6f48 | |
parent | a759b22c29fed7d6c77efe0c3e27772371d0889b (diff) | |
download | busybox-w32-2262746e2b798361a9c293e02f76cb4f06b7b100.tar.gz busybox-w32-2262746e2b798361a9c293e02f76cb4f06b7b100.tar.bz2 busybox-w32-2262746e2b798361a9c293e02f76cb4f06b7b100.zip |
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>
-rw-r--r-- | NOFORK_NOEXEC.lst | 6 | ||||
-rw-r--r-- | libbb/xfuncs.c | 2 | ||||
-rw-r--r-- | networking/slattach.c | 167 |
3 files changed, 68 insertions, 107 deletions
diff --git a/NOFORK_NOEXEC.lst b/NOFORK_NOEXEC.lst index 9b33afc32..3bd82aa60 100644 --- a/NOFORK_NOEXEC.lst +++ b/NOFORK_NOEXEC.lst | |||
@@ -78,7 +78,7 @@ conspy - interactive, longterm | |||
78 | cp - noexec. runner | 78 | cp - noexec. runner |
79 | cpio - runner | 79 | cpio - runner |
80 | crond - daemon | 80 | crond - daemon |
81 | crontab 0 leaks: open+xasprintf | 81 | crontab - longterm (runs $EDITOR), leaks: open+xasprintf |
82 | cryptpw - noexec. changes state: with --password-fd=N, moves N to stdin | 82 | cryptpw - noexec. changes state: with --password-fd=N, moves N to stdin |
83 | cttyhack - noexec. spawner | 83 | cttyhack - noexec. spawner |
84 | cut - noexec. runner | 84 | cut - noexec. runner |
@@ -311,7 +311,7 @@ setkeycodes | |||
311 | setlogcons | 311 | setlogcons |
312 | setpriv - spawner, changes state, let's play safe and not be noexec | 312 | setpriv - spawner, changes state, let's play safe and not be noexec |
313 | setserial | 313 | setserial |
314 | setsid - spawner, uses fork_or_rexec() [not audted to work in noexec], let's play safe and not be noexec | 314 | setsid - spawner, uses fork_or_rexec() [not audited to work in noexec], let's play safe and not be noexec |
315 | setuidgid - noexec. spawner | 315 | setuidgid - noexec. spawner |
316 | sha1sum - noexec. runner | 316 | sha1sum - noexec. runner |
317 | sha256sum - noexec. runner | 317 | sha256sum - noexec. runner |
@@ -320,7 +320,7 @@ sha512sum - noexec. runner | |||
320 | showkey - interactive, longterm | 320 | showkey - interactive, longterm |
321 | shred - runner | 321 | shred - runner |
322 | shuf - noexec. runner | 322 | shuf - noexec. runner |
323 | slattach | 323 | slattach - longterm (may sleep forever), uses bb_common_bufsiz1 |
324 | sleep - runner, longterm | 324 | sleep - runner, longterm |
325 | smemcap - runner | 325 | smemcap - runner |
326 | softlimit - noexec. spawner | 326 | softlimit - noexec. spawner |
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c index 98d3531d6..1b3a1667b 100644 --- a/libbb/xfuncs.c +++ b/libbb/xfuncs.c | |||
@@ -313,7 +313,7 @@ int FAST_FUNC tcsetattr_stdin_TCSANOW(const struct termios *tp) | |||
313 | 313 | ||
314 | int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags) | 314 | int FAST_FUNC set_termios_to_raw(int fd, struct termios *oldterm, int flags) |
315 | { | 315 | { |
316 | //TODO: lineedit, microcom and less might be adapted to use this too: | 316 | //TODO: lineedit, microcom, slattach, less might be adapted to use this too: |
317 | // grep for "tcsetattr" | 317 | // grep for "tcsetattr" |
318 | 318 | ||
319 | struct termios newterm; | 319 | struct termios newterm; |
diff --git a/networking/slattach.c b/networking/slattach.c index 71b5bf427..d4659a314 100644 --- a/networking/slattach.c +++ b/networking/slattach.c | |||
@@ -17,23 +17,23 @@ | |||
17 | //config: default y | 17 | //config: default y |
18 | //config: select PLATFORM_LINUX | 18 | //config: select PLATFORM_LINUX |
19 | //config: help | 19 | //config: help |
20 | //config: slattach is a small utility to attach network interfaces to serial | 20 | //config: slattach configures serial line as SLIP network interface. |
21 | //config: lines. | ||
22 | 21 | ||
23 | //applet:IF_SLATTACH(APPLET(slattach, BB_DIR_SBIN, BB_SUID_DROP)) | 22 | //applet:IF_SLATTACH(APPLET(slattach, BB_DIR_SBIN, BB_SUID_DROP)) |
23 | /* shouldn't be NOEXEC: may sleep indefinitely */ | ||
24 | 24 | ||
25 | //kbuild:lib-$(CONFIG_SLATTACH) += slattach.o | 25 | //kbuild:lib-$(CONFIG_SLATTACH) += slattach.o |
26 | 26 | ||
27 | //usage:#define slattach_trivial_usage | 27 | //usage:#define slattach_trivial_usage |
28 | //usage: "[-cehmLF] [-s SPEED] [-p PROTOCOL] DEVICE" | 28 | //usage: "[-ehmLF] [-c SCRIPT] [-s BAUD] [-p PROTOCOL] SERIAL_DEVICE" |
29 | //usage:#define slattach_full_usage "\n\n" | 29 | //usage:#define slattach_full_usage "\n\n" |
30 | //usage: "Attach network interface(s) to serial line(s)\n" | 30 | //usage: "Configure serial line as SLIP network interface\n" |
31 | //usage: "\n -p PROT Set protocol (slip, cslip, slip6, clisp6 or adaptive)" | 31 | //usage: "\n -p PROT Protocol: slip, cslip (default), slip6, clisp6, adaptive" |
32 | //usage: "\n -s SPD Set line speed" | 32 | //usage: "\n -s BAUD Line speed" |
33 | //usage: "\n -e Exit after initializing device" | 33 | //usage: "\n -e Exit after initialization" |
34 | //usage: "\n -h Exit when the carrier is lost" | 34 | //usage: "\n -h Exit if carrier is lost (else never exits)" |
35 | //usage: "\n -c PROG Run PROG when the line is hung up" | 35 | //usage: "\n -c PROG Run PROG on carrier loss" |
36 | //usage: "\n -m Do NOT initialize the line in raw 8 bits mode" | 36 | //usage: "\n -m Do NOT set raw 8bit mode" |
37 | //usage: "\n -L Enable 3-wire operation" | 37 | //usage: "\n -L Enable 3-wire operation" |
38 | //usage: "\n -F Disable RTS/CTS flow control" | 38 | //usage: "\n -F Disable RTS/CTS flow control" |
39 | 39 | ||
@@ -42,103 +42,53 @@ | |||
42 | #include "libiproute/utils.h" /* invarg_1_to_2() */ | 42 | #include "libiproute/utils.h" /* invarg_1_to_2() */ |
43 | 43 | ||
44 | struct globals { | 44 | struct globals { |
45 | int handle; | ||
46 | int saved_disc; | 45 | int saved_disc; |
47 | struct termios saved_state; | 46 | struct termios saved_state; |
48 | } FIX_ALIASING; | 47 | } FIX_ALIASING; |
49 | #define G (*(struct globals*)bb_common_bufsiz1) | 48 | #define G (*(struct globals*)bb_common_bufsiz1) |
50 | #define handle (G.handle ) | ||
51 | #define saved_disc (G.saved_disc ) | ||
52 | #define saved_state (G.saved_state ) | ||
53 | #define INIT_G() do { setup_common_bufsiz(); } while (0) | 49 | #define INIT_G() do { setup_common_bufsiz(); } while (0) |
54 | 50 | ||
51 | #define serial_fd 3 | ||
55 | 52 | ||
56 | /* | 53 | static int tcsetattr_serial_or_warn(struct termios *state) |
57 | * Save tty state and line discipline | ||
58 | * | ||
59 | * It is fine here to bail out on errors, since we haven modified anything yet | ||
60 | */ | ||
61 | static void save_state(void) | ||
62 | { | ||
63 | /* Save line status */ | ||
64 | if (tcgetattr(handle, &saved_state) < 0) | ||
65 | bb_perror_msg_and_die("get state"); | ||
66 | |||
67 | /* Save line discipline */ | ||
68 | xioctl(handle, TIOCGETD, &saved_disc); | ||
69 | } | ||
70 | |||
71 | static int set_termios_state_or_warn(struct termios *state) | ||
72 | { | 54 | { |
73 | int ret; | 55 | int ret; |
74 | 56 | ||
75 | ret = tcsetattr(handle, TCSANOW, state); | 57 | ret = tcsetattr(serial_fd, TCSANOW, state); |
76 | if (ret < 0) { | 58 | if (ret != 0) { |
77 | bb_perror_msg("set state"); | 59 | bb_perror_msg("tcsetattr"); |
78 | return 1; /* used as exitcode */ | 60 | return 1; /* used as exitcode */ |
79 | } | 61 | } |
80 | return 0; | 62 | return ret; /* 0 */ |
81 | } | 63 | } |
82 | 64 | ||
83 | /* | ||
84 | * Restore state and line discipline for ALL managed ttys | ||
85 | * | ||
86 | * Restoring ALL managed ttys is the only way to have a single | ||
87 | * hangup delay. | ||
88 | * | ||
89 | * Go on after errors: we want to restore as many controlled ttys | ||
90 | * as possible. | ||
91 | */ | ||
92 | static void restore_state_and_exit(int exitcode) NORETURN; | 65 | static void restore_state_and_exit(int exitcode) NORETURN; |
93 | static void restore_state_and_exit(int exitcode) | 66 | static void restore_state_and_exit(int exitcode) |
94 | { | 67 | { |
95 | struct termios state; | 68 | struct termios state; |
96 | 69 | ||
97 | /* Restore line discipline */ | 70 | /* Restore line discipline */ |
98 | if (ioctl_or_warn(handle, TIOCSETD, &saved_disc) < 0) { | 71 | if (ioctl_or_warn(serial_fd, TIOCSETD, &G.saved_disc)) { |
99 | exitcode = 1; | 72 | exitcode = 1; |
100 | } | 73 | } |
101 | 74 | ||
102 | /* Hangup */ | 75 | /* Hangup */ |
103 | memcpy(&state, &saved_state, sizeof(state)); | 76 | memcpy(&state, &G.saved_state, sizeof(state)); |
104 | cfsetispeed(&state, B0); | 77 | cfsetispeed(&state, B0); |
105 | cfsetospeed(&state, B0); | 78 | cfsetospeed(&state, B0); |
106 | if (set_termios_state_or_warn(&state)) | 79 | exitcode |= tcsetattr_serial_or_warn(&state); |
107 | exitcode = 1; | ||
108 | sleep(1); | 80 | sleep(1); |
109 | 81 | ||
110 | /* Restore line status */ | 82 | /* Restore line status */ |
111 | if (set_termios_state_or_warn(&saved_state)) | 83 | if (tcsetattr_serial_or_warn(&G.saved_state)) |
112 | exit(EXIT_FAILURE); | 84 | exit(EXIT_FAILURE); |
85 | |||
113 | if (ENABLE_FEATURE_CLEAN_UP) | 86 | if (ENABLE_FEATURE_CLEAN_UP) |
114 | close(handle); | 87 | close(serial_fd); |
115 | 88 | ||
116 | exit(exitcode); | 89 | exit(exitcode); |
117 | } | 90 | } |
118 | 91 | ||
119 | /* | ||
120 | * Set tty state, line discipline and encapsulation | ||
121 | */ | ||
122 | static void set_state(struct termios *state, int encap) | ||
123 | { | ||
124 | int disc; | ||
125 | |||
126 | /* Set line status */ | ||
127 | if (set_termios_state_or_warn(state)) | ||
128 | goto bad; | ||
129 | /* Set line discliple (N_SLIP always) */ | ||
130 | disc = N_SLIP; | ||
131 | if (ioctl_or_warn(handle, TIOCSETD, &disc) < 0) { | ||
132 | goto bad; | ||
133 | } | ||
134 | |||
135 | /* Set encapsulation (SLIP, CSLIP, etc) */ | ||
136 | if (ioctl_or_warn(handle, SIOCSIFENCAP, &encap) < 0) { | ||
137 | bad: | ||
138 | restore_state_and_exit(EXIT_FAILURE); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | static void sig_handler(int signo UNUSED_PARAM) | 92 | static void sig_handler(int signo UNUSED_PARAM) |
143 | { | 93 | { |
144 | restore_state_and_exit(EXIT_SUCCESS); | 94 | restore_state_and_exit(EXIT_SUCCESS); |
@@ -155,13 +105,14 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |||
155 | "cslip6\0" /* 3 */ | 105 | "cslip6\0" /* 3 */ |
156 | "adaptive\0" /* 8 */ | 106 | "adaptive\0" /* 8 */ |
157 | ; | 107 | ; |
108 | static const int int_N_SLIP = N_SLIP; | ||
158 | 109 | ||
159 | int i, encap, opt; | 110 | int encap, opt, fd; |
160 | struct termios state; | 111 | struct termios state; |
161 | const char *proto = "cslip"; | 112 | const char *proto = "cslip"; |
162 | const char *extcmd; /* Command to execute after hangup */ | 113 | const char *extcmd; /* Command to execute after hangup */ |
163 | const char *baud_str; | 114 | const char *baud_str; |
164 | int baud_code = -1; /* Line baud rate (system code) */ | 115 | int baud_code = baud_code; /* for compiler */ |
165 | 116 | ||
166 | enum { | 117 | enum { |
167 | OPT_p_proto = 1 << 0, | 118 | OPT_p_proto = 1 << 0, |
@@ -177,15 +128,12 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |||
177 | INIT_G(); | 128 | INIT_G(); |
178 | 129 | ||
179 | /* Parse command line options */ | 130 | /* Parse command line options */ |
131 | opt_complementary = "=1"; | ||
180 | opt = getopt32(argv, "p:s:c:ehmLF", &proto, &baud_str, &extcmd); | 132 | opt = getopt32(argv, "p:s:c:ehmLF", &proto, &baud_str, &extcmd); |
181 | /*argc -= optind;*/ | 133 | /*argc -= optind;*/ |
182 | argv += optind; | 134 | argv += optind; |
183 | 135 | ||
184 | if (!*argv) | ||
185 | bb_show_usage(); | ||
186 | |||
187 | encap = index_in_strings(proto_names, proto); | 136 | encap = index_in_strings(proto_names, proto); |
188 | |||
189 | if (encap < 0) | 137 | if (encap < 0) |
190 | invarg_1_to_2(proto, "protocol"); | 138 | invarg_1_to_2(proto, "protocol"); |
191 | if (encap > 3) | 139 | if (encap > 3) |
@@ -198,6 +146,22 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |||
198 | invarg_1_to_2(baud_str, "baud rate"); | 146 | invarg_1_to_2(baud_str, "baud rate"); |
199 | } | 147 | } |
200 | 148 | ||
149 | /* Open tty */ | ||
150 | fd = open(*argv, O_RDWR | O_NDELAY); | ||
151 | if (fd < 0) { | ||
152 | char *buf = concat_path_file("/dev", *argv); | ||
153 | fd = xopen(buf, O_RDWR | O_NDELAY); | ||
154 | /* maybe if (ENABLE_FEATURE_CLEAN_UP) ?? */ | ||
155 | free(buf); | ||
156 | } | ||
157 | xmove_fd(fd, serial_fd); | ||
158 | |||
159 | /* Save current tty state */ | ||
160 | if (tcgetattr(serial_fd, &G.saved_state) != 0) | ||
161 | bb_perror_msg_and_die("tcgetattr"); | ||
162 | /* Save line discipline */ | ||
163 | xioctl(serial_fd, TIOCGETD, &G.saved_disc); | ||
164 | |||
201 | /* Trap signals in order to restore tty states upon exit */ | 165 | /* Trap signals in order to restore tty states upon exit */ |
202 | if (!(opt & OPT_e_quit)) { | 166 | if (!(opt & OPT_e_quit)) { |
203 | bb_signals(0 | 167 | bb_signals(0 |
@@ -208,43 +172,37 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |||
208 | , sig_handler); | 172 | , sig_handler); |
209 | } | 173 | } |
210 | 174 | ||
211 | /* Open tty */ | ||
212 | handle = open(*argv, O_RDWR | O_NDELAY); | ||
213 | if (handle < 0) { | ||
214 | char *buf = concat_path_file("/dev", *argv); | ||
215 | handle = xopen(buf, O_RDWR | O_NDELAY); | ||
216 | /* maybe if (ENABLE_FEATURE_CLEAN_UP) ?? */ | ||
217 | free(buf); | ||
218 | } | ||
219 | |||
220 | /* Save current tty state */ | ||
221 | save_state(); | ||
222 | |||
223 | /* Configure tty */ | 175 | /* Configure tty */ |
224 | memcpy(&state, &saved_state, sizeof(state)); | 176 | memcpy(&state, &G.saved_state, sizeof(state)); |
225 | if (!(opt & OPT_m_nonraw)) { /* raw not suppressed */ | 177 | if (!(opt & OPT_m_nonraw)) { /* raw not suppressed */ |
226 | memset(&state.c_cc, 0, sizeof(state.c_cc)); | 178 | memset(&state.c_cc, 0, sizeof(state.c_cc)); |
227 | state.c_cc[VMIN] = 1; | 179 | state.c_cc[VMIN] = 1; |
228 | state.c_iflag = IGNBRK | IGNPAR; | 180 | state.c_iflag = IGNBRK | IGNPAR; |
229 | state.c_oflag = 0; | 181 | /*state.c_oflag = 0;*/ |
230 | state.c_lflag = 0; | 182 | /*state.c_lflag = 0;*/ |
231 | state.c_cflag = CS8 | HUPCL | CREAD | 183 | state.c_cflag = CS8 | HUPCL | CREAD |
232 | | ((opt & OPT_L_local) ? CLOCAL : 0) | 184 | | ((opt & OPT_L_local) ? CLOCAL : 0) |
233 | | ((opt & OPT_F_noflow) ? 0 : CRTSCTS); | 185 | | ((opt & OPT_F_noflow) ? 0 : CRTSCTS); |
234 | cfsetispeed(&state, cfgetispeed(&saved_state)); | 186 | cfsetispeed(&state, cfgetispeed(&G.saved_state)); |
235 | cfsetospeed(&state, cfgetospeed(&saved_state)); | 187 | cfsetospeed(&state, cfgetospeed(&G.saved_state)); |
236 | } | 188 | } |
237 | |||
238 | if (opt & OPT_s_baud) { | 189 | if (opt & OPT_s_baud) { |
239 | cfsetispeed(&state, baud_code); | 190 | cfsetispeed(&state, baud_code); |
240 | cfsetospeed(&state, baud_code); | 191 | cfsetospeed(&state, baud_code); |
241 | } | 192 | } |
242 | 193 | /* Set line status */ | |
243 | set_state(&state, encap); | 194 | if (tcsetattr_serial_or_warn(&state)) |
195 | goto bad; | ||
196 | /* Set line disclipline (N_SLIP always) */ | ||
197 | if (ioctl_or_warn(serial_fd, TIOCSETD, (void*)&int_N_SLIP)) | ||
198 | goto bad; | ||
199 | /* Set encapsulation (SLIP, CSLIP, etc) */ | ||
200 | if (ioctl_or_warn(serial_fd, SIOCSIFENCAP, &encap)) | ||
201 | goto bad; | ||
244 | 202 | ||
245 | /* Exit now if option -e was passed */ | 203 | /* Exit now if option -e was passed */ |
246 | if (opt & OPT_e_quit) | 204 | if (opt & OPT_e_quit) |
247 | return 0; | 205 | return EXIT_SUCCESS; |
248 | 206 | ||
249 | /* If we're not requested to watch, just keep descriptor open | 207 | /* If we're not requested to watch, just keep descriptor open |
250 | * until we are killed */ | 208 | * until we are killed */ |
@@ -254,17 +212,20 @@ int slattach_main(int argc UNUSED_PARAM, char **argv) | |||
254 | 212 | ||
255 | /* Watch line for hangup */ | 213 | /* Watch line for hangup */ |
256 | while (1) { | 214 | while (1) { |
257 | if (ioctl(handle, TIOCMGET, &i) < 0 || !(i & TIOCM_CAR)) | 215 | int modem_stat; |
258 | goto no_carrier; | 216 | if (ioctl(serial_fd, TIOCMGET, &modem_stat)) |
217 | break; | ||
218 | if (!(modem_stat & TIOCM_CAR)) | ||
219 | break; | ||
259 | sleep(15); | 220 | sleep(15); |
260 | } | 221 | } |
261 | 222 | ||
262 | no_carrier: | ||
263 | |||
264 | /* Execute command on hangup */ | 223 | /* Execute command on hangup */ |
265 | if (opt & OPT_c_extcmd) | 224 | if (opt & OPT_c_extcmd) |
266 | system(extcmd); | 225 | system(extcmd); |
267 | 226 | ||
268 | /* Restore states and exit */ | 227 | /* Restore states and exit */ |
269 | restore_state_and_exit(EXIT_SUCCESS); | 228 | restore_state_and_exit(EXIT_SUCCESS); |
229 | bad: | ||
230 | restore_state_and_exit(EXIT_FAILURE); | ||
270 | } | 231 | } |