Merge branch 'obsd-master'

This commit is contained in:
Thomas Adam 2017-01-13 12:01:12 +00:00
commit 2311bbd28a
5 changed files with 74 additions and 7 deletions

View File

@ -50,6 +50,8 @@ static enum {
static int client_exitval; static int client_exitval;
static enum msgtype client_exittype; static enum msgtype client_exittype;
static const char *client_exitsession; static const char *client_exitsession;
static const char *client_execshell;
static const char *client_execcmd;
static int client_attached; static int client_attached;
static __dead void client_exec(const char *,const char *); static __dead void client_exec(const char *,const char *);
@ -361,6 +363,14 @@ client_main(struct event_base *base, int argc, char **argv, int flags,
/* Start main loop. */ /* Start main loop. */
proc_loop(client_proc, NULL); proc_loop(client_proc, NULL);
/* Run command if user requested exec, instead of exiting. */
if (client_exittype == MSG_EXEC) {
if (client_flags & CLIENT_CONTROLCONTROL)
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
clear_signals(0);
client_exec(client_execshell, client_execcmd);
}
/* Print the exit message, if any, and exit. */ /* Print the exit message, if any, and exit. */
if (client_attached) { if (client_attached) {
if (client_exitreason != CLIENT_EXIT_NONE) if (client_exitreason != CLIENT_EXIT_NONE)
@ -660,6 +670,16 @@ client_dispatch_attached(struct imsg *imsg)
client_exitreason = CLIENT_EXIT_DETACHED; client_exitreason = CLIENT_EXIT_DETACHED;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0); proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break; break;
case MSG_EXEC:
if (datalen == 0 || data[datalen - 1] != '\0' ||
strlen(data) + 1 == (size_t)datalen)
fatalx("bad MSG_EXEC string");
client_execcmd = xstrdup(data);
client_execshell = xstrdup(data + strlen(data) + 1);
client_exittype = imsg->hdr.type;
proc_send(client_peer, MSG_EXITING, -1, NULL, 0);
break;
case MSG_EXIT: case MSG_EXIT:
if (datalen != 0 && datalen != sizeof (int)) if (datalen != 0 && datalen != sizeof (int))
fatalx("bad MSG_EXIT size"); fatalx("bad MSG_EXIT size");

View File

@ -33,8 +33,9 @@ const struct cmd_entry cmd_detach_client_entry = {
.name = "detach-client", .name = "detach-client",
.alias = "detach", .alias = "detach",
.args = { "as:t:P", 0, 0 }, .args = { "aE:s:t:P", 0, 0 },
.usage = "[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE, .usage = "[-aP] [-E shell-command] "
"[-s target-session] " CMD_TARGET_CLIENT_USAGE,
.sflag = CMD_SESSION, .sflag = CMD_SESSION,
.tflag = CMD_CLIENT, .tflag = CMD_CLIENT,
@ -63,6 +64,7 @@ cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
struct client *c = item->state.c, *cloop; struct client *c = item->state.c, *cloop;
struct session *s; struct session *s;
enum msgtype msgtype; enum msgtype msgtype;
const char *cmd = args_get(args, 'E');
if (self->entry == &cmd_suspend_client_entry) { if (self->entry == &cmd_suspend_client_entry) {
tty_stop_tty(&c->tty); tty_stop_tty(&c->tty);
@ -79,20 +81,31 @@ cmd_detach_client_exec(struct cmd *self, struct cmdq_item *item)
if (args_has(args, 's')) { if (args_has(args, 's')) {
s = item->state.sflag.s; s = item->state.sflag.s;
TAILQ_FOREACH(cloop, &clients, entry) { TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session == s) if (cloop->session == s) {
server_client_detach(cloop, msgtype); if (cmd != NULL)
server_client_exec(cloop, cmd);
else
server_client_detach(cloop, msgtype);
}
} }
return (CMD_RETURN_STOP); return (CMD_RETURN_STOP);
} }
if (args_has(args, 'a')) { if (args_has(args, 'a')) {
TAILQ_FOREACH(cloop, &clients, entry) { TAILQ_FOREACH(cloop, &clients, entry) {
if (cloop->session != NULL && cloop != c) if (cloop->session != NULL && cloop != c) {
server_client_detach(cloop, msgtype); if (cmd != NULL)
server_client_exec(cloop, cmd);
else
server_client_detach(cloop, msgtype);
}
} }
return (CMD_RETURN_NORMAL); return (CMD_RETURN_NORMAL);
} }
server_client_detach(c, msgtype); if (cmd != NULL)
server_client_exec(c, cmd);
else
server_client_detach(c, msgtype);
return (CMD_RETURN_STOP); return (CMD_RETURN_STOP);
} }

View File

@ -294,6 +294,32 @@ server_client_detach(struct client *c, enum msgtype msgtype)
proc_send_s(c->peer, msgtype, s->name); proc_send_s(c->peer, msgtype, s->name);
} }
/* Execute command to replace a client, */
void
server_client_exec(struct client *c, const char *cmd)
{
struct session *s = c->session;
char *msg, *shell;
size_t cmdsize, shellsize;
if (*cmd == '\0')
return;
cmdsize = strlen(cmd) + 1;
if (s != NULL)
shell = options_get_string(s->options, "default-shell");
else
shell = options_get_string(global_s_options, "default-shell");
shellsize = strlen(shell) + 1;
msg = xmalloc(cmdsize + shellsize);
memcpy(msg, cmd, cmdsize);
memcpy(msg + cmdsize, shell, shellsize);
proc_send(c->peer, MSG_EXEC, -1, msg, cmdsize + shellsize);
free(msg);
}
/* Check for mouse keys. */ /* Check for mouse keys. */
static key_code static key_code
server_client_check_mouse(struct client *c) server_client_check_mouse(struct client *c)

6
tmux.1
View File

@ -728,6 +728,7 @@ is used, the
option will not be applied. option will not be applied.
.It Xo Ic detach-client .It Xo Ic detach-client
.Op Fl aP .Op Fl aP
.Op Fl E Ar shell-command
.Op Fl s Ar target-session .Op Fl s Ar target-session
.Op Fl t Ar target-client .Op Fl t Ar target-client
.Xc .Xc
@ -744,6 +745,11 @@ If
.Fl P .Fl P
is given, send SIGHUP to the parent process of the client, typically causing it is given, send SIGHUP to the parent process of the client, typically causing it
to exit. to exit.
With
.Fl E ,
run
.Ar shell-command
to replace the client.
.It Ic has-session Op Fl t Ar target-session .It Ic has-session Op Fl t Ar target-session
.D1 (alias: Ic has ) .D1 (alias: Ic has )
Report an error and exit with 1 if the specified session does not exist. Report an error and exit with 1 if the specified session does not exist.

2
tmux.h
View File

@ -445,6 +445,7 @@ enum msgtype {
MSG_SUSPEND, MSG_SUSPEND,
MSG_UNLOCK, MSG_UNLOCK,
MSG_WAKEUP, MSG_WAKEUP,
MSG_EXEC,
}; };
/* /*
@ -1882,6 +1883,7 @@ int server_client_open(struct client *, char **);
void server_client_unref(struct client *); void server_client_unref(struct client *);
void server_client_lost(struct client *); void server_client_lost(struct client *);
void server_client_detach(struct client *, enum msgtype); void server_client_detach(struct client *, enum msgtype);
void server_client_exec(struct client *, const char *);
void server_client_loop(void); void server_client_loop(void);
void server_client_push_stdout(struct client *); void server_client_push_stdout(struct client *);
void server_client_push_stderr(struct client *); void server_client_push_stderr(struct client *);