char * format_window_name(struct window *w) { struct format_tree *ft; char *fmt, *name; ft = format_create(NULL, 0); format_defaults_window(ft, w); format_defaults_pane(ft, w->active); fmt = options_get_string(w->options, "automatic-rename-format"); name = format_expand(ft, fmt); format_free(ft); return (name); }
enum cmd_retval cmd_run_shell_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct cmd_run_shell_data *cdata; char *shellcmd; struct client *c; struct session *s = NULL; struct winlink *wl = NULL; struct window_pane *wp = NULL; struct format_tree *ft; if (args_has(args, 't')) wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); else { c = cmd_find_client(cmdq, NULL, 1); if (c != NULL && c->session != NULL) { s = c->session; wl = s->curw; wp = wl->window->active; } } ft = format_create(); if (s != NULL) format_session(ft, s); if (s != NULL && wl != NULL) format_winlink(ft, s, wl); if (wp != NULL) format_window_pane(ft, wp); shellcmd = format_expand(ft, args->argv[0]); format_free(ft); cdata = xmalloc(sizeof *cdata); cdata->cmd = shellcmd; cdata->bflag = args_has(args, 'b'); cdata->wp_id = wp != NULL ? (int) wp->id : -1; cdata->cmdq = cmdq; cmdq->references++; job_run(shellcmd, s, cmd_run_shell_callback, cmd_run_shell_free, cdata); if (cdata->bflag) return (CMD_RETURN_NORMAL); return (CMD_RETURN_WAIT); }
unsigned int get_python_format_unnamed_arg_count (const char *string) { /* Parse the format string. */ char *invalid_reason = NULL; struct spec *descr = (struct spec *) format_parse (string, false, &invalid_reason); if (descr != NULL) { unsigned int result = descr->unnamed_arg_count; format_free (descr); return result; } else { free (invalid_reason); return 0; } }
enum cmd_retval cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct session *s; struct winlink *wl; struct client *c; const char *cmd, *template; char *cause, *cp; int idx, last, detached, cwd, fd = -1; struct format_tree *ft; if (args_has(args, 'a')) { wl = cmd_find_window(cmdq, args_get(args, 't'), &s); if (wl == NULL) return (CMD_RETURN_ERROR); idx = wl->idx + 1; /* Find the next free index. */ for (last = idx; last < INT_MAX; last++) { if (winlink_find_by_index(&s->windows, last) == NULL) break; } if (last == INT_MAX) { cmdq_error(cmdq, "no free window indexes"); return (CMD_RETURN_ERROR); } /* Move everything from last - 1 to idx up a bit. */ for (; last > idx; last--) { wl = winlink_find_by_index(&s->windows, last - 1); server_link_window(s, wl, s, last, 0, 0, NULL); server_unlink_window(s, wl); } } else { if ((idx = cmd_find_index(cmdq, args_get(args, 't'), &s)) == -2) return (CMD_RETURN_ERROR); } detached = args_has(args, 'd'); wl = NULL; if (idx != -1) wl = winlink_find_by_index(&s->windows, idx); if (wl != NULL && args_has(args, 'k')) { /* * Can't use session_detach as it will destroy session if this * makes it empty. */ notify_window_unlinked(s, wl->window); wl->flags &= ~WINLINK_ALERTFLAGS; winlink_stack_remove(&s->lastw, wl); winlink_remove(&s->windows, wl); /* Force select/redraw if current. */ if (wl == s->curw) { detached = 0; s->curw = NULL; } } 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; if (idx == -1) idx = -1 - options_get_number(&s->options, "base-index"); wl = session_new(s, args_get(args, 'n'), cmd, cwd, idx, &cause); if (wl == NULL) { cmdq_error(cmdq, "create window failed: %s", cause); free(cause); goto error; } if (!detached) { session_select(s, wl->idx); server_redraw_session_group(s); } else server_status_session_group(s); if (args_has(args, 'P')) { if ((template = args_get(args, 'F')) == NULL)
enum cmd_retval cmd_pipe_pane_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c = cmdq->state.c; struct window_pane *wp = cmdq->state.tflag.wp; struct session *s = cmdq->state.tflag.s; struct winlink *wl = cmdq->state.tflag.wl; char *cmd; int old_fd, pipe_fd[2], null_fd; struct format_tree *ft; /* Destroy the old pipe. */ old_fd = wp->pipe_fd; if (wp->pipe_fd != -1) { bufferevent_free(wp->pipe_event); close(wp->pipe_fd); wp->pipe_fd = -1; } /* If no pipe command, that is enough. */ if (args->argc == 0 || *args->argv[0] == '\0') return (CMD_RETURN_NORMAL); /* * With -o, only open the new pipe if there was no previous one. This * allows a pipe to be toggled with a single key, for example: * * bind ^p pipep -o 'cat >>~/output' */ if (args_has(self->args, 'o') && old_fd != -1) return (CMD_RETURN_NORMAL); /* Open the new pipe. */ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) { cmdq_error(cmdq, "socketpair error: %s", strerror(errno)); return (CMD_RETURN_ERROR); } /* Expand the command. */ ft = format_create(cmdq, 0); format_defaults(ft, c, s, wl, wp); cmd = format_expand_time(ft, args->argv[0], time(NULL)); format_free(ft); /* Fork the child. */ switch (fork()) { case -1: cmdq_error(cmdq, "fork error: %s", strerror(errno)); free(cmd); return (CMD_RETURN_ERROR); case 0: /* Child process. */ close(pipe_fd[0]); clear_signals(1); if (dup2(pipe_fd[1], STDIN_FILENO) == -1) _exit(1); if (pipe_fd[1] != STDIN_FILENO) close(pipe_fd[1]); null_fd = open(_PATH_DEVNULL, O_WRONLY, 0); if (dup2(null_fd, STDOUT_FILENO) == -1) _exit(1); if (dup2(null_fd, STDERR_FILENO) == -1) _exit(1); if (null_fd != STDOUT_FILENO && null_fd != STDERR_FILENO) close(null_fd); closefrom(STDERR_FILENO + 1); execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); _exit(1); default: /* Parent process. */ close(pipe_fd[1]); wp->pipe_fd = pipe_fd[0]; wp->pipe_off = EVBUFFER_LENGTH(wp->event->input); wp->pipe_event = bufferevent_new(wp->pipe_fd, NULL, NULL, cmd_pipe_pane_error_callback, wp); bufferevent_enable(wp->pipe_event, EV_WRITE); setblocking(wp->pipe_fd, 0); free(cmd); 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)
enum cmd_retval cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct client *c = cmdq->client, *c0; struct session *s, *groupwith; struct window *w; struct environ env; struct termios tio, *tiop; const char *newname, *target, *update, *errstr, *template; const char *path; char **argv, *cmd, *cause, *cp; int detached, already_attached, idx, cwd, fd = -1; int argc; u_int sx, sy; struct format_tree *ft; struct environ_entry *envent; if (self->entry == &cmd_has_session_entry) { if (cmd_find_session(cmdq, args_get(args, 't'), 0) == NULL) return (CMD_RETURN_ERROR); return (CMD_RETURN_NORMAL); } if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) { cmdq_error(cmdq, "command or window name given with target"); return (CMD_RETURN_ERROR); } newname = args_get(args, 's'); if (newname != NULL) { if (!session_check_name(newname)) { cmdq_error(cmdq, "bad session name: %s", newname); return (CMD_RETURN_ERROR); } if (session_find(newname) != NULL) { if (args_has(args, 'A')) { return (cmd_attach_session(cmdq, newname, args_has(args, 'D'), 0, NULL, args_has(args, 'E'))); } cmdq_error(cmdq, "duplicate session: %s", newname); return (CMD_RETURN_ERROR); } } target = args_get(args, 't'); if (target != NULL) { groupwith = cmd_find_session(cmdq, target, 0); if (groupwith == NULL) return (CMD_RETURN_ERROR); } else groupwith = NULL; /* Set -d if no client. */ detached = args_has(args, 'd'); if (c == NULL) detached = 1; /* Is this client already attached? */ already_attached = 0; if (c != NULL && c->session != NULL) already_attached = 1; /* Get the new session working directory. */ if (args_has(args, 'c')) { ft = format_create(); format_defaults(ft, cmd_find_client(cmdq, NULL, 1), NULL, NULL, NULL); cp = format_expand(ft, args_get(args, 'c')); format_free(ft); if (cp != NULL && *cp != '\0') { 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); } } else if (cp != NULL) free(cp); cwd = fd; } else if (c != NULL && c->session == NULL) cwd = c->cwd; else if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL) cwd = c0->session->cwd; else { fd = open(".", O_RDONLY); cwd = fd; } /* * If this is a new client, check for nesting and save the termios * settings (part of which is used for new windows in this session). * * tcgetattr() is used rather than using tty.tio since if the client is * detached, tty_open won't be called. It must be done before opening * the terminal as that calls tcsetattr() to prepare for tmux taking * over. */ if (!detached && !already_attached && c->tty.fd != -1) { if (server_client_check_nested(cmdq->client)) { cmdq_error(cmdq, "sessions should be nested with care, " "unset $TMUX to force"); return (CMD_RETURN_ERROR); } if (tcgetattr(c->tty.fd, &tio) != 0) fatal("tcgetattr failed"); tiop = &tio; } else tiop = NULL; /* Open the terminal if necessary. */ if (!detached && !already_attached) { if (server_client_open(c, &cause) != 0) { cmdq_error(cmdq, "open terminal failed: %s", cause); free(cause); goto error; } } /* Find new session size. */ if (c != NULL) { sx = c->tty.sx; sy = c->tty.sy; } else { sx = 80; sy = 24; } if (detached && args_has(args, 'x')) { sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr); if (errstr != NULL) { cmdq_error(cmdq, "width %s", errstr); goto error; } } if (detached && args_has(args, 'y')) { sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr); if (errstr != NULL) { cmdq_error(cmdq, "height %s", errstr); goto error; } } if (sy > 0 && options_get_number(&global_s_options, "status")) sy--; if (sx == 0) sx = 1; if (sy == 0) sy = 1; /* Figure out the command for the new window. */ argc = -1; argv = NULL; if (target == NULL && args->argc != 0) { argc = args->argc; argv = args->argv; } else if (target == NULL) { cmd = options_get_string(&global_s_options, "default-command"); if (cmd != NULL && *cmd != '\0') { argc = 1; argv = &cmd; } else { argc = 0; argv = NULL; } } path = NULL; if (c != NULL && c->session == NULL) envent = environ_find(&c->environ, "PATH"); else envent = environ_find(&global_environ, "PATH"); if (envent != NULL) path = envent->value; /* Construct the environment. */ environ_init(&env); if (c != NULL && !args_has(args, 'E')) { update = options_get_string(&global_s_options, "update-environment"); environ_update(update, &c->environ, &env); } /* Create the new session. */ idx = -1 - options_get_number(&global_s_options, "base-index"); s = session_create(newname, argc, argv, path, cwd, &env, tiop, idx, sx, sy, &cause); if (s == NULL) { cmdq_error(cmdq, "create session failed: %s", cause); free(cause); goto error; } environ_free(&env); /* Set the initial window name if one given. */ if (argc >= 0 && args_has(args, 'n')) { w = s->curw->window; window_set_name(w, args_get(args, 'n')); options_set_number(&w->options, "automatic-rename", 0); } /* * If a target session is given, this is to be part of a session group, * so add it to the group and synchronize. */ if (groupwith != NULL) { session_group_add(groupwith, s); session_group_synchronize_to(s); session_select(s, RB_MIN(winlinks, &s->windows)->idx); } /* * Set the client to the new session. If a command client exists, it is * taking this session and needs to get MSG_READY and stay around. */ if (!detached) { if (!already_attached) server_write_ready(c); else if (c->session != NULL) c->last_session = c->session; c->session = s; status_timer_start(c); notify_attached_session_changed(c); session_update_activity(s); server_redraw_client(c); } recalculate_sizes(); server_update_socket(); /* * If there are still configuration file errors to display, put the new * session's current window into more mode and display them now. */ if (cfg_finished) cfg_show_causes(s); /* Print if requested. */ if (args_has(args, 'P')) { if ((template = args_get(args, 'F')) == NULL)
int set_axisgrid_data(AGridUI *ui, Quark *q, void *caller) { tickmarks *t = axisgrid_get_data(q); if (t && ui) { AMem *amem = quark_get_amem(q); int i; if (!caller || caller == ui->type) { t->type = GetOptionChoice(ui->type); } if (!caller || caller == ui->tmajor) { if (xv_evalexpr(ui->tmajor, &t->tmajor) != RETURN_SUCCESS) { errmsg("Specify major tick spacing"); return RETURN_FAILURE; } } if (!caller || caller == ui->nminor) { t->nminor = (int) SpinChoiceGetValue(ui->nminor); } if (!caller || caller == ui->tlform) { Format *format = GetFormatChoice(ui->tlform); AMem *amem = quark_get_amem(q); amem_free(amem, t->tl_format.fstring); t->tl_format = *format; t->tl_format.fstring = amem_strdup(amem, format->fstring); format_free(format); } if (!caller || caller == ui->tlfont) { t->tl_tprops.font = GetOptionChoice(ui->tlfont); } if (!caller || caller == ui->tlcolor) { t->tl_tprops.color = GetOptionChoice(ui->tlcolor); } if (!caller || caller == ui->barpen) { GetPenChoice(ui->barpen, &t->bar.pen); } if (!caller || caller == ui->barlinew) { t->bar.width = SpinChoiceGetValue(ui->barlinew); } if (!caller || caller == ui->barlines) { t->bar.style = GetOptionChoice(ui->barlines); } if (!caller || caller == ui->tlcharsize) { t->tl_tprops.charsize = SpinChoiceGetValue(ui->tlcharsize); } if (!caller || caller == ui->tlangle) { t->tl_tprops.angle = GetAngleChoice(ui->tlangle); } if (!caller || caller == ui->tlstagger) { t->tl_staggered = GetOptionChoice(ui->tlstagger); } if (!caller || caller == ui->tlstarttype) { t->tl_starttype = GetOptionChoice(ui->tlstarttype) == 0 ? TYPE_AUTO : TYPE_SPEC; } if (!caller || caller == ui->tlstart) { if (t->tl_starttype == TYPE_SPEC) { if (xv_evalexpr(ui->tlstart, &t->tl_start) != RETURN_SUCCESS) { errmsg("Specify tick label start"); return RETURN_FAILURE; } } } if (!caller || caller == ui->tlstoptype) { t->tl_stoptype = GetOptionChoice(ui->tlstoptype) == 0 ? TYPE_AUTO : TYPE_SPEC; } if (!caller || caller == ui->tlstop) { if (t->tl_stoptype == TYPE_SPEC) { if (xv_evalexpr(ui->tlstop, &t->tl_stop) != RETURN_SUCCESS) { errmsg("Specify tick label stop"); return RETURN_FAILURE; } } } if (!caller || caller == ui->tlskip) { t->tl_skip = GetOptionChoice(ui->tlskip); } if (!caller || caller == ui->tlformula) { char *s = TextGetString(ui->tlformula); t->tl_formula = amem_strcpy(amem, t->tl_formula, s); xfree(s); } if (!caller || caller == ui->tlprestr) { char *s = TextGetString(ui->tlprestr); t->tl_prestr = amem_strcpy(amem, t->tl_prestr, s); xfree(s); } if (!caller || caller == ui->tlappstr) { char *s = TextGetString(ui->tlappstr); t->tl_appstr = amem_strcpy(amem, t->tl_appstr, s); xfree(s); } if (!caller || caller == ui->tlgap_para) { xv_evalexpr(ui->tlgap_para, &t->tl_gap.x); } if (!caller || caller == ui->tlgap_perp) { xv_evalexpr(ui->tlgap_perp, &t->tl_gap.y); } if (!caller || caller == ui->tround) { t->t_round = ToggleButtonGetState(ui->tround); } if (!caller || caller == ui->autonum) { t->t_autonum = GetOptionChoice(ui->autonum) + 2; } if (!caller || caller == ui->tgrid) { t->gprops.onoff = ToggleButtonGetState(ui->tgrid); } if (!caller || caller == ui->tgridpen) { GetPenChoice(ui->tgridpen, &t->gprops.line.pen); } if (!caller || caller == ui->tgridlinew) { t->gprops.line.width = SpinChoiceGetValue(ui->tgridlinew); } if (!caller || caller == ui->tgridlines) { t->gprops.line.style = GetOptionChoice(ui->tgridlines); } if (!caller || caller == ui->tmgrid) { t->mgprops.onoff = ToggleButtonGetState(ui->tmgrid); } if (!caller || caller == ui->tmgridpen) { GetPenChoice(ui->tmgridpen, &t->mgprops.line.pen); } if (!caller || caller == ui->tmgridlinew) { t->mgprops.line.width = SpinChoiceGetValue(ui->tmgridlinew); } if (!caller || caller == ui->tmgridlines) { t->mgprops.line.style = GetOptionChoice(ui->tmgridlines); } if (!caller || caller == ui->tinout) { t->props.inout = GetOptionChoice(ui->tinout); } if (!caller || caller == ui->tlen) { t->props.size = SpinChoiceGetValue(ui->tlen); } if (!caller || caller == ui->tpen) { GetPenChoice(ui->tpen, &t->props.line.pen); } if (!caller || caller == ui->tgridlinew) { t->props.line.width = SpinChoiceGetValue(ui->tlinew); } if (!caller || caller == ui->tgridlines) { t->props.line.style = GetOptionChoice(ui->tlines); } if (!caller || caller == ui->tminout) { t->mprops.inout = GetOptionChoice(ui->tminout); } if (!caller || caller == ui->tmlen) { t->mprops.size = SpinChoiceGetValue(ui->tmlen); } if (!caller || caller == ui->tmpen) { GetPenChoice(ui->tmpen, &t->mprops.line.pen); } if (!caller || caller == ui->tmgridlinew) { t->mprops.line.width = SpinChoiceGetValue(ui->tmlinew); } if (!caller || caller == ui->tmgridlines) { t->mprops.line.style = GetOptionChoice(ui->tmlines); } if (!caller || caller == ui->specticks || caller == ui->nspec || caller == ui->specloc) { t->t_spec = GetOptionChoice(ui->specticks); /* only read special info if special ticks used */ if (t->t_spec != TICKS_SPEC_NONE) { t->nticks = (int) SpinChoiceGetValue(ui->nspec); /* ensure that enough tick positions have been specified */ for (i = 0; i < t->nticks; i++) { if (xv_evalexpr(ui->specloc[i], &t->tloc[i].wtpos) == RETURN_SUCCESS) { char *cp, *s; cp = TextGetString(ui->speclabel[i]); if (cp[0] == '\0') { t->tloc[i].type = TICK_TYPE_MINOR; } else { t->tloc[i].type = TICK_TYPE_MAJOR; } if (t->t_spec == TICKS_SPEC_BOTH) { s = cp; } else { s = NULL; } t->tloc[i].label = amem_strcpy(amem, t->tloc[i].label, s); xfree(cp); } } } } quark_dirtystate_set(q, TRUE); return RETURN_SUCCESS; } else { return RETURN_FAILURE; } }
static void window_buffer_build(void *modedata, u_int sort_type, __unused uint64_t *tag, const char *filter) { struct window_buffer_modedata *data = modedata; struct window_buffer_itemdata *item; u_int i; struct paste_buffer *pb; char *text, *cp; struct format_tree *ft; struct session *s = NULL; struct winlink *wl = NULL; struct window_pane *wp = NULL; for (i = 0; i < data->item_size; i++) window_buffer_free_item(data->item_list[i]); free(data->item_list); data->item_list = NULL; data->item_size = 0; pb = NULL; while ((pb = paste_walk(pb)) != NULL) { item = window_buffer_add_item(data); item->name = xstrdup(paste_buffer_name(pb)); paste_buffer_data(pb, &item->size); item->order = paste_buffer_order(pb); } switch (sort_type) { case WINDOW_BUFFER_BY_NAME: qsort(data->item_list, data->item_size, sizeof *data->item_list, window_buffer_cmp_name); break; case WINDOW_BUFFER_BY_TIME: qsort(data->item_list, data->item_size, sizeof *data->item_list, window_buffer_cmp_time); break; case WINDOW_BUFFER_BY_SIZE: qsort(data->item_list, data->item_size, sizeof *data->item_list, window_buffer_cmp_size); break; } if (cmd_find_valid_state(&data->fs)) { s = data->fs.s; wl = data->fs.wl; wp = data->fs.wp; } for (i = 0; i < data->item_size; i++) { item = data->item_list[i]; pb = paste_get_name(item->name); if (pb == NULL) continue; ft = format_create(NULL, NULL, FORMAT_NONE, 0); format_defaults(ft, NULL, s, wl, wp); format_defaults_paste_buffer(ft, pb); if (filter != NULL) { cp = format_expand(ft, filter); if (!format_true(cp)) { free(cp); format_free(ft); continue; } free(cp); } text = format_expand(ft, data->format); mode_tree_add(data->data, NULL, item, item->order, item->name, text, -1); free(text); format_free(ft); } }
enum cmd_retval cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag, const char *cflag) { struct session *s; struct client *c; struct winlink *wl = NULL; struct window *w = NULL; struct window_pane *wp = NULL; const char *update; char *cause; u_int i; int fd; struct format_tree *ft; char *cp; if (RB_EMPTY(&sessions)) { cmdq_error(cmdq, "no sessions"); return (CMD_RETURN_ERROR); } if (tflag == NULL) { if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL) return (CMD_RETURN_ERROR); } else if (tflag[strcspn(tflag, ":.")] != '\0') { if ((wl = cmd_find_pane(cmdq, tflag, &s, &wp)) == NULL) return (CMD_RETURN_ERROR); } else { if ((s = cmd_find_session(cmdq, tflag, 1)) == NULL) return (CMD_RETURN_ERROR); w = cmd_lookup_windowid(tflag); if (w == NULL && (wp = cmd_lookup_paneid(tflag)) != NULL) w = wp->window; if (w != NULL) wl = winlink_find_by_window(&s->windows, w); } if (cmdq->client == NULL) return (CMD_RETURN_NORMAL); if (wl != NULL) { if (wp != NULL) window_set_active_pane(wp->window, wp); session_set_current(s, wl); } if (cmdq->client->session != NULL) { if (dflag) { /* * Can't use server_write_session in case attaching to * the same session as currently attached to. */ for (i = 0; i < ARRAY_LENGTH(&clients); i++) { c = ARRAY_ITEM(&clients, i); if (c == NULL || c->session != s) continue; if (c == cmdq->client) continue; server_write_client(c, MSG_DETACH, c->session->name, strlen(c->session->name) + 1); } } if (cflag != NULL) { 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, cflag); 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); } close(s->cwd); s->cwd = fd; } cmdq->client->session = s; notify_attached_session_changed(cmdq->client); session_update_activity(s); server_redraw_client(cmdq->client); s->curw->flags &= ~WINLINK_ALERTFLAGS; } else { if (server_client_open(cmdq->client, s, &cause) != 0) { cmdq_error(cmdq, "open terminal failed: %s", cause); free(cause); return (CMD_RETURN_ERROR); } if (cflag != NULL) { 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, cflag); 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); } close(s->cwd); s->cwd = fd; } if (rflag) cmdq->client->flags |= CLIENT_READONLY; if (dflag) { server_write_session(s, MSG_DETACH, s->name, strlen(s->name) + 1); } update = options_get_string(&s->options, "update-environment"); environ_update(update, &cmdq->client->environ, &s->environ); cmdq->client->session = s; notify_attached_session_changed(cmdq->client); session_update_activity(s); server_redraw_client(cmdq->client); s->curw->flags &= ~WINLINK_ALERTFLAGS; server_write_ready(cmdq->client); cmdq->client_exit = 0; } recalculate_sizes(); server_update_socket(); return (CMD_RETURN_NORMAL); }
static enum cmd_retval cmd_pipe_pane_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = self->args; struct client *c = cmd_find_client(item, NULL, 1); struct window_pane *wp = item->target.wp; struct session *s = item->target.s; struct winlink *wl = item->target.wl; char *cmd; int old_fd, pipe_fd[2], null_fd, in, out; struct format_tree *ft; sigset_t set, oldset; /* Destroy the old pipe. */ old_fd = wp->pipe_fd; if (wp->pipe_fd != -1) { bufferevent_free(wp->pipe_event); close(wp->pipe_fd); wp->pipe_fd = -1; if (window_pane_destroy_ready(wp)) { server_destroy_pane(wp, 1); return (CMD_RETURN_NORMAL); } } /* If no pipe command, that is enough. */ if (args->argc == 0 || *args->argv[0] == '\0') return (CMD_RETURN_NORMAL); /* * With -o, only open the new pipe if there was no previous one. This * allows a pipe to be toggled with a single key, for example: * * bind ^p pipep -o 'cat >>~/output' */ if (args_has(self->args, 'o') && old_fd != -1) return (CMD_RETURN_NORMAL); /* What do we want to do? Neither -I or -O is -O. */ if (args_has(self->args, 'I')) { in = 1; out = args_has(self->args, 'O'); } else { in = 0; out = 1; } /* Open the new pipe. */ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_fd) != 0) { cmdq_error(item, "socketpair error: %s", strerror(errno)); return (CMD_RETURN_ERROR); } /* Expand the command. */ ft = format_create(item->client, item, FORMAT_NONE, 0); format_defaults(ft, c, s, wl, wp); cmd = format_expand_time(ft, args->argv[0]); format_free(ft); /* Fork the child. */ sigfillset(&set); sigprocmask(SIG_BLOCK, &set, &oldset); switch (fork()) { case -1: sigprocmask(SIG_SETMASK, &oldset, NULL); cmdq_error(item, "fork error: %s", strerror(errno)); free(cmd); return (CMD_RETURN_ERROR); case 0: /* Child process. */ proc_clear_signals(server_proc, 1); sigprocmask(SIG_SETMASK, &oldset, NULL); close(pipe_fd[0]); null_fd = open(_PATH_DEVNULL, O_WRONLY, 0); if (out) { if (dup2(pipe_fd[1], STDIN_FILENO) == -1) _exit(1); } else { if (dup2(null_fd, STDIN_FILENO) == -1) _exit(1); } if (in) { if (dup2(pipe_fd[1], STDOUT_FILENO) == -1) _exit(1); if (pipe_fd[1] != STDOUT_FILENO) close(pipe_fd[1]); } else { if (dup2(null_fd, STDOUT_FILENO) == -1) _exit(1); } if (dup2(null_fd, STDERR_FILENO) == -1) _exit(1); closefrom(STDERR_FILENO + 1); execl(_PATH_BSHELL, "sh", "-c", cmd, (char *) NULL); _exit(1); default: /* Parent process. */ sigprocmask(SIG_SETMASK, &oldset, NULL); close(pipe_fd[1]); wp->pipe_fd = pipe_fd[0]; if (wp->fd != -1) wp->pipe_off = EVBUFFER_LENGTH(wp->event->input); else wp->pipe_off = 0; setblocking(wp->pipe_fd, 0); wp->pipe_event = bufferevent_new(wp->pipe_fd, cmd_pipe_pane_read_callback, cmd_pipe_pane_write_callback, cmd_pipe_pane_error_callback, wp); if (wp->pipe_event == NULL) fatalx("out of memory"); if (out) bufferevent_enable(wp->pipe_event, EV_WRITE); if (in) bufferevent_enable(wp->pipe_event, EV_READ); free(cmd); return (CMD_RETURN_NORMAL); } }
enum cmd_retval cmd_if_shell_exec(struct cmd *self, struct cmd_q *cmdq) { struct args *args = self->args; struct cmd_if_shell_data *cdata; char *shellcmd, *cmd, *cause; struct cmd_list *cmdlist; struct client *c; struct session *s = NULL; struct winlink *wl = NULL; struct window_pane *wp = NULL; struct format_tree *ft; int cwd; if (args_has(args, 't')) { wl = cmd_find_pane(cmdq, args_get(args, 't'), &s, &wp); cwd = wp->cwd; } else { c = cmd_find_client(cmdq, NULL, 1); if (c != NULL && c->session != NULL) { s = c->session; wl = s->curw; wp = wl->window->active; } if (cmdq->client != NULL && cmdq->client->session == NULL) cwd = cmdq->client->cwd; else if (s != NULL) cwd = s->cwd; else cwd = -1; } ft = format_create(); format_defaults(ft, NULL, s, wl, wp); shellcmd = format_expand(ft, args->argv[0]); format_free(ft); if (args_has(args, 'F')) { cmd = NULL; if (*shellcmd != '0' && *shellcmd != '\0') cmd = args->argv[1]; else if (args->argc == 3) cmd = args->argv[2]; if (cmd == NULL) return (CMD_RETURN_NORMAL); if (cmd_string_parse(cmd, &cmdlist, NULL, 0, &cause) != 0) { if (cause != NULL) { cmdq_error(cmdq, "%s", cause); free(cause); } return (CMD_RETURN_ERROR); } cmdq_run(cmdq, cmdlist, &cmdq->item->mouse); cmd_list_free(cmdlist); return (CMD_RETURN_NORMAL); } cdata = xmalloc(sizeof *cdata); cdata->cmd_if = xstrdup(args->argv[1]); if (args->argc == 3) cdata->cmd_else = xstrdup(args->argv[2]); else cdata->cmd_else = NULL; cdata->bflag = args_has(args, 'b'); cdata->cmdq = cmdq; memcpy(&cdata->mouse, &cmdq->item->mouse, sizeof cdata->mouse); cmdq->references++; cdata->references = 1; job_run(shellcmd, s, cwd, cmd_if_shell_callback, cmd_if_shell_free, cdata); free(shellcmd); if (cdata->bflag) return (CMD_RETURN_NORMAL); return (CMD_RETURN_WAIT); }
int graph_set_data(GraphUI *ui, Quark *q, void *caller) { if (quark_fid_get(q) == QFlavorGraph) { double axislim, znorm; world w; GLocator *locator; graph_get_world(q, &w); locator = graph_get_locator(q); if (!caller || caller == ui->graph_type) { graph_set_type(q, GetOptionChoice(ui->graph_type)); } if (!caller || caller == ui->stacked) { graph_set_stacked(q, GetToggleButtonState(ui->stacked)); } if (!caller || caller == ui->flip_xy) { graph_set_xyflip(q, GetToggleButtonState(ui->flip_xy)); } if (!caller || caller == ui->start_x) { if (xv_evalexpr(ui->start_x, &axislim) != RETURN_SUCCESS) { errmsg("Axis start/stop values undefined"); return RETURN_FAILURE; } w.xg1 = axislim; } if (!caller || caller == ui->stop_x) { if (xv_evalexpr(ui->stop_x, &axislim) != RETURN_SUCCESS) { errmsg("Axis start/stop values undefined"); return RETURN_FAILURE; } w.xg2 = axislim; } if (!caller || caller == ui->start_y) { if (xv_evalexpr(ui->start_y, &axislim) != RETURN_SUCCESS) { errmsg("Axis start/stop values undefined"); return RETURN_FAILURE; } w.yg1 = axislim; } if (!caller || caller == ui->stop_y) { if (xv_evalexpr(ui->stop_y, &axislim) != RETURN_SUCCESS) { errmsg("Axis start/stop values undefined"); return RETURN_FAILURE; } w.yg2 = axislim; } if (!caller || caller == ui->start_x || caller == ui->stop_x || caller == ui->start_y || caller == ui->stop_y) { graph_set_world(q, &w); } if (!caller || caller == ui->scale_x) { graph_set_xscale(q, GetOptionChoice(ui->scale_x)); } if (!caller || caller == ui->invert_x) { graph_set_xinvert(q, GetToggleButtonState(ui->invert_x)); } if (!caller || caller == ui->scale_y) { graph_set_yscale(q, GetOptionChoice(ui->scale_y)); } if (!caller || caller == ui->invert_y) { graph_set_yinvert(q, GetToggleButtonState(ui->invert_y)); } if (!caller || caller == ui->bargap) { graph_set_bargap(q, GetSpinChoice(ui->bargap)); } if (!caller || caller == ui->znorm) { xv_evalexpr(ui->znorm, &znorm); graph_set_znorm(q, znorm); } if (!caller || caller == ui->loc_type) { locator->type = GetOptionChoice(ui->loc_type); quark_dirtystate_set(q, TRUE); } if (!caller || caller == ui->loc_fx) { Format *format = GetFormatChoice(ui->loc_fx); AMem *amem = quark_get_amem(q); amem_free(amem, locator->fx.fstring); locator->fx = *format; locator->fx.fstring = amem_strdup(amem, format->fstring); format_free(format); quark_dirtystate_set(q, TRUE); } if (!caller || caller == ui->loc_fy) { Format *format = GetFormatChoice(ui->loc_fy); AMem *amem = quark_get_amem(q); amem_free(amem, locator->fy.fstring); locator->fy = *format; locator->fy.fstring = amem_strdup(amem, format->fstring); format_free(format); quark_dirtystate_set(q, TRUE); } if (!caller || caller == ui->fixedp) { locator->pointset = GetToggleButtonState(ui->fixedp); quark_dirtystate_set(q, TRUE); } if (!caller || caller == ui->locx) { xv_evalexpr(ui->locx, &locator->origin.x); quark_dirtystate_set(q, TRUE); } if (!caller || caller == ui->locy) { xv_evalexpr(ui->locy, &locator->origin.y); quark_dirtystate_set(q, TRUE); } return RETURN_SUCCESS; } else { return RETURN_FAILURE; } }
static enum cmd_retval cmd_new_session_exec(struct cmd *self, struct cmdq_item *item) { struct args *args = self->args; struct client *c = item->client; struct session *s, *as; struct session *groupwith = item->state.tflag.s; struct window *w; struct environ *env; struct termios tio, *tiop; const char *newname, *target, *update, *errstr, *template; const char *path, *cwd, *to_free = NULL; char **argv, *cmd, *cause, *cp; int detached, already_attached, idx, argc; u_int sx, sy; struct format_tree *ft; struct environ_entry *envent; struct cmd_find_state fs; if (self->entry == &cmd_has_session_entry) { /* * cmd_prepare() will fail if the session cannot be found, * hence always return success here. */ return (CMD_RETURN_NORMAL); } if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) { cmdq_error(item, "command or window name given with target"); return (CMD_RETURN_ERROR); } newname = args_get(args, 's'); if (newname != NULL) { if (!session_check_name(newname)) { cmdq_error(item, "bad session name: %s", newname); return (CMD_RETURN_ERROR); } if ((as = session_find(newname)) != NULL) { if (args_has(args, 'A')) { /* * This item is now destined for * attach-session. Because attach-session will * have already been prepared, copy this * session into its tflag so it can be used. */ cmd_find_from_session(&item->state.tflag, as); return (cmd_attach_session(item, args_has(args, 'D'), 0, NULL, args_has(args, 'E'))); } cmdq_error(item, "duplicate session: %s", newname); return (CMD_RETURN_ERROR); } } if ((target = args_get(args, 't')) != NULL) { if (groupwith == NULL) { cmdq_error(item, "no such session: %s", target); goto error; } } else groupwith = NULL; /* Set -d if no client. */ detached = args_has(args, 'd'); if (c == NULL) detached = 1; /* Is this client already attached? */ already_attached = 0; if (c != NULL && c->session != NULL) already_attached = 1; /* Get the new session working directory. */ if (args_has(args, 'c')) { ft = format_create(item, 0); format_defaults(ft, c, NULL, NULL, NULL); to_free = cwd = format_expand(ft, args_get(args, 'c')); format_free(ft); } else if (c != NULL && c->session == NULL && c->cwd != NULL) cwd = c->cwd; else cwd = "."; /* * If this is a new client, check for nesting and save the termios * settings (part of which is used for new windows in this session). * * tcgetattr() is used rather than using tty.tio since if the client is * detached, tty_open won't be called. It must be done before opening * the terminal as that calls tcsetattr() to prepare for tmux taking * over. */ if (!detached && !already_attached && c->tty.fd != -1) { if (server_client_check_nested(item->client)) { cmdq_error(item, "sessions should be nested with care, " "unset $TMUX to force"); return (CMD_RETURN_ERROR); } if (tcgetattr(c->tty.fd, &tio) != 0) fatal("tcgetattr failed"); tiop = &tio; } else tiop = NULL; /* Open the terminal if necessary. */ if (!detached && !already_attached) { if (server_client_open(c, &cause) != 0) { cmdq_error(item, "open terminal failed: %s", cause); free(cause); goto error; } } /* Find new session size. */ if (c != NULL) { sx = c->tty.sx; sy = c->tty.sy; } else { sx = 80; sy = 24; } if (detached && args_has(args, 'x')) { sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr); if (errstr != NULL) { cmdq_error(item, "width %s", errstr); goto error; } } if (detached && args_has(args, 'y')) { sy = strtonum(args_get(args, 'y'), 1, USHRT_MAX, &errstr); if (errstr != NULL) { cmdq_error(item, "height %s", errstr); goto error; } } if (sy > 0 && options_get_number(global_s_options, "status")) sy--; if (sx == 0) sx = 1; if (sy == 0) sy = 1; /* Figure out the command for the new window. */ argc = -1; argv = NULL; if (!args_has(args, 't') && args->argc != 0) { argc = args->argc; argv = args->argv; } else if (groupwith == NULL) { cmd = options_get_string(global_s_options, "default-command"); if (cmd != NULL && *cmd != '\0') { argc = 1; argv = &cmd; } else { argc = 0; argv = NULL; } } path = NULL; if (c != NULL && c->session == NULL) envent = environ_find(c->environ, "PATH"); else envent = environ_find(global_environ, "PATH"); if (envent != NULL) path = envent->value; /* Construct the environment. */ env = environ_create(); if (c != NULL && !args_has(args, 'E')) { update = options_get_string(global_s_options, "update-environment"); environ_update(update, c->environ, env); } /* Create the new session. */ idx = -1 - options_get_number(global_s_options, "base-index"); s = session_create(newname, argc, argv, path, cwd, env, tiop, idx, sx, sy, &cause); environ_free(env); if (s == NULL) { cmdq_error(item, "create session failed: %s", cause); free(cause); goto error; } /* Set the initial window name if one given. */ if (argc >= 0 && args_has(args, 'n')) { w = s->curw->window; window_set_name(w, args_get(args, 'n')); options_set_number(w->options, "automatic-rename", 0); } /* * If a target session is given, this is to be part of a session group, * so add it to the group and synchronize. */ if (groupwith != NULL) { session_group_add(groupwith, s); session_group_synchronize_to(s); session_select(s, RB_MIN(winlinks, &s->windows)->idx); } notify_session("session-created", s); /* * Set the client to the new session. If a command client exists, it is * taking this session and needs to get MSG_READY and stay around. */ if (!detached) { if (!already_attached) { if (~c->flags & CLIENT_CONTROL) proc_send(c->peer, MSG_READY, -1, NULL, 0); } else if (c->session != NULL) c->last_session = c->session; c->session = s; server_client_set_key_table(c, NULL); status_timer_start(c); notify_client("client-session-changed", c); session_update_activity(s, NULL); gettimeofday(&s->last_attached_time, NULL); server_redraw_client(c); } recalculate_sizes(); server_update_socket(); /* * If there are still configuration file errors to display, put the new * session's current window into more mode and display them now. */ if (cfg_finished) cfg_show_causes(s); /* Print if requested. */ if (args_has(args, 'P')) { if ((template = args_get(args, 'F')) == NULL)