1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39#include "libbb.h"
40#include "common_bufsiz.h"
41#include "libiproute/utils.h"
42
43struct globals {
44 int saved_disc;
45 struct termios saved_state;
46} FIX_ALIASING;
47#define G (*(struct globals*)bb_common_bufsiz1)
48#define INIT_G() do { setup_common_bufsiz(); } while (0)
49
50#define serial_fd 3
51
52static int tcsetattr_serial_or_warn(struct termios *state)
53{
54 int ret;
55
56 ret = tcsetattr(serial_fd, TCSANOW, state);
57 if (ret != 0) {
58 bb_simple_perror_msg("tcsetattr");
59 return 1;
60 }
61 return ret;
62}
63
64static void restore_state_and_exit(int exitcode) NORETURN;
65static void restore_state_and_exit(int exitcode)
66{
67 struct termios state;
68
69
70 if (ioctl_or_warn(serial_fd, TIOCSETD, &G.saved_disc)) {
71 exitcode = 1;
72 }
73
74
75 memcpy(&state, &G.saved_state, sizeof(state));
76 cfsetispeed(&state, B0);
77 cfsetospeed(&state, B0);
78 exitcode |= tcsetattr_serial_or_warn(&state);
79 sleep1();
80
81
82 if (tcsetattr_serial_or_warn(&G.saved_state))
83 exit(EXIT_FAILURE);
84
85 if (ENABLE_FEATURE_CLEAN_UP)
86 close(serial_fd);
87
88 exit(exitcode);
89}
90
91static void sig_handler(int signo UNUSED_PARAM)
92{
93 restore_state_and_exit(EXIT_SUCCESS);
94}
95
96int slattach_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
97int slattach_main(int argc UNUSED_PARAM, char **argv)
98{
99
100 static const char proto_names[] ALIGN1 =
101 "slip\0"
102 "cslip\0"
103 "slip6\0"
104 "cslip6\0"
105 "adaptive\0"
106 ;
107 static const int int_N_SLIP = N_SLIP;
108
109 int encap, opt, fd;
110 struct termios state;
111 const char *proto = "cslip";
112 const char *extcmd;
113 const char *baud_str;
114 int baud_code = baud_code;
115
116 enum {
117 OPT_p_proto = 1 << 0,
118 OPT_s_baud = 1 << 1,
119 OPT_c_extcmd = 1 << 2,
120 OPT_e_quit = 1 << 3,
121 OPT_h_watch = 1 << 4,
122 OPT_m_nonraw = 1 << 5,
123 OPT_L_local = 1 << 6,
124 OPT_F_noflow = 1 << 7
125 };
126
127 INIT_G();
128
129
130 opt = getopt32(argv, "^" "p:s:c:ehmLF" "\0" "=1",
131 &proto, &baud_str, &extcmd
132 );
133
134 argv += optind;
135
136 encap = index_in_strings(proto_names, proto);
137 if (encap < 0)
138 invarg_1_to_2(proto, "protocol");
139 if (encap > 3)
140 encap = 8;
141
142
143 if (opt & OPT_s_baud) {
144 baud_code = tty_value_to_baud(xatoi(baud_str));
145 if (baud_code < 0)
146 invarg_1_to_2(baud_str, "baud rate");
147 }
148
149
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
155 free(buf);
156 }
157 xmove_fd(fd, serial_fd);
158
159
160 if (tcgetattr(serial_fd, &G.saved_state) != 0)
161 bb_simple_perror_msg_and_die("tcgetattr");
162
163 xioctl(serial_fd, TIOCGETD, &G.saved_disc);
164
165
166 if (!(opt & OPT_e_quit)) {
167 bb_signals(0
168 + (1 << SIGHUP)
169 + (1 << SIGINT)
170 + (1 << SIGQUIT)
171 + (1 << SIGTERM)
172 , sig_handler);
173 }
174
175
176 memcpy(&state, &G.saved_state, sizeof(state));
177 if (!(opt & OPT_m_nonraw)) {
178 memset(&state.c_cc, 0, sizeof(state.c_cc));
179 state.c_cc[VMIN] = 1;
180 state.c_iflag = IGNBRK | IGNPAR;
181
182
183 state.c_cflag = CS8 | HUPCL | CREAD
184 | ((opt & OPT_L_local) ? CLOCAL : 0)
185 | ((opt & OPT_F_noflow) ? 0 : CRTSCTS);
186 cfsetispeed(&state, cfgetispeed(&G.saved_state));
187 cfsetospeed(&state, cfgetospeed(&G.saved_state));
188 }
189 if (opt & OPT_s_baud) {
190 cfsetispeed(&state, baud_code);
191 cfsetospeed(&state, baud_code);
192 }
193
194 if (tcsetattr_serial_or_warn(&state))
195 goto bad;
196
197 if (ioctl_or_warn(serial_fd, TIOCSETD, (void*)&int_N_SLIP))
198 goto bad;
199
200 if (ioctl_or_warn(serial_fd, SIOCSIFENCAP, &encap))
201 goto bad;
202
203
204 if (opt & OPT_e_quit)
205 return EXIT_SUCCESS;
206
207
208
209 if (!(opt & OPT_h_watch))
210 while (1)
211 sleep(24*60*60);
212
213
214 while (1) {
215 int modem_stat;
216 if (ioctl(serial_fd, TIOCMGET, &modem_stat))
217 break;
218 if (!(modem_stat & TIOCM_CAR))
219 break;
220 sleep(15);
221 }
222
223
224 if (opt & OPT_c_extcmd)
225 system(extcmd);
226
227
228 restore_state_and_exit(EXIT_SUCCESS);
229 bad:
230 restore_state_and_exit(EXIT_FAILURE);
231}
232