Merge branch 'obsd-master' into master

This commit is contained in:
Thomas Adam 2021-02-17 09:58:51 +00:00
commit 3a76a56824
5 changed files with 169 additions and 72 deletions

View File

@ -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);

View File

@ -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
View File

@ -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);

View File

@ -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
View File

@ -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);