ptyfwd.c revision 04d39279245834494baccfdb9349db8bf80abd13
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering/***
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering This file is part of systemd.
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering Copyright 2010-2013 Lennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering systemd is free software; you can redistribute it and/or modify it
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering under the terms of the GNU Lesser General Public License as published by
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering the Free Software Foundation; either version 2.1 of the License, or
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering (at your option) any later version.
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering systemd is distributed in the hope that it will be useful, but
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering Lesser General Public License for more details.
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering You should have received a copy of the GNU Lesser General Public License
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering***/
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering#include <sys/epoll.h>
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering#include <sys/signalfd.h>
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering#include <sys/ioctl.h>
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering#include <limits.h>
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering#include <termios.h>
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering#include "util.h"
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering#include "ptyfwd.h"
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering#define ESCAPE_USEC USEC_PER_SEC
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic bool look_for_escape(usec_t *timestamp, unsigned *counter, const char *buffer, size_t n) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering const char *p;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(timestamp);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(counter);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(buffer);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering assert(n > 0);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering for (p = buffer; p < buffer + n; p++) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Check for ^] */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*p == 0x1D) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering usec_t nw = now(CLOCK_MONOTONIC);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*counter == 0 || nw > *timestamp + USEC_PER_SEC) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *timestamp = nw;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *counter = 1;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering (*counter)++;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (*counter >= 3)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *timestamp = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering *counter = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringstatic int process_pty_loop(int master, sigset_t *mask, pid_t kill_pid, int signo) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering char in_buffer[LINE_MAX], out_buffer[LINE_MAX];
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering size_t in_buffer_full = 0, out_buffer_full = 0;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering struct epoll_event stdin_ev, stdout_ev, master_ev, signal_ev;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering bool stdin_readable = false, stdout_writable = false, master_readable = false, master_writable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering bool stdin_hangup = false, stdout_hangup = false, master_hangup = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering bool tried_orderly_shutdown = false, process_signalfd = false, quit = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering usec_t escape_timestamp = 0;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering unsigned escape_counter = 0;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering _cleanup_close_ int ep = -1, signal_fd = -1;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering assert(master >= 0);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering assert(mask);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering assert(kill_pid == 0 || kill_pid > 1);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering assert(signo >= 0 && signo < _NSIG);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering fd_nonblock(STDIN_FILENO, 1);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering fd_nonblock(STDOUT_FILENO, 1);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering fd_nonblock(master, 1);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering signal_fd = signalfd(-1, mask, SFD_NONBLOCK|SFD_CLOEXEC);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (signal_fd < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("signalfd(): %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering ep = epoll_create1(EPOLL_CLOEXEC);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (ep < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("Failed to create epoll: %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering /* We read from STDIN only if this is actually a TTY,
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering * otherwise we assume non-interactivity. */
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (isatty(STDIN_FILENO)) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering zero(stdin_ev);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdin_ev.events = EPOLLIN|EPOLLET;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdin_ev.data.fd = STDIN_FILENO;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (epoll_ctl(ep, EPOLL_CTL_ADD, STDIN_FILENO, &stdin_ev) < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("Failed to register STDIN in epoll: %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering zero(stdout_ev);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdout_ev.events = EPOLLOUT|EPOLLET;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdout_ev.data.fd = STDOUT_FILENO;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering zero(master_ev);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering master_ev.events = EPOLLIN|EPOLLOUT|EPOLLET;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering master_ev.data.fd = master;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering zero(signal_ev);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering signal_ev.events = EPOLLIN;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering signal_ev.data.fd = signal_fd;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (epoll_ctl(ep, EPOLL_CTL_ADD, STDOUT_FILENO, &stdout_ev) < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (errno != EPERM) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("Failed to register stdout in epoll: %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering /* stdout without epoll support. Likely redirected to regular file. */
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdout_writable = true;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (epoll_ctl(ep, EPOLL_CTL_ADD, master, &master_ev) < 0 ||
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering epoll_ctl(ep, EPOLL_CTL_ADD, signal_fd, &signal_ev) < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("Failed to register fds in epoll: %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering for (;;) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering struct epoll_event ev[16];
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering ssize_t k;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering int i, nfds;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering nfds = epoll_wait(ep, ev, ELEMENTSOF(ev), quit ? 0 : -1);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (nfds < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (errno == EINTR || errno == EAGAIN)
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering continue;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("epoll_wait(): %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (nfds == 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return 0;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering for (i = 0; i < nfds; i++) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (ev[i].data.fd == STDIN_FILENO) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (ev[i].events & (EPOLLIN|EPOLLHUP))
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdin_readable = true;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering } else if (ev[i].data.fd == STDOUT_FILENO) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (ev[i].events & (EPOLLOUT|EPOLLHUP))
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdout_writable = true;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering } else if (ev[i].data.fd == master) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (ev[i].events & (EPOLLIN|EPOLLHUP))
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering master_readable = true;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (ev[i].events & (EPOLLOUT|EPOLLHUP))
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering master_writable = true;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else if (ev[i].data.fd == signal_fd)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering process_signalfd = true;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering while ((stdin_readable && in_buffer_full <= 0) ||
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering (master_writable && in_buffer_full > 0) ||
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering (master_readable && out_buffer_full <= 0) ||
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering (stdout_writable && out_buffer_full > 0)) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (stdin_readable && in_buffer_full < LINE_MAX) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering k = read(STDIN_FILENO, in_buffer + in_buffer_full, LINE_MAX - in_buffer_full);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (k < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno == EAGAIN)
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdin_readable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (errno == EIO || errno == EPIPE || errno == ECONNRESET) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering stdin_readable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering stdin_hangup = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering epoll_ctl(ep, EPOLL_CTL_DEL, STDIN_FILENO, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("read(): %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Check if ^] has been
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * pressed three times within
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * one second. If we get this
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * we quite immediately. */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (look_for_escape(&escape_timestamp, &escape_counter, in_buffer + in_buffer_full, k))
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return !quit;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering in_buffer_full += (size_t) k;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (master_writable && in_buffer_full > 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering k = write(master, in_buffer, in_buffer_full);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (k < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno == EAGAIN || errno == EIO)
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering master_writable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (errno == EPIPE || errno == ECONNRESET) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering master_writable = master_readable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering master_hangup = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering epoll_ctl(ep, EPOLL_CTL_DEL, master, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("write(): %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering } else {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering assert(in_buffer_full >= (size_t) k);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering memmove(in_buffer, in_buffer + k, in_buffer_full - k);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering in_buffer_full -= k;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (master_readable && out_buffer_full < LINE_MAX) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering k = read(master, out_buffer + out_buffer_full, LINE_MAX - out_buffer_full);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (k < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Note that EIO on the master
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * device might be cause by
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * vhangup() or temporary
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * closing of everything on
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * the other side, we treat it
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * like EAGAIN here and try
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * again. */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno == EAGAIN || errno == EIO)
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering master_readable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (errno == EPIPE || errno == ECONNRESET) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering master_readable = master_writable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering master_hangup = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering epoll_ctl(ep, EPOLL_CTL_DEL, master, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("read(): %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering } else
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering out_buffer_full += (size_t) k;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (stdout_writable && out_buffer_full > 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering k = write(STDOUT_FILENO, out_buffer, out_buffer_full);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering if (k < 0) {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno == EAGAIN)
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering stdout_writable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else if (errno == EIO || errno == EPIPE || errno == ECONNRESET) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering stdout_writable = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering stdout_hangup = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering epoll_ctl(ep, EPOLL_CTL_DEL, STDOUT_FILENO, NULL);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering log_error("write(): %m");
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering return -errno;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering } else {
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering assert(out_buffer_full >= (size_t) k);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering memmove(out_buffer, out_buffer + k, out_buffer_full - k);
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering out_buffer_full -= k;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (process_signalfd) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering struct signalfd_siginfo sfsi;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ssize_t n;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering n = read(signal_fd, &sfsi, sizeof(sfsi));
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (n != sizeof(sfsi)) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (n >= 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Failed to read from signalfd: invalid block size");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -EIO;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (errno != EINTR && errno != EAGAIN) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_error("Failed to read from signalfd: %m");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return -errno;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (sfsi.ssi_signo == SIGWINCH) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering struct winsize ws;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* The window size changed, let's forward that. */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ioctl(master, TIOCSWINSZ, &ws);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else if (sfsi.ssi_signo == SIGTERM && kill_pid > 0 && signo > 0 && !tried_orderly_shutdown) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (kill(kill_pid, signo) < 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering quit = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering else {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering log_info("Trying to halt container. Send SIGTERM again to trigger immediate termination.");
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* This only works for systemd... */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering tried_orderly_shutdown = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering } else
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Signals that where
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * delivered via signalfd that
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * we didn't know are a reason
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * for us to quit */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering quit = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (stdin_hangup || stdout_hangup || master_hangup) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering /* Exit the loop if any side hung up and if
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * there's nothing more to write or nothing we
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering * could write. */
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if ((out_buffer_full <= 0 || stdout_hangup) &&
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering (in_buffer_full <= 0 || master_hangup))
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return !quit;
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering }
4ba93280223ceb5de1bcedb196c38252f334521aLennart Poettering}
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poetteringint process_pty(int master, sigset_t *mask, pid_t kill_pid, int signo) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering struct termios saved_attr;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering bool saved = false;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering struct winsize ws;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering int r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (ioctl(STDIN_FILENO, TIOCGWINSZ, &ws) >= 0)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering ioctl(master, TIOCSWINSZ, &ws);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (tcgetattr(STDIN_FILENO, &saved_attr) >= 0) {
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering struct termios raw_attr;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering saved = true;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering raw_attr = saved_attr;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering cfmakeraw(&raw_attr);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering raw_attr.c_lflag &= ~ECHO;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering tcsetattr(STDIN_FILENO, TCSANOW, &raw_attr);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering }
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering r = process_pty_loop(master, mask, kill_pid, signo);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering if (saved)
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering tcsetattr(STDIN_FILENO, TCSANOW, &saved_attr);
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering return r;
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering
04d39279245834494baccfdb9349db8bf80abd13Lennart Poettering}