aboutsummaryrefslogtreecommitdiff
path: root/networking/slattach.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-06-20 15:23:03 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-06-20 15:23:03 +0000
commit14923db72fe6e97d9c596236841a9eb6338231db (patch)
treead221dd5c71bb7eec7788c86af30ba4c933d9cc2 /networking/slattach.c
parentcd0e80ce902f6e79b31888af4ff4545846ce1c0e (diff)
downloadbusybox-w32-14923db72fe6e97d9c596236841a9eb6338231db.tar.gz
busybox-w32-14923db72fe6e97d9c596236841a9eb6338231db.tar.bz2
busybox-w32-14923db72fe6e97d9c596236841a9eb6338231db.zip
slattach: new applet.
Diffstat (limited to 'networking/slattach.c')
-rw-r--r--networking/slattach.c240
1 files changed, 240 insertions, 0 deletions
diff --git a/networking/slattach.c b/networking/slattach.c
new file mode 100644
index 000000000..1c00fddb6
--- /dev/null
+++ b/networking/slattach.c
@@ -0,0 +1,240 @@
1/*
2 * Stripped down version of net-tools for busybox.
3 *
4 * Author: Ignacio Garcia Perez (iggarpe at gmail dot com)
5 *
6 * License: GPLv2 or later, see LICENSE file in this tarball.
7 *
8 * There are some differences from the standard net-tools slattach:
9 *
10 * - The -l option is not supported.
11 *
12 * - The -F options allows disabling of RTS/CTS flow control.
13 */
14
15#include "libbb.h"
16
17/* Line discipline code table */
18static const char *const proto_names[] = {
19 "slip", /* 0 */
20 "cslip", /* 1 */
21 "slip6", /* 2 */
22 "cslip6", /* 3 */
23 "adaptive", /* 8 */
24 NULL
25};
26
27struct globals {
28 int handle;
29 int saved_disc;
30 struct termios saved_state;
31};
32#define G (*(struct globals*)&bb_common_bufsiz1)
33#define handle (G.handle )
34#define saved_disc (G.saved_disc )
35#define saved_state (G.saved_state )
36#define INIT_G() do {} while (0)
37
38
39/*
40 * Save tty state and line discipline
41 *
42 * It is fine here to bail out on errors, since we haven modified anything yet
43 */
44static void save_state(void)
45{
46 /* Save line status */
47 if (tcgetattr(handle, &saved_state) < 0)
48 bb_perror_msg_and_die("get state");
49
50 /* Save line discipline */
51 if (ioctl(handle, TIOCGETD, &saved_disc) < 0)
52 bb_perror_msg_and_die("get discipline");
53}
54
55/*
56 * Restore state and line discipline for ALL managed ttys
57 *
58 * Restoring ALL managed ttys is the only way to have a single
59 * hangup delay.
60 *
61 * Go on after errors: we want to restore as many controlled ttys
62 * as possible.
63 */
64static void restore_state_and_exit(int exitcode) ATTRIBUTE_NORETURN;
65static void restore_state_and_exit(int exitcode)
66{
67 struct termios state;
68
69 /* Restore line discipline */
70 if (ioctl(handle, TIOCSETD, &saved_disc) < 0) {
71 bb_perror_msg("set discipline");
72 exitcode = 1;
73 }
74
75 /* Hangup */
76 memcpy(&state, &saved_state, sizeof(state));
77 cfsetispeed(&state, B0);
78 cfsetospeed(&state, B0);
79 if (tcsetattr(handle, TCSANOW, &state) < 0) {
80 bb_perror_msg("set state");
81 exitcode = 1;
82 }
83
84 sleep(1);
85
86 /* Restore line status */
87 if (tcsetattr(handle, TCSANOW, &saved_state) < 0) {
88 bb_perror_msg_and_die("set state");
89 }
90
91 if (ENABLE_FEATURE_CLEAN_UP)
92 close(handle);
93
94 exit(exitcode);
95}
96
97/*
98 * Set tty state, line discipline and encapsulation
99 */
100static void set_state(struct termios *state, int encap)
101{
102 int disc;
103
104 /* Set line status */
105 if (tcsetattr(handle, TCSANOW, state) < 0) {
106 bb_perror_msg("set state");
107 goto bad;
108 }
109
110 /* Set line discliple (N_SLIP always) */
111 disc = N_SLIP;
112 if (ioctl(handle, TIOCSETD, &disc) < 0) {
113 bb_perror_msg("set discipline");
114 goto bad;
115 }
116
117 /* Set encapsulation (SLIP, CSLIP, etc) */
118 if (ioctl(handle, SIOCSIFENCAP, &encap) < 0) {
119 bb_perror_msg("set encapsulation");
120 bad:
121 restore_state_and_exit(1);
122 }
123}
124
125static void sig_handler(int signo)
126{
127 restore_state_and_exit(0);
128}
129
130int slattach_main(int argc, char **argv);
131int slattach_main(int argc, char **argv)
132{
133 int i, encap, opt;
134 struct termios state;
135 const char *proto = "cslip";
136 const char *extcmd; /* Command to execute after hangup */
137 const char *baud_str;
138 int baud_code = -1; /* Line baud rate (system code) */
139
140 enum {
141 OPT_p_proto = 1 << 0,
142 OPT_s_baud = 1 << 1,
143 OPT_c_extcmd = 1 << 2,
144 OPT_e_quit = 1 << 3,
145 OPT_h_watch = 1 << 4,
146 OPT_m_nonraw = 1 << 5,
147 OPT_L_local = 1 << 6,
148 OPT_F_noflow = 1 << 7,
149 };
150
151 INIT_G();
152
153 /* Parse command line options */
154 opt = getopt32(argc, argv, "p:s:c:ehmLF", &proto, &baud_str, &extcmd);
155 /*argc -= optind;*/
156 argv += optind;
157
158 if (!*argv)
159 bb_show_usage();
160
161 encap = index_in_str_array(proto_names, proto);
162
163 if (encap < 0)
164 bb_error_msg_and_die("invalid protocol %s", proto);
165 if (encap > 3)
166 encap = 8;
167
168 /* We want to know if the baud rate is valid before we start touching the ttys */
169 if (opt & OPT_s_baud) {
170 baud_code = tty_value_to_baud(xatoi(baud_str));
171 if (baud_code < 0)
172 bb_error_msg_and_die("invalid baud rate");
173 }
174
175 /* Trap signals in order to restore tty states upon exit */
176 if (!(opt & OPT_e_quit)) {
177 signal(SIGHUP, sig_handler);
178 signal(SIGINT, sig_handler);
179 signal(SIGQUIT, sig_handler);
180 signal(SIGTERM, sig_handler);
181 }
182
183 /* Open tty */
184 handle = open(*argv, O_RDWR | O_NDELAY);
185 if (handle < 0) {
186 char *buf = xasprintf("/dev/%s", *argv);
187 handle = xopen(buf, O_RDWR | O_NDELAY);
188 /* maybe if (ENABLE_FEATURE_CLEAN_UP) ?? */
189 free(buf);
190 }
191
192 /* Save current tty state */
193 save_state();
194
195 /* Confgure tty */
196 memcpy(&state, &saved_state, sizeof(state));
197 if (!(opt & OPT_m_nonraw)) { /* raw not suppressed */
198 memset(&state.c_cc, 0, sizeof(state.c_cc));
199 state.c_cc[VMIN] = 1;
200 state.c_iflag = IGNBRK | IGNPAR;
201 state.c_oflag = 0;
202 state.c_lflag = 0;
203 state.c_cflag = CS8 | HUPCL | CREAD
204 | ((opt & OPT_L_local) ? CLOCAL : 0)
205 | ((opt & OPT_F_noflow) ? 0 : CRTSCTS);
206 }
207
208 if (opt & OPT_s_baud) {
209 cfsetispeed(&state, baud_code);
210 cfsetospeed(&state, baud_code);
211 }
212
213 set_state(&state, encap);
214
215 /* Exit now if option -e was passed */
216 if (opt & OPT_e_quit)
217 return 0;
218
219 /* If we're not requested to watch, just keep descriptor open
220 * till we are killed */
221 if (!(opt & OPT_h_watch))
222 while (1)
223 sleep(24*60*60);
224
225 /* Watch line for hangup */
226 while (1) {
227 if (ioctl(handle, TIOCMGET, &i) < 0 || !(i & TIOCM_CAR))
228 goto no_carrier;
229 sleep(15);
230 }
231
232 no_carrier:
233
234 /* Execute command on hangup */
235 if (opt & OPT_c_extcmd)
236 system(extcmd);
237
238 /* Restore states and exit */
239 restore_state_and_exit(0);
240}