Move the call to setupterm() into the client and have it pass the
authornicm <nicm@openbsd.org>
Wed, 17 Feb 2021 07:18:36 +0000 (07:18 +0000)
committernicm <nicm@openbsd.org>
Wed, 17 Feb 2021 07:18:36 +0000 (07:18 +0000)
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.

usr.bin/tmux/client.c
usr.bin/tmux/server-client.c
usr.bin/tmux/tmux.h
usr.bin/tmux/tty-term.c
usr.bin/tmux/tty.c

index 0004d97..a1db86c 100644 (file)
@@ -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 <nicholas.marriott@gmail.com>
@@ -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);
index 0a1245c..cdfc95c 100644 (file)
@@ -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 <nicholas.marriott@gmail.com>
@@ -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");
index 0e6fd2f..cb1b8a7 100644 (file)
@@ -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 <nicholas.marriott@gmail.com>
@@ -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);
index 2f4722b..07ba8f9 100644 (file)
@@ -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 <nicholas.marriott@gmail.com>
@@ -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)
 {
index 9232bab..6e7e97d 100644 (file)
@@ -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 <nicholas.marriott@gmail.com>
@@ -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);