int cmd_set_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; u_int limit; char *pdata, *cause; size_t psize; int buffer; limit = options_get_number(&global_options, "buffer-limit"); pdata = xstrdup(args->argv[0]); psize = strlen(pdata); if (!args_has(args, 'b')) { paste_add(&global_buffers, pdata, psize, limit); return (0); } buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "buffer %s", cause); xfree(cause); xfree(pdata); return (-1); } if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { ctx->error(ctx, "no buffer %d", buffer); xfree(pdata); return (-1); } return (0); }
enum cmd_retval cmd_delete_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; char *cause; int buffer; if (!args_has(args, 'b')) { paste_free_top(&global_buffers); return (CMD_RETURN_NORMAL); } buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } if (paste_free_index(&global_buffers, buffer) != 0) { cmdq_error(cmdq, "no buffer %d", buffer); return (CMD_RETURN_ERROR); } return (CMD_RETURN_NORMAL); }
int cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct client *c = ctx->cmdclient; struct paste_buffer *pb; const char *path; char *cause; int buffer; mode_t mask; FILE *f; if (!args_has(args, 'b')) { if ((pb = paste_get_top(&global_buffers)) == NULL) { ctx->error(ctx, "no buffers"); return (-1); } } else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "buffer %s", cause); xfree(cause); return (-1); } pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { ctx->error(ctx, "no buffer %d", buffer); return (-1); } } path = args->argv[0]; if (strcmp(path, "-") == 0) { if (c == NULL) { ctx->error(ctx, "%s: can't write to stdout", path); return (-1); } bufferevent_write(c->stdout_event, pb->data, pb->size); } else { mask = umask(S_IRWXG | S_IRWXO); if (args_has(self->args, 'a')) f = fopen(path, "ab"); else f = fopen(path, "wb"); umask(mask); if (f == NULL) { ctx->error(ctx, "%s: %s", path, strerror(errno)); return (-1); } if (fwrite(pb->data, 1, pb->size, f) != pb->size) { ctx->error(ctx, "%s: fwrite error", path); fclose(f); return (-1); } fclose(f); } return (0); }
int cmd_paste_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct window_pane *wp; struct session *s; struct paste_buffer *pb; const char *sepstr; char *cause; int buffer; int pflag; if (cmd_find_pane(ctx, args_get(args, 't'), &s, &wp) == NULL) return (-1); if (!args_has(args, 'b')) buffer = -1; else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "buffer %s", cause); xfree(cause); return (-1); } } if (buffer == -1) pb = paste_get_top(&global_buffers); else { pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { ctx->error(ctx, "no buffer %d", buffer); return (-1); } } if (pb != NULL) { sepstr = args_get(args, 's'); if (sepstr == NULL) { if (args_has(args, 'r')) sepstr = "\n"; else sepstr = "\r"; } pflag = args_has(args, 'p') && (wp->screen->mode & MODE_BRACKETPASTE); cmd_paste_buffer_filter(wp, pb->data, pb->size, sepstr, pflag); } /* Delete the buffer if -d. */ if (args_has(args, 'd')) { if (buffer == -1) paste_free_top(&global_buffers); else paste_free_index(&global_buffers, buffer); } return (0); }
enum cmd_retval cmd_paste_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct window_pane *wp; struct session *s; struct paste_buffer *pb; const char *sepstr; char *cause; int buffer; int pflag; if (cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp) == NULL) return (CMD_RETURN_ERROR); if (!args_has(args, 'b')) buffer = -1; else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } } if (buffer == -1) pb = paste_get_top(&global_buffers); else { pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { cmdq_error(cmdq, "no buffer %d", buffer); return (CMD_RETURN_ERROR); } } if (pb != NULL) { sepstr = args_get(args, 's'); if (sepstr == NULL) { if (args_has(args, 'r')) sepstr = "\n"; else sepstr = "\r"; } pflag = (wp->screen->mode & MODE_BRACKETPASTE); paste_send_pane(pb, wp, sepstr, args_has(args, 'p') && pflag); } /* Delete the buffer if -d. */ if (args_has(args, 'd')) { if (buffer == -1) paste_free_top(&global_buffers); else paste_free_index(&global_buffers, buffer); } return (CMD_RETURN_NORMAL); }
enum cmd_retval cmd_capture_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; struct window_pane *wp; char *buf, *cause; int buffer; u_int limit; size_t len; if (cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp) == NULL) return (CMD_RETURN_ERROR); len = 0; if (args_has(args, 'P')) buf = cmd_capture_pane_pending(args, wp, &len); else buf = cmd_capture_pane_history(args, cmdq, wp, &len); if (buf == NULL) return (CMD_RETURN_ERROR); if (args_has(args, 'p')) { c = cmdq->client; if (c == NULL || (c->session != NULL && !(c->flags & CLIENT_CONTROL))) { cmdq_error(cmdq, "can't write to stdout"); return (CMD_RETURN_ERROR); } evbuffer_add(c->stdout_data, buf, len); if (args_has(args, 'P') && len > 0) evbuffer_add(c->stdout_data, "\n", 1); server_push_stdout(c); } else { limit = options_get_number(&global_options, "buffer-limit"); if (!args_has(args, 'b')) { paste_add(buf, len, limit); return (CMD_RETURN_NORMAL); } buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "buffer %s", cause); free(buf); free(cause); return (CMD_RETURN_ERROR); } if (paste_replace(buffer, buf, len) != 0) { cmdq_error(cmdq, "no buffer %d", buffer); free(buf); return (CMD_RETURN_ERROR); } } return (CMD_RETURN_NORMAL); }
enum cmd_retval cmd_set_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct paste_buffer *pb; u_int limit; char *pdata, *cause; size_t psize, newsize; int buffer; limit = options_get_number(&global_options, "buffer-limit"); psize = 0; pdata = NULL; pb = NULL; buffer = -1; if (args_has(args, 'b')) { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { cmdq_error(cmdq, "no buffer %d", buffer); return (CMD_RETURN_ERROR); } } else if (args_has(args, 'a')) { pb = paste_get_top(&global_buffers); if (pb != NULL) buffer = 0; } if (args_has(args, 'a') && pb != NULL) { psize = pb->size; pdata = xmalloc(psize); memcpy(pdata, pb->data, psize); } newsize = strlen(args->argv[0]); pdata = xrealloc(pdata, 1, psize + newsize); memcpy(pdata + psize, args->argv[0], newsize); psize += newsize; if (buffer == -1) paste_add(&global_buffers, pdata, psize, limit); else paste_replace(&global_buffers, buffer, pdata, psize); return (CMD_RETURN_NORMAL); }
enum cmd_retval cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct session *s; struct winlink *wl; struct window *w; struct window_pane *wp, *new_wp = NULL; struct environ env; const char *cmd, *cwd, *shell; char *cause, *new_cause; u_int hlimit; int size, percentage; enum layout_type type; struct layout_cell *lc; const char *template; struct client *c; struct format_tree *ft; char *cp; if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; environ_init(&env); environ_copy(&global_environ, &env); environ_copy(&s->environ, &env); server_fill_environ(s, &env); if (args->argc == 0) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; cwd = cmd_get_default_path(ctx, args_get(args, 'c')); type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; size = -1; if (args_has(args, 'l')) { size = args_strtonum(args, 'l', 0, INT_MAX, &cause); if (cause != NULL) { xasprintf(&new_cause, "size %s", cause); free(cause); cause = new_cause; goto error; } } else if (args_has(args, 'p')) { percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause); if (cause != NULL) { xasprintf(&new_cause, "percentage %s", cause); free(cause); cause = new_cause; goto error; } if (type == LAYOUT_TOPBOTTOM) size = (wp->sy * percentage) / 100; else size = (wp->sx * percentage) / 100; } hlimit = options_get_number(&s->options, "history-limit"); shell = options_get_string(&s->options, "default-shell"); if (*shell == '\0' || areshell(shell)) shell = _PATH_BSHELL; if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) { cause = xstrdup("pane too small"); goto error; } new_wp = window_add_pane(w, hlimit); if (window_pane_spawn( new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0) goto error; layout_assign_pane(lc, new_wp); server_redraw_window(w); if (!args_has(args, 'd')) { window_set_active_pane(w, new_wp); session_select(s, wl->idx); server_redraw_session(s); } else server_status_session(s); environ_free(&env); if (args_has(args, 'P')) { if ((template = args_get(args, 'F')) == NULL)
static char * cmd_capture_pane_history(struct args *args, struct cmd_q *cmdq, struct window_pane *wp, size_t *len) { struct grid *gd; const struct grid_line *gl; struct grid_cell *gc = NULL; int n, with_codes, escape_c0, join_lines; u_int i, sx, top, bottom, tmp; char *cause, *buf, *line; const char *Sflag, *Eflag; size_t linelen; sx = screen_size_x(&wp->base); if (args_has(args, 'a')) { gd = wp->saved_grid; if (gd == NULL) { if (!args_has(args, 'q')) { cmdq_error(cmdq, "no alternate screen"); return (NULL); } return (xstrdup("")); } } else gd = wp->base.grid; Sflag = args_get(args, 'S'); if (Sflag != NULL && strcmp(Sflag, "-") == 0) top = 0; else { n = args_strtonum(args, 'S', INT_MIN, SHRT_MAX, &cause); if (cause != NULL) { top = gd->hsize; free(cause); } else if (n < 0 && (u_int) -n > gd->hsize) top = 0; else top = gd->hsize + n; if (top > gd->hsize + gd->sy - 1) top = gd->hsize + gd->sy - 1; } Eflag = args_get(args, 'E'); if (Eflag != NULL && strcmp(Eflag, "-") == 0) bottom = gd->hsize + gd->sy - 1; else { n = args_strtonum(args, 'E', INT_MIN, SHRT_MAX, &cause); if (cause != NULL) { bottom = gd->hsize + gd->sy - 1; free(cause); } else if (n < 0 && (u_int) -n > gd->hsize) bottom = 0; else bottom = gd->hsize + n; if (bottom > gd->hsize + gd->sy - 1) bottom = gd->hsize + gd->sy - 1; } if (bottom < top) { tmp = bottom; bottom = top; top = tmp; } with_codes = args_has(args, 'e'); escape_c0 = args_has(args, 'C'); join_lines = args_has(args, 'J'); buf = NULL; for (i = top; i <= bottom; i++) { line = grid_string_cells(gd, 0, i, sx, &gc, with_codes, escape_c0, !join_lines); linelen = strlen(line); buf = cmd_capture_pane_append(buf, len, line, linelen); gl = grid_peek_line(gd, i); if (!join_lines || !(gl->flags & GRID_LINE_WRAPPED)) buf[(*len)++] = '\n'; free(line); } return (buf); }
int cmd_join_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct session *dst_s; struct winlink *src_wl, *dst_wl; struct window *src_w, *dst_w; struct window_pane *src_wp, *dst_wp; char *cause; int size, percentage, dst_idx; enum layout_type type; struct layout_cell *lc; dst_wl = cmd_find_pane(ctx, args_get(args, 't'), &dst_s, &dst_wp); if (dst_wl == NULL) return (-1); dst_w = dst_wl->window; dst_idx = dst_wl->idx; src_wl = cmd_find_pane(ctx, args_get(args, 's'), NULL, &src_wp); if (src_wl == NULL) return (-1); src_w = src_wl->window; if (src_w == dst_w) { ctx->error(ctx, "can't join a pane to its own window"); return (-1); } type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; size = -1; if (args_has(args, 'l')) { size = args_strtonum(args, 'l', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "size %s", cause); xfree(cause); return (-1); } } else if (args_has(args, 'p')) { percentage = args_strtonum(args, 'p', 0, 100, &cause); if (cause != NULL) { ctx->error(ctx, "percentage %s", cause); xfree(cause); return (-1); } if (type == LAYOUT_TOPBOTTOM) size = (dst_wp->sy * percentage) / 100; else size = (dst_wp->sx * percentage) / 100; } if ((lc = layout_split_pane(dst_wp, type, size)) == NULL) { ctx->error(ctx, "create pane failed: pane too small"); return (-1); } layout_close_pane(src_wp); if (src_w->active == src_wp) { src_w->active = TAILQ_PREV(src_wp, window_panes, entry); if (src_w->active == NULL) src_w->active = TAILQ_NEXT(src_wp, entry); } TAILQ_REMOVE(&src_w->panes, src_wp, entry); if (window_count_panes(src_w) == 0) server_kill_window(src_w); src_wp->window = dst_w; TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry); layout_assign_pane(lc, src_wp); recalculate_sizes(); server_redraw_window(src_w); server_redraw_window(dst_w); if (!args_has(args, 'd')) { window_set_active_pane(dst_w, src_wp); session_select(dst_s, dst_idx); server_redraw_session(dst_s); } else server_status_session(dst_s); return (0); }
int cmd_load_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct client *c = ctx->cmdclient; FILE *f; const char *path; char *pdata, *new_pdata, *cause; size_t psize; u_int limit; int ch, buffer; int *buffer_ptr; if (!args_has(args, 'b')) buffer = -1; else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "buffer %s", cause); xfree(cause); return (-1); } } path = args->argv[0]; if (strcmp(path, "-") == 0) { if (c == NULL) { ctx->error(ctx, "%s: can't read from stdin", path); return (-1); } if (c->flags & CLIENT_TERMINAL) { ctx->error(ctx, "%s: stdin is a tty", path); return (-1); } if (c->stdin_fd == -1) { ctx->error(ctx, "%s: can't read from stdin", path); return (-1); } buffer_ptr = xmalloc(sizeof *buffer_ptr); *buffer_ptr = buffer; c->stdin_data = buffer_ptr; c->stdin_callback = cmd_load_buffer_callback; c->references++; bufferevent_enable(c->stdin_event, EV_READ); return (1); } if ((f = fopen(path, "rb")) == NULL) { ctx->error(ctx, "%s: %s", path, strerror(errno)); return (-1); } pdata = NULL; psize = 0; while ((ch = getc(f)) != EOF) { /* Do not let the server die due to memory exhaustion. */ if ((new_pdata = realloc(pdata, psize + 2)) == NULL) { ctx->error(ctx, "realloc error: %s", strerror(errno)); goto error; } pdata = new_pdata; pdata[psize++] = ch; } if (ferror(f)) { ctx->error(ctx, "%s: read error", path); goto error; } if (pdata != NULL) pdata[psize] = '\0'; fclose(f); limit = options_get_number(&global_options, "buffer-limit"); if (buffer == -1) { paste_add(&global_buffers, pdata, psize, limit); return (0); } if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { ctx->error(ctx, "no buffer %d", buffer); return (-1); } return (0); error: if (pdata != NULL) xfree(pdata); if (f != NULL) fclose(f); return (-1); }
enum cmd_retval cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c = cmdq->client; struct session *s; FILE *f; const char *path; char *pdata, *new_pdata, *cause; size_t psize; u_int limit; int ch, error, buffer, *buffer_ptr, cwd, fd; if (!args_has(args, 'b')) buffer = -1; else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } } path = args->argv[0]; if (strcmp(path, "-") == 0) { buffer_ptr = xmalloc(sizeof *buffer_ptr); *buffer_ptr = buffer; error = server_set_stdin_callback(c, cmd_load_buffer_callback, buffer_ptr, &cause); if (error != 0) { cmdq_error(cmdq, "%s: %s", path, cause); free(cause); return (CMD_RETURN_ERROR); } return (CMD_RETURN_WAIT); } if (c != NULL && c->session == NULL) cwd = c->cwd; else if ((s = cmd_current_session(cmdq, 0)) != NULL) cwd = s->cwd; else cwd = AT_FDCWD; if ((fd = openat(cwd, path, O_RDONLY)) == -1 || (f = fdopen(fd, "rb")) == NULL) { if (fd != -1) close(fd); cmdq_error(cmdq, "%s: %s", path, strerror(errno)); return (CMD_RETURN_ERROR); } pdata = NULL; psize = 0; while ((ch = getc(f)) != EOF) { /* Do not let the server die due to memory exhaustion. */ if ((new_pdata = realloc(pdata, psize + 2)) == NULL) { cmdq_error(cmdq, "realloc error: %s", strerror(errno)); goto error; } pdata = new_pdata; pdata[psize++] = ch; } if (ferror(f)) { cmdq_error(cmdq, "%s: read error", path); goto error; } if (pdata != NULL) pdata[psize] = '\0'; fclose(f); limit = options_get_number(&global_options, "buffer-limit"); if (buffer == -1) { paste_add(&global_buffers, pdata, psize, limit); return (CMD_RETURN_NORMAL); } if (paste_replace(&global_buffers, buffer, pdata, psize) != 0) { cmdq_error(cmdq, "no buffer %d", buffer); free(pdata); return (CMD_RETURN_ERROR); } return (CMD_RETURN_NORMAL); error: free(pdata); if (f != NULL) fclose(f); return (CMD_RETURN_ERROR); }
enum cmd_retval cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c; struct session *s; struct paste_buffer *pb; const char *path, *newpath, *wd; char *cause, *start, *end; size_t size, used; int buffer; mode_t mask; FILE *f; char *msg; size_t msglen; if (!args_has(args, 'b')) { if ((pb = paste_get_top(&global_buffers)) == NULL) { cmdq_error(cmdq, "no buffers"); return (CMD_RETURN_ERROR); } } else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { cmdq_error(cmdq, "no buffer %d", buffer); return (CMD_RETURN_ERROR); } } if (self->entry == &cmd_show_buffer_entry) path = "-"; else path = args->argv[0]; if (strcmp(path, "-") == 0) { c = cmdq->client; if (c == NULL) { cmdq_error(cmdq, "can't write to stdout"); return (CMD_RETURN_ERROR); } if (c->session == NULL || (c->flags & CLIENT_CONTROL)) goto do_stdout; goto do_print; } c = cmdq->client; if (c != NULL) wd = c->cwd; else if ((s = cmd_current_session(cmdq, 0)) != NULL) { wd = options_get_string(&s->options, "default-path"); if (*wd == '\0') wd = s->cwd; } else wd = NULL; if (wd != NULL && *wd != '\0') { newpath = get_full_path(wd, path); if (newpath != NULL) path = newpath; } mask = umask(S_IRWXG | S_IRWXO); if (args_has(self->args, 'a')) f = fopen(path, "ab"); else f = fopen(path, "wb"); umask(mask); if (f == NULL) { cmdq_error(cmdq, "%s: %s", path, strerror(errno)); return (CMD_RETURN_ERROR); } if (fwrite(pb->data, 1, pb->size, f) != pb->size) { cmdq_error(cmdq, "%s: fwrite error", path); fclose(f); return (CMD_RETURN_ERROR); } fclose(f); return (CMD_RETURN_NORMAL); do_stdout: evbuffer_add(c->stdout_data, pb->data, pb->size); server_push_stdout(c); return (CMD_RETURN_NORMAL); do_print: if (pb->size > (INT_MAX / 4) - 1) { cmdq_error(cmdq, "buffer too big"); return (CMD_RETURN_ERROR); } msg = NULL; msglen = 0; used = 0; while (used != pb->size) { start = pb->data + used; end = memchr(start, '\n', pb->size - used); if (end != NULL) size = end - start; else size = pb->size - used; msglen = size * 4 + 1; msg = xrealloc(msg, 1, msglen); strvisx(msg, start, size, VIS_OCTAL|VIS_TAB); cmdq_print(cmdq, "%s", msg); used += size + (end != NULL); } free(msg); return (CMD_RETURN_NORMAL); }
enum cmd_retval cmd_resize_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct winlink *wl; struct window *w; const char *errstr; char *cause; struct window_pane *wp; u_int adjust; int x, y; if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), NULL, &wp)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; if (args_has(args, 'Z')) { if (w->flags & WINDOW_ZOOMED) window_unzoom(w); else window_zoom(wp); server_redraw_window(w); server_status_window(w); return (CMD_RETURN_NORMAL); } server_unzoom_window(w); if (args->argc == 0) adjust = 1; else { adjust = strtonum(args->argv[0], 1, INT_MAX, &errstr); if (errstr != NULL) { cmdq_error(cmdq, "adjustment %s", errstr); return (CMD_RETURN_ERROR); } } if (args_has(self->args, 'x')) { x = args_strtonum(self->args, 'x', PANE_MINIMUM, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "width %s", cause); free(cause); return (CMD_RETURN_ERROR); } layout_resize_pane_to(wp, LAYOUT_LEFTRIGHT, x); } if (args_has(self->args, 'y')) { y = args_strtonum(self->args, 'y', PANE_MINIMUM, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "height %s", cause); free(cause); return (CMD_RETURN_ERROR); } layout_resize_pane_to(wp, LAYOUT_TOPBOTTOM, y); } if (args_has(self->args, 'L')) layout_resize_pane(wp, LAYOUT_LEFTRIGHT, -adjust); else if (args_has(self->args, 'R')) layout_resize_pane(wp, LAYOUT_LEFTRIGHT, adjust); else if (args_has(self->args, 'U')) layout_resize_pane(wp, LAYOUT_TOPBOTTOM, -adjust); else if (args_has(self->args, 'D')) layout_resize_pane(wp, LAYOUT_TOPBOTTOM, adjust); server_redraw_window(wl->window); return (CMD_RETURN_NORMAL); }
enum cmd_retval join_pane(struct cmd *self, struct cmd_q *cmdq, int not_same_window) { struct args *args = self->args; struct session *dst_s; struct winlink *src_wl, *dst_wl; struct window *src_w, *dst_w; struct window_pane *src_wp, *dst_wp; char *cause; int size, percentage, dst_idx; enum layout_type type; struct layout_cell *lc; dst_wl = cmd_find_pane(cmdq, args_get(args, 't'), &dst_s, &dst_wp); if (dst_wl == NULL) return (CMD_RETURN_ERROR); dst_w = dst_wl->window; dst_idx = dst_wl->idx; server_unzoom_window(dst_w); src_wl = cmd_find_pane(cmdq, args_get(args, 's'), NULL, &src_wp); if (src_wl == NULL) return (CMD_RETURN_ERROR); src_w = src_wl->window; server_unzoom_window(src_w); if (not_same_window && src_w == dst_w) { cmdq_error(cmdq, "can't join a pane to its own window"); return (CMD_RETURN_ERROR); } if (!not_same_window && src_wp == dst_wp) { cmdq_error(cmdq, "source and target panes must be different"); return (CMD_RETURN_ERROR); } type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; size = -1; if (args_has(args, 'l')) { size = args_strtonum(args, 'l', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "size %s", cause); free(cause); return (CMD_RETURN_ERROR); } } else if (args_has(args, 'p')) { percentage = args_strtonum(args, 'p', 0, 100, &cause); if (cause != NULL) { cmdq_error(cmdq, "percentage %s", cause); free(cause); return (CMD_RETURN_ERROR); } if (type == LAYOUT_TOPBOTTOM) size = (dst_wp->sy * percentage) / 100; else size = (dst_wp->sx * percentage) / 100; } lc = layout_split_pane(dst_wp, type, size, args_has(args, 'b')); if (lc == NULL) { cmdq_error(cmdq, "create pane failed: pane too small"); return (CMD_RETURN_ERROR); } layout_close_pane(src_wp); window_lost_pane(src_w, src_wp); TAILQ_REMOVE(&src_w->panes, src_wp, entry); if (window_count_panes(src_w) == 0) server_kill_window(src_w); else notify_window_layout_changed(src_w); src_wp->window = dst_w; TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry); layout_assign_pane(lc, src_wp); recalculate_sizes(); server_redraw_window(src_w); server_redraw_window(dst_w); if (!args_has(args, 'd')) { window_set_active_pane(dst_w, src_wp); session_select(dst_s, dst_idx); server_redraw_session(dst_s); } else server_status_session(dst_s); notify_window_layout_changed(dst_w); return (CMD_RETURN_NORMAL); }
enum cmd_retval cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; struct winlink *wl; struct window *w; struct window_pane *wp, *new_wp = NULL; struct environ env; const char *cmd, *shell, *template; char *cause, *new_cause, *cp; u_int hlimit; int size, percentage, cwd, fd = -1; enum layout_type type; struct layout_cell *lc; struct client *c; struct format_tree *ft; if ((wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp)) == NULL) return (CMD_RETURN_ERROR); w = wl->window; server_unzoom_window(w); environ_init(&env); environ_copy(&global_environ, &env); environ_copy(&s->environ, &env); server_fill_environ(s, &env); if (args->argc == 0) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; if (args_has(args, 'c')) { ft = format_create(); if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL) format_client(ft, c); format_session(ft, s); format_winlink(ft, s, s->curw); format_window_pane(ft, s->curw->window->active); cp = format_expand(ft, args_get(args, 'c')); format_free(ft); fd = open(cp, O_RDONLY|O_DIRECTORY); free(cp); if (fd == -1) { cmdq_error(cmdq, "bad working directory: %s", strerror(errno)); return (CMD_RETURN_ERROR); } cwd = fd; } else if (cmdq->client != NULL && cmdq->client->session == NULL) cwd = cmdq->client->cwd; else cwd = s->cwd; type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; size = -1; if (args_has(args, 'l')) { size = args_strtonum(args, 'l', 0, INT_MAX, &cause); if (cause != NULL) { xasprintf(&new_cause, "size %s", cause); free(cause); cause = new_cause; goto error; } } else if (args_has(args, 'p')) { percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause); if (cause != NULL) { xasprintf(&new_cause, "percentage %s", cause); free(cause); cause = new_cause; goto error; } if (type == LAYOUT_TOPBOTTOM) size = (wp->sy * percentage) / 100; else size = (wp->sx * percentage) / 100; } hlimit = options_get_number(&s->options, "history-limit"); shell = options_get_string(&s->options, "default-shell"); if (*shell == '\0' || areshell(shell)) shell = _PATH_BSHELL; if ((lc = layout_split_pane(wp, type, size, 0)) == NULL) { cause = xstrdup("pane too small"); goto error; } new_wp = window_add_pane(w, hlimit); if (window_pane_spawn( new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0) goto error; layout_assign_pane(lc, new_wp); server_redraw_window(w); if (!args_has(args, 'd')) { window_set_active_pane(w, new_wp); session_select(s, wl->idx); server_redraw_session(s); } else server_status_session(s); environ_free(&env); if (args_has(args, 'P')) { if ((template = args_get(args, 'F')) == NULL)
int cmd_split_window_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct session *s; struct winlink *wl; struct window *w; struct window_pane *wp, *new_wp = NULL; struct environ env; char *cmd, *cwd, *cause; const char *shell; u_int hlimit, paneidx; int size, percentage; enum layout_type type; struct layout_cell *lc; if ((wl = cmd_find_pane(ctx, args_get(args, 't'), &s, &wp)) == NULL) return (-1); w = wl->window; environ_init(&env); environ_copy(&global_environ, &env); environ_copy(&s->environ, &env); server_fill_environ(s, &env); if (args->argc == 0) cmd = options_get_string(&s->options, "default-command"); else cmd = args->argv[0]; cwd = options_get_string(&s->options, "default-path"); if (*cwd == '\0') { if (ctx->cmdclient != NULL && ctx->cmdclient->cwd != NULL) cwd = ctx->cmdclient->cwd; else cwd = s->cwd; } type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; size = -1; if (args_has(args, 's')) { size = args_strtonum(args, 's', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "size %s", cause); xfree(cause); return (-1); } } else if (args_has(args, 'p')) { percentage = args_strtonum(args, 'p', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "percentage %s", cause); xfree(cause); return (-1); } if (type == LAYOUT_TOPBOTTOM) size = (wp->sy * percentage) / 100; else size = (wp->sx * percentage) / 100; } hlimit = options_get_number(&s->options, "history-limit"); shell = options_get_string(&s->options, "default-shell"); if (*shell == '\0' || areshell(shell)) shell = _PATH_BSHELL; if ((lc = layout_split_pane(wp, type, size)) == NULL) { cause = xstrdup("pane too small"); goto error; } new_wp = window_add_pane(w, hlimit); if (window_pane_spawn( new_wp, cmd, shell, cwd, &env, s->tio, &cause) != 0) goto error; layout_assign_pane(lc, new_wp); server_redraw_window(w); if (!args_has(args, 'd')) { window_set_active_pane(w, new_wp); session_select(s, wl->idx); server_redraw_session(s); } else server_status_session(s); environ_free(&env); if (args_has(args, 'P')) { paneidx = window_pane_index(wl->window, new_wp); ctx->print(ctx, "%s:%u.%u", s->name, wl->idx, paneidx); } return (0); error: environ_free(&env); if (new_wp != NULL) window_remove_pane(w, new_wp); ctx->error(ctx, "create pane failed: %s", cause); xfree(cause); return (-1); }
int cmd_capture_pane_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct window_pane *wp; char *buf, *line, *cause; struct screen *s; struct grid *gd; int buffer, n; u_int i, limit, top, bottom, tmp; size_t len, linelen; if (cmd_find_pane(ctx, args_get(args, 't'), NULL, &wp) == NULL) return (-1); s = &wp->base; gd = s->grid; buf = NULL; len = 0; n = args_strtonum(args, 'S', SHRT_MIN, SHRT_MAX, &cause); if (cause != NULL) { top = gd->hsize; xfree(cause); } else if (n < 0 && (u_int) -n > gd->hsize) top = 0; else top = gd->hsize + n; if (top > gd->hsize + gd->sy - 1) top = gd->hsize + gd->sy - 1; n = args_strtonum(args, 'E', SHRT_MIN, SHRT_MAX, &cause); if (cause != NULL) { bottom = gd->hsize + gd->sy - 1; xfree(cause); } else if (n < 0 && (u_int) -n > gd->hsize) bottom = 0; else bottom = gd->hsize + n; if (bottom > gd->hsize + gd->sy - 1) bottom = gd->hsize + gd->sy - 1; if (bottom < top) { tmp = bottom; bottom = top; top = tmp; } for (i = top; i <= bottom; i++) { line = grid_string_cells(s->grid, 0, i, screen_size_x(s)); linelen = strlen(line); buf = xrealloc(buf, 1, len + linelen + 1); memcpy(buf + len, line, linelen); len += linelen; buf[len++] = '\n'; xfree(line); } limit = options_get_number(&global_options, "buffer-limit"); if (!args_has(args, 'b')) { paste_add(&global_buffers, buf, len, limit); return (0); } buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "buffer %s", cause); xfree(cause); return (-1); } if (paste_replace(&global_buffers, buffer, buf, len) != 0) { ctx->error(ctx, "no buffer %d", buffer); xfree(buf); return (-1); } return (0); }
int cmd_save_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct client *c = ctx->cmdclient; struct session *s; struct paste_buffer *pb; const char *path, *newpath, *wd; char *cause; int buffer; mode_t mask; FILE *f; if (!args_has(args, 'b')) { if ((pb = paste_get_top(&global_buffers)) == NULL) { ctx->error(ctx, "no buffers"); return (-1); } } else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "buffer %s", cause); xfree(cause); return (-1); } pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { ctx->error(ctx, "no buffer %d", buffer); return (-1); } } path = args->argv[0]; if (strcmp(path, "-") == 0) { if (c == NULL) { ctx->error(ctx, "%s: can't write to stdout", path); return (-1); } evbuffer_add(c->stdout_data, pb->data, pb->size); server_push_stdout(c); } else { if (c != NULL) wd = c->cwd; else if ((s = cmd_current_session(ctx, 0)) != NULL) { wd = options_get_string(&s->options, "default-path"); if (*wd == '\0') wd = s->cwd; } else wd = NULL; if (wd != NULL && *wd != '\0') { newpath = get_full_path(wd, path); if (newpath != NULL) path = newpath; } mask = umask(S_IRWXG | S_IRWXO); if (args_has(self->args, 'a')) f = fopen(path, "ab"); else f = fopen(path, "wb"); umask(mask); if (f == NULL) { ctx->error(ctx, "%s: %s", path, strerror(errno)); return (-1); } if (fwrite(pb->data, 1, pb->size, f) != pb->size) { ctx->error(ctx, "%s: fwrite error", path); fclose(f); return (-1); } fclose(f); } return (0); }
enum cmd_retval cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c = cmdq->client; struct session *s; struct paste_buffer *pb; const char *path; char *cause, *start, *end, *msg; size_t size, used, msglen; int cwd, fd, buffer; FILE *f; if (!args_has(args, 'b')) { if ((pb = paste_get_top(&global_buffers)) == NULL) { cmdq_error(cmdq, "no buffers"); return (CMD_RETURN_ERROR); } } else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(cmdq, "buffer %s", cause); free(cause); return (CMD_RETURN_ERROR); } pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { cmdq_error(cmdq, "no buffer %d", buffer); return (CMD_RETURN_ERROR); } } if (self->entry == &cmd_show_buffer_entry) path = "-"; else path = args->argv[0]; if (strcmp(path, "-") == 0) { if (c == NULL) { cmdq_error(cmdq, "can't write to stdout"); return (CMD_RETURN_ERROR); } if (c->session == NULL || (c->flags & CLIENT_CONTROL)) goto do_stdout; goto do_print; } if (c != NULL && c->session == NULL) cwd = c->cwd; else if ((s = cmd_current_session(cmdq, 0)) != NULL) cwd = s->cwd; else cwd = AT_FDCWD; f = NULL; if (args_has(self->args, 'a')) { fd = openat(cwd, path, O_CREAT|O_RDWR|O_APPEND, 0600); if (fd != -1) f = fdopen(fd, "ab"); } else { fd = openat(cwd, path, O_CREAT|O_RDWR, 0600); if (fd != -1) f = fdopen(fd, "wb"); } if (f == NULL) { if (fd != -1) close(fd); cmdq_error(cmdq, "%s: %s", path, strerror(errno)); return (CMD_RETURN_ERROR); } if (fwrite(pb->data, 1, pb->size, f) != pb->size) { cmdq_error(cmdq, "%s: fwrite error", path); fclose(f); return (CMD_RETURN_ERROR); } fclose(f); return (CMD_RETURN_NORMAL); do_stdout: evbuffer_add(c->stdout_data, pb->data, pb->size); server_push_stdout(c); return (CMD_RETURN_NORMAL); do_print: if (pb->size > (INT_MAX / 4) - 1) { cmdq_error(cmdq, "buffer too big"); return (CMD_RETURN_ERROR); } msg = NULL; msglen = 0; used = 0; while (used != pb->size) { start = pb->data + used; end = memchr(start, '\n', pb->size - used); if (end != NULL) size = end - start; else size = pb->size - used; msglen = size * 4 + 1; msg = xrealloc(msg, 1, msglen); strvisx(msg, start, size, VIS_OCTAL|VIS_TAB); cmdq_print(cmdq, "%s", msg); used += size + (end != NULL); } free(msg); return (CMD_RETURN_NORMAL); }
int cmd_show_buffer_exec(struct cmd *self, struct cmd_ctx *ctx) { struct args *args = self->args; struct session *s; struct paste_buffer *pb; int buffer; char *in, *buf, *ptr, *cause; size_t size, len; u_int width; if ((s = cmd_find_session(ctx, NULL, 0)) == NULL) return (-1); if (!args_has(args, 'b')) { if ((pb = paste_get_top(&global_buffers)) == NULL) { ctx->error(ctx, "no buffers"); return (-1); } } else { buffer = args_strtonum(args, 'b', 0, INT_MAX, &cause); if (cause != NULL) { ctx->error(ctx, "buffer %s", cause); xfree(cause); return (-1); } pb = paste_get_index(&global_buffers, buffer); if (pb == NULL) { ctx->error(ctx, "no buffer %d", buffer); return (-1); } } size = pb->size; if (size > SIZE_MAX / 4 - 1) size = SIZE_MAX / 4 - 1; in = xmalloc(size * 4 + 1); strvisx(in, pb->data, size, VIS_OCTAL|VIS_TAB); width = s->sx; if (ctx->cmdclient != NULL) width = ctx->cmdclient->tty.sx; buf = xmalloc(width + 1); len = 0; ptr = in; do { buf[len++] = *ptr++; if (len == width || buf[len - 1] == '\n') { if (buf[len - 1] == '\n') len--; buf[len] = '\0'; ctx->print(ctx, "%s", buf); len = 0; } } while (*ptr != '\0'); if (len != 0) { buf[len] = '\0'; ctx->print(ctx, "%s", buf); } xfree(buf); xfree(in); return (0); }
static enum cmd_retval cmd_join_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = self->args; struct cmd_find_state *current = &item->shared->current; struct session *dst_s; struct winlink *src_wl, *dst_wl; struct window *src_w, *dst_w; struct window_pane *src_wp, *dst_wp; char *cause; int size, percentage, dst_idx; enum layout_type type; struct layout_cell *lc; int not_same_window, flags; if (self->entry == &cmd_join_pane_entry) not_same_window = 1; else not_same_window = 0; dst_s = item->target.s; dst_wl = item->target.wl; dst_wp = item->target.wp; dst_w = dst_wl->window; dst_idx = dst_wl->idx; server_unzoom_window(dst_w); src_wl = item->source.wl; src_wp = item->source.wp; src_w = src_wl->window; server_unzoom_window(src_w); if (not_same_window && src_w == dst_w) { cmdq_error(item, "can't join a pane to its own window"); return (CMD_RETURN_ERROR); } if (!not_same_window && src_wp == dst_wp) { cmdq_error(item, "source and target panes must be different"); return (CMD_RETURN_ERROR); } type = LAYOUT_TOPBOTTOM; if (args_has(args, 'h')) type = LAYOUT_LEFTRIGHT; size = -1; if (args_has(args, 'l')) { size = args_strtonum(args, 'l', 0, INT_MAX, &cause); if (cause != NULL) { cmdq_error(item, "size %s", cause); free(cause); return (CMD_RETURN_ERROR); } } else if (args_has(args, 'p')) { percentage = args_strtonum(args, 'p', 0, 100, &cause); if (cause != NULL) { cmdq_error(item, "percentage %s", cause); free(cause); return (CMD_RETURN_ERROR); } if (type == LAYOUT_TOPBOTTOM) size = (dst_wp->sy * percentage) / 100; else size = (dst_wp->sx * percentage) / 100; } if (args_has(args, 'b')) flags = SPAWN_BEFORE; else flags = 0; lc = layout_split_pane(dst_wp, type, size, flags); if (lc == NULL) { cmdq_error(item, "create pane failed: pane too small"); return (CMD_RETURN_ERROR); } layout_close_pane(src_wp); window_lost_pane(src_w, src_wp); TAILQ_REMOVE(&src_w->panes, src_wp, entry); src_wp->window = dst_w; TAILQ_INSERT_AFTER(&dst_w->panes, dst_wp, src_wp, entry); layout_assign_pane(lc, src_wp); recalculate_sizes(); server_redraw_window(src_w); server_redraw_window(dst_w); if (!args_has(args, 'd')) { window_set_active_pane(dst_w, src_wp, 1); session_select(dst_s, dst_idx); cmd_find_from_session(current, dst_s, 0); server_redraw_session(dst_s); } else server_status_session(dst_s); if (window_count_panes(src_w) == 0) server_kill_window(src_w); else notify_window("window-layout-changed", src_w); notify_window("window-layout-changed", dst_w); return (CMD_RETURN_NORMAL); }