Lines Matching refs:f
80 static void pty_forward_disconnect(PTYForward *f) { in pty_forward_disconnect() argument
82 if (!f) in pty_forward_disconnect()
85 f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); in pty_forward_disconnect()
86 f->stdout_event_source = sd_event_source_unref(f->stdout_event_source); in pty_forward_disconnect()
88 f->master_event_source = sd_event_source_unref(f->master_event_source); in pty_forward_disconnect()
89 f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source); in pty_forward_disconnect()
90 f->event = sd_event_unref(f->event); in pty_forward_disconnect()
92 if (f->output_fd >= 0) { in pty_forward_disconnect()
93 if (f->saved_stdout) in pty_forward_disconnect()
94 (void) tcsetattr(f->output_fd, TCSANOW, &f->saved_stdout_attr); in pty_forward_disconnect()
97 (void) fd_nonblock(f->output_fd, false); in pty_forward_disconnect()
98 if (f->close_output_fd) in pty_forward_disconnect()
99 f->output_fd = safe_close(f->output_fd); in pty_forward_disconnect()
102 if (f->input_fd >= 0) { in pty_forward_disconnect()
103 if (f->saved_stdin) in pty_forward_disconnect()
104 (void) tcsetattr(f->input_fd, TCSANOW, &f->saved_stdin_attr); in pty_forward_disconnect()
106 (void) fd_nonblock(f->input_fd, false); in pty_forward_disconnect()
107 if (f->close_input_fd) in pty_forward_disconnect()
108 f->input_fd = safe_close(f->input_fd); in pty_forward_disconnect()
111 f->saved_stdout = f->saved_stdin = false; in pty_forward_disconnect()
114 static int pty_forward_done(PTYForward *f, int rcode) { in pty_forward_done() argument
116 assert(f); in pty_forward_done()
118 if (f->done) in pty_forward_done()
121 e = sd_event_ref(f->event); in pty_forward_done()
123 f->done = true; in pty_forward_done()
124 pty_forward_disconnect(f); in pty_forward_done()
126 if (f->handler) in pty_forward_done()
127 return f->handler(f, rcode, f->userdata); in pty_forward_done()
132 static bool look_for_escape(PTYForward *f, const char *buffer, size_t n) { in look_for_escape() argument
135 assert(f); in look_for_escape()
145 if (f->escape_counter == 0 || nw > f->escape_timestamp + ESCAPE_USEC) { in look_for_escape()
146 f->escape_timestamp = nw; in look_for_escape()
147 f->escape_counter = 1; in look_for_escape()
149 (f->escape_counter)++; in look_for_escape()
151 if (f->escape_counter >= 3) in look_for_escape()
155 f->escape_timestamp = 0; in look_for_escape()
156 f->escape_counter = 0; in look_for_escape()
163 static bool ignore_vhangup(PTYForward *f) { in ignore_vhangup() argument
164 assert(f); in ignore_vhangup()
166 if (f->flags & PTY_FORWARD_IGNORE_VHANGUP) in ignore_vhangup()
169 if ((f->flags & PTY_FORWARD_IGNORE_INITIAL_VHANGUP) && !f->read_from_master) in ignore_vhangup()
175 static bool drained(PTYForward *f) { in drained() argument
178 assert(f); in drained()
180 if (f->out_buffer_full > 0) in drained()
183 if (f->master_readable) in drained()
186 if (ioctl(f->master, TIOCINQ, &q) < 0) in drained()
191 if (ioctl(f->master, TIOCOUTQ, &q) < 0) in drained()
199 static int shovel(PTYForward *f) { in shovel() argument
202 assert(f); in shovel()
204 while ((f->stdin_readable && f->in_buffer_full <= 0) || in shovel()
205 (f->master_writable && f->in_buffer_full > 0) || in shovel()
206 (f->master_readable && f->out_buffer_full <= 0) || in shovel()
207 (f->stdout_writable && f->out_buffer_full > 0)) { in shovel()
209 if (f->stdin_readable && f->in_buffer_full < LINE_MAX) { in shovel()
211 … k = read(f->input_fd, f->in_buffer + f->in_buffer_full, LINE_MAX - f->in_buffer_full); in shovel()
215 f->stdin_readable = false; in shovel()
217 f->stdin_readable = false; in shovel()
218 f->stdin_hangup = true; in shovel()
220 … f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); in shovel()
223 return pty_forward_done(f, -errno); in shovel()
227 f->stdin_readable = false; in shovel()
228 f->stdin_hangup = true; in shovel()
230 … f->stdin_event_source = sd_event_source_unref(f->stdin_event_source); in shovel()
234 if (look_for_escape(f, f->in_buffer + f->in_buffer_full, k)) in shovel()
235 return pty_forward_done(f, -ECANCELED); in shovel()
237 f->in_buffer_full += (size_t) k; in shovel()
241 if (f->master_writable && f->in_buffer_full > 0) { in shovel()
243 k = write(f->master, f->in_buffer, f->in_buffer_full); in shovel()
247 f->master_writable = false; in shovel()
249 f->master_writable = f->master_readable = false; in shovel()
250 f->master_hangup = true; in shovel()
252 … f->master_event_source = sd_event_source_unref(f->master_event_source); in shovel()
255 return pty_forward_done(f, -errno); in shovel()
258 assert(f->in_buffer_full >= (size_t) k); in shovel()
259 memmove(f->in_buffer, f->in_buffer + k, f->in_buffer_full - k); in shovel()
260 f->in_buffer_full -= k; in shovel()
264 if (f->master_readable && f->out_buffer_full < LINE_MAX) { in shovel()
266 … k = read(f->master, f->out_buffer + f->out_buffer_full, LINE_MAX - f->out_buffer_full); in shovel()
276 if (errno == EAGAIN || (errno == EIO && ignore_vhangup(f))) in shovel()
277 f->master_readable = false; in shovel()
279 f->master_readable = f->master_writable = false; in shovel()
280 f->master_hangup = true; in shovel()
282 … f->master_event_source = sd_event_source_unref(f->master_event_source); in shovel()
285 return pty_forward_done(f, -errno); in shovel()
288 f->read_from_master = true; in shovel()
289 f->out_buffer_full += (size_t) k; in shovel()
293 if (f->stdout_writable && f->out_buffer_full > 0) { in shovel()
295 k = write(f->output_fd, f->out_buffer, f->out_buffer_full); in shovel()
299 f->stdout_writable = false; in shovel()
301 f->stdout_writable = false; in shovel()
302 f->stdout_hangup = true; in shovel()
303 … f->stdout_event_source = sd_event_source_unref(f->stdout_event_source); in shovel()
306 return pty_forward_done(f, -errno); in shovel()
312 f->last_char = f->out_buffer[k-1]; in shovel()
313 f->last_char_set = true; in shovel()
316 assert(f->out_buffer_full >= (size_t) k); in shovel()
317 memmove(f->out_buffer, f->out_buffer + k, f->out_buffer_full - k); in shovel()
318 f->out_buffer_full -= k; in shovel()
323 if (f->stdin_hangup || f->stdout_hangup || f->master_hangup) { in shovel()
327 if ((f->out_buffer_full <= 0 || f->stdout_hangup) && in shovel()
328 (f->in_buffer_full <= 0 || f->master_hangup)) in shovel()
329 return pty_forward_done(f, 0); in shovel()
334 if (f->drain && drained(f)) in shovel()
335 return pty_forward_done(f, 0); in shovel()
341 PTYForward *f = userdata; in on_master_event() local
343 assert(f); in on_master_event()
345 assert(e == f->master_event_source); in on_master_event()
347 assert(fd == f->master); in on_master_event()
350 f->master_readable = true; in on_master_event()
353 f->master_writable = true; in on_master_event()
355 return shovel(f); in on_master_event()
359 PTYForward *f = userdata; in on_stdin_event() local
361 assert(f); in on_stdin_event()
363 assert(e == f->stdin_event_source); in on_stdin_event()
365 assert(fd == f->input_fd); in on_stdin_event()
368 f->stdin_readable = true; in on_stdin_event()
370 return shovel(f); in on_stdin_event()
374 PTYForward *f = userdata; in on_stdout_event() local
376 assert(f); in on_stdout_event()
378 assert(e == f->stdout_event_source); in on_stdout_event()
380 assert(fd == f->output_fd); in on_stdout_event()
383 f->stdout_writable = true; in on_stdout_event()
385 return shovel(f); in on_stdout_event()
389 PTYForward *f = userdata; in on_sigwinch_event() local
392 assert(f); in on_sigwinch_event()
394 assert(e == f->sigwinch_event_source); in on_sigwinch_event()
397 if (ioctl(f->output_fd, TIOCGWINSZ, &ws) >= 0) in on_sigwinch_event()
398 (void) ioctl(f->master, TIOCSWINSZ, &ws); in on_sigwinch_event()
409 _cleanup_(pty_forward_freep) PTYForward *f = NULL; in pty_forward_new()
413 f = new(PTYForward, 1); in pty_forward_new()
414 if (!f) in pty_forward_new()
417 *f = (struct PTYForward) { in pty_forward_new()
425 f->event = sd_event_ref(event); in pty_forward_new()
427 r = sd_event_default(&f->event); in pty_forward_new()
433 f->output_fd = STDOUT_FILENO; in pty_forward_new()
443 f->input_fd = fd_reopen(STDIN_FILENO, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); in pty_forward_new()
444 if (f->input_fd < 0) { in pty_forward_new()
447 … log_debug_errno(f->input_fd, "Failed to reopen stdin, using original fd: %m"); in pty_forward_new()
453 f->input_fd = STDIN_FILENO; in pty_forward_new()
455 f->close_input_fd = true; in pty_forward_new()
457 f->output_fd = fd_reopen(STDOUT_FILENO, O_WRONLY|O_CLOEXEC|O_NOCTTY|O_NONBLOCK); in pty_forward_new()
458 if (f->output_fd < 0) { in pty_forward_new()
459 … log_debug_errno(f->output_fd, "Failed to reopen stdout, using original fd: %m"); in pty_forward_new()
465 f->output_fd = STDOUT_FILENO; in pty_forward_new()
467 f->close_output_fd = true; in pty_forward_new()
474 f->master = master; in pty_forward_new()
476 if (ioctl(f->output_fd, TIOCGWINSZ, &ws) < 0) in pty_forward_new()
487 assert(f->input_fd >= 0); in pty_forward_new()
489 if (tcgetattr(f->input_fd, &f->saved_stdin_attr) >= 0) { in pty_forward_new()
492 f->saved_stdin = true; in pty_forward_new()
494 raw_stdin_attr = f->saved_stdin_attr; in pty_forward_new()
496 raw_stdin_attr.c_oflag = f->saved_stdin_attr.c_oflag; in pty_forward_new()
497 tcsetattr(f->input_fd, TCSANOW, &raw_stdin_attr); in pty_forward_new()
500 if (tcgetattr(f->output_fd, &f->saved_stdout_attr) >= 0) { in pty_forward_new()
503 f->saved_stdout = true; in pty_forward_new()
505 raw_stdout_attr = f->saved_stdout_attr; in pty_forward_new()
507 raw_stdout_attr.c_iflag = f->saved_stdout_attr.c_iflag; in pty_forward_new()
508 raw_stdout_attr.c_lflag = f->saved_stdout_attr.c_lflag; in pty_forward_new()
509 tcsetattr(f->output_fd, TCSANOW, &raw_stdout_attr); in pty_forward_new()
512 …r = sd_event_add_io(f->event, &f->stdin_event_source, f->input_fd, EPOLLIN|EPOLLET, on_stdin_event… in pty_forward_new()
517 … (void) sd_event_source_set_description(f->stdin_event_source, "ptyfwd-stdin"); in pty_forward_new()
520 …r = sd_event_add_io(f->event, &f->stdout_event_source, f->output_fd, EPOLLOUT|EPOLLET, on_stdout_e… in pty_forward_new()
523 f->stdout_writable = true; in pty_forward_new()
527 (void) sd_event_source_set_description(f->stdout_event_source, "ptyfwd-stdout"); in pty_forward_new()
529 …r = sd_event_add_io(f->event, &f->master_event_source, master, EPOLLIN|EPOLLOUT|EPOLLET, on_master… in pty_forward_new()
533 (void) sd_event_source_set_description(f->master_event_source, "ptyfwd-master"); in pty_forward_new()
535 … r = sd_event_add_signal(f->event, &f->sigwinch_event_source, SIGWINCH, on_sigwinch_event, f); in pty_forward_new()
539 (void) sd_event_source_set_description(f->sigwinch_event_source, "ptyfwd-sigwinch"); in pty_forward_new()
541 *ret = TAKE_PTR(f); in pty_forward_new()
546 PTYForward *pty_forward_free(PTYForward *f) { in pty_forward_free() argument
547 pty_forward_disconnect(f); in pty_forward_free()
548 return mfree(f); in pty_forward_free()
551 int pty_forward_get_last_char(PTYForward *f, char *ch) { in pty_forward_get_last_char() argument
552 assert(f); in pty_forward_get_last_char()
555 if (!f->last_char_set) in pty_forward_get_last_char()
558 *ch = f->last_char; in pty_forward_get_last_char()
562 int pty_forward_set_ignore_vhangup(PTYForward *f, bool b) { in pty_forward_set_ignore_vhangup() argument
565 assert(f); in pty_forward_set_ignore_vhangup()
567 if (!!(f->flags & PTY_FORWARD_IGNORE_VHANGUP) == b) in pty_forward_set_ignore_vhangup()
570 SET_FLAG(f->flags, PTY_FORWARD_IGNORE_VHANGUP, b); in pty_forward_set_ignore_vhangup()
572 if (!ignore_vhangup(f)) { in pty_forward_set_ignore_vhangup()
577 f->master_readable = true; in pty_forward_set_ignore_vhangup()
578 r = shovel(f); in pty_forward_set_ignore_vhangup()
586 bool pty_forward_get_ignore_vhangup(PTYForward *f) { in pty_forward_get_ignore_vhangup() argument
587 assert(f); in pty_forward_get_ignore_vhangup()
589 return !!(f->flags & PTY_FORWARD_IGNORE_VHANGUP); in pty_forward_get_ignore_vhangup()
592 bool pty_forward_is_done(PTYForward *f) { in pty_forward_is_done() argument
593 assert(f); in pty_forward_is_done()
595 return f->done; in pty_forward_is_done()
598 void pty_forward_set_handler(PTYForward *f, PTYForwardHandler cb, void *userdata) { in pty_forward_set_handler() argument
599 assert(f); in pty_forward_set_handler()
601 f->handler = cb; in pty_forward_set_handler()
602 f->userdata = userdata; in pty_forward_set_handler()
605 bool pty_forward_drain(PTYForward *f) { in pty_forward_drain() argument
606 assert(f); in pty_forward_drain()
615 f->drain = true; in pty_forward_drain()
616 return drained(f); in pty_forward_drain()
619 int pty_forward_set_priority(PTYForward *f, int64_t priority) { in pty_forward_set_priority() argument
621 assert(f); in pty_forward_set_priority()
623 if (f->stdin_event_source) { in pty_forward_set_priority()
624 r = sd_event_source_set_priority(f->stdin_event_source, priority); in pty_forward_set_priority()
629 r = sd_event_source_set_priority(f->stdout_event_source, priority); in pty_forward_set_priority()
633 r = sd_event_source_set_priority(f->master_event_source, priority); in pty_forward_set_priority()
637 r = sd_event_source_set_priority(f->sigwinch_event_source, priority); in pty_forward_set_priority()
644 int pty_forward_set_width_height(PTYForward *f, unsigned width, unsigned height) { in pty_forward_set_width_height() argument
647 assert(f); in pty_forward_set_width_height()
661 if (ioctl(f->master, TIOCGWINSZ, &ws) < 0) in pty_forward_set_width_height()
674 if (ioctl(f->master, TIOCSWINSZ, &ws) < 0) in pty_forward_set_width_height()
678 f->sigwinch_event_source = sd_event_source_unref(f->sigwinch_event_source); in pty_forward_set_width_height()