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