From: nicm Date: Wed, 17 Feb 2021 07:18:36 +0000 (+0000) Subject: Move the call to setupterm() into the client and have it pass the X-Git-Url: http://artulab.com/gitweb/?a=commitdiff_plain;h=c05282f8eea07b70b4f0e3905b9849fff97f0f85;p=openbsd Move the call to setupterm() into the client and have it pass the results to the server over imsg, means the server does not need to enter ncurses or read terminfo db. Old clients will not work with a new server. --- diff --git a/usr.bin/tmux/client.c b/usr.bin/tmux/client.c index 0004d97cd6a..a1db86c7110 100644 --- a/usr.bin/tmux/client.c +++ b/usr.bin/tmux/client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: client.c,v 1.154 2021/02/12 06:52:48 nicm Exp $ */ +/* $OpenBSD: client.c,v 1.155 2021/02/17 07:18:36 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -62,7 +62,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 *); @@ -235,13 +236,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); @@ -297,6 +299,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 @@ -312,6 +316,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); @@ -340,7 +354,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) { @@ -423,27 +438,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); diff --git a/usr.bin/tmux/server-client.c b/usr.bin/tmux/server-client.c index 0a1245ccc93..cdfc95c3775 100644 --- a/usr.bin/tmux/server-client.c +++ b/usr.bin/tmux/server-client.c @@ -1,4 +1,4 @@ -/* $OpenBSD: server-client.c,v 1.369 2021/02/11 08:28:45 nicm Exp $ */ +/* $OpenBSD: server-client.c,v 1.370 2021/02/17 07:18:36 nicm Exp $ */ /* * Copyright (c) 2009 Nicholas Marriott @@ -307,6 +307,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); @@ -1997,16 +1998,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; @@ -2200,6 +2202,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"); diff --git a/usr.bin/tmux/tmux.h b/usr.bin/tmux/tmux.h index 0e6fd2f851a..cb1b8a7e49d 100644 --- a/usr.bin/tmux/tmux.h +++ b/usr.bin/tmux/tmux.h @@ -1,4 +1,4 @@ -/* $OpenBSD: tmux.h,v 1.1091 2021/02/15 09:39:38 nicm Exp $ */ +/* $OpenBSD: tmux.h,v 1.1092 2021/02/17 07:18:36 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -500,6 +500,7 @@ enum msgtype { MSG_IDENTIFY_FEATURES, MSG_IDENTIFY_STDOUT, MSG_IDENTIFY_LONGFLAGS, + MSG_IDENTIFY_TERMINFO, MSG_COMMAND = 200, MSG_DETACH, @@ -1603,6 +1604,8 @@ struct client { char *term_name; int term_features; char *term_type; + char **term_caps; + u_int term_ncaps; char *ttyname; struct tty tty; @@ -2167,8 +2170,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); diff --git a/usr.bin/tmux/tty-term.c b/usr.bin/tmux/tty-term.c index 2f4722b19f6..07ba8f94d7d 100644 --- a/usr.bin/tmux/tty-term.c +++ b/usr.bin/tmux/tty-term.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty-term.c,v 1.86 2021/02/05 12:29:19 nicm Exp $ */ +/* $OpenBSD: tty-term.c,v 1.87 2021/02/17 07:18:36 nicm Exp $ */ /* * Copyright (c) 2008 Nicholas Marriott @@ -450,7 +450,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; @@ -458,10 +459,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); @@ -472,57 +472,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; + } } } @@ -643,6 +624,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) { diff --git a/usr.bin/tmux/tty.c b/usr.bin/tmux/tty.c index 9232bab6b09..6e7e97d9ab9 100644 --- a/usr.bin/tmux/tty.c +++ b/usr.bin/tmux/tty.c @@ -1,4 +1,4 @@ -/* $OpenBSD: tty.c,v 1.388 2021/01/18 10:27:54 nicm Exp $ */ +/* $OpenBSD: tty.c,v 1.389 2021/02/17 07:18:36 nicm Exp $ */ /* * Copyright (c) 2007 Nicholas Marriott @@ -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);