mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-07 16:54:01 +01:00
Alter how tmux handles the working directory to internally use file
descriptors rather than strings. - Each session still has a current working directory. - New sessions still get their working directory from the client that created them or its attached session if any. - New windows are created by default in the session working directory. - The -c flag to new, neww, splitw allows the working directory to be overridden. - The -c flag to attach let's the session working directory be changed. - The default-path option has been removed. To get the equivalent to default-path '.', do: bind c neww -c $PWD To get the equivalent of default-path '~', do: bind c neww -c ~ This also changes the client identify protocol to be a set of messages rather than one as well as some other changes that should make it easier to make backwards-compatible protocol changes in future.
This commit is contained in:
parent
165aa59760
commit
282c5f9644
56
client.c
56
client.c
@ -53,7 +53,6 @@ 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);
|
int client_write_one(enum msgtype, int, const void *, size_t);
|
||||||
int client_write_server(enum msgtype, const void *, size_t);
|
int client_write_server(enum msgtype, const void *, size_t);
|
||||||
void client_update_event(void);
|
void client_update_event(void);
|
||||||
@ -257,8 +256,7 @@ 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. */
|
||||||
client_send_environ();
|
|
||||||
client_send_identify(flags);
|
client_send_identify(flags);
|
||||||
|
|
||||||
/* Send first command. */
|
/* Send first command. */
|
||||||
@ -316,45 +314,39 @@ client_main(int argc, char **argv, int flags)
|
|||||||
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);
|
||||||
|
|
||||||
if ((fd = dup(STDIN_FILENO)) == -1)
|
if ((fd = dup(STDIN_FILENO)) == -1)
|
||||||
fatal("dup failed");
|
fatal("dup failed");
|
||||||
imsg_compose(&client_ibuf,
|
client_write_one(MSG_IDENTIFY_STDIN, fd, NULL, 0);
|
||||||
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. */
|
|
||||||
void
|
|
||||||
client_send_environ(void)
|
|
||||||
{
|
|
||||||
struct msg_environ_data data;
|
|
||||||
char **var;
|
|
||||||
|
|
||||||
for (var = environ; *var != NULL; var++) {
|
|
||||||
if (strlcpy(data.var, *var, sizeof data.var) >= sizeof data.var)
|
|
||||||
continue;
|
|
||||||
client_write_server(MSG_ENVIRON, &data, sizeof data);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Helper to send one message. */
|
/* Helper to send one message. */
|
||||||
int
|
int
|
||||||
client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
|
client_write_one(enum msgtype type, int fd, const void *buf, size_t len)
|
||||||
@ -595,8 +587,6 @@ client_dispatch_wait(void *data0)
|
|||||||
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);
|
||||||
@ -675,8 +665,6 @@ client_dispatch_attached(void)
|
|||||||
system(data);
|
system(data);
|
||||||
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,21 +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_CANTNEST|CMD_STARTSERVER,
|
||||||
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");
|
||||||
@ -73,6 +81,27 @@ cmd_attach_session(struct cmd_q *cmdq, const char* tflag, int dflag, int rflag)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
@ -85,6 +114,27 @@ 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;
|
||||||
|
|
||||||
@ -115,5 +165,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')));
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
@ -49,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;
|
||||||
@ -81,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);
|
||||||
}
|
}
|
||||||
|
@ -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>
|
||||||
@ -47,18 +49,15 @@ 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, *base, *cwd;
|
|
||||||
const char *errstr, *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'))) {
|
if (args_has(args, 't') && (args->argc != 0 || args_has(args, 'n'))) {
|
||||||
@ -75,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);
|
||||||
@ -100,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->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.
|
||||||
@ -121,26 +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)
|
|
||||||
base = c->cwd;
|
|
||||||
else {
|
|
||||||
pw = getpwuid(getuid());
|
|
||||||
if (pw->pw_dir != NULL && *pw->pw_dir != '\0')
|
|
||||||
base = pw->pw_dir;
|
|
||||||
else
|
|
||||||
base = "/";
|
|
||||||
}
|
|
||||||
if (args_has(args, 'c'))
|
|
||||||
cwd = args_get(args, 'c');
|
|
||||||
else
|
|
||||||
cwd = options_get_string(&global_s_options, "default-path");
|
|
||||||
cwd = cmd_default_path(base, base, cwd);
|
|
||||||
|
|
||||||
/* Find new session size. */
|
/* Find new session size. */
|
||||||
if (c != NULL) {
|
if (c != NULL) {
|
||||||
sx = c->tty.sx;
|
sx = c->tty.sx;
|
||||||
@ -153,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"))
|
||||||
@ -190,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);
|
||||||
|
|
||||||
@ -241,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);
|
||||||
@ -254,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"
|
||||||
|
|
||||||
@ -45,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')) {
|
||||||
@ -102,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 = cmdq_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->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");
|
||||||
@ -110,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);
|
||||||
@ -136,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);
|
||||||
}
|
}
|
||||||
|
24
cmd-queue.c
24
cmd-queue.c
@ -283,27 +283,3 @@ cmdq_flush(struct cmd_q *cmdq)
|
|||||||
}
|
}
|
||||||
cmdq->item = NULL;
|
cmdq->item = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get default path using command queue. */
|
|
||||||
const char *
|
|
||||||
cmdq_default_path(struct cmd_q *cmdq, const char *cwd)
|
|
||||||
{
|
|
||||||
struct client *c = cmdq->client;
|
|
||||||
struct session *s;
|
|
||||||
const char *current;
|
|
||||||
|
|
||||||
if ((s = cmd_current_session(cmdq, 0)) == NULL)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
if (cwd == NULL)
|
|
||||||
cwd = options_get_string(&s->options, "default-path");
|
|
||||||
|
|
||||||
if (c != NULL && c->session == NULL && c->cwd != NULL)
|
|
||||||
current = c->cwd;
|
|
||||||
else if (s->curw != NULL)
|
|
||||||
current = get_proc_cwd(s->curw->window->active->fd);
|
|
||||||
else
|
|
||||||
current = NULL;
|
|
||||||
|
|
||||||
return (cmd_default_path(s->cwd, current, cwd));
|
|
||||||
}
|
|
||||||
|
@ -20,8 +20,10 @@
|
|||||||
#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 <vis.h>
|
||||||
|
|
||||||
#include "tmux.h"
|
#include "tmux.h"
|
||||||
@ -54,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) {
|
||||||
@ -91,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);
|
||||||
@ -101,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);
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,11 @@
|
|||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <paths.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"
|
||||||
@ -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 = cmdq_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->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);
|
||||||
}
|
}
|
||||||
|
3
format.c
3
format.c
@ -403,7 +403,6 @@ 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)
|
if (c->tty.path != NULL)
|
||||||
@ -552,8 +551,6 @@ 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)
|
|
||||||
format_add(ft, "pane_start_path", "%s", wp->cwd);
|
|
||||||
if ((cwd = get_proc_cwd(wp->fd)) != NULL)
|
if ((cwd = get_proc_cwd(wp->fd)) != NULL)
|
||||||
format_add(ft, "pane_current_path", "%s", cwd);
|
format_add(ft, "pane_current_path", "%s", cwd);
|
||||||
if ((cmd = get_proc_name(wp->fd, wp->tty)) != NULL) {
|
if ((cmd = get_proc_name(wp->fd, wp->tty)) != NULL) {
|
||||||
|
@ -126,11 +126,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
|
||||||
|
123
server-client.c
123
server-client.c
@ -41,8 +41,7 @@ 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 imsg *);
|
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. */
|
||||||
@ -151,6 +150,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 +163,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 +181,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);
|
||||||
@ -786,8 +787,6 @@ int
|
|||||||
server_client_msg_dispatch(struct client *c)
|
server_client_msg_dispatch(struct client *c)
|
||||||
{
|
{
|
||||||
struct imsg imsg;
|
struct imsg imsg;
|
||||||
struct msg_identify_data identifydata;
|
|
||||||
struct msg_environ_data environdata;
|
|
||||||
struct msg_stdin_data stdindata;
|
struct msg_stdin_data stdindata;
|
||||||
const char *data;
|
const char *data;
|
||||||
ssize_t n, datalen;
|
ssize_t n, datalen;
|
||||||
@ -813,12 +812,14 @@ server_client_msg_dispatch(struct client *c)
|
|||||||
|
|
||||||
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_IDENTIFY:
|
case MSG_IDENTIFY_FLAGS:
|
||||||
if (datalen != sizeof identifydata)
|
case MSG_IDENTIFY_TERM:
|
||||||
fatalx("bad MSG_IDENTIFY size");
|
case MSG_IDENTIFY_TTYNAME:
|
||||||
memcpy(&identifydata, imsg.data, sizeof identifydata);
|
case MSG_IDENTIFY_CWD:
|
||||||
|
case MSG_IDENTIFY_STDIN:
|
||||||
server_client_msg_identify(c, &identifydata, imsg.fd);
|
case MSG_IDENTIFY_ENVIRON:
|
||||||
|
case MSG_IDENTIFY_DONE:
|
||||||
|
server_client_msg_identify(c, &imsg);
|
||||||
break;
|
break;
|
||||||
case MSG_COMMAND:
|
case MSG_COMMAND:
|
||||||
server_client_msg_command(c, &imsg);
|
server_client_msg_command(c, &imsg);
|
||||||
@ -876,23 +877,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);
|
||||||
@ -951,46 +941,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 & CLIENT_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 (data[datalen - 1] != '\0')
|
||||||
|
fatalx("bad MSG_IDENTIFY_TERM string");
|
||||||
|
c->term = xstrdup(data);
|
||||||
|
break;
|
||||||
|
case MSG_IDENTIFY_TTYNAME:
|
||||||
|
if (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 (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 & CLIENT_CONTROLCONTROL)
|
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 (fd == -1)
|
if (c->fd == -1)
|
||||||
return;
|
return;
|
||||||
if (!isatty(fd)) {
|
if (!isatty(c->fd)) {
|
||||||
close(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 & CLIENT_UTF8)
|
|
||||||
c->tty.flags |= TTY_UTF8;
|
c->tty.flags |= TTY_UTF8;
|
||||||
if (data->flags & CLIENT_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 & CLIENT_CONTROL))
|
if (!(c->flags & CLIENT_CONTROL))
|
||||||
c->flags |= CLIENT_TERMINAL;
|
c->flags |= CLIENT_TERMINAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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;
|
||||||
|
17
session.c
17
session.c
@ -85,9 +85,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;
|
||||||
|
|
||||||
@ -99,7 +98,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);
|
||||||
@ -171,7 +170,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);
|
||||||
}
|
}
|
||||||
@ -227,8 +226,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;
|
||||||
@ -251,8 +250,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);
|
||||||
|
24
tmux.1
24
tmux.1
@ -564,6 +564,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 )
|
||||||
@ -597,6 +598,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
|
||||||
@ -1509,13 +1514,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,17 +2173,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 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 .
|
|
||||||
The default is
|
|
||||||
.Ql ~ .
|
|
||||||
.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
|
||||||
@ -3054,7 +3041,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"
|
||||||
|
28
tmux.c
28
tmux.c
@ -124,30 +124,6 @@ areshell(const char *shell)
|
|||||||
return (0);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char*
|
|
||||||
get_full_path(const char *wd, const char *path)
|
|
||||||
{
|
|
||||||
int fd;
|
|
||||||
static char newpath[MAXPATHLEN];
|
|
||||||
const char *retval;
|
|
||||||
|
|
||||||
fd = open(".", O_RDONLY);
|
|
||||||
if (fd == -1)
|
|
||||||
return (NULL);
|
|
||||||
|
|
||||||
retval = NULL;
|
|
||||||
if (chdir(wd) == 0) {
|
|
||||||
if (realpath(path, newpath) == 0)
|
|
||||||
retval = newpath;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fchdir(fd) != 0)
|
|
||||||
chdir("/");
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
return (retval);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
parseenvironment(void)
|
parseenvironment(void)
|
||||||
{
|
{
|
||||||
@ -246,7 +222,7 @@ 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;
|
int opt, flags, quiet, keys;
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@ -327,6 +303,8 @@ main(int argc, char **argv)
|
|||||||
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);
|
||||||
|
52
tmux.h
52
tmux.h
@ -58,13 +58,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 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.
|
||||||
@ -463,9 +456,6 @@ enum msgtype {
|
|||||||
MSG_SUSPEND,
|
MSG_SUSPEND,
|
||||||
MSG_UNLOCK,
|
MSG_UNLOCK,
|
||||||
MSG_WAKEUP,
|
MSG_WAKEUP,
|
||||||
|
|
||||||
MSG_IDENTIFY = 300,
|
|
||||||
MSG_ENVIRON
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -480,17 +470,6 @@ struct msg_command_data {
|
|||||||
int argc;
|
int argc;
|
||||||
}; /* followed by packed argv */
|
}; /* followed by packed argv */
|
||||||
|
|
||||||
struct msg_identify_data {
|
|
||||||
char cwd[MAXPATHLEN];
|
|
||||||
char term[TERMINAL_LENGTH];
|
|
||||||
|
|
||||||
int flags;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct msg_environ_data {
|
|
||||||
char var[ENVIRON_LENGTH];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct msg_stdin_data {
|
struct msg_stdin_data {
|
||||||
ssize_t size;
|
ssize_t size;
|
||||||
char data[BUFSIZ];
|
char data[BUFSIZ];
|
||||||
@ -937,7 +916,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];
|
||||||
@ -1084,7 +1063,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;
|
||||||
@ -1284,6 +1263,7 @@ RB_HEAD(status_out_tree, status_out);
|
|||||||
struct client {
|
struct client {
|
||||||
struct imsgbuf ibuf;
|
struct imsgbuf ibuf;
|
||||||
|
|
||||||
|
int fd;
|
||||||
struct event event;
|
struct event event;
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
@ -1293,8 +1273,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 *);
|
||||||
@ -1527,7 +1509,6 @@ 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 *);
|
||||||
|
|
||||||
@ -1763,7 +1744,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_default_path(const char *, const char *, 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;
|
||||||
@ -1854,7 +1834,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 **);
|
||||||
@ -1872,7 +1853,6 @@ 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 *);
|
||||||
void cmdq_flush(struct cmd_q *);
|
void cmdq_flush(struct cmd_q *);
|
||||||
const char *cmdq_default_path(struct cmd_q *, const char *);
|
|
||||||
|
|
||||||
/* cmd-string.c */
|
/* cmd-string.c */
|
||||||
int cmd_string_parse(const char *, struct cmd_list **, const char *,
|
int cmd_string_parse(const char *, struct cmd_list **, const char *,
|
||||||
@ -2144,9 +2124,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 +2150,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);
|
||||||
@ -2307,7 +2287,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 *);
|
||||||
@ -2315,8 +2295,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 *);
|
||||||
|
16
window.c
16
window.c
@ -309,7 +309,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;
|
||||||
@ -675,7 +675,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;
|
||||||
@ -730,7 +730,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);
|
||||||
@ -738,7 +738,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];
|
||||||
@ -757,9 +757,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);
|
||||||
@ -774,7 +774,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)
|
||||||
|
Loading…
Reference in New Issue
Block a user