version 1.46, 2019/06/13 21:44:13 |
version 1.47, 2019/12/12 11:39:56 |
|
|
.exec = cmd_save_buffer_exec |
.exec = cmd_save_buffer_exec |
}; |
}; |
|
|
|
static void |
|
cmd_save_buffer_done(__unused struct client *c, const char *path, int error, |
|
__unused int closed, __unused struct evbuffer *buffer, void *data) |
|
{ |
|
struct cmdq_item *item = data; |
|
|
|
if (!closed) |
|
return; |
|
|
|
if (error != 0) |
|
cmdq_error(item, "%s: %s", path, strerror(error)); |
|
cmdq_continue(item); |
|
} |
|
|
static enum cmd_retval |
static enum cmd_retval |
cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item) |
cmd_save_buffer_exec(struct cmd *self, struct cmdq_item *item) |
{ |
{ |
|
|
struct winlink *wl = item->target.wl; |
struct winlink *wl = item->target.wl; |
struct window_pane *wp = item->target.wp; |
struct window_pane *wp = item->target.wp; |
struct paste_buffer *pb; |
struct paste_buffer *pb; |
const char *bufname, *bufdata, *start, *end, *flags; |
int flags; |
char *msg, *path, *file; |
const char *bufname = args_get(args, 'b'), *bufdata; |
size_t size, used, msglen, bufsize; |
size_t bufsize; |
FILE *f; |
char *path; |
|
|
if (!args_has(args, 'b')) { |
if (bufname == NULL) { |
if ((pb = paste_get_top(NULL)) == NULL) { |
if ((pb = paste_get_top(NULL)) == NULL) { |
cmdq_error(item, "no buffers"); |
cmdq_error(item, "no buffers"); |
return (CMD_RETURN_ERROR); |
return (CMD_RETURN_ERROR); |
} |
} |
} else { |
} else { |
bufname = args_get(args, 'b'); |
|
pb = paste_get_name(bufname); |
pb = paste_get_name(bufname); |
if (pb == NULL) { |
if (pb == NULL) { |
cmdq_error(item, "no buffer %s", bufname); |
cmdq_error(item, "no buffer %s", bufname); |
|
|
path = xstrdup("-"); |
path = xstrdup("-"); |
else |
else |
path = format_single(item, args->argv[0], c, s, wl, wp); |
path = format_single(item, args->argv[0], c, s, wl, wp); |
if (strcmp(path, "-") == 0) { |
|
free(path); |
|
c = item->client; |
|
if (c == NULL) { |
|
cmdq_error(item, "can't write to stdout"); |
|
return (CMD_RETURN_ERROR); |
|
} |
|
if (c->session == NULL || (c->flags & CLIENT_CONTROL)) |
|
goto do_stdout; |
|
goto do_print; |
|
} |
|
|
|
flags = "wb"; |
|
if (args_has(self->args, 'a')) |
if (args_has(self->args, 'a')) |
flags = "ab"; |
flags = O_APPEND; |
|
else |
file = server_client_get_path(item->client, path); |
flags = 0; |
|
file_write(item->client, path, flags, bufdata, bufsize, |
|
cmd_save_buffer_done, item); |
free(path); |
free(path); |
|
|
f = fopen(file, flags); |
return (CMD_RETURN_WAIT); |
if (f == NULL) { |
|
cmdq_error(item, "%s: %s", file, strerror(errno)); |
|
free(file); |
|
return (CMD_RETURN_ERROR); |
|
} |
|
|
|
if (fwrite(bufdata, 1, bufsize, f) != bufsize) { |
|
cmdq_error(item, "%s: write error", file); |
|
fclose(f); |
|
free(file); |
|
return (CMD_RETURN_ERROR); |
|
} |
|
|
|
fclose(f); |
|
free(file); |
|
|
|
return (CMD_RETURN_NORMAL); |
|
|
|
do_stdout: |
|
evbuffer_add(c->stdout_data, bufdata, bufsize); |
|
server_client_push_stdout(c); |
|
return (CMD_RETURN_NORMAL); |
|
|
|
do_print: |
|
if (bufsize > (INT_MAX / 4) - 1) { |
|
cmdq_error(item, "buffer too big"); |
|
return (CMD_RETURN_ERROR); |
|
} |
|
msg = NULL; |
|
|
|
used = 0; |
|
while (used != bufsize) { |
|
start = bufdata + used; |
|
end = memchr(start, '\n', bufsize - used); |
|
if (end != NULL) |
|
size = end - start; |
|
else |
|
size = bufsize - used; |
|
|
|
msglen = size * 4 + 1; |
|
msg = xrealloc(msg, msglen); |
|
|
|
strvisx(msg, start, size, VIS_OCTAL|VIS_TAB); |
|
cmdq_print(item, "%s", msg); |
|
|
|
used += size + (end != NULL); |
|
} |
|
|
|
free(msg); |
|
return (CMD_RETURN_NORMAL); |
|
} |
} |