[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.13

1.13    ! nicm        1: /* $OpenBSD: cmd-load-buffer.c,v 1.12 2010/06/28 22:10:42 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;
        !            84:                cdata->buffer = data->buffer;
        !            85:                c->stdin_data = cdata;
        !            86:                c->stdin_callback = cmd_load_buffer_callback;
        !            87:
        !            88:                c->references++;
        !            89:                bufferevent_enable(c->stdin_event, EV_READ);
        !            90:                return (1);
        !            91:        }
        !            92:
        !            93:        if ((f = fopen(data->arg, "rb")) == NULL) {
        !            94:                ctx->error(ctx, "%s: %s", data->arg, strerror(errno));
        !            95:                return (-1);
1.1       nicm       96:        }
                     97:
1.11      nicm       98:        pdata = NULL;
                     99:        psize = 0;
                    100:        while ((ch = getc(f)) != EOF) {
                    101:                /* Do not let the server die due to memory exhaustion. */
                    102:                if ((new_pdata = realloc(pdata, psize + 2)) == NULL) {
                    103:                        ctx->error(ctx, "realloc error: %s", strerror(errno));
                    104:                        goto error;
                    105:                }
                    106:                pdata = new_pdata;
                    107:                pdata[psize++] = ch;
1.1       nicm      108:        }
1.11      nicm      109:        if (ferror(f)) {
                    110:                ctx->error(ctx, "%s: read error", data->arg);
1.9       nicm      111:                goto error;
1.1       nicm      112:        }
1.11      nicm      113:        if (pdata != NULL)
                    114:                pdata[psize] = '\0';
1.1       nicm      115:
1.13    ! nicm      116:        fclose(f);
        !           117:        f = NULL;
1.1       nicm      118:
                    119:        limit = options_get_number(&s->options, "buffer-limit");
                    120:        if (data->buffer == -1) {
1.9       nicm      121:                paste_add(&s->buffers, pdata, psize, limit);
1.1       nicm      122:                return (0);
                    123:        }
1.9       nicm      124:        if (paste_replace(&s->buffers, data->buffer, pdata, psize) != 0) {
1.1       nicm      125:                ctx->error(ctx, "no buffer %d", data->buffer);
1.13    ! nicm      126:                return (-1);
1.1       nicm      127:        }
                    128:
                    129:        return (0);
1.9       nicm      130:
                    131: error:
                    132:        if (pdata != NULL)
                    133:                xfree(pdata);
1.13    ! nicm      134:        if (f != NULL)
        !           135:                fclose(f);
1.9       nicm      136:        return (-1);
1.13    ! nicm      137: }
        !           138:
        !           139: void
        !           140: cmd_load_buffer_callback(struct client *c, void *data)
        !           141: {
        !           142:        struct cmd_load_buffer_cdata    *cdata = data;
        !           143:        struct session                  *s = cdata->session;
        !           144:        char                            *pdata;
        !           145:        size_t                           psize;
        !           146:        u_int                            limit;
        !           147:        int                              idx;
        !           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? */
        !           156:        if (session_index(s, &idx) != 0)
        !           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:
        !           183:        xfree(cdata);
1.1       nicm      184: }