[BACK]Return to cmd-load-buffer.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / tmux

Annotation of src/usr.bin/tmux/cmd-load-buffer.c, Revision 1.14

1.14    ! nicm        1: /* $OpenBSD: cmd-load-buffer.c,v 1.13 2010/07/24 20:11:59 nicm Exp $ */
1.1       nicm        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:
1.12      nicm       19: #include <sys/types.h>
                     20:
1.1       nicm       21: #include <errno.h>
1.11      nicm       22: #include <stdio.h>
1.1       nicm       23: #include <stdlib.h>
                     24: #include <string.h>
1.12      nicm       25: #include <unistd.h>
1.1       nicm       26:
                     27: #include "tmux.h"
                     28:
                     29: /*
                     30:  * Loads a session paste buffer from a file.
                     31:  */
                     32:
                     33: int    cmd_load_buffer_exec(struct cmd *, struct cmd_ctx *);
1.13      nicm       34: void   cmd_load_buffer_callback(struct client *, void *);
1.1       nicm       35:
                     36: const struct cmd_entry cmd_load_buffer_entry = {
                     37:        "load-buffer", "loadb",
                     38:        CMD_BUFFER_SESSION_USAGE " path",
1.8       nicm       39:        CMD_ARG1, "",
1.1       nicm       40:        cmd_buffer_init,
                     41:        cmd_buffer_parse,
                     42:        cmd_load_buffer_exec,
                     43:        cmd_buffer_free,
                     44:        cmd_buffer_print
                     45: };
                     46:
1.13      nicm       47: struct cmd_load_buffer_cdata {
                     48:        struct session  *session;
                     49:        int              buffer;
                     50: };
                     51:
1.1       nicm       52: int
                     53: cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx)
                     54: {
1.13      nicm       55:        struct cmd_buffer_data          *data = self->data;
                     56:        struct cmd_load_buffer_cdata    *cdata;
                     57:        struct session                  *s;
                     58:        struct client                   *c = ctx->cmdclient;
                     59:        FILE                            *f;
                     60:        char                            *pdata, *new_pdata;
                     61:        size_t                           psize;
                     62:        u_int                            limit;
                     63:        int                              ch;
1.1       nicm       64:
                     65:        if ((s = cmd_find_session(ctx, data->target)) == NULL)
                     66:                return (-1);
                     67:
1.13      nicm       68:        if (strcmp(data->arg, "-") == 0) {
                     69:                if (c == NULL) {
1.12      nicm       70:                        ctx->error(ctx, "%s: can't read from stdin", data->arg);
                     71:                        return (-1);
                     72:                }
1.13      nicm       73:                if (c->flags & CLIENT_TERMINAL) {
1.12      nicm       74:                        ctx->error(ctx, "%s: stdin is a tty", data->arg);
                     75:                        return (-1);
                     76:                }
1.13      nicm       77:                if (c->stdin_fd == -1) {
                     78:                        ctx->error(ctx, "%s: can't read from stdin", data->arg);
1.12      nicm       79:                        return (-1);
                     80:                }
1.13      nicm       81:
                     82:                cdata = xmalloc(sizeof *cdata);
                     83:                cdata->session = s;
1.14    ! nicm       84:                cdata->session->references++;
1.13      nicm       85:                cdata->buffer = data->buffer;
                     86:                c->stdin_data = cdata;
                     87:                c->stdin_callback = cmd_load_buffer_callback;
                     88:
                     89:                c->references++;
                     90:                bufferevent_enable(c->stdin_event, EV_READ);
                     91:                return (1);
                     92:        }
                     93:
                     94:        if ((f = fopen(data->arg, "rb")) == NULL) {
                     95:                ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
                     96:                return (-1);
1.1       nicm       97:        }
                     98:
1.11      nicm       99:        pdata = NULL;
                    100:        psize = 0;
                    101:        while ((ch = getc(f)) != EOF) {
                    102:                /* Do not let the server die due to memory exhaustion. */
                    103:                if ((new_pdata = realloc(pdata, psize + 2)) == NULL) {
                    104:                        ctx->error(ctx, "realloc error: %s", strerror(errno));
                    105:                        goto error;
                    106:                }
                    107:                pdata = new_pdata;
                    108:                pdata[psize++] = ch;
1.1       nicm      109:        }
1.11      nicm      110:        if (ferror(f)) {
                    111:                ctx->error(ctx, "%s: read error", data->arg);
1.9       nicm      112:                goto error;
1.1       nicm      113:        }
1.11      nicm      114:        if (pdata != NULL)
                    115:                pdata[psize] = '\0';
1.1       nicm      116:
1.13      nicm      117:        fclose(f);
                    118:        f = NULL;
1.1       nicm      119:
                    120:        limit = options_get_number(&s->options, "buffer-limit");
                    121:        if (data->buffer == -1) {
1.9       nicm      122:                paste_add(&s->buffers, pdata, psize, limit);
1.1       nicm      123:                return (0);
                    124:        }
1.9       nicm      125:        if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) {
1.1       nicm      126:                ctx->error(ctx, "no buffer %d", data->buffer);
1.13      nicm      127:                return (-1);
1.1       nicm      128:        }
                    129:
                    130:        return (0);
1.9       nicm      131:
                    132: error:
                    133:        if (pdata != NULL)
                    134:                xfree(pdata);
1.13      nicm      135:        if (f != NULL)
                    136:                fclose(f);
1.9       nicm      137:        return (-1);
1.13      nicm      138: }
                    139:
                    140: void
                    141: cmd_load_buffer_callback(struct client *c, void *data)
                    142: {
                    143:        struct cmd_load_buffer_cdata    *cdata = data;
                    144:        struct session                  *s = cdata->session;
                    145:        char                            *pdata;
                    146:        size_t                           psize;
                    147:        u_int                            limit;
                    148:
                    149:        /*
                    150:         * Event callback has already checked client is not dead and reduced
                    151:         * its reference count. But tell it to exit.
                    152:         */
                    153:        c->flags |= CLIENT_EXIT;
                    154:
                    155:        /* Does the target session still exist? */
1.14    ! nicm      156:        if (!session_alive(s))
1.13      nicm      157:                goto out;
                    158:
                    159:        psize = EVBUFFER_LENGTH(c->stdin_event->input);
                    160:        if (psize == 0)
                    161:                goto out;
                    162:
                    163:        pdata = malloc(psize + 1);
                    164:        if (pdata == NULL)
                    165:                goto out;
                    166:        bufferevent_read(c->stdin_event, pdata, psize);
                    167:        pdata[psize] = '\0';
                    168:
                    169:        limit = options_get_number(&s->options, "buffer-limit");
                    170:        if (cdata->buffer == -1) {
                    171:                paste_add(&s->buffers, pdata, psize, limit);
                    172:                goto out;
                    173:        }
                    174:        if (paste_replace(&s->buffers, cdata->buffer, pdata, psize) != 0) {
                    175:                /* No context so can't use server_client_msg_error. */
                    176:                evbuffer_add_printf(
                    177:                    c->stderr_event->output, "no buffer %d\n", cdata->buffer);
                    178:                bufferevent_enable(c->stderr_event, EV_WRITE);
                    179:                goto out;
                    180:        }
                    181:
                    182: out:
1.14    ! nicm      183:        cdata->session->references--;
1.13      nicm      184:        xfree(cdata);
1.1       nicm      185: }