2 * Copyright (C) 2020 Daniel Golle <daniel@makrotopia.org>
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU Lesser General Public License version 2.1
6 * as published by the Free Software Foundation
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
16 #include <libubox/ustream.h>
24 #include <sys/types.h>
27 static inline int setup_tios(int fd
, struct termios
*oldtios
)
29 struct termios newtios
;
35 /* Get current termios */
36 if (tcgetattr(fd
, oldtios
))
41 /* Remove the echo characters and signal reception, the echo
42 * will be done with master proxying */
43 newtios
.c_iflag
&= ~IGNBRK
;
44 newtios
.c_iflag
&= BRKINT
;
45 newtios
.c_lflag
&= ~(ECHO
|ICANON
|ISIG
);
46 newtios
.c_cc
[VMIN
] = 1;
47 newtios
.c_cc
[VTIME
] = 0;
49 /* Set new attributes */
50 if (tcsetattr(fd
, TCSAFLUSH
, &newtios
))
58 #define OPT_ARGS "i:s:"
60 static struct ustream_fd cufd
;
61 static struct ustream_fd lufd
;
65 fprintf(stderr
, "ujail-console -s <service> [-i <instance>]\n");
69 static void client_cb(struct ustream
*s
, int bytes
)
75 buf
= ustream_get_read_buf(s
, &len
);
79 rv
= ustream_write(&lufd
.stream
, buf
, len
, false);
82 ustream_consume(s
, rv
);
89 static void local_cb(struct ustream
*s
, int bytes
)
95 buf
= ustream_get_read_buf(s
, &len
);
99 if ((len
> 0) && (buf
[0] == 2))
102 rv
= ustream_write(&cufd
.stream
, buf
, len
, false);
105 ustream_consume(s
, rv
);
112 int main(int argc
, char **argv
)
114 struct ubus_context
*ctx
;
116 static struct blob_buf req
;
117 char *service_name
= NULL
, *instance_name
= NULL
;
118 int client_fd
, server_fd
, tty_fd
;
119 struct termios oldtermios
;
122 while ((ch
= getopt(argc
, argv
, OPT_ARGS
)) != -1) {
125 instance_name
= optarg
;
128 service_name
= optarg
;
138 ctx
= ubus_connect(NULL
);
140 fprintf(stderr
, "can't connect to ubus!\n");
144 /* open pseudo-terminal pair */
145 client_fd
= posix_openpt(O_RDWR
| O_NOCTTY
);
147 fprintf(stderr
, "can't create virtual console!\n");
151 setup_tios(client_fd
, &oldtermios
);
154 server_fd
= open(ptsname(client_fd
), O_RDWR
| O_NOCTTY
);
156 fprintf(stderr
, "can't open virtual console!\n");
162 setup_tios(server_fd
, &oldtermios
);
163 tty_fd
= open("/dev/tty", O_RDWR
);
164 setup_tios(tty_fd
, &oldtermios
);
166 /* register server-side with procd */
167 blob_buf_init(&req
, 0);
168 blobmsg_add_string(&req
, "name", service_name
);
170 blobmsg_add_string(&req
, "instance", instance_name
);
172 if (ubus_lookup_id(ctx
, "service", &id
) ||
173 ubus_invoke_fd(ctx
, id
, "console_attach", req
.head
, NULL
, NULL
, 3000, server_fd
)) {
174 fprintf(stderr
, "ubus request failed\n");
188 /* forward between stdio and client_fd until detach is requested */
189 lufd
.stream
.notify_read
= local_cb
;
190 ustream_fd_init(&lufd
, tty_fd
);
192 cufd
.stream
.notify_read
= client_cb
;
193 /* ToDo: handle remote close and other events */
194 // cufd.stream.notify_state = client_state_cb;
195 ustream_fd_init(&cufd
, client_fd
);
197 fprintf(stderr
, "attaching to jail console. press [CTRL]+[B] to exit.\n");
203 tcsetattr(tty_fd
, TCSAFLUSH
, &oldtermios
);
204 ustream_free(&lufd
.stream
);
205 ustream_free(&cufd
.stream
);