1 /* $OpenBSD: cmd-load-buffer.c,v 1.64 2021/08/21 10:22:39 nicm Exp $ */ 2 3 /* 4 * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> 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 * Loads a paste buffer from a file. 32 */ 33 34 static enum cmd_retval cmd_load_buffer_exec(struct cmd *, struct cmdq_item *); 35 36 const struct cmd_entry cmd_load_buffer_entry = { 37 .name = "load-buffer", 38 .alias = "loadb", 39 40 .args = { "b:t:w", 1, 1, NULL }, 41 .usage = CMD_BUFFER_USAGE " " CMD_TARGET_CLIENT_USAGE " path", 42 43 .flags = CMD_AFTERHOOK|CMD_CLIENT_TFLAG|CMD_CLIENT_CANFAIL, 44 .exec = cmd_load_buffer_exec 45 }; 46 47 struct cmd_load_buffer_data { 48 struct client *client; 49 struct cmdq_item *item; 50 char *name; 51 }; 52 53 static void 54 cmd_load_buffer_done(__unused struct client *c, const char *path, int error, 55 int closed, struct evbuffer *buffer, void *data) 56 { 57 struct cmd_load_buffer_data *cdata = data; 58 struct client *tc = cdata->client; 59 struct cmdq_item *item = cdata->item; 60 void *bdata = EVBUFFER_DATA(buffer); 61 size_t bsize = EVBUFFER_LENGTH(buffer); 62 void *copy; 63 char *cause; 64 65 if (!closed) 66 return; 67 68 if (error != 0) 69 cmdq_error(item, "%s: %s", path, strerror(error)); 70 else if (bsize != 0) { 71 copy = xmalloc(bsize); 72 memcpy(copy, bdata, bsize); 73 if (paste_set(copy, bsize, cdata->name, &cause) != 0) { 74 cmdq_error(item, "%s", cause); 75 free(cause); 76 free(copy); 77 } else if (tc != NULL && 78 tc->session != NULL && 79 (~tc->flags & CLIENT_DEAD)) 80 tty_set_selection(&tc->tty, copy, bsize); 81 if (tc != NULL) 82 server_client_unref(tc); 83 } 84 cmdq_continue(item); 85 86 free(cdata->name); 87 free(cdata); 88 } 89 90 static enum cmd_retval 91 cmd_load_buffer_exec(struct cmd *self, struct cmdq_item *item) 92 { 93 struct args *args = cmd_get_args(self); 94 struct client *tc = cmdq_get_target_client(item); 95 struct cmd_load_buffer_data *cdata; 96 const char *bufname = args_get(args, 'b'); 97 char *path; 98 99 cdata = xcalloc(1, sizeof *cdata); 100 cdata->item = item; 101 if (bufname != NULL) 102 cdata->name = xstrdup(bufname); 103 if (args_has(args, 'w') && tc != NULL) { 104 cdata->client = tc; 105 cdata->client->references++; 106 } 107 108 path = format_single_from_target(item, args_string(args, 0)); 109 file_read(cmdq_get_client(item), path, cmd_load_buffer_done, cdata); 110 free(path); 111 112 return (CMD_RETURN_WAIT); 113 } 114