-/* $OpenBSD: client.c,v 1.158 2022/05/30 12:48:57 nicm Exp $ */
+/* $OpenBSD: client.c,v 1.159 2023/01/06 07:09:27 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
NULL);
break;
+ case MSG_READ_CANCEL:
+ file_read_cancel(&client_files, imsg);
+ break;
case MSG_WRITE_OPEN:
file_write_open(&client_files, client_peer, imsg, 1,
!(client_flags & CLIENT_CONTROL), client_file_check_cb,
-/* $OpenBSD: file.c,v 1.13 2022/08/24 07:22:30 nicm Exp $ */
+/* $OpenBSD: file.c,v 1.14 2023/01/06 07:09:27 nicm Exp $ */
/*
* Copyright (c) 2019 Nicholas Marriott <nicholas.marriott@gmail.com>
struct client_file *cf = arg;
struct client *c = cf->c;
- if (cf->cb != NULL && (c == NULL || (~c->flags & CLIENT_DEAD)))
+ if (cf->cb != NULL &&
+ (cf->closed || c == NULL || (~c->flags & CLIENT_DEAD)))
cf->cb(c, cf->path, cf->error, 1, cf->buffer, cf->data);
file_free(cf);
}
}
/* Read a file. */
-void
+struct client_file *
file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
{
struct client_file *cf;
goto done;
}
free(msg);
- return;
+ return cf;
done:
file_fire_done(cf);
+ return NULL;
+}
+
+/* Cancel a file read. */
+void
+file_cancel(struct client_file *cf)
+{
+ struct msg_read_cancel msg;
+
+ log_debug("read cancel file %d", cf->stream);
+
+ if (cf->closed)
+ return;
+ cf->closed = 1;
+
+ msg.stream = cf->stream;
+ proc_send(cf->peer, MSG_READ_CANCEL, -1, &msg, sizeof msg);
}
/* Push event, fired if there is more writing to be done. */
proc_send(peer, MSG_READ_DONE, -1, &reply, sizeof reply);
}
+/* Handle a read cancel message (client). */
+void
+file_read_cancel(struct client_files *files, struct imsg *imsg)
+{
+ struct msg_read_cancel *msg = imsg->data;
+ size_t msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
+ struct client_file find, *cf;
+
+ if (msglen != sizeof *msg)
+ fatalx("bad MSG_READ_CANCEL size");
+ find.stream = msg->stream;
+ if ((cf = RB_FIND(client_files, files, &find)) == NULL)
+ fatalx("unknown stream number");
+ log_debug("cancel file %d", cf->stream);
+
+ file_read_error_callback(NULL, 0, cf);
+}
+
/* Handle a write ready message (server). */
void
file_write_ready(struct client_files *files, struct imsg *imsg)
return;
log_debug("file %d read %zu bytes", cf->stream, bsize);
- if (cf->error == 0) {
+ if (cf->error == 0 && !cf->closed) {
if (evbuffer_add(cf->buffer, bdata, bsize) != 0) {
cf->error = ENOMEM;
file_fire_done(cf);
-/* $OpenBSD: tmux-protocol.h,v 1.1 2021/08/13 07:37:58 nicm Exp $ */
+/* $OpenBSD: tmux-protocol.h,v 1.2 2023/01/06 07:09:27 nicm Exp $ */
/*
* Copyright (c) 2021 Nicholas Marriott <nicholas.marriott@gmail.com>
MSG_WRITE_OPEN,
MSG_WRITE,
MSG_WRITE_READY,
- MSG_WRITE_CLOSE
+ MSG_WRITE_CLOSE,
+ MSG_READ_CANCEL
};
/*
int error;
};
+struct msg_read_cancel {
+ int stream;
+};
+
struct msg_write_open {
int stream;
int fd;
-/* $OpenBSD: tmux.h,v 1.1189 2023/01/03 11:43:24 nicm Exp $ */
+/* $OpenBSD: tmux.h,v 1.1190 2023/01/06 07:09:27 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
void printflike(2, 3) file_error(struct client *, const char *, ...);
void file_write(struct client *, const char *, int, const void *, size_t,
client_file_cb, void *);
-void file_read(struct client *, const char *, client_file_cb, void *);
+struct client_file *file_read(struct client *, const char *, client_file_cb,
+ void *);
+void file_cancel(struct client_file *);
void file_push(struct client_file *);
int file_write_left(struct client_files *);
void file_write_open(struct client_files *, struct tmuxpeer *,
void file_write_ready(struct client_files *, struct imsg *);
void file_read_data(struct client_files *, struct imsg *);
void file_read_done(struct client_files *, struct imsg *);
+void file_read_cancel(struct client_files *, struct imsg *);
/* server.c */
extern struct tmuxproc *server_proc;
-/* $OpenBSD: window.c,v 1.282 2022/08/24 07:22:30 nicm Exp $ */
+/* $OpenBSD: window.c,v 1.283 2023/01/06 07:09:27 nicm Exp $ */
/*
* Copyright (c) 2007 Nicholas Marriott <nicholas.marriott@gmail.com>
struct window_pane_input_data {
struct cmdq_item *item;
u_int wp;
+ struct client_file *file;
};
static struct window_pane *window_pane_create(struct window *, u_int, u_int,
size_t len = EVBUFFER_LENGTH(buffer);
wp = window_pane_find_by_id(cdata->wp);
- if (wp == NULL || closed || error != 0 || (c->flags & CLIENT_DEAD)) {
+ if (cdata->file != NULL && (wp == NULL || c->flags & CLIENT_DEAD)) {
if (wp == NULL)
c->flags |= CLIENT_EXIT;
-
- evbuffer_drain(buffer, len);
+ file_cancel(cdata->file);
+ } else if (cdata->file == NULL || closed || error != 0) {
cmdq_continue(cdata->item);
-
server_client_unref(c);
free(cdata);
- return;
- }
- input_parse_buffer(wp, buf, len);
+ } else
+ input_parse_buffer(wp, buf, len);
evbuffer_drain(buffer, len);
}
cdata = xmalloc(sizeof *cdata);
cdata->item = item;
cdata->wp = wp->id;
-
+ cdata->file = file_read(c, "-", window_pane_input_callback, cdata);
c->references++;
- file_read(c, "-", window_pane_input_callback, cdata);
return (0);
}