source: MondoRescue/branches/3.3/mindi-busybox/networking/slattach.c@ 3734

Last change on this file since 3734 was 3621, checked in by Bruno Cornec, 10 years ago

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

  • Property svn:eol-style set to native
File size: 6.2 KB
Line 
1/* vi: set sw=4 ts=4: */
2/*
3 * Stripped down version of net-tools for busybox.
4 *
5 * Author: Ignacio Garcia Perez (iggarpe at gmail dot com)
6 *
7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
8 *
9 * There are some differences from the standard net-tools slattach:
10 *
11 * - The -l option is not supported.
12 *
13 * - The -F options allows disabling of RTS/CTS flow control.
14 */
15
16//usage:#define slattach_trivial_usage
17//usage: "[-cehmLF] [-s SPEED] [-p PROTOCOL] DEVICE"
18//usage:#define slattach_full_usage "\n\n"
19//usage: "Attach network interface(s) to serial line(s)\n"
20//usage: "\n -p PROT Set protocol (slip, cslip, slip6, clisp6 or adaptive)"
21//usage: "\n -s SPD Set line speed"
22//usage: "\n -e Exit after initializing device"
23//usage: "\n -h Exit when the carrier is lost"
24//usage: "\n -c PROG Run PROG when the line is hung up"
25//usage: "\n -m Do NOT initialize the line in raw 8 bits mode"
26//usage: "\n -L Enable 3-wire operation"
27//usage: "\n -F Disable RTS/CTS flow control"
28
29#include "libbb.h"
30#include "common_bufsiz.h"
31#include "libiproute/utils.h" /* invarg_1_to_2() */
32
33struct globals {
34 int handle;
35 int saved_disc;
36 struct termios saved_state;
37} FIX_ALIASING;
38#define G (*(struct globals*)bb_common_bufsiz1)
39#define handle (G.handle )
40#define saved_disc (G.saved_disc )
41#define saved_state (G.saved_state )
42#define INIT_G() do { setup_common_bufsiz(); } while (0)
43
44
45/*
46 * Save tty state and line discipline
47 *
48 * It is fine here to bail out on errors, since we haven modified anything yet
49 */
50static void save_state(void)
51{
52 /* Save line status */
53 if (tcgetattr(handle, &saved_state) < 0)
54 bb_perror_msg_and_die("get state");
55
56 /* Save line discipline */
57 xioctl(handle, TIOCGETD, &saved_disc);
58}
59
60static int set_termios_state_or_warn(struct termios *state)
61{
62 int ret;
63
64 ret = tcsetattr(handle, TCSANOW, state);
65 if (ret < 0) {
66 bb_perror_msg("set state");
67 return 1; /* used as exitcode */
68 }
69 return 0;
70}
71
72/*
73 * Restore state and line discipline for ALL managed ttys
74 *
75 * Restoring ALL managed ttys is the only way to have a single
76 * hangup delay.
77 *
78 * Go on after errors: we want to restore as many controlled ttys
79 * as possible.
80 */
81static void restore_state_and_exit(int exitcode) NORETURN;
82static void restore_state_and_exit(int exitcode)
83{
84 struct termios state;
85
86 /* Restore line discipline */
87 if (ioctl_or_warn(handle, TIOCSETD, &saved_disc) < 0) {
88 exitcode = 1;
89 }
90
91 /* Hangup */
92 memcpy(&state, &saved_state, sizeof(state));
93 cfsetispeed(&state, B0);
94 cfsetospeed(&state, B0);
95 if (set_termios_state_or_warn(&state))
96 exitcode = 1;
97 sleep(1);
98
99 /* Restore line status */
100 if (set_termios_state_or_warn(&saved_state))
101 exit(EXIT_FAILURE);
102 if (ENABLE_FEATURE_CLEAN_UP)
103 close(handle);
104
105 exit(exitcode);
106}
107
108/*
109 * Set tty state, line discipline and encapsulation
110 */
111static void set_state(struct termios *state, int encap)
112{
113 int disc;
114
115 /* Set line status */
116 if (set_termios_state_or_warn(state))
117 goto bad;
118 /* Set line discliple (N_SLIP always) */
119 disc = N_SLIP;
120 if (ioctl_or_warn(handle, TIOCSETD, &disc) < 0) {
121 goto bad;
122 }
123
124 /* Set encapsulation (SLIP, CSLIP, etc) */
125 if (ioctl_or_warn(handle, SIOCSIFENCAP, &encap) < 0) {
126 bad:
127 restore_state_and_exit(EXIT_FAILURE);
128 }
129}
130
131static void sig_handler(int signo UNUSED_PARAM)
132{
133 restore_state_and_exit(EXIT_SUCCESS);
134}
135
136int slattach_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
137int slattach_main(int argc UNUSED_PARAM, char **argv)
138{
139 /* Line discipline code table */
140 static const char proto_names[] ALIGN1 =
141 "slip\0" /* 0 */
142 "cslip\0" /* 1 */
143 "slip6\0" /* 2 */
144 "cslip6\0" /* 3 */
145 "adaptive\0" /* 8 */
146 ;
147
148 int i, encap, opt;
149 struct termios state;
150 const char *proto = "cslip";
151 const char *extcmd; /* Command to execute after hangup */
152 const char *baud_str;
153 int baud_code = -1; /* Line baud rate (system code) */
154
155 enum {
156 OPT_p_proto = 1 << 0,
157 OPT_s_baud = 1 << 1,
158 OPT_c_extcmd = 1 << 2,
159 OPT_e_quit = 1 << 3,
160 OPT_h_watch = 1 << 4,
161 OPT_m_nonraw = 1 << 5,
162 OPT_L_local = 1 << 6,
163 OPT_F_noflow = 1 << 7
164 };
165
166 INIT_G();
167
168 /* Parse command line options */
169 opt = getopt32(argv, "p:s:c:ehmLF", &proto, &baud_str, &extcmd);
170 /*argc -= optind;*/
171 argv += optind;
172
173 if (!*argv)
174 bb_show_usage();
175
176 encap = index_in_strings(proto_names, proto);
177
178 if (encap < 0)
179 invarg_1_to_2(proto, "protocol");
180 if (encap > 3)
181 encap = 8;
182
183 /* We want to know if the baud rate is valid before we start touching the ttys */
184 if (opt & OPT_s_baud) {
185 baud_code = tty_value_to_baud(xatoi(baud_str));
186 if (baud_code < 0)
187 invarg_1_to_2(baud_str, "baud rate");
188 }
189
190 /* Trap signals in order to restore tty states upon exit */
191 if (!(opt & OPT_e_quit)) {
192 bb_signals(0
193 + (1 << SIGHUP)
194 + (1 << SIGINT)
195 + (1 << SIGQUIT)
196 + (1 << SIGTERM)
197 , sig_handler);
198 }
199
200 /* Open tty */
201 handle = open(*argv, O_RDWR | O_NDELAY);
202 if (handle < 0) {
203 char *buf = concat_path_file("/dev", *argv);
204 handle = xopen(buf, O_RDWR | O_NDELAY);
205 /* maybe if (ENABLE_FEATURE_CLEAN_UP) ?? */
206 free(buf);
207 }
208
209 /* Save current tty state */
210 save_state();
211
212 /* Configure tty */
213 memcpy(&state, &saved_state, sizeof(state));
214 if (!(opt & OPT_m_nonraw)) { /* raw not suppressed */
215 memset(&state.c_cc, 0, sizeof(state.c_cc));
216 state.c_cc[VMIN] = 1;
217 state.c_iflag = IGNBRK | IGNPAR;
218 state.c_oflag = 0;
219 state.c_lflag = 0;
220 state.c_cflag = CS8 | HUPCL | CREAD
221 | ((opt & OPT_L_local) ? CLOCAL : 0)
222 | ((opt & OPT_F_noflow) ? 0 : CRTSCTS);
223 cfsetispeed(&state, cfgetispeed(&saved_state));
224 cfsetospeed(&state, cfgetospeed(&saved_state));
225 }
226
227 if (opt & OPT_s_baud) {
228 cfsetispeed(&state, baud_code);
229 cfsetospeed(&state, baud_code);
230 }
231
232 set_state(&state, encap);
233
234 /* Exit now if option -e was passed */
235 if (opt & OPT_e_quit)
236 return 0;
237
238 /* If we're not requested to watch, just keep descriptor open
239 * until we are killed */
240 if (!(opt & OPT_h_watch))
241 while (1)
242 sleep(24*60*60);
243
244 /* Watch line for hangup */
245 while (1) {
246 if (ioctl(handle, TIOCMGET, &i) < 0 || !(i & TIOCM_CAR))
247 goto no_carrier;
248 sleep(15);
249 }
250
251 no_carrier:
252
253 /* Execute command on hangup */
254 if (opt & OPT_c_extcmd)
255 system(extcmd);
256
257 /* Restore states and exit */
258 restore_state_and_exit(EXIT_SUCCESS);
259}
Note: See TracBrowser for help on using the repository browser.