typedef void (*sighandler_t)(int);
-__attribute__((constructor))
-void lxc_console_init(void)
+__attribute__((constructor)) void lxc_console_init(void)
{
lxc_list_init(&lxc_ttys);
}
void lxc_console_winsz(int srcfd, int dstfd)
{
+ int ret;
struct winsize wsz;
- if (isatty(srcfd) && ioctl(srcfd, TIOCGWINSZ, &wsz) == 0) {
- DEBUG("set winsz dstfd:%d cols:%d rows:%d", dstfd,
- wsz.ws_col, wsz.ws_row);
- ioctl(dstfd, TIOCSWINSZ, &wsz);
+
+ if (!isatty(srcfd))
+ return;
+
+ ret = ioctl(srcfd, TIOCGWINSZ, &wsz);
+ if (ret < 0) {
+ WARN("Failed to get window size");
+ return;
}
+
+ ret = ioctl(dstfd, TIOCSWINSZ, &wsz);
+ if (ret < 0)
+ WARN("Failed to set window size");
+ else
+ DEBUG("Set window size to %d columns and %d rows", wsz.ws_col,
+ wsz.ws_row);
+
+ return;
}
static void lxc_console_winch(struct lxc_tty_state *ts)
{
lxc_console_winsz(ts->stdinfd, ts->masterfd);
+
if (ts->winch_proxy)
lxc_cmd_console_winch(ts->winch_proxy, ts->winch_proxy_lxcpath);
}
}
}
-int lxc_console_cb_sigwinch_fd(int fd, uint32_t events, void *cbdata,
- struct lxc_epoll_descr *descr)
+int lxc_console_cb_signal_fd(int fd, uint32_t events, void *cbdata,
+ struct lxc_epoll_descr *descr)
{
struct signalfd_siginfo siginfo;
struct lxc_tty_state *ts = cbdata;
ssize_t ret = read(fd, &siginfo, sizeof(siginfo));
if (ret < 0 || (size_t)ret < sizeof(siginfo)) {
- ERROR("failed to read signal info");
+ ERROR("Failed to read signal info");
return -1;
}
return 0;
}
-struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd)
+struct lxc_tty_state *lxc_console_signal_init(int srcfd, int dstfd)
{
+ bool istty;
sigset_t mask;
struct lxc_tty_state *ts;
ts->masterfd = dstfd;
ts->sigfd = -1;
- if (!isatty(srcfd)) {
+ istty = isatty(srcfd) == 1;
+ if (!istty) {
INFO("fd %d does not refer to a tty device", srcfd);
return ts;
}
sigemptyset(&mask);
sigaddset(&mask, SIGWINCH);
if (sigprocmask(SIG_BLOCK, &mask, &ts->oldmask)) {
- SYSERROR("failed to block SIGWINCH");
+ SYSERROR("Failed to block SIGWINCH signal");
ts->sigfd = -1;
lxc_list_del(&ts->node);
return ts;
ts->sigfd = signalfd(-1, &mask, 0);
if (ts->sigfd < 0) {
- SYSERROR("failed to create signal fd");
+ SYSERROR("Failed to create signal fd");
sigprocmask(SIG_SETMASK, &ts->oldmask, NULL);
ts->sigfd = -1;
lxc_list_del(&ts->node);
return ts;
}
- DEBUG("process %d created signal fd %d to handle SIGWINCH events", getpid(), ts->sigfd);
+ DEBUG("Process %d created signal fd %d", getpid(), ts->sigfd);
return ts;
}
-void lxc_console_sigwinch_fini(struct lxc_tty_state *ts)
+void lxc_console_signal_fini(struct lxc_tty_state *ts)
{
if (ts->sigfd >= 0) {
close(ts->sigfd);
lxc_mainloop_del_handler(descr, fd);
if (fd == console->peer) {
if (console->tty_state) {
- lxc_console_sigwinch_fini(console->tty_state);
+ lxc_console_signal_fini(console->tty_state);
console->tty_state = NULL;
}
console->peer = -1;
if (console->peer >= 0) {
if (lxc_mainloop_add_handler(console->descr, console->peer,
lxc_console_cb_con, console))
- WARN("console peer not added to mainloop");
+ WARN("Failed to add console peer handler to mainloop");
}
if (console->tty_state && console->tty_state->sigfd != -1) {
if (lxc_mainloop_add_handler(console->descr,
console->tty_state->sigfd,
- lxc_console_cb_sigwinch_fd,
+ lxc_console_cb_signal_fd,
console->tty_state)) {
- WARN("failed to add to mainloop SIGWINCH handler for '%d'",
- console->tty_state->sigfd);
+ WARN("Failed to add signal handler to mainloop");
}
}
}
static void lxc_console_peer_proxy_free(struct lxc_console *console)
{
if (console->tty_state) {
- lxc_console_sigwinch_fini(console->tty_state);
+ lxc_console_signal_fini(console->tty_state);
console->tty_state = NULL;
}
close(console->peerpty.master);
if (lxc_setup_tios(console->peerpty.slave, &oldtermio) < 0)
goto err1;
- ts = lxc_console_sigwinch_init(console->peerpty.master, console->master);
+ ts = lxc_console_signal_init(console->peerpty.master, console->master);
if (!ts)
goto err1;
goto on_error1;
}
- ts = lxc_console_sigwinch_init(console->peer, console->master);
+ ts = lxc_console_signal_init(console->peer, console->master);
console->tty_state = ts;
if (!ts) {
- WARN("unable to install SIGWINCH handler");
+ WARN("Failed to install signal handler");
goto on_error1;
}
if (ret < 0)
TRACE("Process is already group leader");
- ts = lxc_console_sigwinch_init(stdinfd, masterfd);
+ ts = lxc_console_signal_init(stdinfd, masterfd);
if (!ts) {
ret = -1;
goto close_fds;
if (ts->sigfd != -1) {
ret = lxc_mainloop_add_handler(&descr, ts->sigfd,
- lxc_console_cb_sigwinch_fd, ts);
+ lxc_console_cb_signal_fd, ts);
if (ret < 0) {
- ERROR("Failed to add SIGWINCH handler");
+ ERROR("Failed to add signal handler to mainloop");
goto close_mainloop;
}
}
lxc_mainloop_close(&descr);
sigwinch_fini:
- lxc_console_sigwinch_fini(ts);
+ lxc_console_signal_fini(ts);
close_fds:
close(masterfd);
#ifndef __LXC_CONSOLE_H
#define __LXC_CONSOLE_H
+#include <signal.h>
+#include <stdio.h>
+
#include "conf.h"
#include "list.h"
/* Escape sequence to use for exiting the pty. A single char can be
* specified. The pty can then exited by doing: Ctrl + specified_char + q.
* This field is checked by lxc_console_cb_tty_stdin(). Set to -1 to
- * disable exiting the pty via a escape sequence. */
+ * disable exiting the pty via a escape sequence.
+ */
int escape;
/* Used internally by lxc_console_cb_tty_stdin() to check whether an
- * escape sequence has been received. */
+ * escape sequence has been received.
+ */
int saw_escape;
/* Name of the container to forward the SIGWINCH event to. */
const char *winch_proxy;
/* Path of the container to forward the SIGWINCH event to. */
const char *winch_proxy_lxcpath;
- /* File descriptor that accepts SIGWINCH signals. If set to -1 no
- * SIGWINCH handler could be installed. This also means that
- * the sigset_t oldmask member is meaningless. */
+ /* File descriptor that accepts signals. If set to -1 no signal handler
+ * could be installed. This also means that the sigset_t oldmask member
+ * is meaningless.
+ */
int sigfd;
sigset_t oldmask;
};
extern void lxc_console_winsz(int srcfd, int dstfd);
/*
- * lxc_console_sigwinch_init: install SIGWINCH handler
+ * lxc_console_signal_init: install signal handler
*
* @srcfd : src for winsz in SIGWINCH handler
* @dstfd : dst for winsz in SIGWINCH handler
*
* Returns lxc_tty_state structure on success or NULL on failure. The sigfd
* member of the returned lxc_tty_state can be select()/poll()ed/epoll()ed
- * on (ie added to a mainloop) for SIGWINCH.
+ * on (ie added to a mainloop) for signals.
*
* Must be called with process_lock held to protect the lxc_ttys list, or
* from a non-threaded context.
*
- * Note that SIGWINCH isn't installed as a classic asychronous handler,
- * rather signalfd(2) is used so that we can handle the signal when we're
- * ready for it. This avoids deadlocks since a signal handler
- * (ie lxc_console_sigwinch()) would need to take the thread mutex to
- * prevent lxc_ttys list corruption, but using the fd we can provide the
- * tty_state needed to the callback (lxc_console_cb_sigwinch_fd()).
+ * Note that the signal handler isn't installed as a classic asychronous
+ * handler, rather signalfd(2) is used so that we can handle the signal when
+ * we're ready for it. This avoids deadlocks since a signal handler (ie
+ * lxc_console_sigwinch()) would need to take the thread mutex to prevent
+ * lxc_ttys list corruption, but using the fd we can provide the tty_state
+ * needed to the callback (lxc_console_cb_signal_fd()).
*
* This function allocates memory. It is up to the caller to free it.
*/
-extern struct lxc_tty_state *lxc_console_sigwinch_init(int srcfd, int dstfd);
+extern struct lxc_tty_state *lxc_console_signal_init(int srcfd, int dstfd);
/*
- * Handler for SIGWINCH events. To be registered via the corresponding functions
+ * Handler for signal events. To be registered via the corresponding functions
* declared and defined in mainloop.{c,h} or lxc_console_mainloop_add().
*/
-extern int lxc_console_cb_sigwinch_fd(int fd, uint32_t events, void *cbdata,
- struct lxc_epoll_descr *descr);
+extern int lxc_console_cb_signal_fd(int fd, uint32_t events, void *cbdata,
+ struct lxc_epoll_descr *descr);
/*
- * lxc_console_sigwinch_fini: uninstall SIGWINCH handler
+ * lxc_console_signal_fini: uninstall signal handler
*
- * @ts : the lxc_tty_state returned by lxc_console_sigwinch_init
+ * @ts : the lxc_tty_state returned by lxc_console_signal_init
*
* Restore the saved signal handler that was in effect at the time
- * lxc_console_sigwinch_init() was called.
+ * lxc_console_signal_init() was called.
*
* Must be called with process_lock held to protect the lxc_ttys list, or
* from a non-threaded context.
*/
-extern void lxc_console_sigwinch_fini(struct lxc_tty_state *ts);
+extern void lxc_console_signal_fini(struct lxc_tty_state *ts);
#endif