Home | History | Annotate | Line # | Download | only in dist
      1 /* $OpenBSD$ */
      2 
      3 /*
      4  * Copyright (c) 2019 Nicholas Marriott <nicholas.marriott (at) gmail.com>
      5  *
      6  * Permission to use, copy, modify, and distribute this software for any
      7  * purpose with or without fee is hereby granted, provided that the above
      8  * copyright notice and this permission notice appear in all copies.
      9  *
     10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
     11  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
     12  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
     13  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
     14  * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
     15  * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
     16  * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
     17  */
     18 
     19 #include <sys/types.h>
     20 
     21 #include <errno.h>
     22 #include <fcntl.h>
     23 #include <stdio.h>
     24 #include <stdlib.h>
     25 #include <string.h>
     26 #include <unistd.h>
     27 
     28 #include "tmux.h"
     29 
     30 /*
     31  * IPC file handling. Both client and server use the same data structures
     32  * (client_file and client_files) to store list of active files. Most functions
     33  * are for use either in client or server but not both.
     34  */
     35 
     36 static int	file_next_stream = 3;
     37 
     38 RB_GENERATE(client_files, client_file, entry, file_cmp);
     39 
     40 /* Get path for file, either as given or from working directory. */
     41 static char *
     42 file_get_path(struct client *c, const char *file)
     43 {
     44 	const char	*home;
     45 	char		*path, *full_path;
     46 
     47 	if (strncmp(file, "~/", 2) != 0)
     48 		path = xstrdup(file);
     49 	else {
     50 		home = find_home();
     51 		if (home == NULL)
     52 			home = "";
     53 		xasprintf(&path, "%s%s", home, file + 1);
     54 	}
     55 	if (*path == '/')
     56 		return (path);
     57 	xasprintf(&full_path, "%s/%s", server_client_get_cwd(c, NULL), path);
     58 	return (full_path);
     59 }
     60 
     61 /* Tree comparison function. */
     62 int
     63 file_cmp(struct client_file *cf1, struct client_file *cf2)
     64 {
     65 	if (cf1->stream < cf2->stream)
     66 		return (-1);
     67 	if (cf1->stream > cf2->stream)
     68 		return (1);
     69 	return (0);
     70 }
     71 
     72 /*
     73  * Create a file object in the client process - the peer is the server to send
     74  * messages to. Check callback is fired when the file is finished with so the
     75  * process can decide if it needs to exit (if it is waiting for files to
     76  * flush).
     77  */
     78 struct client_file *
     79 file_create_with_peer(struct tmuxpeer *peer, struct client_files *files,
     80     int stream, client_file_cb cb, void *cbdata)
     81 {
     82 	struct client_file	*cf;
     83 
     84 	cf = xcalloc(1, sizeof *cf);
     85 	cf->c = NULL;
     86 	cf->references = 1;
     87 	cf->stream = stream;
     88 
     89 	cf->buffer = evbuffer_new();
     90 	if (cf->buffer == NULL)
     91 		fatalx("out of memory");
     92 
     93 	cf->cb = cb;
     94 	cf->data = cbdata;
     95 
     96 	cf->peer = peer;
     97 	cf->tree = files;
     98 	RB_INSERT(client_files, files, cf);
     99 
    100 	return (cf);
    101 }
    102 
    103 /* Create a file object in the server, communicating with the given client. */
    104 struct client_file *
    105 file_create_with_client(struct client *c, int stream, client_file_cb cb,
    106     void *cbdata)
    107 {
    108 	struct client_file	*cf;
    109 
    110 	if (c != NULL && (c->flags & CLIENT_ATTACHED))
    111 		c = NULL;
    112 
    113 	cf = xcalloc(1, sizeof *cf);
    114 	cf->c = c;
    115 	cf->references = 1;
    116 	cf->stream = stream;
    117 
    118 	cf->buffer = evbuffer_new();
    119 	if (cf->buffer == NULL)
    120 		fatalx("out of memory");
    121 
    122 	cf->cb = cb;
    123 	cf->data = cbdata;
    124 
    125 	if (cf->c != NULL) {
    126 		cf->peer = cf->c->peer;
    127 		cf->tree = &cf->c->files;
    128 		RB_INSERT(client_files, &cf->c->files, cf);
    129 		cf->c->references++;
    130 	}
    131 
    132 	return (cf);
    133 }
    134 
    135 /* Free a file. */
    136 void
    137 file_free(struct client_file *cf)
    138 {
    139 	if (--cf->references != 0)
    140 		return;
    141 
    142 	evbuffer_free(cf->buffer);
    143 	free(cf->path);
    144 
    145 	if (cf->tree != NULL)
    146 		RB_REMOVE(client_files, cf->tree, cf);
    147 	if (cf->c != NULL)
    148 		server_client_unref(cf->c);
    149 
    150 	free(cf);
    151 }
    152 
    153 /* Event to fire the done callback. */
    154 static void
    155 file_fire_done_cb(__unused int fd, __unused short events, void *arg)
    156 {
    157 	struct client_file	*cf = arg;
    158 	struct client		*c = cf->c;
    159 
    160 	if (cf->cb != NULL &&
    161 	    (cf->closed || c == NULL || (~c->flags & CLIENT_DEAD)))
    162 		cf->cb(c, cf->path, cf->error, 1, cf->buffer, cf->data);
    163 	file_free(cf);
    164 }
    165 
    166 /* Add an event to fire the done callback (used by the server). */
    167 void
    168 file_fire_done(struct client_file *cf)
    169 {
    170 	event_once(-1, EV_TIMEOUT, file_fire_done_cb, cf, NULL);
    171 }
    172 
    173 /* Fire the read callback. */
    174 void
    175 file_fire_read(struct client_file *cf)
    176 {
    177 	if (cf->cb != NULL)
    178 		cf->cb(cf->c, cf->path, cf->error, 0, cf->buffer, cf->data);
    179 }
    180 
    181 /* Can this file be printed to? */
    182 int
    183 file_can_print(struct client *c)
    184 {
    185 	if (c == NULL ||
    186 	    (c->flags & CLIENT_ATTACHED) ||
    187 	    (c->flags & CLIENT_CONTROL))
    188 		return (0);
    189 	return (1);
    190 }
    191 
    192 /* Print a message to a file. */
    193 void
    194 file_print(struct client *c, const char *fmt, ...)
    195 {
    196 	va_list	ap;
    197 
    198 	va_start(ap, fmt);
    199 	file_vprint(c, fmt, ap);
    200 	va_end(ap);
    201 }
    202 
    203 /* Print a message to a file. */
    204 void
    205 file_vprint(struct client *c, const char *fmt, va_list ap)
    206 {
    207 	struct client_file	 find, *cf;
    208 	struct msg_write_open	 msg;
    209 
    210 	if (!file_can_print(c))
    211 		return;
    212 
    213 	find.stream = 1;
    214 	if ((cf = RB_FIND(client_files, &c->files, &find)) == NULL) {
    215 		cf = file_create_with_client(c, 1, NULL, NULL);
    216 		cf->path = xstrdup("-");
    217 
    218 		evbuffer_add_vprintf(cf->buffer, fmt, ap);
    219 
    220 		msg.stream = 1;
    221 		msg.fd = STDOUT_FILENO;
    222 		msg.flags = 0;
    223 		proc_send(c->peer, MSG_WRITE_OPEN, -1, &msg, sizeof msg);
    224 	} else {
    225 		evbuffer_add_vprintf(cf->buffer, fmt, ap);
    226 		file_push(cf);
    227 	}
    228 }
    229 
    230 /* Print a buffer to a file. */
    231 void
    232 file_print_buffer(struct client *c, void *data, size_t size)
    233 {
    234 	struct client_file	 find, *cf;
    235 	struct msg_write_open	 msg;
    236 
    237 	if (!file_can_print(c))
    238 		return;
    239 
    240 	find.stream = 1;
    241 	if ((cf = RB_FIND(client_files, &c->files, &find)) == NULL) {
    242 		cf = file_create_with_client(c, 1, NULL, NULL);
    243 		cf->path = xstrdup("-");
    244 
    245 		evbuffer_add(cf->buffer, data, size);
    246 
    247 		msg.stream = 1;
    248 		msg.fd = STDOUT_FILENO;
    249 		msg.flags = 0;
    250 		proc_send(c->peer, MSG_WRITE_OPEN, -1, &msg, sizeof msg);
    251 	} else {
    252 		evbuffer_add(cf->buffer, data, size);
    253 		file_push(cf);
    254 	}
    255 }
    256 
    257 /* Report an error to a file. */
    258 void
    259 file_error(struct client *c, const char *fmt, ...)
    260 {
    261 	struct client_file	 find, *cf;
    262 	struct msg_write_open	 msg;
    263 	va_list			 ap;
    264 
    265 	if (!file_can_print(c))
    266 		return;
    267 
    268 	va_start(ap, fmt);
    269 
    270 	find.stream = 2;
    271 	if ((cf = RB_FIND(client_files, &c->files, &find)) == NULL) {
    272 		cf = file_create_with_client(c, 2, NULL, NULL);
    273 		cf->path = xstrdup("-");
    274 
    275 		evbuffer_add_vprintf(cf->buffer, fmt, ap);
    276 
    277 		msg.stream = 2;
    278 		msg.fd = STDERR_FILENO;
    279 		msg.flags = 0;
    280 		proc_send(c->peer, MSG_WRITE_OPEN, -1, &msg, sizeof msg);
    281 	} else {
    282 		evbuffer_add_vprintf(cf->buffer, fmt, ap);
    283 		file_push(cf);
    284 	}
    285 
    286 	va_end(ap);
    287 }
    288 
    289 /* Write data to a file. */
    290 void
    291 file_write(struct client *c, const char *path, int flags, const void *bdata,
    292     size_t bsize, client_file_cb cb, void *cbdata)
    293 {
    294 	struct client_file	*cf;
    295 	struct msg_write_open	*msg;
    296 	size_t			 msglen;
    297 	int			 fd = -1;
    298 	u_int			 stream = file_next_stream++;
    299 	FILE			*f;
    300 	const char		*mode;
    301 
    302 	if (strcmp(path, "-") == 0) {
    303 		cf = file_create_with_client(c, stream, cb, cbdata);
    304 		cf->path = xstrdup("-");
    305 
    306 		fd = STDOUT_FILENO;
    307 		if (c == NULL ||
    308 		    (c->flags & CLIENT_ATTACHED) ||
    309 		    (c->flags & CLIENT_CONTROL)) {
    310 			cf->error = EBADF;
    311 			goto done;
    312 		}
    313 		goto skip;
    314 	}
    315 
    316 	cf = file_create_with_client(c, stream, cb, cbdata);
    317 	cf->path = file_get_path(c, path);
    318 
    319 	if (c == NULL || c->flags & CLIENT_ATTACHED) {
    320 		if (flags & O_APPEND)
    321 			mode = "ab";
    322 		else
    323 			mode = "wb";
    324 		f = fopen(cf->path, mode);
    325 		if (f == NULL) {
    326 			cf->error = errno;
    327 			goto done;
    328 		}
    329 		if (fwrite(bdata, 1, bsize, f) != bsize) {
    330 			fclose(f);
    331 			cf->error = EIO;
    332 			goto done;
    333 		}
    334 		fclose(f);
    335 		goto done;
    336 	}
    337 
    338 skip:
    339 	evbuffer_add(cf->buffer, bdata, bsize);
    340 
    341 	msglen = strlen(cf->path) + 1 + sizeof *msg;
    342 	if (msglen > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
    343 		cf->error = E2BIG;
    344 		goto done;
    345 	}
    346 	msg = xmalloc(msglen);
    347 	msg->stream = cf->stream;
    348 	msg->fd = fd;
    349 	msg->flags = flags;
    350 	memcpy(msg + 1, cf->path, msglen - sizeof *msg);
    351 	if (proc_send(cf->peer, MSG_WRITE_OPEN, -1, msg, msglen) != 0) {
    352 		free(msg);
    353 		cf->error = EINVAL;
    354 		goto done;
    355 	}
    356 	free(msg);
    357 	return;
    358 
    359 done:
    360 	file_fire_done(cf);
    361 }
    362 
    363 /* Read a file. */
    364 struct client_file *
    365 file_read(struct client *c, const char *path, client_file_cb cb, void *cbdata)
    366 {
    367 	struct client_file	*cf;
    368 	struct msg_read_open	*msg;
    369 	size_t			 msglen;
    370 	int			 fd = -1;
    371 	u_int			 stream = file_next_stream++;
    372 	FILE			*f = NULL;
    373 	size_t			 size;
    374 	char			 buffer[BUFSIZ];
    375 
    376 	if (strcmp(path, "-") == 0) {
    377 		cf = file_create_with_client(c, stream, cb, cbdata);
    378 		cf->path = xstrdup("-");
    379 
    380 		fd = STDIN_FILENO;
    381 		if (c == NULL ||
    382 		    (c->flags & CLIENT_ATTACHED) ||
    383 		    (c->flags & CLIENT_CONTROL)) {
    384 			cf->error = EBADF;
    385 			goto done;
    386 		}
    387 		goto skip;
    388 	}
    389 
    390 	cf = file_create_with_client(c, stream, cb, cbdata);
    391 	cf->path = file_get_path(c, path);
    392 
    393 	if (c == NULL || c->flags & CLIENT_ATTACHED) {
    394 		f = fopen(cf->path, "rb");
    395 		if (f == NULL) {
    396 			cf->error = errno;
    397 			goto done;
    398 		}
    399 		for (;;) {
    400 			size = fread(buffer, 1, sizeof buffer, f);
    401 			if (evbuffer_add(cf->buffer, buffer, size) != 0) {
    402 				cf->error = ENOMEM;
    403 				goto done;
    404 			}
    405 			if (size != sizeof buffer)
    406 				break;
    407 		}
    408 		if (ferror(f)) {
    409 			cf->error = EIO;
    410 			goto done;
    411 		}
    412 		goto done;
    413 	}
    414 
    415 skip:
    416 	msglen = strlen(cf->path) + 1 + sizeof *msg;
    417 	if (msglen > MAX_IMSGSIZE - IMSG_HEADER_SIZE) {
    418 		cf->error = E2BIG;
    419 		goto done;
    420 	}
    421 	msg = xmalloc(msglen);
    422 	msg->stream = cf->stream;
    423 	msg->fd = fd;
    424 	memcpy(msg + 1, cf->path, msglen - sizeof *msg);
    425 	if (proc_send(cf->peer, MSG_READ_OPEN, -1, msg, msglen) != 0) {
    426 		free(msg);
    427 		cf->error = EINVAL;
    428 		goto done;
    429 	}
    430 	free(msg);
    431 	return cf;
    432 
    433 done:
    434 	if (f != NULL)
    435 		fclose(f);
    436 	file_fire_done(cf);
    437 	return NULL;
    438 }
    439 
    440 /* Cancel a file read. */
    441 void
    442 file_cancel(struct client_file *cf)
    443 {
    444 	struct msg_read_cancel	 msg;
    445 
    446 	log_debug("read cancel file %d", cf->stream);
    447 
    448 	if (cf->closed)
    449 		return;
    450 	cf->closed = 1;
    451 
    452 	msg.stream = cf->stream;
    453 	proc_send(cf->peer, MSG_READ_CANCEL, -1, &msg, sizeof msg);
    454 }
    455 
    456 /* Push event, fired if there is more writing to be done. */
    457 static void
    458 file_push_cb(__unused int fd, __unused short events, void *arg)
    459 {
    460 	struct client_file	*cf = arg;
    461 
    462 	if (cf->c == NULL || ~cf->c->flags & CLIENT_DEAD)
    463 		file_push(cf);
    464 	file_free(cf);
    465 }
    466 
    467 /* Push uwritten data to the client for a file, if it will accept it. */
    468 void
    469 file_push(struct client_file *cf)
    470 {
    471 	struct msg_write_data	*msg;
    472 	size_t			 msglen, sent, left;
    473 	struct msg_write_close	 close;
    474 
    475 	msg = xmalloc(sizeof *msg);
    476 	left = EVBUFFER_LENGTH(cf->buffer);
    477 	while (left != 0) {
    478 		sent = left;
    479 		if (sent > MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof *msg)
    480 			sent = MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof *msg;
    481 
    482 		msglen = (sizeof *msg) + sent;
    483 		msg = xrealloc(msg, msglen);
    484 		msg->stream = cf->stream;
    485 		memcpy(msg + 1, EVBUFFER_DATA(cf->buffer), sent);
    486 		if (proc_send(cf->peer, MSG_WRITE, -1, msg, msglen) != 0)
    487 			break;
    488 		evbuffer_drain(cf->buffer, sent);
    489 
    490 		left = EVBUFFER_LENGTH(cf->buffer);
    491 		log_debug("file %d sent %zu, left %zu", cf->stream, sent, left);
    492 	}
    493 	if (left != 0) {
    494 		cf->references++;
    495 		event_once(-1, EV_TIMEOUT, file_push_cb, cf, NULL);
    496 	} else if (cf->stream > 2) {
    497 		close.stream = cf->stream;
    498 		proc_send(cf->peer, MSG_WRITE_CLOSE, -1, &close, sizeof close);
    499 		file_fire_done(cf);
    500 	}
    501 	free(msg);
    502 }
    503 
    504 /* Check if any files have data left to write. */
    505 int
    506 file_write_left(struct client_files *files)
    507 {
    508 	struct client_file	*cf;
    509 	size_t			 left;
    510 	int			 waiting = 0;
    511 
    512 	RB_FOREACH(cf, client_files, files) {
    513 		if (cf->event == NULL)
    514 			continue;
    515 		left = EVBUFFER_LENGTH(cf->event->output);
    516 		if (left != 0) {
    517 			waiting++;
    518 			log_debug("file %u %zu bytes left", cf->stream, left);
    519 		}
    520 	}
    521 	return (waiting != 0);
    522 }
    523 
    524 /* Client file write error callback. */
    525 static void
    526 file_write_error_callback(__unused struct bufferevent *bev, __unused short what,
    527     void *arg)
    528 {
    529 	struct client_file	*cf = arg;
    530 
    531 	log_debug("write error file %d", cf->stream);
    532 
    533 	bufferevent_free(cf->event);
    534 	cf->event = NULL;
    535 
    536 	close(cf->fd);
    537 	cf->fd = -1;
    538 
    539 	if (cf->cb != NULL)
    540 		cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
    541 }
    542 
    543 /* Client file write callback. */
    544 static void
    545 file_write_callback(__unused struct bufferevent *bev, void *arg)
    546 {
    547 	struct client_file	*cf = arg;
    548 
    549 	log_debug("write check file %d", cf->stream);
    550 
    551 	if (cf->cb != NULL)
    552 		cf->cb(NULL, NULL, 0, -1, NULL, cf->data);
    553 
    554 	if (cf->closed && EVBUFFER_LENGTH(cf->event->output) == 0) {
    555 		bufferevent_free(cf->event);
    556 		close(cf->fd);
    557 		RB_REMOVE(client_files, cf->tree, cf);
    558 		file_free(cf);
    559 	}
    560 }
    561 
    562 /* Handle a file write open message (client). */
    563 void
    564 file_write_open(struct client_files *files, struct tmuxpeer *peer,
    565     struct imsg *imsg, int allow_streams, int close_received,
    566     client_file_cb cb, void *cbdata)
    567 {
    568 	struct msg_write_open	*msg = imsg->data;
    569 	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
    570 	const char		*path;
    571 	struct msg_write_ready	 reply;
    572 	struct client_file	 find, *cf;
    573 	const int		 flags = O_NONBLOCK|O_WRONLY|O_CREAT;
    574 	int			 error = 0;
    575 
    576 	if (msglen < sizeof *msg)
    577 		fatalx("bad MSG_WRITE_OPEN size");
    578 	if (msglen == sizeof *msg)
    579 		path = "-";
    580 	else
    581 		path = (const char *)(msg + 1);
    582 	log_debug("open write file %d %s", msg->stream, path);
    583 
    584 	find.stream = msg->stream;
    585 	if (RB_FIND(client_files, files, &find) != NULL) {
    586 		error = EBADF;
    587 		goto reply;
    588 	}
    589 	cf = file_create_with_peer(peer, files, msg->stream, cb, cbdata);
    590 	if (cf->closed) {
    591 		error = EBADF;
    592 		goto reply;
    593 	}
    594 
    595 	cf->fd = -1;
    596 	if (msg->fd == -1)
    597 		cf->fd = open(path, msg->flags|flags, 0644);
    598 	else if (allow_streams) {
    599 		if (msg->fd != STDOUT_FILENO && msg->fd != STDERR_FILENO)
    600 			errno = EBADF;
    601 		else {
    602 			cf->fd = dup(msg->fd);
    603 			if (close_received)
    604 				close(msg->fd); /* can only be used once */
    605 		}
    606 	} else
    607 	      errno = EBADF;
    608 	if (cf->fd == -1) {
    609 		error = errno;
    610 		goto reply;
    611 	}
    612 
    613 	cf->event = bufferevent_new(cf->fd, NULL, file_write_callback,
    614 	    file_write_error_callback, cf);
    615 	if (cf->event == NULL)
    616 		fatalx("out of memory");
    617 	bufferevent_enable(cf->event, EV_WRITE);
    618 	goto reply;
    619 
    620 reply:
    621 	reply.stream = msg->stream;
    622 	reply.error = error;
    623 	proc_send(peer, MSG_WRITE_READY, -1, &reply, sizeof reply);
    624 }
    625 
    626 /* Handle a file write data message (client). */
    627 void
    628 file_write_data(struct client_files *files, struct imsg *imsg)
    629 {
    630 	struct msg_write_data	*msg = imsg->data;
    631 	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
    632 	struct client_file	 find, *cf;
    633 	size_t			 size = msglen - sizeof *msg;
    634 
    635 	if (msglen < sizeof *msg)
    636 		fatalx("bad MSG_WRITE size");
    637 	find.stream = msg->stream;
    638 	if ((cf = RB_FIND(client_files, files, &find)) == NULL)
    639 		fatalx("unknown stream number");
    640 	log_debug("write %zu to file %d", size, cf->stream);
    641 
    642 	if (cf->event != NULL)
    643 		bufferevent_write(cf->event, msg + 1, size);
    644 }
    645 
    646 /* Handle a file write close message (client). */
    647 void
    648 file_write_close(struct client_files *files, struct imsg *imsg)
    649 {
    650 	struct msg_write_close	*msg = imsg->data;
    651 	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
    652 	struct client_file	 find, *cf;
    653 
    654 	if (msglen != sizeof *msg)
    655 		fatalx("bad MSG_WRITE_CLOSE size");
    656 	find.stream = msg->stream;
    657 	if ((cf = RB_FIND(client_files, files, &find)) == NULL)
    658 		fatalx("unknown stream number");
    659 	log_debug("close file %d", cf->stream);
    660 
    661 	if (cf->event == NULL || EVBUFFER_LENGTH(cf->event->output) == 0) {
    662 		if (cf->event != NULL)
    663 			bufferevent_free(cf->event);
    664 		if (cf->fd != -1)
    665 			close(cf->fd);
    666 		RB_REMOVE(client_files, files, cf);
    667 		file_free(cf);
    668 	}
    669 }
    670 
    671 /* Client file read error callback. */
    672 static void
    673 file_read_error_callback(__unused struct bufferevent *bev, __unused short what,
    674     void *arg)
    675 {
    676 	struct client_file	*cf = arg;
    677 	struct msg_read_done	 msg;
    678 
    679 	log_debug("read error file %d", cf->stream);
    680 
    681 	msg.stream = cf->stream;
    682 	msg.error = 0;
    683 	proc_send(cf->peer, MSG_READ_DONE, -1, &msg, sizeof msg);
    684 
    685 	bufferevent_free(cf->event);
    686 	close(cf->fd);
    687 	RB_REMOVE(client_files, cf->tree, cf);
    688 	file_free(cf);
    689 }
    690 
    691 /* Client file read callback. */
    692 static void
    693 file_read_callback(__unused struct bufferevent *bev, void *arg)
    694 {
    695 	struct client_file	*cf = arg;
    696 	void			*bdata;
    697 	size_t			 bsize;
    698 	struct msg_read_data	*msg;
    699 	size_t			 msglen;
    700 
    701 	msg = xmalloc(sizeof *msg);
    702 	for (;;) {
    703 		bdata = EVBUFFER_DATA(cf->event->input);
    704 		bsize = EVBUFFER_LENGTH(cf->event->input);
    705 
    706 		if (bsize == 0)
    707 			break;
    708 		if (bsize > MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof *msg)
    709 			bsize = MAX_IMSGSIZE - IMSG_HEADER_SIZE - sizeof *msg;
    710 		log_debug("read %zu from file %d", bsize, cf->stream);
    711 
    712 		msglen = (sizeof *msg) + bsize;
    713 		msg = xrealloc(msg, msglen);
    714 		msg->stream = cf->stream;
    715 		memcpy(msg + 1, bdata, bsize);
    716 		proc_send(cf->peer, MSG_READ, -1, msg, msglen);
    717 
    718 		evbuffer_drain(cf->event->input, bsize);
    719 	}
    720 	free(msg);
    721 }
    722 
    723 /* Handle a file read open message (client). */
    724 void
    725 file_read_open(struct client_files *files, struct tmuxpeer *peer,
    726     struct imsg *imsg, int allow_streams, int close_received, client_file_cb cb,
    727     void *cbdata)
    728 {
    729 	struct msg_read_open	*msg = imsg->data;
    730 	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
    731 	const char		*path;
    732 	struct msg_read_done	 reply;
    733 	struct client_file	 find, *cf;
    734 	const int		 flags = O_NONBLOCK|O_RDONLY;
    735 	int			 error;
    736 
    737 	if (msglen < sizeof *msg)
    738 		fatalx("bad MSG_READ_OPEN size");
    739 	if (msglen == sizeof *msg)
    740 		path = "-";
    741 	else
    742 		path = (const char *)(msg + 1);
    743 	log_debug("open read file %d %s", msg->stream, path);
    744 
    745 	find.stream = msg->stream;
    746 	if (RB_FIND(client_files, files, &find) != NULL) {
    747 		error = EBADF;
    748 		goto reply;
    749 	}
    750 	cf = file_create_with_peer(peer, files, msg->stream, cb, cbdata);
    751 	if (cf->closed) {
    752 		error = EBADF;
    753 		goto reply;
    754 	}
    755 
    756 	cf->fd = -1;
    757 	if (msg->fd == -1)
    758 		cf->fd = open(path, flags);
    759 	else if (allow_streams) {
    760 		if (msg->fd != STDIN_FILENO)
    761 			errno = EBADF;
    762 		else {
    763 			cf->fd = dup(msg->fd);
    764 			if (close_received)
    765 				close(msg->fd); /* can only be used once */
    766 		}
    767 	} else
    768 		errno = EBADF;
    769 	if (cf->fd == -1) {
    770 		error = errno;
    771 		goto reply;
    772 	}
    773 
    774 	cf->event = bufferevent_new(cf->fd, file_read_callback, NULL,
    775 	    file_read_error_callback, cf);
    776 	if (cf->event == NULL)
    777 		fatalx("out of memory");
    778 	bufferevent_enable(cf->event, EV_READ);
    779 	return;
    780 
    781 reply:
    782 	reply.stream = msg->stream;
    783 	reply.error = error;
    784 	proc_send(peer, MSG_READ_DONE, -1, &reply, sizeof reply);
    785 }
    786 
    787 /* Handle a read cancel message (client). */
    788 void
    789 file_read_cancel(struct client_files *files, struct imsg *imsg)
    790 {
    791 	struct msg_read_cancel	*msg = imsg->data;
    792 	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
    793 	struct client_file	 find, *cf;
    794 
    795 	if (msglen != sizeof *msg)
    796 		fatalx("bad MSG_READ_CANCEL size");
    797 	find.stream = msg->stream;
    798 	if ((cf = RB_FIND(client_files, files, &find)) == NULL)
    799 		fatalx("unknown stream number");
    800 	log_debug("cancel file %d", cf->stream);
    801 
    802 	file_read_error_callback(NULL, 0, cf);
    803 }
    804 
    805 /* Handle a write ready message (server). */
    806 void
    807 file_write_ready(struct client_files *files, struct imsg *imsg)
    808 {
    809 	struct msg_write_ready	*msg = imsg->data;
    810 	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
    811 	struct client_file	 find, *cf;
    812 
    813 	if (msglen != sizeof *msg)
    814 		fatalx("bad MSG_WRITE_READY size");
    815 	find.stream = msg->stream;
    816 	if ((cf = RB_FIND(client_files, files, &find)) == NULL)
    817 		return;
    818 	if (msg->error != 0) {
    819 		cf->error = msg->error;
    820 		file_fire_done(cf);
    821 	} else
    822 		file_push(cf);
    823 }
    824 
    825 /* Handle read data message (server). */
    826 void
    827 file_read_data(struct client_files *files, struct imsg *imsg)
    828 {
    829 	struct msg_read_data	*msg = imsg->data;
    830 	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
    831 	struct client_file	 find, *cf;
    832 	void			*bdata = msg + 1;
    833 	size_t			 bsize = msglen - sizeof *msg;
    834 
    835 	if (msglen < sizeof *msg)
    836 		fatalx("bad MSG_READ_DATA size");
    837 	find.stream = msg->stream;
    838 	if ((cf = RB_FIND(client_files, files, &find)) == NULL)
    839 		return;
    840 
    841 	log_debug("file %d read %zu bytes", cf->stream, bsize);
    842 	if (cf->error == 0 && !cf->closed) {
    843 		if (evbuffer_add(cf->buffer, bdata, bsize) != 0) {
    844 			cf->error = ENOMEM;
    845 			file_fire_done(cf);
    846 		} else
    847 			file_fire_read(cf);
    848 	}
    849 }
    850 
    851 /* Handle a read done message (server). */
    852 void
    853 file_read_done(struct client_files *files, struct imsg *imsg)
    854 {
    855 	struct msg_read_done	*msg = imsg->data;
    856 	size_t			 msglen = imsg->hdr.len - IMSG_HEADER_SIZE;
    857 	struct client_file	 find, *cf;
    858 
    859 	if (msglen != sizeof *msg)
    860 		fatalx("bad MSG_READ_DONE size");
    861 	find.stream = msg->stream;
    862 	if ((cf = RB_FIND(client_files, files, &find)) == NULL)
    863 		return;
    864 
    865 	log_debug("file %d read done", cf->stream);
    866 	cf->error = msg->error;
    867 	file_fire_done(cf);
    868 }
    869