mirror of
https://github.com/tmux/tmux.git
synced 2024-11-16 01:18:52 +00:00
Merge branch 'obsd-master'
This commit is contained in:
commit
2311bbd28a
20
client.c
20
client.c
@ -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");
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
6
tmux.1
@ -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
2
tmux.h
@ -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 *);
|
||||||
|
Loading…
Reference in New Issue
Block a user