]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/terminal.h
8c7742f8102bfb841df466557bd44a47e77c4c9c
[mirror_lxc.git] / src / lxc / terminal.h
1 /* SPDX-License-Identifier: LGPL-2.1+ */
2
3 #ifndef __LXC_TERMINAL_H
4 #define __LXC_TERMINAL_H
5
6 #include <signal.h>
7 #include <stdio.h>
8
9 #include "compiler.h"
10 #include "list.h"
11 #include "macro.h"
12 #include "ringbuf.h"
13
14 struct lxc_container;
15 struct lxc_conf;
16 struct lxc_async_descr;
17
18 struct lxc_terminal_info {
19 /* the path name of the pty side */
20 char name[PATH_MAX];
21
22 /* the file descriptor of the ptx */
23 int ptx;
24
25 /* the file descriptor of the pty */
26 int pty;
27
28 /* whether the terminal is currently used */
29 int busy;
30 };
31
32 struct lxc_terminal_state {
33 struct lxc_list node;
34 int stdinfd;
35 int stdoutfd;
36 int ptxfd;
37
38 /* Escape sequence to use for exiting the terminal. A single char can
39 * be specified. The terminal can then exited by doing: Ctrl +
40 * specified_char + q. This field is checked by
41 * lxc_terminal_stdin_cb(). Set to -1 to disable exiting the terminal
42 * via a escape sequence.
43 */
44 int escape;
45
46 /* Used internally by lxc_terminal_stdin_cb() to check whether an
47 * escape sequence has been received.
48 */
49 int saw_escape;
50
51 /* File descriptor that accepts signals. If set to -1 no signal handler
52 * could be installed. This also means that the sigset_t oldmask member
53 * is meaningless.
54 */
55 int sigfd;
56
57 sigset_t oldmask;
58 };
59
60 struct lxc_terminal {
61 int pty_nr;
62 int pty;
63 int ptx;
64 int peer;
65 struct lxc_terminal_info proxy;
66 struct lxc_async_descr *descr;
67 char *path;
68 char name[PATH_MAX];
69 struct termios *tios;
70 struct lxc_terminal_state *tty_state;
71
72 struct /* lxc_terminal_log */ {
73 /* size of the log file */
74 uint64_t log_size;
75
76 /* path to the log file */
77 char *log_path;
78
79 /* fd to the log file */
80 int log_fd;
81
82 /* whether the log file will be rotated */
83 unsigned int log_rotate;
84 };
85
86 struct /* lxc_terminal_ringbuf */ {
87 /* size of the ringbuffer */
88 uint64_t buffer_size;
89
90 /* the in-memory ringbuffer */
91 struct lxc_ringbuf ringbuf;
92 };
93 };
94
95 /**
96 * lxc_terminal_allocate: allocate the console or a tty
97 *
98 * @conf : the configuration of the container to allocate from
99 * @sockfd : the socket fd whose remote side when closed, will be an
100 * indication that the console or tty is no longer in use
101 * @ttyreq : the tty requested to be opened, -1 for any, 0 for the console
102 */
103 __hidden extern int lxc_terminal_allocate(struct lxc_conf *conf, int sockfd, int *ttynum);
104
105 /**
106 * Create a new terminal:
107 * - calls openpty() to allocate a ptx/pty pair
108 * - sets the FD_CLOEXEC flag on the ptx/pty fds
109 * - allocates either the current controlling terminal (default) or a user
110 * specified terminal as proxy for the newly created ptx/pty pair
111 * - sets up SIGWINCH handler, winsz, and new terminal settings
112 * (Handlers for SIGWINCH and I/O are not registered in a mainloop.)
113 */
114 __hidden extern int lxc_terminal_create(const char *name, const char *lxcpath,
115 struct lxc_conf *conf,
116 struct lxc_terminal *console);
117
118 /**
119 * lxc_terminal_setup: Create a new terminal.
120 * - In addition to lxc_terminal_create() also sets up logging.
121 */
122 __hidden extern int lxc_terminal_setup(struct lxc_conf *);
123
124 /**
125 * Delete a terminal created via lxc_terminal_create() or lxc_terminal_setup():
126 * Note, registered handlers are not automatically deleted.
127 */
128 __hidden extern void lxc_terminal_delete(struct lxc_terminal *);
129
130 /**
131 * lxc_terminal_free: mark the terminal as unallocated and free any resources
132 * allocated by lxc_terminal_allocate().
133 *
134 * @conf : the configuration of the container whose tty was closed
135 * @fd : the socket fd whose remote side was closed, which indicated
136 * the terminal is no longer in use. this is used to match
137 * which terminal is being freed.
138 */
139 __hidden extern void lxc_terminal_free(struct lxc_conf *conf, int fd);
140
141 /**
142 * Register terminal event handlers in an open mainloop.
143 */
144 __hidden extern int lxc_terminal_mainloop_add(struct lxc_async_descr *, struct lxc_terminal *);
145
146 /**
147 * Handle SIGWINCH events on the allocated terminals.
148 */
149 __hidden extern void lxc_terminal_sigwinch(int sig);
150
151 /**
152 * Connect to one of the ttys given to the container via lxc.tty.max.
153 * - allocates either the current controlling terminal (default) or a user specified
154 * terminal as proxy terminal for the containers tty
155 * - sets up SIGWINCH handler, winsz, and new terminal settings
156 * - opens mainloop
157 * - registers SIGWINCH, I/O handlers in the mainloop
158 * - performs all necessary cleanup operations
159 */
160 __hidden extern int lxc_console(struct lxc_container *c, int ttynum, int stdinfd, int stdoutfd,
161 int stderrfd, int escape);
162
163 /**
164 * Allocate one of the tty given to the container via lxc.tty.max. Returns an
165 * open fd to the allocated tty.
166 * Set ttynum to -1 to allocate the first available tty, or to a value within
167 * the range specified by lxc.tty.max to allocate a specific tty.
168 */
169 __hidden extern int lxc_terminal_getfd(struct lxc_container *c, int *ttynum, int *ptxfd);
170
171 /**
172 * Make fd a duplicate of the standard file descriptors. The fd is made a
173 * duplicate of a specific standard file descriptor iff the standard file
174 * descriptor refers to a terminal.
175 */
176 __hidden extern int lxc_terminal_set_stdfds(int fd);
177
178 /**
179 * Handler for events on the stdin fd of the terminal. To be registered via the
180 * corresponding functions declared and defined in mainloop.{c,h} or
181 * lxc_terminal_mainloop_add().
182 * This function exits the loop cleanly when an EPOLLHUP event is received.
183 */
184 __hidden extern int lxc_terminal_stdin_cb(int fd, uint32_t events, void *cbdata,
185 struct lxc_async_descr *descr);
186
187 /**
188 * Handler for events on the ptx fd of the terminal. To be registered via
189 * the corresponding functions declared and defined in mainloop.{c,h} or
190 * lxc_terminal_mainloop_add().
191 * This function exits the loop cleanly when an EPOLLHUP event is received.
192 */
193 __hidden extern int lxc_terminal_ptx_cb(int fd, uint32_t events, void *cbdata,
194 struct lxc_async_descr *descr);
195
196 /**
197 * Setup new terminal properties. The old terminal settings are stored in
198 * oldtios.
199 */
200 __hidden extern int lxc_setup_tios(int fd, struct termios *oldtios);
201
202 /**
203 * lxc_terminal_winsz: propagate winsz from one terminal to another
204 *
205 * @srcfd
206 * - terminal to get size from (typically a pty pty)
207 * @dstfd
208 * - terminal to set size on (typically a ptx pty)
209 */
210 __hidden extern void lxc_terminal_winsz(int srcfd, int dstfd);
211
212 /*
213 * lxc_terminal_signal_init: install signal handler
214 *
215 * @srcfd
216 * - src for winsz in SIGWINCH handler
217 * @dstfd
218 * - dst for winsz in SIGWINCH handler
219 *
220 * Returns lxc_terminal_state structure on success or NULL on failure. The
221 * sigfd member of the returned lxc_terminal_state can be
222 * select()/poll()ed/epoll()ed on (i.e. added to a mainloop) for signals.
223 *
224 * Must be called with process_lock held to protect the lxc_ttys list, or from
225 * a non-threaded context.
226 *
227 * Note that the signal handler isn't installed as a classic asynchronous
228 * handler, rather signalfd(2) is used so that we can handle the signal when
229 * we're ready for it. This avoids deadlocks since a signal handler (ie
230 * lxc_terminal_sigwinch()) would need to take the thread mutex to prevent
231 * lxc_ttys list corruption, but using the fd we can provide the tty_state
232 * needed to the callback (lxc_terminal_signalfd_cb()).
233 *
234 * This function allocates memory. It is up to the caller to free it.
235 */
236 __hidden extern struct lxc_terminal_state *lxc_terminal_signal_init(int srcfd, int dstfd);
237
238 /**
239 * Handler for signal events. To be registered via the corresponding functions
240 * declared and defined in mainloop.{c,h} or lxc_terminal_mainloop_add().
241 */
242 __hidden extern int lxc_terminal_signalfd_cb(int fd, uint32_t events, void *cbdata,
243 struct lxc_async_descr *descr);
244
245 __hidden extern int lxc_terminal_write_ringbuffer(struct lxc_terminal *terminal);
246 __hidden extern int lxc_terminal_create_log_file(struct lxc_terminal *terminal);
247 __hidden extern int lxc_terminal_io_cb(int fd, uint32_t events, void *data,
248 struct lxc_async_descr *descr);
249
250 __hidden extern int lxc_make_controlling_terminal(int fd);
251 __hidden extern int lxc_terminal_prepare_login(int fd);
252 __hidden extern void lxc_terminal_conf_free(struct lxc_terminal *terminal);
253 __hidden extern void lxc_terminal_info_init(struct lxc_terminal_info *terminal);
254 __hidden extern void lxc_terminal_init(struct lxc_terminal *terminal);
255 __hidden extern int lxc_terminal_signal_sigmask_safe_blocked(struct lxc_terminal *terminal);
256 __hidden extern int lxc_devpts_terminal(int devpts_fd, int *ret_ptx,
257 int *ret_pty, int *ret_pty_nr,
258 bool require_tiocgptpeer);
259 __hidden extern int lxc_terminal_parent(struct lxc_conf *conf);
260
261 static inline bool wants_console(const struct lxc_terminal *terminal)
262 {
263 return !terminal->path || !strequal(terminal->path, "none");
264 }
265
266 #endif /* __LXC_TERMINAL_H */