mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-23 08:33:17 +01:00
Merge branch 'obsd-master' into mtemp
This commit is contained in:
commit
7f479ffdce
190
client.c
190
client.c
@ -48,13 +48,14 @@ enum {
|
||||
} client_exitreason = CLIENT_EXIT_NONE;
|
||||
int client_exitval;
|
||||
enum msgtype client_exittype;
|
||||
const char *client_exitsession;
|
||||
int client_attached;
|
||||
|
||||
int client_get_lock(char *);
|
||||
int client_connect(char *, int);
|
||||
void client_send_identify(int);
|
||||
void client_send_environ(void);
|
||||
void client_write_server(enum msgtype, void *, size_t);
|
||||
int client_write_one(enum msgtype, int, const void *, size_t);
|
||||
int client_write_server(enum msgtype, const void *, size_t);
|
||||
void client_update_event(void);
|
||||
void client_signal(int, short, void *);
|
||||
void client_stdin_callback(int, short, void *);
|
||||
@ -138,12 +139,24 @@ failed:
|
||||
const char *
|
||||
client_exit_message(void)
|
||||
{
|
||||
static char msg[256];
|
||||
|
||||
switch (client_exitreason) {
|
||||
case CLIENT_EXIT_NONE:
|
||||
break;
|
||||
case CLIENT_EXIT_DETACHED:
|
||||
if (client_exitsession != NULL) {
|
||||
xsnprintf(msg, sizeof msg, "detached "
|
||||
"(from session %s)", client_exitsession);
|
||||
return (msg);
|
||||
}
|
||||
return ("detached");
|
||||
case CLIENT_EXIT_DETACHED_HUP:
|
||||
if (client_exitsession != NULL) {
|
||||
xsnprintf(msg, sizeof msg, "detached and SIGHUP "
|
||||
"(from session %s)", client_exitsession);
|
||||
return (msg);
|
||||
}
|
||||
return ("detached and SIGHUP");
|
||||
case CLIENT_EXIT_LOST_TTY:
|
||||
return ("lost tty");
|
||||
@ -165,12 +178,13 @@ client_main(int argc, char **argv, int flags)
|
||||
{
|
||||
struct cmd *cmd;
|
||||
struct cmd_list *cmdlist;
|
||||
struct msg_command_data cmddata;
|
||||
int cmdflags, fd;
|
||||
struct msg_command_data *data;
|
||||
int cmdflags, fd, i;
|
||||
pid_t ppid;
|
||||
enum msgtype msg;
|
||||
char *cause;
|
||||
struct termios tio, saved_tio;
|
||||
size_t size;
|
||||
|
||||
/* Set up the initial command. */
|
||||
cmdflags = 0;
|
||||
@ -179,7 +193,7 @@ client_main(int argc, char **argv, int flags)
|
||||
cmdflags = CMD_STARTSERVER;
|
||||
} else if (argc == 0) {
|
||||
msg = MSG_COMMAND;
|
||||
cmdflags = CMD_STARTSERVER|CMD_SENDENVIRON|CMD_CANTNEST;
|
||||
cmdflags = CMD_STARTSERVER|CMD_CANTNEST;
|
||||
} else {
|
||||
msg = MSG_COMMAND;
|
||||
|
||||
@ -197,8 +211,6 @@ client_main(int argc, char **argv, int flags)
|
||||
TAILQ_FOREACH(cmd, &cmdlist->list, qentry) {
|
||||
if (cmd->entry->flags & CMD_STARTSERVER)
|
||||
cmdflags |= CMD_STARTSERVER;
|
||||
if (cmd->entry->flags & CMD_SENDENVIRON)
|
||||
cmdflags |= CMD_SENDENVIRON;
|
||||
if (cmd->entry->flags & CMD_CANTNEST)
|
||||
cmdflags |= CMD_CANTNEST;
|
||||
}
|
||||
@ -238,7 +250,7 @@ client_main(int argc, char **argv, int flags)
|
||||
setblocking(STDIN_FILENO, 0);
|
||||
event_set(&client_stdin, STDIN_FILENO, EV_READ|EV_PERSIST,
|
||||
client_stdin_callback, NULL);
|
||||
if (flags & IDENTIFY_TERMIOS) {
|
||||
if (flags & CLIENT_CONTROLCONTROL) {
|
||||
if (tcgetattr(STDIN_FILENO, &saved_tio) != 0) {
|
||||
fprintf(stderr, "tcgetattr failed: %s\n",
|
||||
strerror(errno));
|
||||
@ -261,26 +273,33 @@ client_main(int argc, char **argv, int flags)
|
||||
/* Establish signal handlers. */
|
||||
set_signals(client_signal);
|
||||
|
||||
/* Send initial environment. */
|
||||
if (cmdflags & CMD_SENDENVIRON)
|
||||
client_send_environ();
|
||||
/* Send identify messages. */
|
||||
client_send_identify(flags);
|
||||
|
||||
/* Send first command. */
|
||||
if (msg == MSG_COMMAND) {
|
||||
/* Fill in command line arguments. */
|
||||
cmddata.pid = environ_pid;
|
||||
cmddata.session_id = environ_session_id;
|
||||
/* How big is the command? */
|
||||
size = 0;
|
||||
for (i = 0; i < argc; i++)
|
||||
size += strlen(argv[i]) + 1;
|
||||
data = xmalloc((sizeof *data) + size);
|
||||
|
||||
/* Prepare command for server. */
|
||||
cmddata.argc = argc;
|
||||
if (cmd_pack_argv(
|
||||
argc, argv, cmddata.argv, sizeof cmddata.argv) != 0) {
|
||||
data->argc = argc;
|
||||
if (cmd_pack_argv(argc, argv, (char*)(data + 1), size) != 0) {
|
||||
fprintf(stderr, "command too long\n");
|
||||
free(data);
|
||||
return (1);
|
||||
}
|
||||
size += sizeof *data;
|
||||
|
||||
client_write_server(msg, &cmddata, sizeof cmddata);
|
||||
/* Send the command. */
|
||||
if (client_write_server(msg, data, size) != 0) {
|
||||
fprintf(stderr, "failed to send command\n");
|
||||
free(data);
|
||||
return (1);
|
||||
}
|
||||
free(data);
|
||||
} else if (msg == MSG_SHELL)
|
||||
client_write_server(msg, NULL, 0);
|
||||
|
||||
@ -296,37 +315,39 @@ client_main(int argc, char **argv, int flags)
|
||||
ppid = getppid();
|
||||
if (client_exittype == MSG_DETACHKILL && ppid > 1)
|
||||
kill(ppid, SIGHUP);
|
||||
} else if (flags & IDENTIFY_TERMIOS) {
|
||||
if (flags & IDENTIFY_CONTROL) {
|
||||
} else if (flags & CLIENT_CONTROLCONTROL) {
|
||||
if (client_exitreason != CLIENT_EXIT_NONE)
|
||||
printf("%%exit %s\n", client_exit_message());
|
||||
else
|
||||
printf("%%exit\n");
|
||||
printf("\033\\");
|
||||
}
|
||||
tcsetattr(STDOUT_FILENO, TCSAFLUSH, &saved_tio);
|
||||
}
|
||||
setblocking(STDIN_FILENO, 1);
|
||||
return (client_exitval);
|
||||
}
|
||||
|
||||
/* Send identify message to server with the file descriptors. */
|
||||
/* Send identify messages to server. */
|
||||
void
|
||||
client_send_identify(int flags)
|
||||
{
|
||||
struct msg_identify_data data;
|
||||
char *term;
|
||||
const char *s;
|
||||
char **ss;
|
||||
int fd;
|
||||
|
||||
data.flags = flags;
|
||||
client_write_one(MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
|
||||
|
||||
if (getcwd(data.cwd, sizeof data.cwd) == NULL)
|
||||
*data.cwd = '\0';
|
||||
if ((s = getenv("TERM")) == NULL)
|
||||
s = "";
|
||||
client_write_one(MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
|
||||
|
||||
term = getenv("TERM");
|
||||
if (term == NULL ||
|
||||
strlcpy(data.term, term, sizeof data.term) >= sizeof data.term)
|
||||
*data.term = '\0';
|
||||
if ((s = ttyname(STDIN_FILENO)) == NULL)
|
||||
s = "";
|
||||
client_write_one(MSG_IDENTIFY_TTYNAME, -1, s, strlen(s) + 1);
|
||||
|
||||
if ((fd = open(".", O_RDONLY)) == -1)
|
||||
fd = open("/", O_RDONLY);
|
||||
client_write_one(MSG_IDENTIFY_CWD, fd, NULL, 0);
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
snprintf(&data.ttyname, sizeof data.ttyname, "%s",
|
||||
@ -334,32 +355,39 @@ client_send_identify(int flags)
|
||||
#else
|
||||
if ((fd = dup(STDIN_FILENO)) == -1)
|
||||
fatal("dup failed");
|
||||
#endif
|
||||
imsg_compose(&client_ibuf,
|
||||
MSG_IDENTIFY, PROTOCOL_VERSION, -1, fd, &data, sizeof data);
|
||||
client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
|
||||
|
||||
for (ss = environ; *ss != NULL; ss++)
|
||||
client_write_one(MSG_IDENTIFY_ENVIRON, -1, *ss, strlen(*ss) + 1);
|
||||
|
||||
client_write_one(MSG_IDENTIFY_DONE, -1, NULL, 0);
|
||||
|
||||
client_update_event();
|
||||
}
|
||||
|
||||
/* Forward entire environment to server. */
|
||||
void
|
||||
client_send_environ(void)
|
||||
/* Helper to send one message. */
|
||||
int
|
||||
client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
|
||||
{
|
||||
struct msg_environ_data data;
|
||||
char **var;
|
||||
int retval;
|
||||
|
||||
for (var = environ; *var != NULL; var++) {
|
||||
if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
|
||||
continue;
|
||||
client_write_server(MSG_ENVIRON, &data, sizeof data);
|
||||
}
|
||||
retval = imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, fd,
|
||||
(void*)buf, len);
|
||||
if (retval != 1)
|
||||
return (-1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Write a message to the server without a file descriptor. */
|
||||
void
|
||||
client_write_server(enum msgtype type, void *buf, size_t len)
|
||||
int
|
||||
client_write_server(enum msgtype type, const void *buf, size_t len)
|
||||
{
|
||||
imsg_compose(&client_ibuf, type, PROTOCOL_VERSION, -1, -1, buf, len);
|
||||
int retval;
|
||||
|
||||
retval = client_write_one(type, -1, buf, len);
|
||||
if (retval == 0)
|
||||
client_update_event();
|
||||
return (retval);
|
||||
}
|
||||
|
||||
/* Update client event based on whether it needs to read or read and write. */
|
||||
@ -493,33 +521,33 @@ client_write(int fd, const char *data, size_t size)
|
||||
|
||||
/* Dispatch imsgs when in wait state (before MSG_READY). */
|
||||
int
|
||||
client_dispatch_wait(void *data)
|
||||
client_dispatch_wait(void *data0)
|
||||
{
|
||||
struct imsg imsg;
|
||||
char *data;
|
||||
ssize_t n, datalen;
|
||||
struct msg_shell_data shelldata;
|
||||
struct msg_exit_data exitdata;
|
||||
struct msg_stdout_data stdoutdata;
|
||||
struct msg_stderr_data stderrdata;
|
||||
const char *shellcmd = data;
|
||||
int retval;
|
||||
|
||||
for (;;) {
|
||||
if ((n = imsg_get(&client_ibuf, &imsg)) == -1)
|
||||
fatalx("imsg_get failed");
|
||||
if (n == 0)
|
||||
return (0);
|
||||
|
||||
data = imsg.data;
|
||||
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
|
||||
|
||||
log_debug("got %d from server", imsg.hdr.type);
|
||||
switch (imsg.hdr.type) {
|
||||
case MSG_EXIT:
|
||||
case MSG_SHUTDOWN:
|
||||
if (datalen != sizeof exitdata) {
|
||||
if (datalen != 0)
|
||||
if (datalen != sizeof retval && datalen != 0)
|
||||
fatalx("bad MSG_EXIT size");
|
||||
} else {
|
||||
memcpy(&exitdata, imsg.data, sizeof exitdata);
|
||||
client_exitval = exitdata.retcode;
|
||||
if (datalen == sizeof retval) {
|
||||
memcpy(&retval, data, sizeof retval);
|
||||
client_exitval = retval;
|
||||
}
|
||||
imsg_free(&imsg);
|
||||
return (-1);
|
||||
@ -539,17 +567,19 @@ client_dispatch_wait(void *data)
|
||||
break;
|
||||
case MSG_STDOUT:
|
||||
if (datalen != sizeof stdoutdata)
|
||||
fatalx("bad MSG_STDOUT");
|
||||
memcpy(&stdoutdata, imsg.data, sizeof stdoutdata);
|
||||
fatalx("bad MSG_STDOUT size");
|
||||
memcpy(&stdoutdata, data, sizeof stdoutdata);
|
||||
|
||||
client_write(STDOUT_FILENO, stdoutdata.data, stdoutdata.size);
|
||||
client_write(STDOUT_FILENO, stdoutdata.data,
|
||||
stdoutdata.size);
|
||||
break;
|
||||
case MSG_STDERR:
|
||||
if (datalen != sizeof stderrdata)
|
||||
fatalx("bad MSG_STDERR");
|
||||
memcpy(&stderrdata, imsg.data, sizeof stderrdata);
|
||||
fatalx("bad MSG_STDERR size");
|
||||
memcpy(&stderrdata, data, sizeof stderrdata);
|
||||
|
||||
client_write(STDERR_FILENO, stderrdata.data, stderrdata.size);
|
||||
client_write(STDERR_FILENO, stderrdata.data,
|
||||
stderrdata.size);
|
||||
break;
|
||||
case MSG_VERSION:
|
||||
if (datalen != 0)
|
||||
@ -563,23 +593,19 @@ client_dispatch_wait(void *data)
|
||||
imsg_free(&imsg);
|
||||
return (-1);
|
||||
case MSG_SHELL:
|
||||
if (datalen != sizeof shelldata)
|
||||
fatalx("bad MSG_SHELL size");
|
||||
memcpy(&shelldata, imsg.data, sizeof shelldata);
|
||||
shelldata.shell[(sizeof shelldata.shell) - 1] = '\0';
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_SHELL string");
|
||||
|
||||
clear_signals(0);
|
||||
|
||||
shell_exec(shelldata.shell, shellcmd);
|
||||
shell_exec(data, data0);
|
||||
/* NOTREACHED */
|
||||
case MSG_DETACH:
|
||||
case MSG_DETACHKILL:
|
||||
client_write_server(MSG_EXITING, NULL, 0);
|
||||
break;
|
||||
case MSG_EXITED:
|
||||
imsg_free(&imsg);
|
||||
return (-1);
|
||||
default:
|
||||
fatalx("unexpected message");
|
||||
}
|
||||
|
||||
imsg_free(&imsg);
|
||||
@ -591,8 +617,8 @@ int
|
||||
client_dispatch_attached(void)
|
||||
{
|
||||
struct imsg imsg;
|
||||
struct msg_lock_data lockdata;
|
||||
struct sigaction sigact;
|
||||
char *data;
|
||||
ssize_t n, datalen;
|
||||
|
||||
for (;;) {
|
||||
@ -600,15 +626,18 @@ client_dispatch_attached(void)
|
||||
fatalx("imsg_get failed");
|
||||
if (n == 0)
|
||||
return (0);
|
||||
|
||||
data = imsg.data;
|
||||
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
|
||||
|
||||
log_debug("got %d from server", imsg.hdr.type);
|
||||
switch (imsg.hdr.type) {
|
||||
case MSG_DETACHKILL:
|
||||
case MSG_DETACH:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_DETACH size");
|
||||
case MSG_DETACHKILL:
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_DETACH string");
|
||||
|
||||
client_exitsession = xstrdup(data);
|
||||
client_exittype = imsg.hdr.type;
|
||||
if (imsg.hdr.type == MSG_DETACHKILL)
|
||||
client_exitreason = CLIENT_EXIT_DETACHED_HUP;
|
||||
@ -617,8 +646,7 @@ client_dispatch_attached(void)
|
||||
client_write_server(MSG_EXITING, NULL, 0);
|
||||
break;
|
||||
case MSG_EXIT:
|
||||
if (datalen != 0 &&
|
||||
datalen != sizeof (struct msg_exit_data))
|
||||
if (datalen != 0 && datalen != sizeof (int))
|
||||
fatalx("bad MSG_EXIT size");
|
||||
|
||||
client_write_server(MSG_EXITING, NULL, 0);
|
||||
@ -651,16 +679,12 @@ client_dispatch_attached(void)
|
||||
kill(getpid(), SIGTSTP);
|
||||
break;
|
||||
case MSG_LOCK:
|
||||
if (datalen != sizeof lockdata)
|
||||
fatalx("bad MSG_LOCK size");
|
||||
memcpy(&lockdata, imsg.data, sizeof lockdata);
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_LOCK string");
|
||||
|
||||
lockdata.cmd[(sizeof lockdata.cmd) - 1] = '\0';
|
||||
system(lockdata.cmd);
|
||||
system(data);
|
||||
client_write_server(MSG_UNLOCK, NULL, 0);
|
||||
break;
|
||||
default:
|
||||
fatalx("unexpected message");
|
||||
}
|
||||
|
||||
imsg_free(&imsg);
|
||||
|
@ -18,7 +18,11 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@ -30,22 +34,25 @@ enum cmd_retval cmd_attach_session_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_attach_session_entry = {
|
||||
"attach-session", "attach",
|
||||
"drt:", 0, 0,
|
||||
"[-dr] " CMD_TARGET_SESSION_USAGE,
|
||||
CMD_CANTNEST|CMD_STARTSERVER|CMD_SENDENVIRON,
|
||||
NULL,
|
||||
"c:drt:", 0, 0,
|
||||
"[-dr] [-c working-directory] " CMD_TARGET_SESSION_USAGE,
|
||||
CMD_CANTNEST|CMD_STARTSERVER,
|
||||
NULL,
|
||||
cmd_attach_session_exec
|
||||
};
|
||||
|
||||
enum cmd_retval
|
||||
cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
|
||||
cmd_attach_session(struct cmd_q *cmdq, const char *tflag, int dflag, int rflag,
|
||||
const char *cflag)
|
||||
{
|
||||
struct session *s;
|
||||
struct client *c;
|
||||
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");
|
||||
@ -70,10 +77,33 @@ cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
|
||||
continue;
|
||||
if (c == cmdq->client)
|
||||
continue;
|
||||
server_write_client(c, MSG_DETACH, NULL, 0);
|
||||
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);
|
||||
@ -86,11 +116,34 @@ cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
|
||||
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, NULL, 0);
|
||||
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);
|
||||
@ -116,5 +169,5 @@ cmd_attach_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct args *args = self->args;
|
||||
|
||||
return (cmd_attach_session(cmdq, args_get(args, 't'),
|
||||
args_has(args, 'd'), args_has(args, 'r')));
|
||||
args_has(args, 'd'), args_has(args, 'r'), args_get(args, 'c')));
|
||||
}
|
||||
|
@ -27,7 +27,6 @@
|
||||
* Bind a key to a command, this recurses through cmd_*.
|
||||
*/
|
||||
|
||||
enum cmd_retval cmd_bind_key_check(struct args *);
|
||||
enum cmd_retval cmd_bind_key_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
enum cmd_retval cmd_bind_key_table(struct cmd *, struct cmd_q *, int);
|
||||
@ -38,23 +37,9 @@ const struct cmd_entry cmd_bind_key_entry = {
|
||||
"[-cnr] [-t key-table] key command [arguments]",
|
||||
0,
|
||||
NULL,
|
||||
cmd_bind_key_check,
|
||||
cmd_bind_key_exec
|
||||
};
|
||||
|
||||
enum cmd_retval
|
||||
cmd_bind_key_check(struct args *args)
|
||||
{
|
||||
if (args_has(args, 't')) {
|
||||
if (args->argc != 2 && args->argc != 3)
|
||||
return (CMD_RETURN_ERROR);
|
||||
} else {
|
||||
if (args->argc < 2)
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
enum cmd_retval
|
||||
cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
@ -63,6 +48,18 @@ cmd_bind_key_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct cmd_list *cmdlist;
|
||||
int key;
|
||||
|
||||
if (args_has(args, 't')) {
|
||||
if (args->argc != 2 && args->argc != 3) {
|
||||
cmdq_error(cmdq, "not enough arguments");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
} else {
|
||||
if (args->argc < 2) {
|
||||
cmdq_error(cmdq, "not enough arguments");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
key = key_string_lookup_string(args->argv[0]);
|
||||
if (key == KEYC_NONE) {
|
||||
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
|
||||
|
@ -34,7 +34,6 @@ const struct cmd_entry cmd_break_pane_entry = {
|
||||
"[-dP] [-F format] " CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_break_pane_exec
|
||||
};
|
||||
|
||||
|
@ -42,7 +42,6 @@ const struct cmd_entry cmd_capture_pane_entry = {
|
||||
CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_capture_pane_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_choose_buffer_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_choose_buffer_exec
|
||||
};
|
||||
|
||||
|
@ -37,7 +37,6 @@ const struct cmd_entry cmd_choose_client_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_choose_client_exec
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,6 @@ const struct cmd_entry cmd_choose_list_entry = {
|
||||
"[-l items] " CMD_TARGET_WINDOW_USAGE "[template]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_choose_list_exec
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,6 @@ const struct cmd_entry cmd_choose_tree_entry = {
|
||||
"[-W format] " CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_choose_tree_exec
|
||||
};
|
||||
|
||||
@ -51,7 +50,6 @@ const struct cmd_entry cmd_choose_session_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE " [-F format] [template]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_choose_tree_exec
|
||||
};
|
||||
|
||||
@ -61,7 +59,6 @@ const struct cmd_entry cmd_choose_window_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE "[-F format] [template]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_choose_tree_exec
|
||||
};
|
||||
|
||||
@ -228,7 +225,6 @@ windows_only:
|
||||
free(final_win_template_last);
|
||||
|
||||
window_choose_ready(wl->window->active, cur_win, NULL);
|
||||
window_choose_collapse_all(wl->window->active);
|
||||
|
||||
if (args_has(args, 'u')) {
|
||||
window_choose_expand_all(wl->window->active);
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_clear_history_entry = {
|
||||
CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_clear_history_exec
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_clock_mode_entry = {
|
||||
CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_clock_mode_exec
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,6 @@
|
||||
*/
|
||||
|
||||
void cmd_command_prompt_key_binding(struct cmd *, int);
|
||||
int cmd_command_prompt_check(struct args *);
|
||||
enum cmd_retval cmd_command_prompt_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
int cmd_command_prompt_callback(void *, const char *);
|
||||
@ -42,7 +41,6 @@ const struct cmd_entry cmd_command_prompt_entry = {
|
||||
"[-I inputs] [-p prompts] " CMD_TARGET_CLIENT_USAGE " [template]",
|
||||
0,
|
||||
cmd_command_prompt_key_binding,
|
||||
NULL,
|
||||
cmd_command_prompt_exec
|
||||
};
|
||||
|
||||
|
@ -38,7 +38,6 @@ const struct cmd_entry cmd_confirm_before_entry = {
|
||||
"[-p prompt] " CMD_TARGET_CLIENT_USAGE " command",
|
||||
0,
|
||||
cmd_confirm_before_key_binding,
|
||||
NULL,
|
||||
cmd_confirm_before_exec
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,6 @@ const struct cmd_entry cmd_copy_mode_entry = {
|
||||
"[-u] " CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
cmd_copy_mode_key_binding,
|
||||
NULL,
|
||||
cmd_copy_mode_exec
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,6 @@ const struct cmd_entry cmd_delete_buffer_entry = {
|
||||
CMD_BUFFER_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_delete_buffer_exec
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
/*
|
||||
@ -32,7 +34,6 @@ const struct cmd_entry cmd_detach_client_entry = {
|
||||
"[-P] [-a] [-s target-session] " CMD_TARGET_CLIENT_USAGE,
|
||||
CMD_READONLY,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_detach_client_exec
|
||||
};
|
||||
|
||||
@ -57,8 +58,10 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&clients); i++) {
|
||||
c = ARRAY_ITEM(&clients, i);
|
||||
if (c != NULL && c->session == s)
|
||||
server_write_client(c, msgtype, NULL, 0);
|
||||
if (c == NULL || c->session != s)
|
||||
continue;
|
||||
server_write_client(c, msgtype, c->session->name,
|
||||
strlen(c->session->name) + 1);
|
||||
}
|
||||
} else {
|
||||
c = cmd_find_client(cmdq, args_get(args, 't'), 0);
|
||||
@ -70,10 +73,14 @@ cmd_detach_client_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
c2 = ARRAY_ITEM(&clients, i);
|
||||
if (c2 == NULL || c == c2)
|
||||
continue;
|
||||
server_write_client(c2, msgtype, NULL, 0);
|
||||
server_write_client(c2, msgtype,
|
||||
c2->session->name,
|
||||
strlen(c2->session->name) + 1);
|
||||
}
|
||||
} else {
|
||||
server_write_client(c, msgtype, c->session->name,
|
||||
strlen(c->session->name) + 1);
|
||||
}
|
||||
} else
|
||||
server_write_client(c, msgtype, NULL, 0);
|
||||
}
|
||||
|
||||
return (CMD_RETURN_STOP);
|
||||
|
@ -36,7 +36,6 @@ const struct cmd_entry cmd_display_message_entry = {
|
||||
" [message]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_display_message_exec
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_display_panes_entry = {
|
||||
CMD_TARGET_CLIENT_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_display_panes_exec
|
||||
};
|
||||
|
||||
|
@ -48,7 +48,6 @@ const struct cmd_entry cmd_find_window_entry = {
|
||||
"[-CNT] [-F format] " CMD_TARGET_WINDOW_USAGE " match-string",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_find_window_exec
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_has_session_entry = {
|
||||
CMD_TARGET_SESSION_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_has_session_exec
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,6 @@ const struct cmd_entry cmd_if_shell_entry = {
|
||||
"[-b] " CMD_TARGET_PANE_USAGE " shell-command command [command]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_if_shell_exec
|
||||
};
|
||||
|
||||
@ -148,6 +147,9 @@ cmd_if_shell_done(struct cmd_q *cmdq1)
|
||||
struct cmd_if_shell_data *cdata = cmdq1->data;
|
||||
struct cmd_q *cmdq = cdata->cmdq;
|
||||
|
||||
if (cmdq1->client_exit >= 0)
|
||||
cmdq->client_exit = cmdq1->client_exit;
|
||||
|
||||
if (!cmdq_free(cmdq) && !cdata->bflag)
|
||||
cmdq_continue(cmdq);
|
||||
|
||||
|
@ -39,7 +39,6 @@ const struct cmd_entry cmd_join_pane_entry = {
|
||||
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
|
||||
0,
|
||||
cmd_join_pane_key_binding,
|
||||
NULL,
|
||||
cmd_join_pane_exec
|
||||
};
|
||||
|
||||
@ -49,7 +48,6 @@ const struct cmd_entry cmd_move_pane_entry = {
|
||||
"[-bdhv] [-p percentage|-l size] [-s src-pane] [-t dst-pane]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_join_pane_exec
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,6 @@ const struct cmd_entry cmd_kill_pane_entry = {
|
||||
"[-a] " CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_kill_pane_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_kill_server_entry = {
|
||||
"",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_kill_server_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_kill_session_entry = {
|
||||
"[-a] " CMD_TARGET_SESSION_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_kill_session_exec
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_kill_window_entry = {
|
||||
"[-a] " CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_kill_window_exec
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,6 @@ const struct cmd_entry cmd_link_window_entry = {
|
||||
"[-dk] " CMD_SRCDST_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_link_window_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_list_buffers_entry = {
|
||||
"[-F format]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_list_buffers_exec
|
||||
};
|
||||
|
||||
|
@ -36,7 +36,6 @@ const struct cmd_entry cmd_list_clients_entry = {
|
||||
"[-F format] " CMD_TARGET_SESSION_USAGE,
|
||||
CMD_READONLY,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_list_clients_exec
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_list_commands_entry = {
|
||||
"",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_list_commands_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_list_keys_entry = {
|
||||
"[-t key-table]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_list_keys_exec
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,6 @@ const struct cmd_entry cmd_list_panes_entry = {
|
||||
"[-as] [-F format] " CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_list_panes_exec
|
||||
};
|
||||
|
||||
|
@ -36,7 +36,6 @@ const struct cmd_entry cmd_list_sessions_entry = {
|
||||
"[-F format]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_list_sessions_exec
|
||||
};
|
||||
|
||||
|
@ -39,7 +39,6 @@ const struct cmd_entry cmd_list_windows_entry = {
|
||||
"[-a] [-F format] " CMD_TARGET_SESSION_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_list_windows_exec
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -39,7 +40,6 @@ const struct cmd_entry cmd_load_buffer_entry = {
|
||||
CMD_BUFFER_USAGE " path",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_load_buffer_exec
|
||||
};
|
||||
|
||||
@ -50,11 +50,11 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct client *c = cmdq->client;
|
||||
struct session *s;
|
||||
FILE *f;
|
||||
const char *path, *newpath, *wd;
|
||||
const char *path;
|
||||
char *pdata, *new_pdata, *cause;
|
||||
size_t psize;
|
||||
u_int limit;
|
||||
int ch, error, buffer, *buffer_ptr;
|
||||
int ch, error, buffer, *buffer_ptr, cwd, fd;
|
||||
|
||||
if (!args_has(args, 'b'))
|
||||
buffer = -1;
|
||||
@ -82,20 +82,17 @@ cmd_load_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
return (CMD_RETURN_WAIT);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if ((f = fopen(path, "rb")) == NULL) {
|
||||
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);
|
||||
}
|
||||
|
@ -36,7 +36,6 @@ const struct cmd_entry cmd_lock_server_entry = {
|
||||
"",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_lock_server_exec
|
||||
};
|
||||
|
||||
@ -46,7 +45,6 @@ const struct cmd_entry cmd_lock_session_entry = {
|
||||
CMD_TARGET_SESSION_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_lock_server_exec
|
||||
};
|
||||
|
||||
@ -56,7 +54,6 @@ const struct cmd_entry cmd_lock_client_entry = {
|
||||
CMD_TARGET_CLIENT_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_lock_server_exec
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,6 @@ const struct cmd_entry cmd_move_window_entry = {
|
||||
"[-dkr] " CMD_SRCDST_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_move_window_exec
|
||||
};
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -30,46 +32,39 @@
|
||||
* Create a new session and attach to the current terminal unless -d is given.
|
||||
*/
|
||||
|
||||
enum cmd_retval cmd_new_session_check(struct args *);
|
||||
enum cmd_retval cmd_new_session_exec(struct cmd *, struct cmd_q *);
|
||||
|
||||
const struct cmd_entry cmd_new_session_entry = {
|
||||
"new-session", "new",
|
||||
"AdDF:n:Ps:t:x:y:", 0, 1,
|
||||
"[-AdDP] [-F format] [-n window-name] [-s session-name] "
|
||||
CMD_TARGET_SESSION_USAGE " [-x width] [-y height] [command]",
|
||||
CMD_STARTSERVER|CMD_CANTNEST|CMD_SENDENVIRON,
|
||||
"Ac:dDF:n:Ps:t:x:y:", 0, 1,
|
||||
"[-AdDP] [-c start-directory] [-F format] [-n window-name] "
|
||||
"[-s session-name] " CMD_TARGET_SESSION_USAGE " [-x width] [-y height] "
|
||||
"[command]",
|
||||
CMD_STARTSERVER|CMD_CANTNEST,
|
||||
NULL,
|
||||
cmd_new_session_check,
|
||||
cmd_new_session_exec
|
||||
};
|
||||
|
||||
enum cmd_retval
|
||||
cmd_new_session_check(struct args *args)
|
||||
{
|
||||
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n')))
|
||||
return (CMD_RETURN_ERROR);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
enum cmd_retval
|
||||
cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c = cmdq->client;
|
||||
struct client *c = cmdq->client, *c0;
|
||||
struct session *s, *groupwith;
|
||||
struct window *w;
|
||||
struct environ env;
|
||||
struct termios tio, *tiop;
|
||||
struct passwd *pw;
|
||||
const char *newname, *target, *update, *cwd, *errstr;
|
||||
const char *template;
|
||||
const char *newname, *target, *update, *errstr, *template;
|
||||
char *cmd, *cause, *cp;
|
||||
int detached, idx;
|
||||
int detached, already_attached, idx, cwd, fd = -1;
|
||||
u_int sx, sy;
|
||||
int already_attached;
|
||||
struct format_tree *ft;
|
||||
|
||||
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)) {
|
||||
@ -79,7 +74,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (session_find(newname) != NULL) {
|
||||
if (args_has(args, 'A')) {
|
||||
return (cmd_attach_session(cmdq, newname,
|
||||
args_has(args, 'D'), 0));
|
||||
args_has(args, 'D'), 0, NULL));
|
||||
}
|
||||
cmdq_error(cmdq, "duplicate session: %s", newname);
|
||||
return (CMD_RETURN_ERROR);
|
||||
@ -104,6 +99,31 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (c != NULL && c->session != NULL)
|
||||
already_attached = 1;
|
||||
|
||||
/* Get the new session working directory. */
|
||||
if (args_has(args, 'c')) {
|
||||
ft = format_create();
|
||||
if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
|
||||
format_client(ft, c0);
|
||||
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 (c != NULL && c->session == NULL)
|
||||
cwd = c->cwd;
|
||||
else if ((c0 = cmd_current_client(cmdq)) != NULL)
|
||||
cwd = c0->session->cwd;
|
||||
else {
|
||||
fd = open(".", O_RDONLY);
|
||||
cwd = fd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Save the termios settings, part of which is used for new windows in
|
||||
* this session.
|
||||
@ -125,21 +145,10 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (server_client_open(c, NULL, &cause) != 0) {
|
||||
cmdq_error(cmdq, "open terminal failed: %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the new session working directory. */
|
||||
if (c != NULL && c->cwd != NULL)
|
||||
cwd = c->cwd;
|
||||
else {
|
||||
pw = getpwuid(getuid());
|
||||
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
|
||||
cwd = pw->pw_dir;
|
||||
else
|
||||
cwd = "/";
|
||||
}
|
||||
|
||||
/* Find new session size. */
|
||||
if (c != NULL) {
|
||||
sx = c->tty.sx;
|
||||
@ -152,14 +161,14 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
sx = strtonum(args_get(args, 'x'), 1, USHRT_MAX, &errstr);
|
||||
if (errstr != NULL) {
|
||||
cmdq_error(cmdq, "width %s", errstr);
|
||||
return (CMD_RETURN_ERROR);
|
||||
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);
|
||||
return (CMD_RETURN_ERROR);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
if (sy > 0 && options_get_number(&global_s_options, "status"))
|
||||
@ -189,7 +198,7 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (s == NULL) {
|
||||
cmdq_error(cmdq, "create session failed: %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
goto error;
|
||||
}
|
||||
environ_free(&env);
|
||||
|
||||
@ -240,8 +249,8 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
template = NEW_SESSION_TEMPLATE;
|
||||
|
||||
ft = format_create();
|
||||
if ((c = cmd_find_client(cmdq, NULL, 1)) != NULL)
|
||||
format_client(ft, c);
|
||||
if ((c0 = cmd_find_client(cmdq, NULL, 1)) != NULL)
|
||||
format_client(ft, c0);
|
||||
format_session(ft, s);
|
||||
|
||||
cp = format_expand(ft, template);
|
||||
@ -253,5 +262,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
|
||||
if (!detached)
|
||||
cmdq->client_exit = 0;
|
||||
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
error:
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
@ -18,7 +18,11 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@ -35,7 +39,6 @@ const struct cmd_entry cmd_new_window_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE " [command]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_new_window_exec
|
||||
};
|
||||
|
||||
@ -46,9 +49,9 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct session *s;
|
||||
struct winlink *wl;
|
||||
struct client *c;
|
||||
const char *cmd, *cwd, *template;
|
||||
const char *cmd, *template;
|
||||
char *cause, *cp;
|
||||
int idx, last, detached;
|
||||
int idx, last, detached, cwd, fd = -1;
|
||||
struct format_tree *ft;
|
||||
|
||||
if (args_has(args, 'a')) {
|
||||
@ -103,7 +106,29 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
cmd = options_get_string(&s->options, "default-command");
|
||||
else
|
||||
cmd = args->argv[0];
|
||||
cwd = cmd_get_default_path(cmdq, args_get(args, 'c'));
|
||||
|
||||
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");
|
||||
@ -111,7 +136,7 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
if (wl == NULL) {
|
||||
cmdq_error(cmdq, "create window failed: %s", cause);
|
||||
free(cause);
|
||||
return (CMD_RETURN_ERROR);
|
||||
goto error;
|
||||
}
|
||||
if (!detached) {
|
||||
session_select(s, wl->idx);
|
||||
@ -137,5 +162,12 @@ cmd_new_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
format_free(ft);
|
||||
}
|
||||
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
error:
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
@ -38,7 +38,6 @@ const struct cmd_entry cmd_paste_buffer_entry = {
|
||||
"[-dpr] [-s separator] [-b buffer-index] " CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_paste_buffer_exec
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,6 @@ const struct cmd_entry cmd_pipe_pane_entry = {
|
||||
"[-o] " CMD_TARGET_PANE_USAGE " [command]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_pipe_pane_exec
|
||||
};
|
||||
|
||||
|
22
cmd-queue.c
22
cmd-queue.c
@ -35,7 +35,7 @@ cmdq_new(struct client *c)
|
||||
cmdq->dead = 0;
|
||||
|
||||
cmdq->client = c;
|
||||
cmdq->client_exit = 0;
|
||||
cmdq->client_exit = -1;
|
||||
|
||||
TAILQ_INIT(&cmdq->queue);
|
||||
cmdq->item = NULL;
|
||||
@ -143,7 +143,7 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
|
||||
evbuffer_add(c->stderr_data, "\n", 1);
|
||||
|
||||
server_push_stderr(c);
|
||||
c->retcode = 1;
|
||||
c->retval = 1;
|
||||
} else {
|
||||
*msg = toupper((u_char) *msg);
|
||||
status_message_set(c, "%s", msg);
|
||||
@ -154,18 +154,15 @@ cmdq_error(struct cmd_q *cmdq, const char *fmt, ...)
|
||||
|
||||
/* Print a guard line. */
|
||||
int
|
||||
cmdq_guard(struct cmd_q *cmdq, const char *guard)
|
||||
cmdq_guard(struct cmd_q *cmdq, const char *guard, int flags)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
int flags;
|
||||
|
||||
if (c == NULL)
|
||||
return 0;
|
||||
if (!(c->flags & CLIENT_CONTROL))
|
||||
return 0;
|
||||
|
||||
flags = !!(cmdq->cmd->flags & CMD_CONTROL);
|
||||
|
||||
evbuffer_add_printf(c->stdout_data, "%%%s %ld %u %d\n", guard,
|
||||
(long) cmdq->time, cmdq->number, flags);
|
||||
server_push_stdout(c);
|
||||
@ -202,7 +199,7 @@ cmdq_continue(struct cmd_q *cmdq)
|
||||
{
|
||||
struct cmd_q_item *next;
|
||||
enum cmd_retval retval;
|
||||
int empty, guard;
|
||||
int empty, guard, flags;
|
||||
char s[1024];
|
||||
|
||||
notify_disable();
|
||||
@ -228,13 +225,16 @@ cmdq_continue(struct cmd_q *cmdq)
|
||||
cmdq->time = time(NULL);
|
||||
cmdq->number++;
|
||||
|
||||
guard = cmdq_guard(cmdq, "begin");
|
||||
flags = !!(cmdq->cmd->flags & CMD_CONTROL);
|
||||
guard = cmdq_guard(cmdq, "begin", flags);
|
||||
|
||||
retval = cmdq->cmd->entry->exec(cmdq->cmd, cmdq);
|
||||
|
||||
if (guard) {
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
cmdq_guard(cmdq, "error");
|
||||
cmdq_guard(cmdq, "error", flags);
|
||||
else
|
||||
cmdq_guard(cmdq, "end");
|
||||
cmdq_guard(cmdq, "end", flags);
|
||||
}
|
||||
|
||||
if (retval == CMD_RETURN_ERROR)
|
||||
@ -259,7 +259,7 @@ cmdq_continue(struct cmd_q *cmdq)
|
||||
} while (cmdq->item != NULL);
|
||||
|
||||
empty:
|
||||
if (cmdq->client_exit)
|
||||
if (cmdq->client_exit > 0)
|
||||
cmdq->client->flags |= CLIENT_EXIT;
|
||||
if (cmdq->emptyfn != NULL)
|
||||
cmdq->emptyfn(cmdq); /* may free cmdq */
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_refresh_client_entry = {
|
||||
"[-S] [-C size] " CMD_TARGET_CLIENT_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_refresh_client_exec
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,6 @@ const struct cmd_entry cmd_rename_session_entry = {
|
||||
CMD_TARGET_SESSION_USAGE " new-name",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_rename_session_exec
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,6 @@ const struct cmd_entry cmd_rename_window_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE " new-name",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_rename_window_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_resize_pane_entry = {
|
||||
"[-DLRUZ] [-x width] [-y height] " CMD_TARGET_PANE_USAGE " [adjustment]",
|
||||
0,
|
||||
cmd_resize_pane_key_binding,
|
||||
NULL,
|
||||
cmd_resize_pane_exec
|
||||
};
|
||||
|
||||
|
@ -36,7 +36,6 @@ const struct cmd_entry cmd_respawn_pane_entry = {
|
||||
"[-k] " CMD_TARGET_PANE_USAGE " [command]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_respawn_pane_exec
|
||||
};
|
||||
|
||||
@ -78,7 +77,7 @@ cmd_respawn_pane_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
cmd = args->argv[0];
|
||||
else
|
||||
cmd = NULL;
|
||||
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
|
||||
if (window_pane_spawn(wp, cmd, NULL, -1, &env, s->tio, &cause) != 0) {
|
||||
cmdq_error(cmdq, "respawn pane failed: %s", cause);
|
||||
free(cause);
|
||||
environ_free(&env);
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_respawn_window_entry = {
|
||||
"[-k] " CMD_TARGET_WINDOW_USAGE " [command]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_respawn_window_exec
|
||||
};
|
||||
|
||||
@ -80,7 +79,7 @@ cmd_respawn_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
cmd = args->argv[0];
|
||||
else
|
||||
cmd = NULL;
|
||||
if (window_pane_spawn(wp, cmd, NULL, NULL, &env, s->tio, &cause) != 0) {
|
||||
if (window_pane_spawn(wp, cmd, NULL, -1, &env, s->tio, &cause) != 0) {
|
||||
cmdq_error(cmdq, "respawn window failed: %s", cause);
|
||||
free(cause);
|
||||
environ_free(&env);
|
||||
|
@ -33,7 +33,6 @@ const struct cmd_entry cmd_rotate_window_entry = {
|
||||
"[-DU] " CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
cmd_rotate_window_key_binding,
|
||||
NULL,
|
||||
cmd_rotate_window_exec
|
||||
};
|
||||
|
||||
|
@ -41,7 +41,6 @@ const struct cmd_entry cmd_run_shell_entry = {
|
||||
"[-b] " CMD_TARGET_PANE_USAGE " shell-command",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_run_shell_exec
|
||||
};
|
||||
|
||||
|
@ -20,8 +20,11 @@
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <vis.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
@ -37,7 +40,6 @@ const struct cmd_entry cmd_save_buffer_entry = {
|
||||
"[-a] " CMD_BUFFER_USAGE " path",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_save_buffer_exec
|
||||
};
|
||||
|
||||
@ -47,7 +49,6 @@ const struct cmd_entry cmd_show_buffer_entry = {
|
||||
CMD_BUFFER_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_save_buffer_exec
|
||||
};
|
||||
|
||||
@ -55,17 +56,14 @@ enum cmd_retval
|
||||
cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
struct args *args = self->args;
|
||||
struct client *c;
|
||||
struct client *c = cmdq->client;
|
||||
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;
|
||||
const char *path;
|
||||
char *cause, *start, *end, *msg;
|
||||
size_t size, used, msglen;
|
||||
int cwd, fd, buffer;
|
||||
FILE *f;
|
||||
char *msg;
|
||||
size_t msglen;
|
||||
|
||||
if (!args_has(args, 'b')) {
|
||||
if ((pb = paste_get_top(&global_buffers)) == NULL) {
|
||||
@ -92,7 +90,6 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
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);
|
||||
@ -102,28 +99,26 @@ cmd_save_buffer_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
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");
|
||||
if (c != NULL && c->session == NULL)
|
||||
cwd = c->cwd;
|
||||
else if ((s = cmd_current_session(cmdq, 0)) != NULL)
|
||||
cwd = s->cwd;
|
||||
else
|
||||
f = fopen(path, "wb");
|
||||
umask(mask);
|
||||
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);
|
||||
}
|
||||
|
@ -33,7 +33,6 @@ const struct cmd_entry cmd_select_layout_entry = {
|
||||
"[-np] " CMD_TARGET_WINDOW_USAGE " [layout-name]",
|
||||
0,
|
||||
cmd_select_layout_key_binding,
|
||||
NULL,
|
||||
cmd_select_layout_exec
|
||||
};
|
||||
|
||||
@ -43,7 +42,6 @@ const struct cmd_entry cmd_next_layout_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_select_layout_exec
|
||||
};
|
||||
|
||||
@ -53,7 +51,6 @@ const struct cmd_entry cmd_previous_layout_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_select_layout_exec
|
||||
};
|
||||
|
||||
|
@ -33,7 +33,6 @@ const struct cmd_entry cmd_select_pane_entry = {
|
||||
"[-lDLRU] " CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
cmd_select_pane_key_binding,
|
||||
NULL,
|
||||
cmd_select_pane_exec
|
||||
};
|
||||
|
||||
@ -43,7 +42,6 @@ const struct cmd_entry cmd_last_pane_entry = {
|
||||
CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_select_pane_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_select_window_entry = {
|
||||
"[-lnpT] " CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
cmd_select_window_key_binding,
|
||||
NULL,
|
||||
cmd_select_window_exec
|
||||
};
|
||||
|
||||
@ -45,7 +44,6 @@ const struct cmd_entry cmd_next_window_entry = {
|
||||
"[-a] " CMD_TARGET_SESSION_USAGE,
|
||||
0,
|
||||
cmd_select_window_key_binding,
|
||||
NULL,
|
||||
cmd_select_window_exec
|
||||
};
|
||||
|
||||
@ -55,7 +53,6 @@ const struct cmd_entry cmd_previous_window_entry = {
|
||||
"[-a] " CMD_TARGET_SESSION_USAGE,
|
||||
0,
|
||||
cmd_select_window_key_binding,
|
||||
NULL,
|
||||
cmd_select_window_exec
|
||||
};
|
||||
|
||||
@ -65,7 +62,6 @@ const struct cmd_entry cmd_last_window_entry = {
|
||||
CMD_TARGET_SESSION_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_select_window_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_send_keys_entry = {
|
||||
"[-lR] " CMD_TARGET_PANE_USAGE " key ...",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_send_keys_exec
|
||||
};
|
||||
|
||||
@ -45,7 +44,6 @@ const struct cmd_entry cmd_send_prefix_entry = {
|
||||
"[-2] " CMD_TARGET_PANE_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_send_keys_exec
|
||||
};
|
||||
|
||||
|
@ -38,7 +38,6 @@ const struct cmd_entry cmd_server_info_entry = {
|
||||
"",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_server_info_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_set_buffer_entry = {
|
||||
CMD_BUFFER_USAGE " data",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_set_buffer_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_set_environment_entry = {
|
||||
"[-gru] " CMD_TARGET_SESSION_USAGE " name [value]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_set_environment_exec
|
||||
};
|
||||
|
||||
|
@ -67,7 +67,6 @@ const struct cmd_entry cmd_set_option_entry = {
|
||||
"[-agosquw] [-t target-session|target-window] option [value]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_set_option_exec
|
||||
};
|
||||
|
||||
@ -77,7 +76,6 @@ const struct cmd_entry cmd_set_window_option_entry = {
|
||||
"[-agoqu] " CMD_TARGET_WINDOW_USAGE " option [value]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_set_option_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_show_environment_entry = {
|
||||
"[-g] " CMD_TARGET_SESSION_USAGE " [name]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_show_environment_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_show_messages_entry = {
|
||||
CMD_TARGET_CLIENT_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_show_messages_exec
|
||||
};
|
||||
|
||||
|
@ -40,7 +40,6 @@ const struct cmd_entry cmd_show_options_entry = {
|
||||
"[-gqsvw] [-t target-session|target-window] [option]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_show_options_exec
|
||||
};
|
||||
|
||||
@ -50,7 +49,6 @@ const struct cmd_entry cmd_show_window_options_entry = {
|
||||
"[-gv] " CMD_TARGET_WINDOW_USAGE " [option]",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_show_options_exec
|
||||
};
|
||||
|
||||
|
@ -37,7 +37,6 @@ const struct cmd_entry cmd_source_file_entry = {
|
||||
"path",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_source_file_exec
|
||||
};
|
||||
|
||||
@ -96,6 +95,9 @@ cmd_source_file_done(struct cmd_q *cmdq1)
|
||||
{
|
||||
struct cmd_q *cmdq = cmdq1->data;
|
||||
|
||||
if (cmdq1->client_exit >= 0)
|
||||
cmdq->client_exit = cmdq1->client_exit;
|
||||
|
||||
cmdq_free(cmdq1);
|
||||
|
||||
cfg_references--;
|
||||
|
@ -18,7 +18,11 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
@ -37,7 +41,6 @@ const struct cmd_entry cmd_split_window_entry = {
|
||||
CMD_TARGET_PANE_USAGE " [command]",
|
||||
0,
|
||||
cmd_split_window_key_binding,
|
||||
NULL,
|
||||
cmd_split_window_exec
|
||||
};
|
||||
|
||||
@ -58,16 +61,14 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
struct window *w;
|
||||
struct window_pane *wp, *new_wp = NULL;
|
||||
struct environ env;
|
||||
const char *cmd, *cwd, *shell;
|
||||
char *cause, *new_cause;
|
||||
const char *cmd, *shell, *template;
|
||||
char *cause, *new_cause, *cp;
|
||||
u_int hlimit;
|
||||
int size, percentage;
|
||||
int size, percentage, cwd, fd = -1;
|
||||
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(cmdq, args_get(args, 't'), &s, &wp)) == NULL)
|
||||
return (CMD_RETURN_ERROR);
|
||||
@ -83,7 +84,29 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
cmd = options_get_string(&s->options, "default-command");
|
||||
else
|
||||
cmd = args->argv[0];
|
||||
cwd = cmd_get_default_path(cmdq, args_get(args, 'c'));
|
||||
|
||||
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'))
|
||||
@ -156,6 +179,9 @@ cmd_split_window_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
format_free(ft);
|
||||
}
|
||||
notify_window_layout_changed(w);
|
||||
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
|
||||
error:
|
||||
@ -164,5 +190,7 @@ error:
|
||||
window_remove_pane(w, new_wp);
|
||||
cmdq_error(cmdq, "create pane failed: %s", cause);
|
||||
free(cause);
|
||||
if (fd != -1)
|
||||
close(fd);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_start_server_entry = {
|
||||
"",
|
||||
CMD_STARTSERVER,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_start_server_exec
|
||||
};
|
||||
|
||||
|
31
cmd-string.c
31
cmd-string.c
@ -318,10 +318,13 @@ cmd_string_expand_tilde(const char *s, size_t *p)
|
||||
{
|
||||
struct passwd *pw;
|
||||
struct environ_entry *envent;
|
||||
char *home, *path, *username;
|
||||
char *home, *path, *user, *cp;
|
||||
int last;
|
||||
|
||||
home = NULL;
|
||||
if (cmd_string_getc(s, p) == '/') {
|
||||
|
||||
last = cmd_string_getc(s, p);
|
||||
if (last == EOF || last == '/' || last == ' '|| last == '\t') {
|
||||
envent = environ_find(&global_environ, "HOME");
|
||||
if (envent != NULL && *envent->value != '\0')
|
||||
home = envent->value;
|
||||
@ -329,15 +332,27 @@ cmd_string_expand_tilde(const char *s, size_t *p)
|
||||
home = pw->pw_dir;
|
||||
} else {
|
||||
cmd_string_ungetc(p);
|
||||
if ((username = cmd_string_string(s, p, '/', 0)) == NULL)
|
||||
return (NULL);
|
||||
if ((pw = getpwnam(username)) != NULL)
|
||||
home = pw->pw_dir;
|
||||
free(username);
|
||||
|
||||
cp = user = xmalloc(strlen(s));
|
||||
for (;;) {
|
||||
last = cmd_string_getc(s, p);
|
||||
if (last == EOF || last == '/' || last == ' '|| last == '\t')
|
||||
break;
|
||||
*cp++ = last;
|
||||
}
|
||||
*cp = '\0';
|
||||
|
||||
if ((pw = getpwnam(user)) != NULL)
|
||||
home = pw->pw_dir;
|
||||
free(user);
|
||||
}
|
||||
|
||||
if (home == NULL)
|
||||
return (NULL);
|
||||
|
||||
xasprintf(&path, "%s/", home);
|
||||
if (last != EOF)
|
||||
xasprintf(&path, "%s%c", home, last);
|
||||
else
|
||||
xasprintf(&path, "%s", home);
|
||||
return (path);
|
||||
}
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_suspend_client_entry = {
|
||||
CMD_TARGET_CLIENT_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_suspend_client_exec
|
||||
};
|
||||
|
||||
|
@ -35,7 +35,6 @@ const struct cmd_entry cmd_swap_pane_entry = {
|
||||
"[-dDU] " CMD_SRCDST_PANE_USAGE,
|
||||
0,
|
||||
cmd_swap_pane_key_binding,
|
||||
NULL,
|
||||
cmd_swap_pane_exec
|
||||
};
|
||||
|
||||
|
@ -34,7 +34,6 @@ const struct cmd_entry cmd_swap_window_entry = {
|
||||
"[-d] " CMD_SRCDST_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_swap_window_exec
|
||||
};
|
||||
|
||||
|
@ -36,7 +36,6 @@ const struct cmd_entry cmd_switch_client_entry = {
|
||||
"[-lnpr] [-c target-client] [-t target-session]",
|
||||
CMD_READONLY,
|
||||
cmd_switch_client_key_binding,
|
||||
NULL,
|
||||
cmd_switch_client_exec
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,6 @@
|
||||
* Unbind key from command.
|
||||
*/
|
||||
|
||||
enum cmd_retval cmd_unbind_key_check(struct args *);
|
||||
enum cmd_retval cmd_unbind_key_exec(struct cmd *, struct cmd_q *);
|
||||
enum cmd_retval cmd_unbind_key_table(struct cmd *, struct cmd_q *, int);
|
||||
|
||||
@ -36,20 +35,9 @@ const struct cmd_entry cmd_unbind_key_entry = {
|
||||
"[-acn] [-t key-table] key",
|
||||
0,
|
||||
NULL,
|
||||
cmd_unbind_key_check,
|
||||
cmd_unbind_key_exec
|
||||
};
|
||||
|
||||
enum cmd_retval
|
||||
cmd_unbind_key_check(struct args *args)
|
||||
{
|
||||
if (args_has(args, 'a') && args->argc != 0)
|
||||
return (CMD_RETURN_ERROR);
|
||||
if (!args_has(args, 'a') && args->argc != 1)
|
||||
return (CMD_RETURN_ERROR);
|
||||
return (CMD_RETURN_NORMAL);
|
||||
}
|
||||
|
||||
enum cmd_retval
|
||||
cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
{
|
||||
@ -58,13 +46,22 @@ cmd_unbind_key_exec(struct cmd *self, struct cmd_q *cmdq)
|
||||
int key;
|
||||
|
||||
if (!args_has(args, 'a')) {
|
||||
if (args->argc != 1) {
|
||||
cmdq_error(cmdq, "missing key");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
key = key_string_lookup_string(args->argv[0]);
|
||||
if (key == KEYC_NONE) {
|
||||
cmdq_error(cmdq, "unknown key: %s", args->argv[0]);
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
if (args->argc != 0) {
|
||||
cmdq_error(cmdq, "key given with -a");
|
||||
return (CMD_RETURN_ERROR);
|
||||
}
|
||||
key = KEYC_NONE;
|
||||
}
|
||||
|
||||
if (args_has(args, 't'))
|
||||
return (cmd_unbind_key_table(self, cmdq, key));
|
||||
|
@ -32,7 +32,6 @@ const struct cmd_entry cmd_unlink_window_entry = {
|
||||
"[-k] " CMD_TARGET_WINDOW_USAGE,
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_unlink_window_exec
|
||||
};
|
||||
|
||||
|
@ -33,10 +33,9 @@ enum cmd_retval cmd_wait_for_exec(struct cmd *, struct cmd_q *);
|
||||
const struct cmd_entry cmd_wait_for_entry = {
|
||||
"wait-for", "wait",
|
||||
"LSU", 1, 1,
|
||||
"[-LSU] channel",
|
||||
"[-L|-S|-U] channel",
|
||||
0,
|
||||
NULL,
|
||||
NULL,
|
||||
cmd_wait_for_exec
|
||||
};
|
||||
|
||||
|
94
cmd.c
94
cmd.c
@ -254,8 +254,6 @@ cmd_parse(int argc, char **argv, const char *file, u_int line, char **cause)
|
||||
goto usage;
|
||||
if (entry->args_upper != -1 && args->argc > entry->args_upper)
|
||||
goto usage;
|
||||
if (entry->check != NULL && entry->check(args) != 0)
|
||||
goto usage;
|
||||
|
||||
cmd = xcalloc(1, sizeof *cmd);
|
||||
cmd->entry = entry;
|
||||
@ -315,7 +313,6 @@ cmd_print(struct cmd *cmd, char *buf, size_t len)
|
||||
struct session *
|
||||
cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
|
||||
{
|
||||
struct msg_command_data *data = cmdq->msgdata;
|
||||
struct client *c = cmdq->client;
|
||||
struct session *s;
|
||||
struct sessionslist ss;
|
||||
@ -357,13 +354,6 @@ cmd_current_session(struct cmd_q *cmdq, int prefer_unattached)
|
||||
return (s);
|
||||
}
|
||||
|
||||
/* Use the session from the TMUX environment variable. */
|
||||
if (data != NULL && data->pid == getpid() && data->session_id != -1) {
|
||||
s = session_find_by_id(data->session_id);
|
||||
if (s != NULL)
|
||||
return (s);
|
||||
}
|
||||
|
||||
return (cmd_choose_session(prefer_unattached));
|
||||
}
|
||||
|
||||
@ -1278,87 +1268,3 @@ cmd_template_replace(const char *template, const char *s, int idx)
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the default path for a new pane, using the given path or the
|
||||
* default-path option if it is NULL. Several special values are accepted: the
|
||||
* empty string or relative path for the current pane's working directory, ~
|
||||
* for the user's home, - for the session working directory, . for the tmux
|
||||
* server's working directory. The default on failure is the session's working
|
||||
* directory.
|
||||
*/
|
||||
const char *
|
||||
cmd_get_default_path(struct cmd_q *cmdq, const char *cwd)
|
||||
{
|
||||
struct client *c = cmdq->client;
|
||||
struct session *s;
|
||||
struct environ_entry *envent;
|
||||
const char *root;
|
||||
char tmp[MAXPATHLEN];
|
||||
struct passwd *pw;
|
||||
int n;
|
||||
size_t skip;
|
||||
static char path[MAXPATHLEN];
|
||||
|
||||
if ((s = cmd_current_session(cmdq, 0)) == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (cwd == NULL)
|
||||
cwd = options_get_string(&s->options, "default-path");
|
||||
|
||||
skip = 1;
|
||||
if (strcmp(cwd, "$HOME") == 0 || strncmp(cwd, "$HOME/", 6) == 0) {
|
||||
/* User's home directory - $HOME. */
|
||||
skip = 5;
|
||||
goto find_home;
|
||||
} else if (cwd[0] == '~' && (cwd[1] == '\0' || cwd[1] == '/')) {
|
||||
/* User's home directory - ~. */
|
||||
goto find_home;
|
||||
} else if (cwd[0] == '-' && (cwd[1] == '\0' || cwd[1] == '/')) {
|
||||
/* Session working directory. */
|
||||
root = s->cwd;
|
||||
goto complete_path;
|
||||
} else if (cwd[0] == '.' && (cwd[1] == '\0' || cwd[1] == '/')) {
|
||||
/* Server working directory. */
|
||||
if (getcwd(tmp, sizeof tmp) != NULL) {
|
||||
root = tmp;
|
||||
goto complete_path;
|
||||
}
|
||||
return (s->cwd);
|
||||
} else if (*cwd == '/') {
|
||||
/* Absolute path. */
|
||||
return (cwd);
|
||||
} else {
|
||||
/* Empty or relative path. */
|
||||
if (c != NULL && c->session == NULL && c->cwd != NULL)
|
||||
root = c->cwd;
|
||||
else if (s->curw != NULL)
|
||||
root = osdep_get_cwd(s->curw->window->active->fd);
|
||||
else
|
||||
return (s->cwd);
|
||||
skip = 0;
|
||||
if (root != NULL)
|
||||
goto complete_path;
|
||||
}
|
||||
|
||||
return (s->cwd);
|
||||
|
||||
find_home:
|
||||
envent = environ_find(&global_environ, "HOME");
|
||||
if (envent != NULL && *envent->value != '\0')
|
||||
root = envent->value;
|
||||
else if ((pw = getpwuid(getuid())) != NULL)
|
||||
root = pw->pw_dir;
|
||||
else
|
||||
return (s->cwd);
|
||||
|
||||
complete_path:
|
||||
if (root[skip] == '\0') {
|
||||
strlcpy(path, root, sizeof path);
|
||||
return (path);
|
||||
}
|
||||
n = snprintf(path, sizeof path, "%s/%s", root, cwd + skip);
|
||||
if (n > 0 && (size_t)n < sizeof path)
|
||||
return (path);
|
||||
return (s->cwd);
|
||||
}
|
||||
|
@ -73,9 +73,9 @@ control_callback(struct client *c, int closed, unused void *data)
|
||||
c->cmdq->time = time(NULL);
|
||||
c->cmdq->number++;
|
||||
|
||||
cmdq_guard(c->cmdq, "begin");
|
||||
cmdq_guard(c->cmdq, "begin", 1);
|
||||
control_write(c, "parse error: %s", cause);
|
||||
cmdq_guard(c->cmdq, "error");
|
||||
cmdq_guard(c->cmdq, "error", 1);
|
||||
|
||||
free(cause);
|
||||
} else {
|
||||
|
143
format.c
143
format.c
@ -18,6 +18,8 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <ctype.h>
|
||||
#include <errno.h>
|
||||
#include <netdb.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
@ -34,6 +36,7 @@
|
||||
|
||||
int format_replace(struct format_tree *, const char *, size_t, char **,
|
||||
size_t *, size_t *);
|
||||
char *format_get_command(struct window_pane *);
|
||||
void format_window_pane_tabs(struct format_tree *, struct window_pane *);
|
||||
|
||||
/* Format key-value replacement entry. */
|
||||
@ -118,7 +121,7 @@ format_create(void)
|
||||
|
||||
if (gethostname(host, sizeof host) == 0) {
|
||||
format_add(ft, "host", "%s", host);
|
||||
if ((ptr = strrchr(host, '.')) != NULL)
|
||||
if ((ptr = strchr(host, '.')) != NULL)
|
||||
*ptr = '\0';
|
||||
format_add(ft, "host_short", "%s", host);
|
||||
}
|
||||
@ -151,6 +154,7 @@ void
|
||||
format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
|
||||
{
|
||||
struct format_entry *fe;
|
||||
struct format_entry *fe_now;
|
||||
va_list ap;
|
||||
|
||||
fe = xmalloc(sizeof *fe);
|
||||
@ -160,7 +164,13 @@ format_add(struct format_tree *ft, const char *key, const char *fmt, ...)
|
||||
xvasprintf(&fe->value, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
RB_INSERT(format_tree, ft, fe);
|
||||
fe_now = RB_INSERT(format_tree, ft, fe);
|
||||
if (fe_now != NULL) {
|
||||
free(fe_now->value);
|
||||
fe_now->value = fe->value;
|
||||
free(fe->key);
|
||||
free(fe);
|
||||
}
|
||||
}
|
||||
|
||||
/* Find a format entry. */
|
||||
@ -181,18 +191,40 @@ format_find(struct format_tree *ft, const char *key)
|
||||
* #{?blah,a,b} is replace with a if blah exists and is nonzero else b.
|
||||
*/
|
||||
int
|
||||
format_replace(struct format_tree *ft,
|
||||
const char *key, size_t keylen, char **buf, size_t *len, size_t *off)
|
||||
format_replace(struct format_tree *ft, const char *key, size_t keylen,
|
||||
char **buf, size_t *len, size_t *off)
|
||||
{
|
||||
char *copy, *ptr;
|
||||
char *copy, *copy0, *endptr, *ptr, *saved;
|
||||
const char *value;
|
||||
size_t valuelen;
|
||||
u_long limit = ULONG_MAX;
|
||||
|
||||
/* Make a copy of the key. */
|
||||
copy = xmalloc(keylen + 1);
|
||||
copy0 = copy = xmalloc(keylen + 1);
|
||||
memcpy(copy, key, keylen);
|
||||
copy[keylen] = '\0';
|
||||
|
||||
/* Is there a length limit or whatnot? */
|
||||
if (!islower((u_char) *copy) && *copy != '?') {
|
||||
while (*copy != ':' && *copy != '\0') {
|
||||
switch (*copy) {
|
||||
case '=':
|
||||
errno = 0;
|
||||
limit = strtoul(copy + 1, &endptr, 10);
|
||||
if (errno == ERANGE && limit == ULONG_MAX)
|
||||
goto fail;
|
||||
copy = endptr;
|
||||
break;
|
||||
default:
|
||||
copy++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (*copy != ':')
|
||||
goto fail;
|
||||
copy++;
|
||||
}
|
||||
|
||||
/*
|
||||
* Is this a conditional? If so, check it exists and extract either the
|
||||
* first or second element. If not, look up the key directly.
|
||||
@ -216,13 +248,20 @@ format_replace(struct format_tree *ft,
|
||||
goto fail;
|
||||
value = ptr + 1;
|
||||
}
|
||||
saved = format_expand(ft, value);
|
||||
value = saved;
|
||||
} else {
|
||||
value = format_find(ft, copy);
|
||||
if (value == NULL)
|
||||
value = "";
|
||||
saved = NULL;
|
||||
}
|
||||
valuelen = strlen(value);
|
||||
|
||||
/* Truncate the value if needed. */
|
||||
if (valuelen > limit)
|
||||
valuelen = limit;
|
||||
|
||||
/* Expand the buffer and copy in the value. */
|
||||
while (*len - *off < valuelen + 1) {
|
||||
*buf = xrealloc(*buf, 2, *len);
|
||||
@ -231,11 +270,12 @@ format_replace(struct format_tree *ft,
|
||||
memcpy(*buf + *off, value, valuelen);
|
||||
*off += valuelen;
|
||||
|
||||
free(copy);
|
||||
free(saved);
|
||||
free(copy0);
|
||||
return (0);
|
||||
|
||||
fail:
|
||||
free(copy);
|
||||
free(copy0);
|
||||
return (-1);
|
||||
}
|
||||
|
||||
@ -243,10 +283,10 @@ fail:
|
||||
char *
|
||||
format_expand(struct format_tree *ft, const char *fmt)
|
||||
{
|
||||
char *buf, *ptr;
|
||||
const char *s;
|
||||
char *buf;
|
||||
const char *ptr, *s;
|
||||
size_t off, len, n;
|
||||
int ch;
|
||||
int ch, brackets;
|
||||
|
||||
len = 64;
|
||||
buf = xmalloc(len);
|
||||
@ -264,11 +304,16 @@ format_expand(struct format_tree *ft, const char *fmt)
|
||||
fmt++;
|
||||
|
||||
ch = (u_char) *fmt++;
|
||||
|
||||
switch (ch) {
|
||||
case '{':
|
||||
ptr = strchr(fmt, '}');
|
||||
if (ptr == NULL)
|
||||
brackets = 1;
|
||||
for (ptr = fmt; *ptr != '\0'; ptr++) {
|
||||
if (*ptr == '{')
|
||||
brackets++;
|
||||
if (*ptr == '}' && --brackets == 0)
|
||||
break;
|
||||
}
|
||||
if (*ptr != '}' || brackets != 0)
|
||||
break;
|
||||
n = ptr - fmt;
|
||||
|
||||
@ -304,6 +349,26 @@ format_expand(struct format_tree *ft, const char *fmt)
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/* Get command name for format. */
|
||||
char *
|
||||
format_get_command(struct window_pane *wp)
|
||||
{
|
||||
char *cmd, *out;
|
||||
|
||||
cmd = get_proc_name(wp->fd, wp->tty);
|
||||
if (cmd == NULL || *cmd == '\0') {
|
||||
free(cmd);
|
||||
cmd = xstrdup(wp->cmd);
|
||||
if (cmd == NULL || *cmd == '\0') {
|
||||
free(cmd);
|
||||
cmd = xstrdup(wp->shell);
|
||||
}
|
||||
}
|
||||
out = parse_window_name(cmd);
|
||||
free(cmd);
|
||||
return (out);
|
||||
}
|
||||
|
||||
/* Set default format keys for a session. */
|
||||
void
|
||||
format_session(struct format_tree *ft, struct session *s)
|
||||
@ -343,10 +408,11 @@ format_client(struct format_tree *ft, struct client *c)
|
||||
time_t t;
|
||||
struct session *s;
|
||||
|
||||
format_add(ft, "client_cwd", "%s", c->cwd);
|
||||
format_add(ft, "client_height", "%u", c->tty.sy);
|
||||
format_add(ft, "client_width", "%u", c->tty.sx);
|
||||
if (c->tty.path != NULL)
|
||||
format_add(ft, "client_tty", "%s", c->tty.path);
|
||||
if (c->tty.termname != NULL)
|
||||
format_add(ft, "client_termname", "%s", c->tty.termname);
|
||||
|
||||
t = c->creation_time.tv_sec;
|
||||
@ -381,28 +447,50 @@ format_client(struct format_tree *ft, struct client *c)
|
||||
format_add(ft, "client_last_session", "%s", s->name);
|
||||
}
|
||||
|
||||
/* Set default format keys for a window. */
|
||||
void
|
||||
format_window(struct format_tree *ft, struct window *w)
|
||||
{
|
||||
char *layout;
|
||||
|
||||
layout = layout_dump(w);
|
||||
|
||||
format_add(ft, "window_id", "@%u", w->id);
|
||||
format_add(ft, "window_name", "%s", w->name);
|
||||
format_add(ft, "window_width", "%u", w->sx);
|
||||
format_add(ft, "window_height", "%u", w->sy);
|
||||
format_add(ft, "window_layout", "%s", layout);
|
||||
format_add(ft, "window_panes", "%u", window_count_panes(w));
|
||||
|
||||
free(layout);
|
||||
}
|
||||
|
||||
/* Set default format keys for a winlink. */
|
||||
void
|
||||
format_winlink(struct format_tree *ft, struct session *s, struct winlink *wl)
|
||||
{
|
||||
struct window *w = wl->window;
|
||||
char *layout, *flags;
|
||||
char *flags;
|
||||
|
||||
layout = layout_dump(w);
|
||||
flags = window_printable_flags(s, wl);
|
||||
|
||||
format_add(ft, "window_id", "@%u", w->id);
|
||||
format_window(ft, w);
|
||||
|
||||
format_add(ft, "window_index", "%d", wl->idx);
|
||||
format_add(ft, "window_name", "%s", w->name);
|
||||
format_add(ft, "window_width", "%u", w->sx);
|
||||
format_add(ft, "window_height", "%u", w->sy);
|
||||
format_add(ft, "window_flags", "%s", flags);
|
||||
format_add(ft, "window_layout", "%s", layout);
|
||||
format_add(ft, "window_active", "%d", wl == s->curw);
|
||||
format_add(ft, "window_panes", "%u", window_count_panes(w));
|
||||
|
||||
format_add(ft, "window_bell_flag", "%u",
|
||||
!!(wl->flags & WINLINK_BELL));
|
||||
format_add(ft, "window_content_flag", "%u",
|
||||
!!(wl->flags & WINLINK_CONTENT));
|
||||
format_add(ft, "window_activity_flag", "%u",
|
||||
!!(wl->flags & WINLINK_ACTIVITY));
|
||||
format_add(ft, "window_silence_flag", "%u",
|
||||
!!(wl->flags & WINLINK_SILENCE));
|
||||
|
||||
|
||||
free(flags);
|
||||
free(layout);
|
||||
}
|
||||
|
||||
/* Add window pane tabs. */
|
||||
@ -435,7 +523,6 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
|
||||
struct grid_line *gl;
|
||||
unsigned long long size;
|
||||
u_int i, idx;
|
||||
const char *cwd;
|
||||
char *cmd;
|
||||
|
||||
size = 0;
|
||||
@ -468,11 +555,7 @@ format_window_pane(struct format_tree *ft, struct window_pane *wp)
|
||||
format_add(ft, "pane_pid", "%ld", (long) wp->pid);
|
||||
if (wp->cmd != NULL)
|
||||
format_add(ft, "pane_start_command", "%s", wp->cmd);
|
||||
if (wp->cwd != NULL)
|
||||
format_add(ft, "pane_start_path", "%s", wp->cwd);
|
||||
if ((cwd = osdep_get_cwd(wp->fd)) != NULL)
|
||||
format_add(ft, "pane_current_path", "%s", cwd);
|
||||
if ((cmd = osdep_get_name(wp->fd, wp->tty)) != NULL) {
|
||||
if ((cmd = format_get_command(wp)) != NULL) {
|
||||
format_add(ft, "pane_current_command", "%s", cmd);
|
||||
free(cmd);
|
||||
}
|
||||
|
13
grid.c
13
grid.c
@ -268,8 +268,7 @@ grid_get_cell(struct grid *gd, u_int px, u_int py)
|
||||
|
||||
/* Set cell at relative position. */
|
||||
void
|
||||
grid_set_cell(
|
||||
struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||
grid_set_cell(struct grid *gd, u_int px, u_int py, const struct grid_cell *gc)
|
||||
{
|
||||
if (grid_check_y(gd, py) != 0)
|
||||
return;
|
||||
@ -592,6 +591,7 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
|
||||
char *buf, code[128];
|
||||
size_t len, off, size, codelen;
|
||||
u_int xx;
|
||||
const struct grid_line *gl;
|
||||
|
||||
GRID_DEBUG(gd, "px=%u, py=%u, nx=%u", px, py, nx);
|
||||
|
||||
@ -604,8 +604,11 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
|
||||
buf = xmalloc(len);
|
||||
off = 0;
|
||||
|
||||
gl = grid_peek_line(gd, py);
|
||||
for (xx = px; xx < px + nx; xx++) {
|
||||
gc = grid_peek_cell(gd, xx, py);
|
||||
if (gl == NULL || xx >= gl->cellsize)
|
||||
break;
|
||||
gc = &gl->celldata[xx];
|
||||
if (gc->flags & GRID_FLAG_PADDING)
|
||||
continue;
|
||||
grid_cell_get(gc, &ud);
|
||||
@ -653,8 +656,8 @@ grid_string_cells(struct grid *gd, u_int px, u_int py, u_int nx,
|
||||
* available.
|
||||
*/
|
||||
void
|
||||
grid_duplicate_lines(
|
||||
struct grid *dst, u_int dy, struct grid *src, u_int sy, u_int ny)
|
||||
grid_duplicate_lines(struct grid *dst, u_int dy, struct grid *src, u_int sy,
|
||||
u_int ny)
|
||||
{
|
||||
struct grid_line *dstl, *srcl;
|
||||
u_int yy;
|
||||
|
151
input.c
151
input.c
@ -70,6 +70,10 @@ int input_input(struct input_ctx *);
|
||||
int input_c0_dispatch(struct input_ctx *);
|
||||
int input_esc_dispatch(struct input_ctx *);
|
||||
int input_csi_dispatch(struct input_ctx *);
|
||||
void input_csi_dispatch_rm(struct input_ctx *);
|
||||
void input_csi_dispatch_rm_private(struct input_ctx *);
|
||||
void input_csi_dispatch_sm(struct input_ctx *);
|
||||
void input_csi_dispatch_sm_private(struct input_ctx *);
|
||||
void input_csi_dispatch_sgr(struct input_ctx *);
|
||||
int input_dcs_dispatch(struct input_ctx *);
|
||||
int input_utf8_open(struct input_ctx *);
|
||||
@ -1071,7 +1075,6 @@ int
|
||||
input_csi_dispatch(struct input_ctx *ictx)
|
||||
{
|
||||
struct screen_write_ctx *sctx = &ictx->ctx;
|
||||
struct window_pane *wp = ictx->wp;
|
||||
struct screen *s = sctx->s;
|
||||
struct input_table_entry *entry;
|
||||
int n, m;
|
||||
@ -1230,7 +1233,60 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
screen_write_cursormove(sctx, ictx->old_cx, ictx->old_cy);
|
||||
break;
|
||||
case INPUT_CSI_RM:
|
||||
switch (input_get(ictx, 0, 0, -1)) {
|
||||
input_csi_dispatch_rm(ictx);
|
||||
break;
|
||||
case INPUT_CSI_RM_PRIVATE:
|
||||
input_csi_dispatch_rm_private(ictx);
|
||||
break;
|
||||
case INPUT_CSI_SCP:
|
||||
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
|
||||
ictx->old_cx = s->cx;
|
||||
ictx->old_cy = s->cy;
|
||||
break;
|
||||
case INPUT_CSI_SGR:
|
||||
input_csi_dispatch_sgr(ictx);
|
||||
break;
|
||||
case INPUT_CSI_SM:
|
||||
input_csi_dispatch_sm(ictx);
|
||||
break;
|
||||
case INPUT_CSI_SM_PRIVATE:
|
||||
input_csi_dispatch_sm_private(ictx);
|
||||
break;
|
||||
case INPUT_CSI_TBC:
|
||||
switch (input_get(ictx, 0, 0, 0)) {
|
||||
case 0:
|
||||
if (s->cx < screen_size_x(s))
|
||||
bit_clear(s->tabs, s->cx);
|
||||
break;
|
||||
case 3:
|
||||
bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
|
||||
break;
|
||||
default:
|
||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INPUT_CSI_VPA:
|
||||
n = input_get(ictx, 0, 1, 1);
|
||||
screen_write_cursormove(sctx, s->cx, n - 1);
|
||||
break;
|
||||
case INPUT_CSI_DECSCUSR:
|
||||
n = input_get(ictx, 0, 0, 0);
|
||||
screen_set_cursor_style(s, n);
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Handle CSI RM. */
|
||||
void
|
||||
input_csi_dispatch_rm(struct input_ctx *ictx)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ictx->param_list_len; i++) {
|
||||
switch (input_get(ictx, i, 0, -1)) {
|
||||
case 4: /* IRM */
|
||||
screen_write_mode_clear(&ictx->ctx, MODE_INSERT);
|
||||
break;
|
||||
@ -1238,10 +1294,18 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INPUT_CSI_RM_PRIVATE:
|
||||
switch (input_get(ictx, 0, 0, -1)) {
|
||||
case 1: /* GATM */
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle CSI private RM. */
|
||||
void
|
||||
input_csi_dispatch_rm_private(struct input_ctx *ictx)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ictx->param_list_len; i++) {
|
||||
switch (input_get(ictx, i, 0, -1)) {
|
||||
case 1: /* DECCKM */
|
||||
screen_write_mode_clear(&ictx->ctx, MODE_KCURSOR);
|
||||
break;
|
||||
case 3: /* DECCOLM */
|
||||
@ -1271,10 +1335,10 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
break;
|
||||
case 47:
|
||||
case 1047:
|
||||
window_pane_alternate_off(wp, &ictx->cell, 0);
|
||||
window_pane_alternate_off(ictx->wp, &ictx->cell, 0);
|
||||
break;
|
||||
case 1049:
|
||||
window_pane_alternate_off(wp, &ictx->cell, 1);
|
||||
window_pane_alternate_off(ictx->wp, &ictx->cell, 1);
|
||||
break;
|
||||
case 2004:
|
||||
screen_write_mode_clear(&ictx->ctx, MODE_BRACKETPASTE);
|
||||
@ -1283,17 +1347,17 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INPUT_CSI_SCP:
|
||||
memcpy(&ictx->old_cell, &ictx->cell, sizeof ictx->old_cell);
|
||||
ictx->old_cx = s->cx;
|
||||
ictx->old_cy = s->cy;
|
||||
break;
|
||||
case INPUT_CSI_SGR:
|
||||
input_csi_dispatch_sgr(ictx);
|
||||
break;
|
||||
case INPUT_CSI_SM:
|
||||
switch (input_get(ictx, 0, 0, -1)) {
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle CSI SM. */
|
||||
void
|
||||
input_csi_dispatch_sm(struct input_ctx *ictx)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ictx->param_list_len; i++) {
|
||||
switch (input_get(ictx, i, 0, -1)) {
|
||||
case 4: /* IRM */
|
||||
screen_write_mode_set(&ictx->ctx, MODE_INSERT);
|
||||
break;
|
||||
@ -1301,10 +1365,18 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INPUT_CSI_SM_PRIVATE:
|
||||
switch (input_get(ictx, 0, 0, -1)) {
|
||||
case 1: /* GATM */
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle CSI private SM. */
|
||||
void
|
||||
input_csi_dispatch_sm_private(struct input_ctx *ictx)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ictx->param_list_len; i++) {
|
||||
switch (input_get(ictx, i, 0, -1)) {
|
||||
case 1: /* DECCKM */
|
||||
screen_write_mode_set(&ictx->ctx, MODE_KCURSOR);
|
||||
break;
|
||||
case 3: /* DECCOLM */
|
||||
@ -1330,10 +1402,10 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_ANY);
|
||||
break;
|
||||
case 1004:
|
||||
if (s->mode & MODE_FOCUSON)
|
||||
if (ictx->ctx.s->mode & MODE_FOCUSON)
|
||||
break;
|
||||
screen_write_mode_set(&ictx->ctx, MODE_FOCUSON);
|
||||
wp->flags |= PANE_FOCUSPUSH; /* force update */
|
||||
ictx->wp->flags |= PANE_FOCUSPUSH; /* force update */
|
||||
break;
|
||||
case 1005:
|
||||
screen_write_mode_set(&ictx->ctx, MODE_MOUSE_UTF8);
|
||||
@ -1343,10 +1415,10 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
break;
|
||||
case 47:
|
||||
case 1047:
|
||||
window_pane_alternate_on(wp, &ictx->cell, 0);
|
||||
window_pane_alternate_on(ictx->wp, &ictx->cell, 0);
|
||||
break;
|
||||
case 1049:
|
||||
window_pane_alternate_on(wp, &ictx->cell, 1);
|
||||
window_pane_alternate_on(ictx->wp, &ictx->cell, 1);
|
||||
break;
|
||||
case 2004:
|
||||
screen_write_mode_set(&ictx->ctx, MODE_BRACKETPASTE);
|
||||
@ -1355,32 +1427,7 @@ input_csi_dispatch(struct input_ctx *ictx)
|
||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INPUT_CSI_TBC:
|
||||
switch (input_get(ictx, 0, 0, 0)) {
|
||||
case 0:
|
||||
if (s->cx < screen_size_x(s))
|
||||
bit_clear(s->tabs, s->cx);
|
||||
break;
|
||||
case 3:
|
||||
bit_nclear(s->tabs, 0, screen_size_x(s) - 1);
|
||||
break;
|
||||
default:
|
||||
log_debug("%s: unknown '%c'", __func__, ictx->ch);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case INPUT_CSI_VPA:
|
||||
n = input_get(ictx, 0, 1, 1);
|
||||
screen_write_cursormove(sctx, s->cx, n - 1);
|
||||
break;
|
||||
case INPUT_CSI_DECSCUSR:
|
||||
n = input_get(ictx, 0, 0, 0);
|
||||
screen_set_cursor_style(s, n);
|
||||
break;
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/* Handle CSI SGR. */
|
||||
|
5
layout.c
5
layout.c
@ -533,6 +533,9 @@ layout_resize_pane_mouse(struct client *c)
|
||||
pane_border = 0;
|
||||
if (m->event & MOUSE_EVENT_DRAG && m->flags & MOUSE_RESIZE_PANE) {
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if (!window_pane_visible(wp))
|
||||
continue;
|
||||
|
||||
if (wp->xoff + wp->sx == m->lx &&
|
||||
wp->yoff <= 1 + m->ly &&
|
||||
wp->yoff + wp->sy >= m->ly) {
|
||||
@ -550,7 +553,7 @@ layout_resize_pane_mouse(struct client *c)
|
||||
}
|
||||
if (pane_border)
|
||||
server_redraw_window(w);
|
||||
} else if (~m->event & MOUSE_EVENT_UP) {
|
||||
} else if (m->event & MOUSE_EVENT_DOWN) {
|
||||
TAILQ_FOREACH(wp, &w->panes, entry) {
|
||||
if ((wp->xoff + wp->sx == m->x &&
|
||||
wp->yoff <= 1 + m->y &&
|
||||
|
58
names.c
58
names.c
@ -22,12 +22,10 @@
|
||||
#include <libgen.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "tmux.h"
|
||||
|
||||
void window_name_callback(unused int, unused short, void *);
|
||||
char *parse_window_name(const char *);
|
||||
|
||||
void
|
||||
queue_window_name(struct window *w)
|
||||
@ -47,7 +45,7 @@ void
|
||||
window_name_callback(unused int fd, unused short events, void *data)
|
||||
{
|
||||
struct window *w = data;
|
||||
char *name, *wname;
|
||||
char *name;
|
||||
|
||||
if (w->active == NULL)
|
||||
return;
|
||||
@ -59,49 +57,39 @@ window_name_callback(unused int fd, unused short events, void *data)
|
||||
}
|
||||
queue_window_name(w);
|
||||
|
||||
if (w->active->screen != &w->active->base)
|
||||
name = NULL;
|
||||
else
|
||||
name = osdep_get_name(w->active->fd, w->active->tty);
|
||||
if (name == NULL)
|
||||
wname = default_window_name(w);
|
||||
else {
|
||||
/*
|
||||
* If tmux is using the default command, it will be a login
|
||||
* shell and argv[0] may have a - prefix. Remove this if it is
|
||||
* present. Ick.
|
||||
*/
|
||||
if (w->active->cmd != NULL && *w->active->cmd == '\0' &&
|
||||
name != NULL && name[0] == '-' && name[1] != '\0')
|
||||
wname = parse_window_name(name + 1);
|
||||
else
|
||||
wname = parse_window_name(name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
if (w->active->fd == -1) {
|
||||
xasprintf(&name, "%s[dead]", wname);
|
||||
free(wname);
|
||||
wname = name;
|
||||
}
|
||||
|
||||
if (strcmp(wname, w->name)) {
|
||||
window_set_name(w, wname);
|
||||
name = format_window_name(w);
|
||||
if (strcmp(name, w->name) != 0) {
|
||||
window_set_name(w, name);
|
||||
server_status_window(w);
|
||||
}
|
||||
free(wname);
|
||||
free(name);
|
||||
}
|
||||
|
||||
char *
|
||||
default_window_name(struct window *w)
|
||||
{
|
||||
if (w->active->screen != &w->active->base)
|
||||
return (xstrdup("[tmux]"));
|
||||
if (w->active->cmd != NULL && *w->active->cmd != '\0')
|
||||
return (parse_window_name(w->active->cmd));
|
||||
return (parse_window_name(w->active->shell));
|
||||
}
|
||||
|
||||
char *
|
||||
format_window_name(struct window *w)
|
||||
{
|
||||
struct format_tree *ft;
|
||||
char *fmt, *name;
|
||||
|
||||
ft = format_create();
|
||||
format_window(ft, w);
|
||||
format_window_pane(ft, w->active);
|
||||
|
||||
fmt = options_get_string(&w->options, "automatic-rename-format");
|
||||
name = format_expand(ft, fmt);
|
||||
|
||||
format_free(ft);
|
||||
return (name);
|
||||
}
|
||||
|
||||
char *
|
||||
parse_window_name(const char *in)
|
||||
{
|
||||
@ -111,7 +99,7 @@ parse_window_name(const char *in)
|
||||
if (strncmp(name, "exec ", (sizeof "exec ") - 1) == 0)
|
||||
name = name + (sizeof "exec ") - 1;
|
||||
|
||||
while (*name == ' ')
|
||||
while (*name == ' ' || *name == '-')
|
||||
name++;
|
||||
if ((ptr = strchr(name, ' ')) != NULL)
|
||||
*ptr = '\0';
|
||||
|
@ -125,11 +125,6 @@ const struct options_table_entry session_options_table[] = {
|
||||
.default_str = ""
|
||||
},
|
||||
|
||||
{ .name = "default-path",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.default_str = ""
|
||||
},
|
||||
|
||||
{ .name = "default-shell",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.default_str = _PATH_BSHELL
|
||||
@ -386,7 +381,7 @@ const struct options_table_entry session_options_table[] = {
|
||||
|
||||
{ .name = "status-right",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.default_str = "\"#22T\" %H:%M %d-%b-%y"
|
||||
.default_str = "\"#{=22:pane_title}\" %H:%M %d-%b-%y"
|
||||
},
|
||||
|
||||
{ .name = "status-right-attr",
|
||||
@ -481,6 +476,11 @@ const struct options_table_entry window_options_table[] = {
|
||||
.default_num = 1
|
||||
},
|
||||
|
||||
{ .name = "automatic-rename-format",
|
||||
.type = OPTIONS_TABLE_STRING,
|
||||
.default_str = "#{?pane_in_mode,[tmux],#{pane_current_command}}#{?pane_dead,[dead],}"
|
||||
},
|
||||
|
||||
{ .name = "c0-change-trigger",
|
||||
.type = OPTIONS_TABLE_NUMBER,
|
||||
.default_num = 250,
|
||||
|
@ -37,9 +37,7 @@
|
||||
((p)->p_stat == SSTOP || (p)->p_stat == SZOMB || (p)->p_stat == SDEAD)
|
||||
|
||||
struct kinfo_proc *cmp_procs(struct kinfo_proc *, struct kinfo_proc *);
|
||||
char *osdep_get_name(int, char *);
|
||||
char *osdep_get_cwd(int);
|
||||
struct event_base *osdep_event_init(void);
|
||||
char *get_proc_name(int, char *);
|
||||
|
||||
struct kinfo_proc *
|
||||
cmp_procs(struct kinfo_proc *p1, struct kinfo_proc *p2)
|
||||
@ -134,23 +132,3 @@ error:
|
||||
free(buf);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
char*
|
||||
osdep_get_cwd(int fd)
|
||||
{
|
||||
int name[] = { CTL_KERN, KERN_PROC_CWD, 0 };
|
||||
static char path[MAXPATHLEN];
|
||||
size_t pathlen = sizeof path;
|
||||
|
||||
if ((name[2] = tcgetpgrp(fd)) == -1)
|
||||
return (NULL);
|
||||
if (sysctl(name, 3, path, &pathlen, NULL, 0) != 0)
|
||||
return (NULL);
|
||||
return (path);
|
||||
}
|
||||
|
||||
struct event_base *
|
||||
osdep_event_init(void)
|
||||
{
|
||||
return (event_init());
|
||||
}
|
||||
|
2
resize.c
2
resize.c
@ -92,7 +92,7 @@ recalculate_sizes(void)
|
||||
|
||||
for (i = 0; i < ARRAY_LENGTH(&windows); i++) {
|
||||
w = ARRAY_ITEM(&windows, i);
|
||||
if (w == NULL)
|
||||
if (w == NULL || w->active == NULL)
|
||||
continue;
|
||||
flag = options_get_number(&w->options, "aggressive-resize");
|
||||
|
||||
|
179
server-client.c
179
server-client.c
@ -40,9 +40,8 @@ void server_client_reset_state(struct client *);
|
||||
int server_client_assume_paste(struct session *);
|
||||
|
||||
int server_client_msg_dispatch(struct client *);
|
||||
void server_client_msg_command(struct client *, struct msg_command_data *);
|
||||
void server_client_msg_identify(
|
||||
struct client *, struct msg_identify_data *, int);
|
||||
void server_client_msg_command(struct client *, struct imsg *);
|
||||
void server_client_msg_identify(struct client *, struct imsg *);
|
||||
void server_client_msg_shell(struct client *);
|
||||
|
||||
/* Create a new client. */
|
||||
@ -63,6 +62,8 @@ server_client_create(int fd)
|
||||
fatal("gettimeofday failed");
|
||||
memcpy(&c->activity_time, &c->creation_time, sizeof c->activity_time);
|
||||
|
||||
environ_init(&c->environ);
|
||||
|
||||
c->cmdq = cmdq_new(c);
|
||||
c->cmdq->client_exit = 1;
|
||||
|
||||
@ -151,6 +152,8 @@ server_client_lost(struct client *c)
|
||||
*/
|
||||
if (c->flags & CLIENT_TERMINAL)
|
||||
tty_free(&c->tty);
|
||||
free(c->ttyname);
|
||||
free(c->term);
|
||||
|
||||
evbuffer_free (c->stdin_data);
|
||||
evbuffer_free (c->stdout_data);
|
||||
@ -162,6 +165,7 @@ server_client_lost(struct client *c)
|
||||
screen_free(&c->status);
|
||||
|
||||
free(c->title);
|
||||
close(c->cwd);
|
||||
|
||||
evtimer_del(&c->repeat_timer);
|
||||
|
||||
@ -179,7 +183,6 @@ server_client_lost(struct client *c)
|
||||
|
||||
free(c->prompt_string);
|
||||
free(c->prompt_buffer);
|
||||
free(c->cwd);
|
||||
|
||||
c->cmdq->dead = 1;
|
||||
cmdq_free(c->cmdq);
|
||||
@ -695,8 +698,6 @@ server_client_repeat_timer(unused int fd, unused short events, void *data)
|
||||
void
|
||||
server_client_check_exit(struct client *c)
|
||||
{
|
||||
struct msg_exit_data exitdata;
|
||||
|
||||
if (!(c->flags & CLIENT_EXIT))
|
||||
return;
|
||||
|
||||
@ -707,9 +708,7 @@ server_client_check_exit(struct client *c)
|
||||
if (EVBUFFER_LENGTH(c->stderr_data) != 0)
|
||||
return;
|
||||
|
||||
exitdata.retcode = c->retcode;
|
||||
server_write_client(c, MSG_EXIT, &exitdata, sizeof exitdata);
|
||||
|
||||
server_write_client(c, MSG_EXIT, &c->retval, sizeof c->retval);
|
||||
c->flags &= ~CLIENT_EXIT;
|
||||
}
|
||||
|
||||
@ -790,10 +789,8 @@ int
|
||||
server_client_msg_dispatch(struct client *c)
|
||||
{
|
||||
struct imsg imsg;
|
||||
struct msg_command_data commanddata;
|
||||
struct msg_identify_data identifydata;
|
||||
struct msg_environ_data environdata;
|
||||
struct msg_stdin_data stdindata;
|
||||
const char *data;
|
||||
ssize_t n, datalen;
|
||||
|
||||
if ((n = imsg_read(&c->ibuf)) == -1 || n == 0)
|
||||
@ -804,40 +801,37 @@ server_client_msg_dispatch(struct client *c)
|
||||
return (-1);
|
||||
if (n == 0)
|
||||
return (0);
|
||||
|
||||
data = imsg.data;
|
||||
datalen = imsg.hdr.len - IMSG_HEADER_SIZE;
|
||||
|
||||
if (imsg.hdr.peerid != PROTOCOL_VERSION) {
|
||||
server_write_client(c, MSG_VERSION, NULL, 0);
|
||||
c->flags |= CLIENT_BAD;
|
||||
if (imsg.fd != -1)
|
||||
close(imsg.fd);
|
||||
imsg_free(&imsg);
|
||||
continue;
|
||||
}
|
||||
|
||||
log_debug("got %d from client %d", imsg.hdr.type, c->ibuf.fd);
|
||||
switch (imsg.hdr.type) {
|
||||
case MSG_COMMAND:
|
||||
if (datalen != sizeof commanddata)
|
||||
fatalx("bad MSG_COMMAND size");
|
||||
memcpy(&commanddata, imsg.data, sizeof commanddata);
|
||||
|
||||
server_client_msg_command(c, &commanddata);
|
||||
case MSG_IDENTIFY_FLAGS:
|
||||
case MSG_IDENTIFY_TERM:
|
||||
case MSG_IDENTIFY_TTYNAME:
|
||||
case MSG_IDENTIFY_CWD:
|
||||
case MSG_IDENTIFY_STDIN:
|
||||
case MSG_IDENTIFY_ENVIRON:
|
||||
case MSG_IDENTIFY_DONE:
|
||||
server_client_msg_identify(c, &imsg);
|
||||
break;
|
||||
case MSG_IDENTIFY:
|
||||
if (datalen != sizeof identifydata)
|
||||
fatalx("bad MSG_IDENTIFY size");
|
||||
memcpy(&identifydata, imsg.data, sizeof identifydata);
|
||||
#ifdef __CYGWIN__
|
||||
imsg.fd = open(identifydata.ttyname, O_RDWR|O_NOCTTY);
|
||||
#endif
|
||||
if (imsg.fd == -1)
|
||||
fatalx("MSG_IDENTIFY missing fd");
|
||||
|
||||
server_client_msg_identify(c, &identifydata, imsg.fd);
|
||||
case MSG_COMMAND:
|
||||
server_client_msg_command(c, &imsg);
|
||||
break;
|
||||
case MSG_STDIN:
|
||||
if (datalen != sizeof stdindata)
|
||||
fatalx("bad MSG_STDIN size");
|
||||
memcpy(&stdindata, imsg.data, sizeof stdindata);
|
||||
memcpy(&stdindata, data, sizeof stdindata);
|
||||
|
||||
if (c->stdin_callback == NULL)
|
||||
break;
|
||||
@ -887,23 +881,12 @@ server_client_msg_dispatch(struct client *c)
|
||||
server_redraw_client(c);
|
||||
recalculate_sizes();
|
||||
break;
|
||||
case MSG_ENVIRON:
|
||||
if (datalen != sizeof environdata)
|
||||
fatalx("bad MSG_ENVIRON size");
|
||||
memcpy(&environdata, imsg.data, sizeof environdata);
|
||||
|
||||
environdata.var[(sizeof environdata.var) - 1] = '\0';
|
||||
if (strchr(environdata.var, '=') != NULL)
|
||||
environ_put(&c->environ, environdata.var);
|
||||
break;
|
||||
case MSG_SHELL:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_SHELL size");
|
||||
|
||||
server_client_msg_shell(c);
|
||||
break;
|
||||
default:
|
||||
fatalx("unexpected message");
|
||||
}
|
||||
|
||||
imsg_free(&imsg);
|
||||
@ -912,15 +895,26 @@ server_client_msg_dispatch(struct client *c)
|
||||
|
||||
/* Handle command message. */
|
||||
void
|
||||
server_client_msg_command(struct client *c, struct msg_command_data *data)
|
||||
server_client_msg_command(struct client *c, struct imsg *imsg)
|
||||
{
|
||||
struct msg_command_data data;
|
||||
char *buf;
|
||||
size_t len;
|
||||
struct cmd_list *cmdlist = NULL;
|
||||
int argc;
|
||||
char **argv, *cause;
|
||||
|
||||
argc = data->argc;
|
||||
data->argv[(sizeof data->argv) - 1] = '\0';
|
||||
if (cmd_unpack_argv(data->argv, sizeof data->argv, argc, &argv) != 0) {
|
||||
if (imsg->hdr.len - IMSG_HEADER_SIZE < sizeof data)
|
||||
fatalx("bad MSG_COMMAND size");
|
||||
memcpy(&data, imsg->data, sizeof data);
|
||||
|
||||
buf = (char*)imsg->data + sizeof data;
|
||||
len = imsg->hdr.len - IMSG_HEADER_SIZE - sizeof data;
|
||||
if (len > 0 && buf[len - 1] != '\0')
|
||||
fatalx("bad MSG_COMMAND string");
|
||||
|
||||
argc = data.argc;
|
||||
if (cmd_unpack_argv(buf, len, argc, &argv) != 0) {
|
||||
cmdq_error(c->cmdq, "command too long");
|
||||
goto error;
|
||||
}
|
||||
@ -951,44 +945,99 @@ error:
|
||||
|
||||
/* Handle identify message. */
|
||||
void
|
||||
server_client_msg_identify(
|
||||
struct client *c, struct msg_identify_data *data, int fd)
|
||||
server_client_msg_identify(struct client *c, struct imsg *imsg)
|
||||
{
|
||||
c->cwd = NULL;
|
||||
data->cwd[(sizeof data->cwd) - 1] = '\0';
|
||||
if (*data->cwd != '\0')
|
||||
c->cwd = xstrdup(data->cwd);
|
||||
const char *data;
|
||||
size_t datalen;
|
||||
int flags;
|
||||
|
||||
if (data->flags & IDENTIFY_CONTROL) {
|
||||
if (c->flags & CLIENT_IDENTIFIED)
|
||||
fatalx("out-of-order identify message");
|
||||
|
||||
data = imsg->data;
|
||||
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case MSG_IDENTIFY_FLAGS:
|
||||
if (datalen != sizeof flags)
|
||||
fatalx("bad MSG_IDENTIFY_FLAGS size");
|
||||
memcpy(&flags, data, sizeof flags);
|
||||
c->flags |= flags;
|
||||
break;
|
||||
case MSG_IDENTIFY_TERM:
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_IDENTIFY_TERM string");
|
||||
c->term = xstrdup(data);
|
||||
break;
|
||||
case MSG_IDENTIFY_TTYNAME:
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_IDENTIFY_TTYNAME string");
|
||||
c->ttyname = xstrdup(data);
|
||||
break;
|
||||
case MSG_IDENTIFY_CWD:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_IDENTIFY_CWD size");
|
||||
c->cwd = imsg->fd;
|
||||
break;
|
||||
case MSG_IDENTIFY_STDIN:
|
||||
if (datalen != 0)
|
||||
fatalx("bad MSG_IDENTIFY_STDIN size");
|
||||
c->fd = imsg->fd;
|
||||
break;
|
||||
case MSG_IDENTIFY_ENVIRON:
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_IDENTIFY_ENVIRON string");
|
||||
if (strchr(data, '=') != NULL)
|
||||
environ_put(&c->environ, data);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (imsg->hdr.type != MSG_IDENTIFY_DONE)
|
||||
return;
|
||||
c->flags |= CLIENT_IDENTIFIED;
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
c->fd = open(c->ttyname, O_RDWR|O_NOCTTY);
|
||||
c->cwd = open(".", O_RDONLY);
|
||||
#endif
|
||||
|
||||
if (c->flags & CLIENT_CONTROL) {
|
||||
c->stdin_callback = control_callback;
|
||||
|
||||
evbuffer_free(c->stderr_data);
|
||||
c->stderr_data = c->stdout_data;
|
||||
c->flags |= CLIENT_CONTROL;
|
||||
if (data->flags & IDENTIFY_TERMIOS)
|
||||
|
||||
if (c->flags & CLIENT_CONTROLCONTROL)
|
||||
evbuffer_add_printf(c->stdout_data, "\033P1000p");
|
||||
server_write_client(c, MSG_STDIN, NULL, 0);
|
||||
|
||||
c->tty.fd = -1;
|
||||
c->tty.log_fd = -1;
|
||||
|
||||
close(fd);
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isatty(fd)) {
|
||||
close(fd);
|
||||
if (c->fd == -1)
|
||||
return;
|
||||
if (!isatty(c->fd)) {
|
||||
close(c->fd);
|
||||
c->fd = -1;
|
||||
return;
|
||||
}
|
||||
data->term[(sizeof data->term) - 1] = '\0';
|
||||
tty_init(&c->tty, c, fd, data->term);
|
||||
if (data->flags & IDENTIFY_UTF8)
|
||||
tty_init(&c->tty, c, c->fd, c->term);
|
||||
if (c->flags & CLIENT_UTF8)
|
||||
c->tty.flags |= TTY_UTF8;
|
||||
if (data->flags & IDENTIFY_256COLOURS)
|
||||
if (c->flags & CLIENT_256COLOURS)
|
||||
c->tty.term_flags |= TERM_256COLOURS;
|
||||
|
||||
tty_resize(&c->tty);
|
||||
|
||||
if (!(data->flags & IDENTIFY_CONTROL))
|
||||
if (!(c->flags & CLIENT_CONTROL))
|
||||
c->flags |= CLIENT_TERMINAL;
|
||||
}
|
||||
|
||||
@ -996,16 +1045,12 @@ server_client_msg_identify(
|
||||
void
|
||||
server_client_msg_shell(struct client *c)
|
||||
{
|
||||
struct msg_shell_data data;
|
||||
const char *shell;
|
||||
|
||||
shell = options_get_string(&global_s_options, "default-shell");
|
||||
|
||||
if (*shell == '\0' || areshell(shell))
|
||||
shell = _PATH_BSHELL;
|
||||
if (strlcpy(data.shell, shell, sizeof data.shell) >= sizeof data.shell)
|
||||
strlcpy(data.shell, _PATH_BSHELL, sizeof data.shell);
|
||||
server_write_client(c, MSG_SHELL, shell, strlen(shell) + 1);
|
||||
|
||||
server_write_client(c, MSG_SHELL, &data, sizeof data);
|
||||
c->flags |= CLIENT_BAD; /* it will die after exec */
|
||||
}
|
||||
|
22
server-fn.c
22
server-fn.c
@ -56,8 +56,8 @@ server_write_ready(struct client *c)
|
||||
}
|
||||
|
||||
int
|
||||
server_write_client(
|
||||
struct client *c, enum msgtype type, const void *buf, size_t len)
|
||||
server_write_client(struct client *c, enum msgtype type, const void *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct imsgbuf *ibuf = &c->ibuf;
|
||||
int error;
|
||||
@ -73,8 +73,8 @@ server_write_client(
|
||||
}
|
||||
|
||||
void
|
||||
server_write_session(
|
||||
struct session *s, enum msgtype type, const void *buf, size_t len)
|
||||
server_write_session(struct session *s, enum msgtype type, const void *buf,
|
||||
size_t len)
|
||||
{
|
||||
struct client *c;
|
||||
u_int i;
|
||||
@ -236,8 +236,6 @@ void
|
||||
server_lock_client(struct client *c)
|
||||
{
|
||||
const char *cmd;
|
||||
size_t cmdlen;
|
||||
struct msg_lock_data lockdata;
|
||||
|
||||
if (c->flags & CLIENT_CONTROL)
|
||||
return;
|
||||
@ -246,8 +244,7 @@ server_lock_client(struct client *c)
|
||||
return;
|
||||
|
||||
cmd = options_get_string(&c->session->options, "lock-command");
|
||||
cmdlen = strlcpy(lockdata.cmd, cmd, sizeof lockdata.cmd);
|
||||
if (cmdlen >= sizeof lockdata.cmd)
|
||||
if (strlen(cmd) + 1 > MAX_IMSGSIZE - IMSG_HEADER_SIZE)
|
||||
return;
|
||||
|
||||
tty_stop_tty(&c->tty);
|
||||
@ -256,7 +253,7 @@ server_lock_client(struct client *c)
|
||||
tty_raw(&c->tty, tty_term_string(c->tty.term, TTYC_E3));
|
||||
|
||||
c->flags |= CLIENT_SUSPENDED;
|
||||
server_write_client(c, MSG_LOCK, &lockdata, sizeof lockdata);
|
||||
server_write_client(c, MSG_LOCK, cmd, strlen(cmd) + 1);
|
||||
}
|
||||
|
||||
void
|
||||
@ -398,14 +395,15 @@ void
|
||||
server_destroy_session_group(struct session *s)
|
||||
{
|
||||
struct session_group *sg;
|
||||
struct session *s1;
|
||||
|
||||
if ((sg = session_group_find(s)) == NULL)
|
||||
server_destroy_session(s);
|
||||
else {
|
||||
TAILQ_FOREACH(s, &sg->sessions, gentry)
|
||||
TAILQ_FOREACH_SAFE(s, &sg->sessions, gentry, s1) {
|
||||
server_destroy_session(s);
|
||||
TAILQ_REMOVE(&session_groups, sg, entry);
|
||||
free(sg);
|
||||
session_destroy(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
20
session.c
20
session.c
@ -84,9 +84,8 @@ session_find_by_id(u_int id)
|
||||
|
||||
/* Create a new session. */
|
||||
struct session *
|
||||
session_create(const char *name, const char *cmd, const char *cwd,
|
||||
struct environ *env, struct termios *tio, int idx, u_int sx, u_int sy,
|
||||
char **cause)
|
||||
session_create(const char *name, const char *cmd, int cwd, struct environ *env,
|
||||
struct termios *tio, int idx, u_int sx, u_int sy, char **cause)
|
||||
{
|
||||
struct session *s;
|
||||
|
||||
@ -98,7 +97,7 @@ session_create(const char *name, const char *cmd, const char *cwd,
|
||||
fatal("gettimeofday failed");
|
||||
session_update_activity(s);
|
||||
|
||||
s->cwd = xstrdup(cwd);
|
||||
s->cwd = dup(cwd);
|
||||
|
||||
s->curw = NULL;
|
||||
TAILQ_INIT(&s->lastw);
|
||||
@ -150,6 +149,7 @@ void
|
||||
session_destroy(struct session *s)
|
||||
{
|
||||
struct winlink *wl;
|
||||
|
||||
log_debug("session %s destroyed", s->name);
|
||||
|
||||
RB_REMOVE(sessions, &sessions, s);
|
||||
@ -169,7 +169,7 @@ session_destroy(struct session *s)
|
||||
winlink_remove(&s->windows, wl);
|
||||
}
|
||||
|
||||
free(s->cwd);
|
||||
close(s->cwd);
|
||||
|
||||
RB_INSERT(sessions, &dead_sessions, s);
|
||||
}
|
||||
@ -225,8 +225,8 @@ session_previous_session(struct session *s)
|
||||
|
||||
/* Create a new window on a session. */
|
||||
struct winlink *
|
||||
session_new(struct session *s,
|
||||
const char *name, const char *cmd, const char *cwd, int idx, char **cause)
|
||||
session_new(struct session *s, const char *name, const char *cmd, int cwd,
|
||||
int idx, char **cause)
|
||||
{
|
||||
struct window *w;
|
||||
struct winlink *wl;
|
||||
@ -249,8 +249,8 @@ session_new(struct session *s,
|
||||
shell = _PATH_BSHELL;
|
||||
|
||||
hlimit = options_get_number(&s->options, "history-limit");
|
||||
w = window_create(
|
||||
name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy, hlimit, cause);
|
||||
w = window_create(name, cmd, shell, cwd, &env, s->tio, s->sx, s->sy,
|
||||
hlimit, cause);
|
||||
if (w == NULL) {
|
||||
winlink_remove(&s->windows, wl);
|
||||
environ_free(&env);
|
||||
@ -614,7 +614,7 @@ session_renumber_windows(struct session *s)
|
||||
memcpy(&old_lastw, &s->lastw, sizeof old_lastw);
|
||||
TAILQ_INIT(&s->lastw);
|
||||
TAILQ_FOREACH(wl, &old_lastw, sentry) {
|
||||
wl_new = winlink_find_by_index(&s->windows, wl->idx);
|
||||
wl_new = winlink_find_by_window(&s->windows, wl->window);
|
||||
if (wl_new != NULL)
|
||||
TAILQ_INSERT_TAIL(&s->lastw, wl_new, sentry);
|
||||
}
|
||||
|
60
tmux.1
60
tmux.1
@ -99,7 +99,9 @@ Force
|
||||
.Nm
|
||||
to assume the terminal supports 256 colours.
|
||||
.It Fl C
|
||||
Start in control mode.
|
||||
Start in control mode (see the
|
||||
.Sx CONTROL MODE
|
||||
section).
|
||||
Given twice
|
||||
.Xo ( Fl CC ) Xc
|
||||
disables echo.
|
||||
@ -566,6 +568,7 @@ The following commands are available to manage clients and sessions:
|
||||
.Bl -tag -width Ds
|
||||
.It Xo Ic attach-session
|
||||
.Op Fl dr
|
||||
.Op Fl c Ar working-directory
|
||||
.Op Fl t Ar target-session
|
||||
.Xc
|
||||
.D1 (alias: Ic attach )
|
||||
@ -599,6 +602,10 @@ needs to select the most recently used session, it will prefer the most
|
||||
recently used
|
||||
.Em unattached
|
||||
session.
|
||||
.Pp
|
||||
.Fl c
|
||||
will set the session working directory (used for new windows) to
|
||||
.Ar working-directory .
|
||||
.It Xo Ic detach-client
|
||||
.Op Fl P
|
||||
.Op Fl a
|
||||
@ -626,9 +633,10 @@ If it does exist, exit with 0.
|
||||
Kill the
|
||||
.Nm
|
||||
server and clients and destroy all sessions.
|
||||
.It Ic kill-session
|
||||
.It Xo Ic kill-session
|
||||
.Op Fl a
|
||||
.Op Fl t Ar target-session
|
||||
.Xc
|
||||
Destroy the given session, closing any windows linked to it and no other
|
||||
sessions, and detaching all clients attached to it.
|
||||
If
|
||||
@ -673,6 +681,7 @@ Lock all clients attached to
|
||||
.Ar target-session .
|
||||
.It Xo Ic new-session
|
||||
.Op Fl AdDP
|
||||
.Op Fl c Ar start-directory
|
||||
.Op Fl F Ar format
|
||||
.Op Fl n Ar window-name
|
||||
.Op Fl s Ar session-name
|
||||
@ -1509,13 +1518,6 @@ is not specified, the value of the
|
||||
option is used.
|
||||
.Fl c
|
||||
specifies the working directory in which the new window is created.
|
||||
It may have an absolute path or one of the following values (or a subdirectory):
|
||||
.Bl -column "XXXXXXXXXXXX" "XXXXXXXXXXXXXXXXXXXXXXXX" -offset indent
|
||||
.It Li "Empty string" Ta "Current pane's directory"
|
||||
.It Li "~" Ta "User's home directory"
|
||||
.It Li "-" Ta "Where session was started"
|
||||
.It Li "." Ta "Where server was started"
|
||||
.El
|
||||
.Pp
|
||||
When the shell command completes, the window closes.
|
||||
See the
|
||||
@ -2175,15 +2177,6 @@ The default is an empty string, which instructs
|
||||
to create a login shell using the value of the
|
||||
.Ic default-shell
|
||||
option.
|
||||
.It Ic default-path Ar path
|
||||
Set the default working directory for new panes.
|
||||
If empty (the default), the working directory is determined from the process
|
||||
running in the active pane, from the command line environment or from the
|
||||
working directory where the session was created.
|
||||
Otherwise the same options are available as for the
|
||||
.Fl c
|
||||
flag to
|
||||
.Ic new-window .
|
||||
.It Ic default-shell Ar path
|
||||
Specify the default shell.
|
||||
This is used as the login shell for new windows when the
|
||||
@ -2710,8 +2703,8 @@ The default is on.
|
||||
Control automatic window renaming.
|
||||
When this setting is enabled,
|
||||
.Nm
|
||||
will attempt - on supported platforms - to rename the window to reflect the
|
||||
command currently running in it.
|
||||
will rename the window automatically using the format specified by
|
||||
.Ic automatic-rename-format .
|
||||
This flag is automatically disabled for an individual window when a name
|
||||
is specified at creation with
|
||||
.Ic new-window
|
||||
@ -2725,6 +2718,13 @@ It may be switched off globally with:
|
||||
set-window-option -g automatic-rename off
|
||||
.Ed
|
||||
.Pp
|
||||
.It Ic automatic-rename-format Ar format
|
||||
The format (see
|
||||
.Sx FORMATS )
|
||||
used when the
|
||||
.Ic automatic-rename
|
||||
option is enabled.
|
||||
.Pp
|
||||
.It Ic c0-change-interval Ar interval
|
||||
.It Ic c0-change-trigger Ar trigger
|
||||
These two options configure a simple form of rate limiting for a pane.
|
||||
@ -2738,8 +2738,8 @@ instead redraw it entirely every
|
||||
.Ar interval
|
||||
milliseconds.
|
||||
This helps to prevent fast output (such as
|
||||
.Xr yes 1
|
||||
overwhelming the terminal).
|
||||
.Xr yes 1 )
|
||||
overwhelming the terminal.
|
||||
The default is a trigger of 250 and an interval of 100.
|
||||
A trigger of zero disables the rate limiting.
|
||||
.Pp
|
||||
@ -3026,6 +3026,12 @@ will include the string
|
||||
if the session is attached and the string
|
||||
.Ql not attached
|
||||
if it is unattached.
|
||||
A limit may be placed on the length of the resultant string by prefixing it
|
||||
by an
|
||||
.Ql = ,
|
||||
a number and a colon, so
|
||||
.Ql #{=10:pane_title}
|
||||
will include at most the first 10 characters of the pane title.
|
||||
.Pp
|
||||
The following variables are available, where appropriate:
|
||||
.Bl -column "XXXXXXXXXXXXXXXXXXX" "XXXXX"
|
||||
@ -3039,7 +3045,6 @@ The following variables are available, where appropriate:
|
||||
.It Li "client_activity_string" Ta "" Ta "String time client last had activity"
|
||||
.It Li "client_created" Ta "" Ta "Integer time client created"
|
||||
.It Li "client_created_string" Ta "" Ta "String time client created"
|
||||
.It Li "client_cwd" Ta "" Ta "Working directory of client"
|
||||
.It Li "client_height" Ta "" Ta "Height of client"
|
||||
.It Li "client_last_session" Ta "" Ta "Name of the client's last session"
|
||||
.It Li "client_prefix" Ta "" Ta "1 if prefix key has been pressed"
|
||||
@ -3067,7 +3072,6 @@ The following variables are available, where appropriate:
|
||||
.It Li "mouse_utf8_flag" Ta "" Ta "Pane mouse UTF-8 flag"
|
||||
.It Li "pane_active" Ta "" Ta "1 if active pane"
|
||||
.It Li "pane_current_command" Ta "" Ta "Current command if available"
|
||||
.It Li "pane_current_path" Ta "" Ta "Current path if available"
|
||||
.It Li "pane_dead" Ta "" Ta "1 if pane is dead"
|
||||
.It Li "pane_height" Ta "" Ta "Height of pane"
|
||||
.It Li "pane_id" Ta "#D" Ta "Unique pane ID"
|
||||
@ -3096,6 +3100,9 @@ The following variables are available, where appropriate:
|
||||
.It Li "session_width" Ta "" Ta "Width of session"
|
||||
.It Li "session_windows" Ta "" Ta "Number of windows in session"
|
||||
.It Li "window_active" Ta "" Ta "1 if window active"
|
||||
.It Li "window_activity_flag" Ta "" Ta "1 if window has activity alert"
|
||||
.It Li "window_bell_flag" Ta "" Ta "1 if window has bell"
|
||||
.It Li "window_content_flag" Ta "" Ta "1 if window has content alert"
|
||||
.It Li "window_find_matches" Ta "" Ta "Matched data from the find-window"
|
||||
.It Li "window_flags" Ta "#F" Ta "Window flags"
|
||||
.It Li "window_height" Ta "" Ta "Height of window"
|
||||
@ -3104,6 +3111,7 @@ The following variables are available, where appropriate:
|
||||
.It Li "window_layout" Ta "" Ta "Window layout description"
|
||||
.It Li "window_name" Ta "#W" Ta "Name of window"
|
||||
.It Li "window_panes" Ta "" Ta "Number of panes in window"
|
||||
.It Li "window_silence_flag" Ta "" Ta "1 if window has silence alert"
|
||||
.It Li "window_width" Ta "" Ta "Width of window"
|
||||
.It Li "wrap_flag" Ta "" Ta "Pane wrap flag"
|
||||
.El
|
||||
@ -3562,7 +3570,7 @@ If the command doesn't return success, the exit status is also displayed.
|
||||
.D1 (alias: Ic info )
|
||||
Show server information and terminal details.
|
||||
.It Xo Ic wait-for
|
||||
.Fl LSU
|
||||
.Op Fl L | S | U
|
||||
.Ar channel
|
||||
.Xc
|
||||
.D1 (alias: Ic wait )
|
||||
@ -3803,4 +3811,4 @@ bind-key S command-prompt "new-window -n %1 'ssh %1'"
|
||||
.Sh SEE ALSO
|
||||
.Xr pty 4
|
||||
.Sh AUTHORS
|
||||
.An Nicholas Marriott Aq nicm@users.sourceforge.net
|
||||
.An Nicholas Marriott Aq Mt nicm@users.sourceforge.net
|
||||
|
72
tmux.c
72
tmux.c
@ -48,11 +48,8 @@ time_t start_time;
|
||||
char socket_path[MAXPATHLEN];
|
||||
int login_shell;
|
||||
char *environ_path;
|
||||
pid_t environ_pid = -1;
|
||||
int environ_session_id = -1;
|
||||
|
||||
__dead void usage(void);
|
||||
void parseenvironment(void);
|
||||
char *makesocketpath(const char *);
|
||||
|
||||
#ifndef HAVE___PROGNAME
|
||||
@ -127,39 +124,6 @@ areshell(const char *shell)
|
||||
return (0);
|
||||
}
|
||||
|
||||
const char*
|
||||
get_full_path(const char *wd, const char *path)
|
||||
{
|
||||
static char newpath[MAXPATHLEN];
|
||||
char oldpath[MAXPATHLEN];
|
||||
|
||||
if (getcwd(oldpath, sizeof oldpath) == NULL)
|
||||
return (NULL);
|
||||
if (chdir(wd) != 0)
|
||||
return (NULL);
|
||||
if (realpath(path, newpath) != 0)
|
||||
return (NULL);
|
||||
chdir(oldpath);
|
||||
return (newpath);
|
||||
}
|
||||
|
||||
void
|
||||
parseenvironment(void)
|
||||
{
|
||||
char *env, path[256];
|
||||
long pid;
|
||||
int id;
|
||||
|
||||
if ((env = getenv("TMUX")) == NULL)
|
||||
return;
|
||||
|
||||
if (sscanf(env, "%255[^,],%ld,%d", path, &pid, &id) != 3)
|
||||
return;
|
||||
environ_path = xstrdup(path);
|
||||
environ_pid = pid;
|
||||
environ_session_id = id;
|
||||
}
|
||||
|
||||
char *
|
||||
makesocketpath(const char *label)
|
||||
{
|
||||
@ -184,7 +148,8 @@ makesocketpath(const char *label)
|
||||
errno = ENOTDIR;
|
||||
return (NULL);
|
||||
}
|
||||
if (sb.st_uid != uid || (sb.st_mode & (S_IRWXG|S_IRWXO)) != 0) {
|
||||
if (sb.st_uid != uid || (!S_ISDIR(sb.st_mode) &&
|
||||
sb.st_mode & (S_IRWXG|S_IRWXO)) != 0) {
|
||||
errno = EACCES;
|
||||
return (NULL);
|
||||
}
|
||||
@ -240,8 +205,10 @@ int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
struct passwd *pw;
|
||||
char *s, *path, *label, *home, **var;
|
||||
int opt, flags, quiet, keys;
|
||||
char *s, *path, *label, *home, **var, tmp[MAXPATHLEN];
|
||||
char in[256];
|
||||
long long pid;
|
||||
int opt, flags, quiet, keys, session;
|
||||
|
||||
#if defined(DEBUG) && defined(__OpenBSD__)
|
||||
malloc_options = (char *) "AFGJPX";
|
||||
@ -255,17 +222,17 @@ main(int argc, char **argv)
|
||||
while ((opt = getopt(argc, argv, "2c:Cdf:lL:qS:uUVv")) != -1) {
|
||||
switch (opt) {
|
||||
case '2':
|
||||
flags |= IDENTIFY_256COLOURS;
|
||||
flags |= CLIENT_256COLOURS;
|
||||
break;
|
||||
case 'c':
|
||||
free(shell_cmd);
|
||||
shell_cmd = xstrdup(optarg);
|
||||
break;
|
||||
case 'C':
|
||||
if (flags & IDENTIFY_CONTROL)
|
||||
flags |= IDENTIFY_TERMIOS;
|
||||
if (flags & CLIENT_CONTROL)
|
||||
flags |= CLIENT_CONTROLCONTROL;
|
||||
else
|
||||
flags |= IDENTIFY_CONTROL;
|
||||
flags |= CLIENT_CONTROL;
|
||||
break;
|
||||
case 'V':
|
||||
printf("%s %s\n", __progname, VERSION);
|
||||
@ -289,7 +256,7 @@ main(int argc, char **argv)
|
||||
path = xstrdup(optarg);
|
||||
break;
|
||||
case 'u':
|
||||
flags |= IDENTIFY_UTF8;
|
||||
flags |= CLIENT_UTF8;
|
||||
break;
|
||||
case 'v':
|
||||
debug_level++;
|
||||
@ -304,7 +271,7 @@ main(int argc, char **argv)
|
||||
if (shell_cmd != NULL && argc != 0)
|
||||
usage();
|
||||
|
||||
if (!(flags & IDENTIFY_UTF8)) {
|
||||
if (!(flags & CLIENT_UTF8)) {
|
||||
/*
|
||||
* If the user has set whichever of LC_ALL, LC_CTYPE or LANG
|
||||
* exist (in that order) to contain UTF-8, it is a safe
|
||||
@ -318,12 +285,14 @@ main(int argc, char **argv)
|
||||
}
|
||||
if (s != NULL && (strcasestr(s, "UTF-8") != NULL ||
|
||||
strcasestr(s, "UTF8") != NULL))
|
||||
flags |= IDENTIFY_UTF8;
|
||||
flags |= CLIENT_UTF8;
|
||||
}
|
||||
|
||||
environ_init(&global_environ);
|
||||
for (var = environ; *var != NULL; var++)
|
||||
environ_put(&global_environ, *var);
|
||||
if (getcwd(tmp, sizeof tmp) != NULL)
|
||||
environ_set(&global_environ, "PWD", tmp);
|
||||
|
||||
options_init(&global_options, NULL);
|
||||
options_table_populate_tree(server_options_table, &global_options);
|
||||
@ -337,7 +306,7 @@ main(int argc, char **argv)
|
||||
options_table_populate_tree(window_options_table, &global_w_options);
|
||||
|
||||
/* Enable UTF-8 if the first client is on UTF-8 terminal. */
|
||||
if (flags & IDENTIFY_UTF8) {
|
||||
if (flags & CLIENT_UTF8) {
|
||||
options_set_number(&global_s_options, "status-utf8", 1);
|
||||
options_set_number(&global_s_options, "mouse-utf8", 1);
|
||||
options_set_number(&global_w_options, "utf8", 1);
|
||||
@ -370,11 +339,15 @@ main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
/* Get path from environment. */
|
||||
s = getenv("TMUX");
|
||||
if (s != NULL && sscanf(s, "%255[^,],%lld,%d", in, &pid, &session) == 3)
|
||||
environ_path = xstrdup(in);
|
||||
|
||||
/*
|
||||
* Figure out the socket path. If specified on the command-line with -S
|
||||
* or -L, use it, otherwise try $TMUX or assume -L default.
|
||||
*/
|
||||
parseenvironment();
|
||||
if (path == NULL) {
|
||||
/* If no -L, use the environment. */
|
||||
if (label == NULL) {
|
||||
@ -387,7 +360,8 @@ main(int argc, char **argv)
|
||||
/* -L or default set. */
|
||||
if (label != NULL) {
|
||||
if ((path = makesocketpath(label)) == NULL) {
|
||||
fprintf(stderr, "can't create socket\n");
|
||||
fprintf(stderr, "can't create socket: %s\n",
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
162
tmux.h
162
tmux.h
@ -19,7 +19,7 @@
|
||||
#ifndef TMUX_H
|
||||
#define TMUX_H
|
||||
|
||||
#define PROTOCOL_VERSION 7
|
||||
#define PROTOCOL_VERSION 8
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/time.h>
|
||||
@ -51,14 +51,6 @@ extern char **environ;
|
||||
/* Automatic name refresh interval, in milliseconds. */
|
||||
#define NAME_INTERVAL 500
|
||||
|
||||
/*
|
||||
* Maximum sizes of strings in message data. Don't forget to bump
|
||||
* PROTOCOL_VERSION if any of these change!
|
||||
*/
|
||||
#define COMMAND_LENGTH 2048 /* packed argv size */
|
||||
#define TERMINAL_LENGTH 128 /* length of TERM environment variable */
|
||||
#define ENVIRON_LENGTH 1024 /* environment variable length */
|
||||
|
||||
/*
|
||||
* UTF-8 data size. This must be big enough to hold combined characters as well
|
||||
* as single.
|
||||
@ -430,27 +422,33 @@ ARRAY_DECL(causelist, char *);
|
||||
|
||||
/* Message codes. */
|
||||
enum msgtype {
|
||||
MSG_COMMAND,
|
||||
MSG_VERSION = 12,
|
||||
|
||||
MSG_IDENTIFY_FLAGS = 100,
|
||||
MSG_IDENTIFY_TERM,
|
||||
MSG_IDENTIFY_TTYNAME,
|
||||
MSG_IDENTIFY_CWD,
|
||||
MSG_IDENTIFY_STDIN,
|
||||
MSG_IDENTIFY_ENVIRON,
|
||||
MSG_IDENTIFY_DONE,
|
||||
|
||||
MSG_COMMAND = 200,
|
||||
MSG_DETACH,
|
||||
MSG_ERROR,
|
||||
MSG_DETACHKILL,
|
||||
MSG_EXIT,
|
||||
MSG_EXITED,
|
||||
MSG_EXITING,
|
||||
MSG_IDENTIFY,
|
||||
MSG_STDIN,
|
||||
MSG_LOCK,
|
||||
MSG_READY,
|
||||
MSG_RESIZE,
|
||||
MSG_SHUTDOWN,
|
||||
MSG_SUSPEND,
|
||||
MSG_VERSION,
|
||||
MSG_WAKEUP,
|
||||
MSG_ENVIRON,
|
||||
MSG_UNLOCK,
|
||||
MSG_LOCK,
|
||||
MSG_SHELL,
|
||||
MSG_SHUTDOWN,
|
||||
MSG_STDERR,
|
||||
MSG_STDIN,
|
||||
MSG_STDOUT,
|
||||
MSG_DETACHKILL
|
||||
MSG_SUSPEND,
|
||||
MSG_UNLOCK,
|
||||
MSG_WAKEUP,
|
||||
};
|
||||
|
||||
/*
|
||||
@ -459,45 +457,8 @@ enum msgtype {
|
||||
* Don't forget to bump PROTOCOL_VERSION if any of these change!
|
||||
*/
|
||||
struct msg_command_data {
|
||||
pid_t pid; /* from $TMUX or -1 */
|
||||
int session_id; /* from $TMUX or -1 */
|
||||
|
||||
int argc;
|
||||
char argv[COMMAND_LENGTH];
|
||||
};
|
||||
|
||||
struct msg_identify_data {
|
||||
char cwd[MAXPATHLEN];
|
||||
|
||||
char term[TERMINAL_LENGTH];
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
char ttyname[TTY_NAME_MAX];
|
||||
#endif
|
||||
|
||||
#define IDENTIFY_UTF8 0x1
|
||||
#define IDENTIFY_256COLOURS 0x2
|
||||
/* 0x4 unused */
|
||||
#define IDENTIFY_CONTROL 0x8
|
||||
#define IDENTIFY_TERMIOS 0x10
|
||||
int flags;
|
||||
};
|
||||
|
||||
struct msg_lock_data {
|
||||
char cmd[COMMAND_LENGTH];
|
||||
};
|
||||
|
||||
struct msg_environ_data {
|
||||
char var[ENVIRON_LENGTH];
|
||||
};
|
||||
|
||||
struct msg_shell_data {
|
||||
char shell[MAXPATHLEN];
|
||||
};
|
||||
|
||||
struct msg_exit_data {
|
||||
int retcode;
|
||||
};
|
||||
}; /* followed by packed argv */
|
||||
|
||||
struct msg_stdin_data {
|
||||
ssize_t size;
|
||||
@ -945,7 +906,7 @@ struct window_pane {
|
||||
|
||||
char *cmd;
|
||||
char *shell;
|
||||
char *cwd;
|
||||
int cwd;
|
||||
|
||||
pid_t pid;
|
||||
char tty[TTY_NAME_MAX];
|
||||
@ -1005,6 +966,7 @@ struct window {
|
||||
#define WINDOW_REDRAW 0x4
|
||||
#define WINDOW_SILENCE 0x8
|
||||
#define WINDOW_ZOOMED 0x10
|
||||
#define WINDOW_ALERTFLAGS (WINDOW_BELL|WINDOW_ACTIVITY|WINDOW_SILENCE)
|
||||
|
||||
struct options options;
|
||||
|
||||
@ -1091,7 +1053,7 @@ struct session {
|
||||
u_int id;
|
||||
|
||||
char *name;
|
||||
char *cwd;
|
||||
int cwd;
|
||||
|
||||
struct timeval creation_time;
|
||||
struct timeval activity_time;
|
||||
@ -1290,8 +1252,10 @@ RB_HEAD(status_out_tree, status_out);
|
||||
/* Client connection. */
|
||||
struct client {
|
||||
struct imsgbuf ibuf;
|
||||
|
||||
int fd;
|
||||
struct event event;
|
||||
int retcode;
|
||||
int retval;
|
||||
|
||||
struct timeval creation_time;
|
||||
struct timeval activity_time;
|
||||
@ -1299,8 +1263,10 @@ struct client {
|
||||
struct environ environ;
|
||||
|
||||
char *title;
|
||||
char *cwd;
|
||||
int cwd;
|
||||
|
||||
char *term;
|
||||
char *ttyname;
|
||||
struct tty tty;
|
||||
|
||||
void (*stdin_callback)(struct client *, int, void *);
|
||||
@ -1322,7 +1288,7 @@ struct client {
|
||||
#define CLIENT_EXIT 0x4
|
||||
#define CLIENT_REDRAW 0x8
|
||||
#define CLIENT_STATUS 0x10
|
||||
#define CLIENT_REPEAT 0x20 /* allow command to repeat within repeat time */
|
||||
#define CLIENT_REPEAT 0x20
|
||||
#define CLIENT_SUSPENDED 0x40
|
||||
#define CLIENT_BAD 0x80
|
||||
#define CLIENT_IDENTIFY 0x100
|
||||
@ -1331,7 +1297,11 @@ struct client {
|
||||
#define CLIENT_READONLY 0x800
|
||||
#define CLIENT_REDRAWWINDOW 0x1000
|
||||
#define CLIENT_CONTROL 0x2000
|
||||
#define CLIENT_FOCUSED 0x4000
|
||||
#define CLIENT_CONTROLCONTROL 0x4000
|
||||
#define CLIENT_FOCUSED 0x8000
|
||||
#define CLIENT_UTF8 0x10000
|
||||
#define CLIENT_256COLOURS 0x20000
|
||||
#define CLIENT_IDENTIFIED 0x40000
|
||||
int flags;
|
||||
|
||||
struct event identify_timer;
|
||||
@ -1428,8 +1398,6 @@ struct cmd_q {
|
||||
void (*emptyfn)(struct cmd_q *);
|
||||
void *data;
|
||||
|
||||
struct msg_command_data *msgdata;
|
||||
|
||||
TAILQ_ENTRY(cmd_q) waitentry;
|
||||
};
|
||||
|
||||
@ -1446,12 +1414,10 @@ struct cmd_entry {
|
||||
|
||||
#define CMD_STARTSERVER 0x1
|
||||
#define CMD_CANTNEST 0x2
|
||||
#define CMD_SENDENVIRON 0x4
|
||||
#define CMD_READONLY 0x8
|
||||
#define CMD_READONLY 0x4
|
||||
int flags;
|
||||
|
||||
void (*key_binding)(struct cmd *, int);
|
||||
int (*check)(struct args *);
|
||||
enum cmd_retval (*exec)(struct cmd *, struct cmd_q *);
|
||||
};
|
||||
|
||||
@ -1525,13 +1491,10 @@ extern time_t start_time;
|
||||
extern char socket_path[MAXPATHLEN];
|
||||
extern int login_shell;
|
||||
extern char *environ_path;
|
||||
extern pid_t environ_pid;
|
||||
extern int environ_session_id;
|
||||
void logfile(const char *);
|
||||
const char *getshell(void);
|
||||
int checkshell(const char *);
|
||||
int areshell(const char *);
|
||||
const char* get_full_path(const char *, const char *);
|
||||
void setblocking(int, int);
|
||||
__dead void shell_exec(const char *, const char *);
|
||||
|
||||
@ -1549,16 +1512,19 @@ int format_cmp(struct format_entry *, struct format_entry *);
|
||||
RB_PROTOTYPE(format_tree, format_entry, entry, format_cmp);
|
||||
struct format_tree *format_create(void);
|
||||
void format_free(struct format_tree *);
|
||||
void printflike3 format_add(
|
||||
struct format_tree *, const char *, const char *, ...);
|
||||
void printflike3 format_add(struct format_tree *, const char *, const char *,
|
||||
...);
|
||||
const char *format_find(struct format_tree *, const char *);
|
||||
char *format_expand(struct format_tree *, const char *);
|
||||
void format_session(struct format_tree *, struct session *);
|
||||
void format_client(struct format_tree *, struct client *);
|
||||
void format_winlink(
|
||||
struct format_tree *, struct session *, struct winlink *);
|
||||
void format_window_pane(struct format_tree *, struct window_pane *);
|
||||
void format_paste_buffer(struct format_tree *, struct paste_buffer *);
|
||||
void format_window(struct format_tree *, struct window *);
|
||||
void format_winlink(struct format_tree *, struct session *,
|
||||
struct winlink *);
|
||||
void format_window_pane(struct format_tree *,
|
||||
struct window_pane *);
|
||||
void format_paste_buffer(struct format_tree *,
|
||||
struct paste_buffer *);
|
||||
|
||||
/* mode-key.c */
|
||||
extern const struct mode_key_table mode_key_tables[];
|
||||
@ -1764,7 +1730,6 @@ int cmd_find_index(struct cmd_q *, const char *,
|
||||
struct winlink *cmd_find_pane(struct cmd_q *, const char *, struct session **,
|
||||
struct window_pane **);
|
||||
char *cmd_template_replace(const char *, const char *, int);
|
||||
const char *cmd_get_default_path(struct cmd_q *, const char *);
|
||||
extern const struct cmd_entry *cmd_table[];
|
||||
extern const struct cmd_entry cmd_attach_session_entry;
|
||||
extern const struct cmd_entry cmd_bind_key_entry;
|
||||
@ -1855,7 +1820,8 @@ extern const struct cmd_entry cmd_up_pane_entry;
|
||||
extern const struct cmd_entry cmd_wait_for_entry;
|
||||
|
||||
/* cmd-attach-session.c */
|
||||
enum cmd_retval cmd_attach_session(struct cmd_q *, const char*, int, int);
|
||||
enum cmd_retval cmd_attach_session(struct cmd_q *, const char *, int, int,
|
||||
const char *);
|
||||
|
||||
/* cmd-list.c */
|
||||
struct cmd_list *cmd_list_parse(int, char **, const char *, u_int, char **);
|
||||
@ -1868,7 +1834,7 @@ int cmdq_free(struct cmd_q *);
|
||||
void printflike2 cmdq_print(struct cmd_q *, const char *, ...);
|
||||
void printflike2 cmdq_info(struct cmd_q *, const char *, ...);
|
||||
void printflike2 cmdq_error(struct cmd_q *, const char *, ...);
|
||||
int cmdq_guard(struct cmd_q *, const char *);
|
||||
int cmdq_guard(struct cmd_q *, const char *, int);
|
||||
void cmdq_run(struct cmd_q *, struct cmd_list *);
|
||||
void cmdq_append(struct cmd_q *, struct cmd_list *);
|
||||
int cmdq_continue(struct cmd_q *);
|
||||
@ -1919,10 +1885,10 @@ void server_window_loop(void);
|
||||
/* server-fn.c */
|
||||
void server_fill_environ(struct session *, struct environ *);
|
||||
void server_write_ready(struct client *);
|
||||
int server_write_client(
|
||||
struct client *, enum msgtype, const void *, size_t);
|
||||
void server_write_session(
|
||||
struct session *, enum msgtype, const void *, size_t);
|
||||
int server_write_client(struct client *, enum msgtype, const void *,
|
||||
size_t);
|
||||
void server_write_session(struct session *, enum msgtype, const void *,
|
||||
size_t);
|
||||
void server_redraw_client(struct client *);
|
||||
void server_status_client(struct client *);
|
||||
void server_redraw_session(struct session *);
|
||||
@ -2144,9 +2110,9 @@ void winlink_stack_remove(struct winlink_stack *, struct winlink *);
|
||||
int window_index(struct window *, u_int *);
|
||||
struct window *window_find_by_id(u_int);
|
||||
struct window *window_create1(u_int, u_int);
|
||||
struct window *window_create(const char *, const char *, const char *,
|
||||
const char *, struct environ *, struct termios *,
|
||||
u_int, u_int, u_int, char **);
|
||||
struct window *window_create(const char *, const char *, const char *, int,
|
||||
struct environ *, struct termios *, u_int, u_int, u_int,
|
||||
char **);
|
||||
void window_destroy(struct window *);
|
||||
struct window_pane *window_get_active_at(struct window *, u_int, u_int);
|
||||
void window_set_active_at(struct window *, u_int, u_int);
|
||||
@ -2170,8 +2136,8 @@ struct window_pane *window_pane_create(struct window *, u_int, u_int, u_int);
|
||||
void window_pane_destroy(struct window_pane *);
|
||||
void window_pane_timer_start(struct window_pane *);
|
||||
int window_pane_spawn(struct window_pane *, const char *,
|
||||
const char *, const char *, struct environ *,
|
||||
struct termios *, char **);
|
||||
const char *, int, struct environ *, struct termios *,
|
||||
char **);
|
||||
void window_pane_resize(struct window_pane *, u_int, u_int);
|
||||
void window_pane_alternate_on(struct window_pane *,
|
||||
struct grid_cell *, int);
|
||||
@ -2274,6 +2240,8 @@ void window_choose_set_current(struct window_pane *, u_int);
|
||||
/* names.c */
|
||||
void queue_window_name(struct window *);
|
||||
char *default_window_name(struct window *);
|
||||
char *format_window_name(struct window *);
|
||||
char *parse_window_name(const char *);
|
||||
|
||||
/* signal.c */
|
||||
void set_signals(void(*)(int, short, void *));
|
||||
@ -2305,7 +2273,7 @@ RB_PROTOTYPE(sessions, session, entry, session_cmp);
|
||||
int session_alive(struct session *);
|
||||
struct session *session_find(const char *);
|
||||
struct session *session_find_by_id(u_int);
|
||||
struct session *session_create(const char *, const char *, const char *,
|
||||
struct session *session_create(const char *, const char *, int,
|
||||
struct environ *, struct termios *, int, u_int, u_int,
|
||||
char **);
|
||||
void session_destroy(struct session *);
|
||||
@ -2313,8 +2281,8 @@ int session_check_name(const char *);
|
||||
void session_update_activity(struct session *);
|
||||
struct session *session_next_session(struct session *);
|
||||
struct session *session_previous_session(struct session *);
|
||||
struct winlink *session_new(struct session *,
|
||||
const char *, const char *, const char *, int, char **);
|
||||
struct winlink *session_new(struct session *, const char *, const char *, int,
|
||||
int, char **);
|
||||
struct winlink *session_attach(
|
||||
struct session *, struct window *, int, char **);
|
||||
int session_detach(struct session *, struct winlink *);
|
||||
@ -2340,10 +2308,8 @@ int utf8_append(struct utf8_data *, u_char);
|
||||
u_int utf8_combine(const struct utf8_data *);
|
||||
u_int utf8_split2(u_int, u_char *);
|
||||
|
||||
/* osdep-*.c */
|
||||
char *osdep_get_name(int, char *);
|
||||
char *osdep_get_cwd(int);
|
||||
struct event_base *osdep_event_init(void);
|
||||
/* procname.c */
|
||||
char *get_proc_name(int, char *);
|
||||
|
||||
/* log.c */
|
||||
void log_open(int, const char *);
|
||||
|
12
tty-keys.c
12
tty-keys.c
@ -676,11 +676,17 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
log_debug("mouse input: %.*s", (int) *size, buf);
|
||||
|
||||
/* Check and return the mouse input. */
|
||||
if (b < 32 || x < 33 || y < 33)
|
||||
if (b < 32)
|
||||
return (-1);
|
||||
b -= 32;
|
||||
if (x >= 33)
|
||||
x -= 33;
|
||||
else
|
||||
x = 256 - x;
|
||||
if (y >= 33)
|
||||
y -= 33;
|
||||
else
|
||||
y = 256 - y;
|
||||
} else if (buf[2] == '<') {
|
||||
/* Read the three inputs. */
|
||||
*size = 3;
|
||||
@ -740,6 +746,8 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
m->sgr = sgr;
|
||||
m->sgr_xb = sgr_b;
|
||||
m->sgr_rel = sgr_rel;
|
||||
m->x = x;
|
||||
m->y = y;
|
||||
if (b & 64) { /* wheel button */
|
||||
b &= 3;
|
||||
if (b == 0)
|
||||
@ -767,8 +775,6 @@ tty_keys_mouse(struct tty *tty, const char *buf, size_t len, size_t *size)
|
||||
}
|
||||
m->button = (b & 3);
|
||||
}
|
||||
m->x = x;
|
||||
m->y = y;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
@ -81,6 +81,7 @@ int window_choose_key_index(struct window_choose_mode_data *, u_int);
|
||||
int window_choose_index_key(struct window_choose_mode_data *, int);
|
||||
void window_choose_prompt_input(enum window_choose_input_type,
|
||||
const char *, struct window_pane *, int);
|
||||
void window_choose_reset_top(struct window_pane *, u_int);
|
||||
|
||||
void
|
||||
window_choose_add(struct window_pane *wp, struct window_choose_data *wcd)
|
||||
@ -107,8 +108,17 @@ window_choose_set_current(struct window_pane *wp, u_int cur)
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
data->selected = cur;
|
||||
if (data->selected > screen_size_y(s) - 1)
|
||||
data->top = ARRAY_LENGTH(&data->list) - screen_size_y(s);
|
||||
window_choose_reset_top(wp, screen_size_y(s));
|
||||
}
|
||||
|
||||
void
|
||||
window_choose_reset_top(struct window_pane *wp, u_int sy)
|
||||
{
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
|
||||
data->top = 0;
|
||||
if (data->selected > sy - 1)
|
||||
data->top = data->selected - (sy - 1);
|
||||
|
||||
window_choose_redraw_screen(wp);
|
||||
}
|
||||
@ -277,10 +287,7 @@ window_choose_resize(struct window_pane *wp, u_int sx, u_int sy)
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
struct screen *s = &data->screen;
|
||||
|
||||
data->top = 0;
|
||||
if (data->selected > sy - 1)
|
||||
data->top = data->selected - (sy - 1);
|
||||
|
||||
window_choose_reset_top(wp, sy);
|
||||
screen_resize(s, sx, sy, 0);
|
||||
window_choose_redraw_screen(wp);
|
||||
}
|
||||
@ -373,6 +380,7 @@ window_choose_collapse_all(struct window_pane *wp)
|
||||
{
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
struct window_choose_mode_item *item;
|
||||
struct screen *scr = &data->screen;
|
||||
struct session *s, *chosen;
|
||||
u_int i;
|
||||
|
||||
@ -391,7 +399,7 @@ window_choose_collapse_all(struct window_pane *wp)
|
||||
if (item->wcd->type & TREE_SESSION)
|
||||
data->selected = i;
|
||||
}
|
||||
window_choose_redraw_screen(wp);
|
||||
window_choose_reset_top(wp, screen_size_y(scr));
|
||||
}
|
||||
|
||||
void
|
||||
@ -399,6 +407,7 @@ window_choose_expand_all(struct window_pane *wp)
|
||||
{
|
||||
struct window_choose_mode_data *data = wp->modedata;
|
||||
struct window_choose_mode_item *item;
|
||||
struct screen *scr = &data->screen;
|
||||
struct session *s;
|
||||
u_int i;
|
||||
|
||||
@ -414,7 +423,7 @@ window_choose_expand_all(struct window_pane *wp)
|
||||
}
|
||||
}
|
||||
|
||||
window_choose_redraw_screen(wp);
|
||||
window_choose_reset_top(wp, screen_size_y(scr));
|
||||
}
|
||||
|
||||
void
|
||||
|
17
window.c
17
window.c
@ -306,7 +306,7 @@ window_create1(u_int sx, u_int sy)
|
||||
|
||||
struct window *
|
||||
window_create(const char *name, const char *cmd, const char *shell,
|
||||
const char *cwd, struct environ *env, struct termios *tio,
|
||||
int cwd, struct environ *env, struct termios *tio,
|
||||
u_int sx, u_int sy, u_int hlimit, char **cause)
|
||||
{
|
||||
struct window *w;
|
||||
@ -672,7 +672,7 @@ window_pane_create(struct window *w, u_int sx, u_int sy, u_int hlimit)
|
||||
|
||||
wp->cmd = NULL;
|
||||
wp->shell = NULL;
|
||||
wp->cwd = NULL;
|
||||
wp->cwd = -1;
|
||||
|
||||
wp->fd = -1;
|
||||
wp->event = NULL;
|
||||
@ -727,7 +727,7 @@ window_pane_destroy(struct window_pane *wp)
|
||||
|
||||
RB_REMOVE(window_pane_tree, &all_window_panes, wp);
|
||||
|
||||
free(wp->cwd);
|
||||
close(wp->cwd);
|
||||
free(wp->shell);
|
||||
free(wp->cmd);
|
||||
free(wp);
|
||||
@ -735,7 +735,7 @@ window_pane_destroy(struct window_pane *wp)
|
||||
|
||||
int
|
||||
window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
||||
const char *cwd, struct environ *env, struct termios *tio, char **cause)
|
||||
int cwd, struct environ *env, struct termios *tio, char **cause)
|
||||
{
|
||||
struct winsize ws;
|
||||
char *argv0, paneid[16];
|
||||
@ -754,9 +754,9 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
||||
free(wp->shell);
|
||||
wp->shell = xstrdup(shell);
|
||||
}
|
||||
if (cwd != NULL) {
|
||||
free(wp->cwd);
|
||||
wp->cwd = xstrdup(cwd);
|
||||
if (cwd != -1) {
|
||||
close(wp->cwd);
|
||||
wp->cwd = dup(cwd);
|
||||
}
|
||||
|
||||
log_debug("spawn: %s -- %s", wp->shell, wp->cmd);
|
||||
@ -771,7 +771,7 @@ window_pane_spawn(struct window_pane *wp, const char *cmd, const char *shell,
|
||||
xasprintf(cause, "%s: %s", cmd, strerror(errno));
|
||||
return (-1);
|
||||
case 0:
|
||||
if (chdir(wp->cwd) != 0)
|
||||
if (fchdir(wp->cwd) != 0)
|
||||
chdir("/");
|
||||
|
||||
if (tcgetattr(STDIN_FILENO, &tio2) != 0)
|
||||
@ -1243,6 +1243,7 @@ winlink_clear_flags(struct winlink *wl)
|
||||
continue;
|
||||
|
||||
wm->flags &= ~WINLINK_ALERTFLAGS;
|
||||
wm->window->flags &= ~WINDOW_ALERTFLAGS;
|
||||
server_status_session(s);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user