On Fri, Jan 14, 2022 at 12:28:11AM +0100, наб wrote: > -static int write_to_child(struct ul_pty *pty, char *buf, size_t bufsz) > +static int schedule_child_write(struct ul_pty *pty, char *buf, size_t bufsz, int final) > { > - return write_all(pty->master, buf, bufsz); > + struct ul_pty_child_buffer *stash = calloc(1, sizeof(*stash)); It means that for each activity on the file descriptor it will allocate a new buffer (in BUFSIZ). It seems pretty expensive. Cannot we reuse the buffers? Maybe use include/list.h, define two lists, one for not-yet-written buffers and another for ready-to-use buffers and move from one list to another in schedule_child_write() and flush_child_buffers(). > + if (!stash) > + return -1; > + > + memcpy(stash->buf, buf, bufsz); > + stash->size = bufsz; > + stash->final_input = final ? 1 : 0; > + > + if (pty->child_buffer_head) > + pty->child_buffer_tail = pty->child_buffer_tail->next = stash; > + else > + pty->child_buffer_head = pty->child_buffer_tail = stash; > + return 0; > } > > /* > @@ -311,16 +329,13 @@ static int write_to_child(struct ul_pty > * maintains master+slave tty stuff within the session. Use pipe to write to > * pty and assume non-interactive (tee-like) behavior is NOT well supported. > */ > -void ul_pty_write_eof_to_child(struct ul_pty *pty) > +static void drain(struct ul_pty *pty) drain_child_buffers() :-) Anyway, it looks good. Karel -- Karel Zak <kzak@xxxxxxxxxx> http://karelzak.blogspot.com