1*eda6f593SDavid van Moolenbroek /* $Id: cmd-load-buffer.c,v 1.1.1.2 2011/08/17 18:40:04 jmmv Exp $ */ 2*eda6f593SDavid van Moolenbroek 3*eda6f593SDavid van Moolenbroek /* 4*eda6f593SDavid van Moolenbroek * Copyright (c) 2009 Tiago Cunha <me@tiagocunha.org> 5*eda6f593SDavid van Moolenbroek * 6*eda6f593SDavid van Moolenbroek * Permission to use, copy, modify, and distribute this software for any 7*eda6f593SDavid van Moolenbroek * purpose with or without fee is hereby granted, provided that the above 8*eda6f593SDavid van Moolenbroek * copyright notice and this permission notice appear in all copies. 9*eda6f593SDavid van Moolenbroek * 10*eda6f593SDavid van Moolenbroek * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11*eda6f593SDavid van Moolenbroek * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12*eda6f593SDavid van Moolenbroek * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13*eda6f593SDavid van Moolenbroek * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14*eda6f593SDavid van Moolenbroek * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER 15*eda6f593SDavid van Moolenbroek * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING 16*eda6f593SDavid van Moolenbroek * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17*eda6f593SDavid van Moolenbroek */ 18*eda6f593SDavid van Moolenbroek 19*eda6f593SDavid van Moolenbroek #include <sys/types.h> 20*eda6f593SDavid van Moolenbroek 21*eda6f593SDavid van Moolenbroek #include <errno.h> 22*eda6f593SDavid van Moolenbroek #include <stdio.h> 23*eda6f593SDavid van Moolenbroek #include <stdlib.h> 24*eda6f593SDavid van Moolenbroek #include <string.h> 25*eda6f593SDavid van Moolenbroek #include <unistd.h> 26*eda6f593SDavid van Moolenbroek 27*eda6f593SDavid van Moolenbroek #include "tmux.h" 28*eda6f593SDavid van Moolenbroek 29*eda6f593SDavid van Moolenbroek /* 30*eda6f593SDavid van Moolenbroek * Loads a session paste buffer from a file. 31*eda6f593SDavid van Moolenbroek */ 32*eda6f593SDavid van Moolenbroek 33*eda6f593SDavid van Moolenbroek int cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *); 34*eda6f593SDavid van Moolenbroek void cmd_load_buffer_callback(struct client *, void *); 35*eda6f593SDavid van Moolenbroek 36*eda6f593SDavid van Moolenbroek const struct cmd_entry cmd_load_buffer_entry = { 37*eda6f593SDavid van Moolenbroek "load-buffer", "loadb", 38*eda6f593SDavid van Moolenbroek "b:", 1, 1, 39*eda6f593SDavid van Moolenbroek CMD_BUFFER_USAGE " path", 40*eda6f593SDavid van Moolenbroek 0, 41*eda6f593SDavid van Moolenbroek NULL, 42*eda6f593SDavid van Moolenbroek NULL, 43*eda6f593SDavid van Moolenbroek cmd_load_buffer_exec 44*eda6f593SDavid van Moolenbroek }; 45*eda6f593SDavid van Moolenbroek 46*eda6f593SDavid van Moolenbroek int 47*eda6f593SDavid van Moolenbroek cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) 48*eda6f593SDavid van Moolenbroek { 49*eda6f593SDavid van Moolenbroek struct args *args = self->args; 50*eda6f593SDavid van Moolenbroek struct client *c = ctx->cmdclient; 51*eda6f593SDavid van Moolenbroek FILE *f; 52*eda6f593SDavid van Moolenbroek const char *path; 53*eda6f593SDavid van Moolenbroek char *pdata, *new_pdata, *cause; 54*eda6f593SDavid van Moolenbroek size_t psize; 55*eda6f593SDavid van Moolenbroek u_int limit; 56*eda6f593SDavid van Moolenbroek int ch, buffer; 57*eda6f593SDavid van Moolenbroek int *buffer_ptr; 58*eda6f593SDavid van Moolenbroek 59*eda6f593SDavid van Moolenbroek if (!args_has(args, 'b')) 60*eda6f593SDavid van Moolenbroek buffer = -1; 61*eda6f593SDavid van Moolenbroek else { 62*eda6f593SDavid van Moolenbroek buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); 63*eda6f593SDavid van Moolenbroek if (cause != NULL) { 64*eda6f593SDavid van Moolenbroek ctx->error(ctx, "buffer %s", cause); 65*eda6f593SDavid van Moolenbroek xfree(cause); 66*eda6f593SDavid van Moolenbroek return (-1); 67*eda6f593SDavid van Moolenbroek } 68*eda6f593SDavid van Moolenbroek } 69*eda6f593SDavid van Moolenbroek 70*eda6f593SDavid van Moolenbroek path = args->argv[0]; 71*eda6f593SDavid van Moolenbroek if (strcmp(path, "-") == 0) { 72*eda6f593SDavid van Moolenbroek if (c == NULL) { 73*eda6f593SDavid van Moolenbroek ctx->error(ctx, "%s: can't read from stdin", path); 74*eda6f593SDavid van Moolenbroek return (-1); 75*eda6f593SDavid van Moolenbroek } 76*eda6f593SDavid van Moolenbroek if (c->flags & CLIENT_TERMINAL) { 77*eda6f593SDavid van Moolenbroek ctx->error(ctx, "%s: stdin is a tty", path); 78*eda6f593SDavid van Moolenbroek return (-1); 79*eda6f593SDavid van Moolenbroek } 80*eda6f593SDavid van Moolenbroek if (c->stdin_fd == -1) { 81*eda6f593SDavid van Moolenbroek ctx->error(ctx, "%s: can't read from stdin", path); 82*eda6f593SDavid van Moolenbroek return (-1); 83*eda6f593SDavid van Moolenbroek } 84*eda6f593SDavid van Moolenbroek 85*eda6f593SDavid van Moolenbroek buffer_ptr = xmalloc(sizeof *buffer_ptr); 86*eda6f593SDavid van Moolenbroek *buffer_ptr = buffer; 87*eda6f593SDavid van Moolenbroek 88*eda6f593SDavid van Moolenbroek c->stdin_data = buffer_ptr; 89*eda6f593SDavid van Moolenbroek c->stdin_callback = cmd_load_buffer_callback; 90*eda6f593SDavid van Moolenbroek 91*eda6f593SDavid van Moolenbroek c->references++; 92*eda6f593SDavid van Moolenbroek bufferevent_enable(c->stdin_event, EV_READ); 93*eda6f593SDavid van Moolenbroek return (1); 94*eda6f593SDavid van Moolenbroek } 95*eda6f593SDavid van Moolenbroek 96*eda6f593SDavid van Moolenbroek if ((f = fopen(path, "rb")) == NULL) { 97*eda6f593SDavid van Moolenbroek ctx->error(ctx, "%s: %s", path, strerror(errno)); 98*eda6f593SDavid van Moolenbroek return (-1); 99*eda6f593SDavid van Moolenbroek } 100*eda6f593SDavid van Moolenbroek 101*eda6f593SDavid van Moolenbroek pdata = NULL; 102*eda6f593SDavid van Moolenbroek psize = 0; 103*eda6f593SDavid van Moolenbroek while ((ch = getc(f)) != EOF) { 104*eda6f593SDavid van Moolenbroek /* Do not let the server die due to memory exhaustion. */ 105*eda6f593SDavid van Moolenbroek if ((new_pdata = realloc(pdata, psize + 2)) == NULL) { 106*eda6f593SDavid van Moolenbroek ctx->error(ctx, "realloc error: %s", strerror(errno)); 107*eda6f593SDavid van Moolenbroek goto error; 108*eda6f593SDavid van Moolenbroek } 109*eda6f593SDavid van Moolenbroek pdata = new_pdata; 110*eda6f593SDavid van Moolenbroek pdata[psize++] = ch; 111*eda6f593SDavid van Moolenbroek } 112*eda6f593SDavid van Moolenbroek if (ferror(f)) { 113*eda6f593SDavid van Moolenbroek ctx->error(ctx, "%s: read error", path); 114*eda6f593SDavid van Moolenbroek goto error; 115*eda6f593SDavid van Moolenbroek } 116*eda6f593SDavid van Moolenbroek if (pdata != NULL) 117*eda6f593SDavid van Moolenbroek pdata[psize] = '\0'; 118*eda6f593SDavid van Moolenbroek 119*eda6f593SDavid van Moolenbroek fclose(f); 120*eda6f593SDavid van Moolenbroek 121*eda6f593SDavid van Moolenbroek limit = options_get_number(&global_options, "buffer-limit"); 122*eda6f593SDavid van Moolenbroek if (buffer == -1) { 123*eda6f593SDavid van Moolenbroek paste_add(&global_buffers, pdata, psize, limit); 124*eda6f593SDavid van Moolenbroek return (0); 125*eda6f593SDavid van Moolenbroek } 126*eda6f593SDavid van Moolenbroek if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { 127*eda6f593SDavid van Moolenbroek ctx->error(ctx, "no buffer %d", buffer); 128*eda6f593SDavid van Moolenbroek return (-1); 129*eda6f593SDavid van Moolenbroek } 130*eda6f593SDavid van Moolenbroek 131*eda6f593SDavid van Moolenbroek return (0); 132*eda6f593SDavid van Moolenbroek 133*eda6f593SDavid van Moolenbroek error: 134*eda6f593SDavid van Moolenbroek if (pdata != NULL) 135*eda6f593SDavid van Moolenbroek xfree(pdata); 136*eda6f593SDavid van Moolenbroek if (f != NULL) 137*eda6f593SDavid van Moolenbroek fclose(f); 138*eda6f593SDavid van Moolenbroek return (-1); 139*eda6f593SDavid van Moolenbroek } 140*eda6f593SDavid van Moolenbroek 141*eda6f593SDavid van Moolenbroek void 142*eda6f593SDavid van Moolenbroek cmd_load_buffer_callback(struct client *c, void *data) 143*eda6f593SDavid van Moolenbroek { 144*eda6f593SDavid van Moolenbroek int *buffer = data; 145*eda6f593SDavid van Moolenbroek char *pdata; 146*eda6f593SDavid van Moolenbroek size_t psize; 147*eda6f593SDavid van Moolenbroek u_int limit; 148*eda6f593SDavid van Moolenbroek 149*eda6f593SDavid van Moolenbroek /* 150*eda6f593SDavid van Moolenbroek * Event callback has already checked client is not dead and reduced 151*eda6f593SDavid van Moolenbroek * its reference count. But tell it to exit. 152*eda6f593SDavid van Moolenbroek */ 153*eda6f593SDavid van Moolenbroek c->flags |= CLIENT_EXIT; 154*eda6f593SDavid van Moolenbroek 155*eda6f593SDavid van Moolenbroek psize = EVBUFFER_LENGTH(c->stdin_event->input); 156*eda6f593SDavid van Moolenbroek if (psize == 0 || (pdata = malloc(psize + 1)) == NULL) { 157*eda6f593SDavid van Moolenbroek xfree(data); 158*eda6f593SDavid van Moolenbroek return; 159*eda6f593SDavid van Moolenbroek } 160*eda6f593SDavid van Moolenbroek bufferevent_read(c->stdin_event, pdata, psize); 161*eda6f593SDavid van Moolenbroek pdata[psize] = '\0'; 162*eda6f593SDavid van Moolenbroek 163*eda6f593SDavid van Moolenbroek limit = options_get_number(&global_options, "buffer-limit"); 164*eda6f593SDavid van Moolenbroek if (*buffer == -1) 165*eda6f593SDavid van Moolenbroek paste_add(&global_buffers, pdata, psize, limit); 166*eda6f593SDavid van Moolenbroek else if (paste_replace(&global_buffers, *buffer, pdata, psize) != 0) { 167*eda6f593SDavid van Moolenbroek /* No context so can't use server_client_msg_error. */ 168*eda6f593SDavid van Moolenbroek evbuffer_add_printf( 169*eda6f593SDavid van Moolenbroek c->stderr_event->output, "no buffer %d\n", *buffer); 170*eda6f593SDavid van Moolenbroek bufferevent_enable(c->stderr_event, EV_WRITE); 171*eda6f593SDavid van Moolenbroek } 172*eda6f593SDavid van Moolenbroek 173*eda6f593SDavid van Moolenbroek xfree(data); 174*eda6f593SDavid van Moolenbroek } 175