diff options
Diffstat (limited to 'cmd-load-buffer.c')
-rw-r--r-- | cmd-load-buffer.c | 108 |
1 files changed, 87 insertions, 21 deletions
diff --git a/cmd-load-buffer.c b/cmd-load-buffer.c index 0f118490..e28b9c74 100644 --- a/cmd-load-buffer.c +++ b/cmd-load-buffer.c @@ -31,6 +31,7 @@ */ int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *); +void cmd_load_buffer_callback(struct client *, void *); const struct cmd_entry cmd_load_buffer_entry = { "load-buffer", "loadb", @@ -43,37 +44,55 @@ const struct cmd_entry cmd_load_buffer_entry = { cmd_buffer_print }; +struct cmd_load_buffer_cdata { + struct session *session; + int buffer; +}; + int cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { - struct cmd_buffer_data *data = self->data; - struct session *s; - FILE *f, *close_f; - char *pdata, *new_pdata; - size_t psize; - u_int limit; - int ch; + struct cmd_buffer_data *data = self->data; + struct cmd_load_buffer_cdata *cdata; + struct session *s; + struct client *c = ctx->cmdclient; + FILE *f; + char *pdata, *new_pdata; + size_t psize; + u_int limit; + int ch; if ((s = cmd_find_session(ctx, data->target)) == NULL) return (-1); - if (strcmp(data->arg, "-") == 0 ) { - if (ctx->cmdclient == NULL) { + if (strcmp(data->arg, "-") == 0) { + if (c == NULL) { ctx->error(ctx, "%s: can't read from stdin", data->arg); return (-1); } - f = ctx->cmdclient->stdin_file; - if (isatty(fileno(ctx->cmdclient->stdin_file))) { + if (c->flags & CLIENT_TERMINAL) { ctx->error(ctx, "%s: stdin is a tty", data->arg); return (-1); } - close_f = NULL; - } else { - if ((f = fopen(data->arg, "rb")) == NULL) { - ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); + if (c->stdin_fd == -1) { + ctx->error(ctx, "%s: can't read from stdin", data->arg); return (-1); } - close_f = f; + + cdata = xmalloc(sizeof *cdata); + cdata->session = s; + cdata->buffer = data->buffer; + c->stdin_data = cdata; + c->stdin_callback = cmd_load_buffer_callback; + + c->references++; + bufferevent_enable(c->stdin_event, EV_READ); + return (1); + } + + if ((f = fopen(data->arg, "rb")) == NULL) { + ctx->error(ctx, "%s: %s", data->arg, strerror(errno)); + return (-1); } pdata = NULL; @@ -94,8 +113,8 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) if (pdata != NULL) pdata[psize] = '\0'; - if (close_f != NULL) - fclose(close_f); + fclose(f); + f = NULL; limit = options_get_number(&s->options, "buffer-limit"); if (data->buffer == -1) { @@ -104,7 +123,7 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) } if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) { ctx->error(ctx, "no buffer %d", data->buffer); - goto error; + return (-1); } return (0); @@ -112,7 +131,54 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) error: if (pdata != NULL) xfree(pdata); - if (close_f != NULL) - fclose(close_f); + if (f != NULL) + fclose(f); return (-1); } + +void +cmd_load_buffer_callback(struct client *c, void *data) +{ + struct cmd_load_buffer_cdata *cdata = data; + struct session *s = cdata->session; + char *pdata; + size_t psize; + u_int limit; + int idx; + + /* + * Event callback has already checked client is not dead and reduced + * its reference count. But tell it to exit. + */ + c->flags |= CLIENT_EXIT; + + /* Does the target session still exist? */ + if (session_index(s, &idx) != 0) + goto out; + + psize = EVBUFFER_LENGTH(c->stdin_event->input); + if (psize == 0) + goto out; + + pdata = malloc(psize + 1); + if (pdata == NULL) + goto out; + bufferevent_read(c->stdin_event, pdata, psize); + pdata[psize] = '\0'; + + limit = options_get_number(&s->options, "buffer-limit"); + if (cdata->buffer == -1) { + paste_add(&s->buffers, pdata, psize, limit); + goto out; + } + if (paste_replace(&s->buffers, cdata->buffer, pdata, psize) != 0) { + /* No context so can't use server_client_msg_error. */ + evbuffer_add_printf( + c->stderr_event->output, "no buffer %d\n", cdata->buffer); + bufferevent_enable(c->stderr_event, EV_WRITE); + goto out; + } + +out: + xfree(cdata); +} |