-/* $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>
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 *);
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);
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
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);
}
/* 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) {
/* 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);
-/* $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>
free(c->term_name);
free(c->term_type);
+ tty_term_free_list(c->term_caps, c->term_ncaps);
status_free(c);
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;
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");
-/* $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>
MSG_IDENTIFY_FEATURES,
MSG_IDENTIFY_STDOUT,
MSG_IDENTIFY_LONGFLAGS,
+ MSG_IDENTIFY_TERMINFO,
MSG_COMMAND = 200,
MSG_DETACH,
char *term_name;
int term_features;
char *term_type;
+ char **term_caps;
+ u_int term_ncaps;
char *ttyname;
struct tty tty;
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);
-/* $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>
}
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;
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);
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;
+ }
}
}
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)
{
-/* $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>
{
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);