ptyfwd.c revision 3ffd4af22052963e7a29431721ee204e634bea75
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl This file is part of systemd.
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl Copyright 2010-2013 Lennart Poettering
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl systemd is free software; you can redistribute it and/or modify it
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl under the terms of the GNU Lesser General Public License as published by
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl the Free Software Foundation; either version 2.1 of the License, or
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl (at your option) any later version.
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl systemd is distributed in the hope that it will be useful, but
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl WITHOUT ANY WARRANTY; without even the implied warranty of
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl Lesser General Public License for more details.
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl You should have received a copy of the GNU Lesser General Public License
d611dadcc74db10ba533ee6859308f5fc505aee1Michael Biebl along with systemd; If not, see <http://www.gnu.org/licenses/>.
3ce09b7da2eb8b888066468663b2b5c81a05a03cZbigniew Jędrzejewski-Szmek sd_event_source *stdout_event_source;
b5b7ea750388919eee6087eb63f08903b57447cfDave Reisner char in_buffer[LINE_MAX], out_buffer[LINE_MAX];
b5b7ea750388919eee6087eb63f08903b57447cfDave Reisnerstatic bool look_for_escape(PTYForward *f, const char *buffer, size_t n) {
b5b7ea750388919eee6087eb63f08903b57447cfDave Reisner const char *p;
b5b7ea750388919eee6087eb63f08903b57447cfDave Reisner /* Check for ^] */
b5b7ea750388919eee6087eb63f08903b57447cfDave Reisner if (*p == 0x1D) {
b5b7ea750388919eee6087eb63f08903b57447cfDave Reisner if (f->escape_counter == 0 || nw > f->escape_timestamp + ESCAPE_USEC) {
assert(f);
ssize_t k;
assert(f);
f->stdin_readable = false;
f->stdin_readable = false;
f->stdin_hangup = true;
f->stdin_readable = false;
f->stdin_hangup = true;
f->master_writable = false;
f->master_hangup = true;
f->in_buffer_full -= k;
f->master_readable = false;
f->master_hangup = true;
f->read_from_master = true;
f->stdout_writable = false;
f->stdout_writable = false;
f->stdout_hangup = true;
f->last_char_set = true;
f->out_buffer_full -= k;
assert(f);
assert(e);
f->master_readable = true;
f->master_writable = true;
return shovel(f);
assert(f);
assert(e);
f->stdin_readable = true;
return shovel(f);
assert(f);
assert(e);
f->stdout_writable = true;
return shovel(f);
static int on_sigwinch_event(sd_event_source *e, const struct signalfd_siginfo *si, void *userdata) {
assert(f);
assert(e);
int pty_forward_new(
int master,
return -ENOMEM;
if (event)
f->saved_stdin = true;
f->saved_stdout = true;
r = sd_event_add_io(f->event, &f->stdin_event_source, STDIN_FILENO, EPOLLIN|EPOLLET, on_stdin_event, f);
if (r < 0 && r != -EPERM)
r = sd_event_add_io(f->event, &f->stdout_event_source, STDOUT_FILENO, EPOLLOUT|EPOLLET, on_stdout_event, f);
if (r == -EPERM)
f->stdout_writable = true;
r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master_event, f);
*ret = f;
f = NULL;
if (f->saved_stdout)
if (f->saved_stdin)
free(f);
return NULL;
assert(f);
if (!f->last_char_set)
return -ENXIO;
assert(f);
if (!ignore_vhangup(f)) {
f->master_readable = true;
r = shovel(f);
assert(f);