mirror of
https://github.com/tmux/tmux.git
synced 2024-12-04 19:58:48 +00:00
Merge branch 'obsd-master' into master
This commit is contained in:
commit
3a76a56824
46
client.c
46
client.c
@ -61,7 +61,8 @@ static __dead void client_exec(const char *,const char *);
|
||||
static int client_get_lock(char *);
|
||||
static int client_connect(struct event_base *, const char *,
|
||||
uint64_t);
|
||||
static void client_send_identify(const char *, const char *, int);
|
||||
static void client_send_identify(const char *, const char *,
|
||||
char **, u_int, const char *, int);
|
||||
static void client_signal(int);
|
||||
static void client_dispatch(struct imsg *, void *);
|
||||
static void client_dispatch_attached(struct imsg *);
|
||||
@ -234,13 +235,14 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
||||
struct cmd_parse_result *pr;
|
||||
struct msg_command *data;
|
||||
int fd, i;
|
||||
const char *ttynam, *cwd;
|
||||
const char *ttynam, *termname, *cwd;
|
||||
pid_t ppid;
|
||||
enum msgtype msg;
|
||||
struct termios tio, saved_tio;
|
||||
size_t size, linesize = 0;
|
||||
ssize_t linelen;
|
||||
char *line = NULL;
|
||||
char *line = NULL, **caps = NULL, *cause;
|
||||
u_int ncaps = 0;
|
||||
|
||||
/* Ignore SIGCHLD now or daemon() in the server will leave a zombie. */
|
||||
signal(SIGCHLD, SIG_IGN);
|
||||
@ -296,6 +298,8 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
||||
cwd = "/";
|
||||
if ((ttynam = ttyname(STDIN_FILENO)) == NULL)
|
||||
ttynam = "";
|
||||
if ((termname = getenv("TERM")) == NULL)
|
||||
termname = "";
|
||||
|
||||
/*
|
||||
* Drop privileges for client. "proc exec" is needed for -c and for
|
||||
@ -311,6 +315,16 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
||||
NULL) != 0)
|
||||
fatal("pledge failed");
|
||||
|
||||
/* Load terminfo entry if any. */
|
||||
if (isatty(STDIN_FILENO) &&
|
||||
*termname != '\0' &&
|
||||
tty_term_read_list(termname, STDIN_FILENO, &caps, &ncaps,
|
||||
&cause) != 0) {
|
||||
fprintf(stderr, "%s\n", cause);
|
||||
free(cause);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* Free stuff that is not used in the client. */
|
||||
if (ptm_fd != -1)
|
||||
close(ptm_fd);
|
||||
@ -341,7 +355,8 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
||||
}
|
||||
|
||||
/* Send identify messages. */
|
||||
client_send_identify(ttynam, cwd, feat);
|
||||
client_send_identify(ttynam, termname, caps, ncaps, cwd, feat);
|
||||
tty_term_free_list(caps, ncaps);
|
||||
|
||||
/* Send first command. */
|
||||
if (msg == MSG_COMMAND) {
|
||||
@ -424,27 +439,32 @@ client_main(struct event_base *base, int argc, char **argv, uint64_t flags,
|
||||
|
||||
/* Send identify messages to server. */
|
||||
static void
|
||||
client_send_identify(const char *ttynam, const char *cwd, int feat)
|
||||
client_send_identify(const char *ttynam, const char *termname, char **caps,
|
||||
u_int ncaps, const char *cwd, int feat)
|
||||
{
|
||||
const char *s;
|
||||
char **ss;
|
||||
size_t sslen;
|
||||
int fd, flags = client_flags;
|
||||
pid_t pid;
|
||||
char **ss;
|
||||
size_t sslen;
|
||||
int fd, flags = client_flags;
|
||||
pid_t pid;
|
||||
u_int i;
|
||||
|
||||
proc_send(client_peer, MSG_IDENTIFY_FLAGS, -1, &flags, sizeof flags);
|
||||
proc_send(client_peer, MSG_IDENTIFY_LONGFLAGS, -1, &client_flags,
|
||||
sizeof client_flags);
|
||||
|
||||
if ((s = getenv("TERM")) == NULL)
|
||||
s = "";
|
||||
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, s, strlen(s) + 1);
|
||||
proc_send(client_peer, MSG_IDENTIFY_TERM, -1, termname,
|
||||
strlen(termname) + 1);
|
||||
proc_send(client_peer, MSG_IDENTIFY_FEATURES, -1, &feat, sizeof feat);
|
||||
|
||||
proc_send(client_peer, MSG_IDENTIFY_TTYNAME, -1, ttynam,
|
||||
strlen(ttynam) + 1);
|
||||
proc_send(client_peer, MSG_IDENTIFY_CWD, -1, cwd, strlen(cwd) + 1);
|
||||
|
||||
for (i = 0; i < ncaps; i++) {
|
||||
proc_send(client_peer, MSG_IDENTIFY_TERMINFO, -1,
|
||||
caps[i], strlen(caps[i]) + 1);
|
||||
}
|
||||
|
||||
if ((fd = dup(STDIN_FILENO)) == -1)
|
||||
fatal("dup failed");
|
||||
proc_send(client_peer, MSG_IDENTIFY_STDIN, fd, NULL, 0);
|
||||
|
@ -304,6 +304,7 @@ server_client_lost(struct client *c)
|
||||
|
||||
free(c->term_name);
|
||||
free(c->term_type);
|
||||
tty_term_free_list(c->term_caps, c->term_ncaps);
|
||||
|
||||
status_free(c);
|
||||
|
||||
@ -1994,16 +1995,17 @@ server_client_dispatch(struct imsg *imsg, void *arg)
|
||||
datalen = imsg->hdr.len - IMSG_HEADER_SIZE;
|
||||
|
||||
switch (imsg->hdr.type) {
|
||||
case MSG_IDENTIFY_CLIENTPID:
|
||||
case MSG_IDENTIFY_CWD:
|
||||
case MSG_IDENTIFY_ENVIRON:
|
||||
case MSG_IDENTIFY_FEATURES:
|
||||
case MSG_IDENTIFY_FLAGS:
|
||||
case MSG_IDENTIFY_LONGFLAGS:
|
||||
case MSG_IDENTIFY_TERM:
|
||||
case MSG_IDENTIFY_TTYNAME:
|
||||
case MSG_IDENTIFY_CWD:
|
||||
case MSG_IDENTIFY_STDIN:
|
||||
case MSG_IDENTIFY_STDOUT:
|
||||
case MSG_IDENTIFY_ENVIRON:
|
||||
case MSG_IDENTIFY_CLIENTPID:
|
||||
case MSG_IDENTIFY_TERM:
|
||||
case MSG_IDENTIFY_TERMINFO:
|
||||
case MSG_IDENTIFY_TTYNAME:
|
||||
case MSG_IDENTIFY_DONE:
|
||||
server_client_dispatch_identify(c, imsg);
|
||||
break;
|
||||
@ -2197,6 +2199,14 @@ server_client_dispatch_identify(struct client *c, struct imsg *imsg)
|
||||
c->term_name = xstrdup(data);
|
||||
log_debug("client %p IDENTIFY_TERM %s", c, data);
|
||||
break;
|
||||
case MSG_IDENTIFY_TERMINFO:
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_IDENTIFY_TERMINFO string");
|
||||
c->term_caps = xreallocarray(c->term_caps, c->term_ncaps + 1,
|
||||
sizeof *c->term_caps);
|
||||
c->term_caps[c->term_ncaps++] = xstrdup(data);
|
||||
log_debug("client %p IDENTIFY_TERMINFO %s", c, data);
|
||||
break;
|
||||
case MSG_IDENTIFY_TTYNAME:
|
||||
if (datalen == 0 || data[datalen - 1] != '\0')
|
||||
fatalx("bad MSG_IDENTIFY_TTYNAME string");
|
||||
|
9
tmux.h
9
tmux.h
@ -501,6 +501,7 @@ enum msgtype {
|
||||
MSG_IDENTIFY_FEATURES,
|
||||
MSG_IDENTIFY_STDOUT,
|
||||
MSG_IDENTIFY_LONGFLAGS,
|
||||
MSG_IDENTIFY_TERMINFO,
|
||||
|
||||
MSG_COMMAND = 200,
|
||||
MSG_DETACH,
|
||||
@ -1604,6 +1605,8 @@ struct client {
|
||||
char *term_name;
|
||||
int term_features;
|
||||
char *term_type;
|
||||
char **term_caps;
|
||||
u_int term_ncaps;
|
||||
|
||||
char *ttyname;
|
||||
struct tty tty;
|
||||
@ -2168,8 +2171,12 @@ extern struct tty_terms tty_terms;
|
||||
u_int tty_term_ncodes(void);
|
||||
void tty_term_apply(struct tty_term *, const char *, int);
|
||||
void tty_term_apply_overrides(struct tty_term *);
|
||||
struct tty_term *tty_term_create(struct tty *, char *, int *, int, char **);
|
||||
struct tty_term *tty_term_create(struct tty *, char *, char **, u_int, int *,
|
||||
char **);
|
||||
void tty_term_free(struct tty_term *);
|
||||
int tty_term_read_list(const char *, int, char ***, u_int *,
|
||||
char **);
|
||||
void tty_term_free_list(char **, u_int);
|
||||
int tty_term_has(struct tty_term *, enum tty_code_code);
|
||||
const char *tty_term_string(struct tty_term *, enum tty_code_code);
|
||||
const char *tty_term_string1(struct tty_term *, enum tty_code_code, int);
|
||||
|
162
tty-term.c
162
tty-term.c
@ -453,7 +453,8 @@ tty_term_apply_overrides(struct tty_term *term)
|
||||
}
|
||||
|
||||
struct tty_term *
|
||||
tty_term_create(struct tty *tty, char *name, int *feat, int fd, char **cause)
|
||||
tty_term_create(struct tty *tty, char *name, char **caps, u_int ncaps,
|
||||
int *feat, char **cause)
|
||||
{
|
||||
struct tty_term *term;
|
||||
const struct tty_term_code_entry *ent;
|
||||
@ -461,10 +462,9 @@ tty_term_create(struct tty *tty, char *name, int *feat, int fd, char **cause)
|
||||
struct options_entry *o;
|
||||
struct options_array_item *a;
|
||||
union options_value *ov;
|
||||
u_int i;
|
||||
int n, error;
|
||||
const char *s, *acs;
|
||||
size_t offset;
|
||||
u_int i, j;
|
||||
const char *s, *acs, *value;
|
||||
size_t offset, namelen;
|
||||
char *first;
|
||||
|
||||
log_debug("adding term %s", name);
|
||||
@ -475,57 +475,38 @@ tty_term_create(struct tty *tty, char *name, int *feat, int fd, char **cause)
|
||||
term->codes = xcalloc(tty_term_ncodes(), sizeof *term->codes);
|
||||
LIST_INSERT_HEAD(&tty_terms, term, entry);
|
||||
|
||||
/* Set up curses terminal. */
|
||||
if (setupterm(name, fd, &error) != OK) {
|
||||
switch (error) {
|
||||
case 1:
|
||||
xasprintf(cause, "can't use hardcopy terminal: %s",
|
||||
name);
|
||||
break;
|
||||
case 0:
|
||||
xasprintf(cause, "missing or unsuitable terminal: %s",
|
||||
name);
|
||||
break;
|
||||
case -1:
|
||||
xasprintf(cause, "can't find terminfo database");
|
||||
break;
|
||||
default:
|
||||
xasprintf(cause, "unknown error");
|
||||
break;
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Fill in codes. */
|
||||
for (i = 0; i < tty_term_ncodes(); i++) {
|
||||
ent = &tty_term_codes[i];
|
||||
for (i = 0; i < ncaps; i++) {
|
||||
namelen = strcspn(caps[i], "=");
|
||||
if (namelen == 0)
|
||||
continue;
|
||||
value = caps[i] + namelen + 1;
|
||||
|
||||
code = &term->codes[i];
|
||||
code->type = TTYCODE_NONE;
|
||||
switch (ent->type) {
|
||||
case TTYCODE_NONE:
|
||||
break;
|
||||
case TTYCODE_STRING:
|
||||
s = tigetstr((char *) ent->name);
|
||||
if (s == NULL || s == (char *) -1)
|
||||
for (j = 0; j < tty_term_ncodes(); j++) {
|
||||
ent = &tty_term_codes[j];
|
||||
if (strncmp(ent->name, caps[i], namelen) != 0)
|
||||
continue;
|
||||
if (ent->name[namelen] != '\0')
|
||||
continue;
|
||||
|
||||
code = &term->codes[j];
|
||||
code->type = TTYCODE_NONE;
|
||||
switch (ent->type) {
|
||||
case TTYCODE_NONE:
|
||||
break;
|
||||
code->type = TTYCODE_STRING;
|
||||
code->value.string = tty_term_strip(s);
|
||||
break;
|
||||
case TTYCODE_NUMBER:
|
||||
n = tigetnum((char *) ent->name);
|
||||
if (n == -1 || n == -2)
|
||||
case TTYCODE_STRING:
|
||||
code->type = TTYCODE_STRING;
|
||||
code->value.string = tty_term_strip(value);
|
||||
break;
|
||||
code->type = TTYCODE_NUMBER;
|
||||
code->value.number = n;
|
||||
break;
|
||||
case TTYCODE_FLAG:
|
||||
n = tigetflag((char *) ent->name);
|
||||
if (n == -1)
|
||||
case TTYCODE_NUMBER:
|
||||
code->type = TTYCODE_NUMBER;
|
||||
code->value.number = atoi(value);
|
||||
break;
|
||||
code->type = TTYCODE_FLAG;
|
||||
code->value.flag = n;
|
||||
break;
|
||||
case TTYCODE_FLAG:
|
||||
code->type = TTYCODE_FLAG;
|
||||
code->value.flag = (*value == '1');
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -649,6 +630,85 @@ tty_term_free(struct tty_term *term)
|
||||
free(term);
|
||||
}
|
||||
|
||||
int
|
||||
tty_term_read_list(const char *name, int fd, char ***caps, u_int *ncaps,
|
||||
char **cause)
|
||||
{
|
||||
const struct tty_term_code_entry *ent;
|
||||
int error, n;
|
||||
u_int i;
|
||||
const char *s;
|
||||
char tmp[11];
|
||||
|
||||
if (setupterm(name, fd, &error) != OK) {
|
||||
switch (error) {
|
||||
case 1:
|
||||
xasprintf(cause, "can't use hardcopy terminal: %s",
|
||||
name);
|
||||
break;
|
||||
case 0:
|
||||
xasprintf(cause, "missing or unsuitable terminal: %s",
|
||||
name);
|
||||
break;
|
||||
case -1:
|
||||
xasprintf(cause, "can't find terminfo database");
|
||||
break;
|
||||
default:
|
||||
xasprintf(cause, "unknown error");
|
||||
break;
|
||||
}
|
||||
return (-1);
|
||||
}
|
||||
|
||||
*ncaps = 0;
|
||||
*caps = NULL;
|
||||
|
||||
for (i = 0; i < tty_term_ncodes(); i++) {
|
||||
ent = &tty_term_codes[i];
|
||||
switch (ent->type) {
|
||||
case TTYCODE_NONE:
|
||||
break;
|
||||
case TTYCODE_STRING:
|
||||
s = tigetstr((char *)ent->name);
|
||||
if (s == NULL || s == (char *)-1)
|
||||
continue;
|
||||
break;
|
||||
case TTYCODE_NUMBER:
|
||||
n = tigetnum((char *)ent->name);
|
||||
if (n == -1 || n == -2)
|
||||
continue;
|
||||
xsnprintf(tmp, sizeof tmp, "%d", n);
|
||||
s = tmp;
|
||||
break;
|
||||
case TTYCODE_FLAG:
|
||||
n = tigetflag((char *) ent->name);
|
||||
if (n == -1)
|
||||
continue;
|
||||
if (n)
|
||||
s = "1";
|
||||
else
|
||||
s = "0";
|
||||
break;
|
||||
}
|
||||
*caps = xreallocarray(*caps, (*ncaps) + 1, sizeof **caps);
|
||||
xasprintf(&(*caps)[*ncaps], "%s=%s", ent->name, s);
|
||||
(*ncaps)++;
|
||||
}
|
||||
|
||||
del_curterm(cur_term);
|
||||
return (0);
|
||||
}
|
||||
|
||||
void
|
||||
tty_term_free_list(char **caps, u_int ncaps)
|
||||
{
|
||||
u_int i;
|
||||
|
||||
for (i = 0; i < ncaps; i++)
|
||||
free(caps[i]);
|
||||
free(caps);
|
||||
}
|
||||
|
||||
int
|
||||
tty_term_has(struct tty_term *term, enum tty_code_code code)
|
||||
{
|
||||
|
4
tty.c
4
tty.c
@ -249,8 +249,8 @@ tty_open(struct tty *tty, char **cause)
|
||||
{
|
||||
struct client *c = tty->client;
|
||||
|
||||
tty->term = tty_term_create(tty, c->term_name, &c->term_features,
|
||||
c->fd, cause);
|
||||
tty->term = tty_term_create(tty, c->term_name, c->term_caps,
|
||||
c->term_ncaps, &c->term_features, cause);
|
||||
if (tty->term == NULL) {
|
||||
tty_close(tty);
|
||||
return (-1);
|
||||
|
Loading…
Reference in New Issue
Block a user