mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 00:56:10 +00:00 
			
		
		
		
	Merge branch 'obsd-master' into master
This commit is contained in:
		
							
								
								
									
										38
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										38
									
								
								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;
 | 
			
		||||
	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);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										142
									
								
								tty-term.c
									
									
									
									
									
								
							
							
						
						
									
										142
									
								
								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,59 +475,40 @@ 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];
 | 
			
		||||
		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;
 | 
			
		||||
			case TTYCODE_STRING:
 | 
			
		||||
			s = tigetstr((char *) ent->name);
 | 
			
		||||
			if (s == NULL || s == (char *) -1)
 | 
			
		||||
				break;
 | 
			
		||||
				code->type = TTYCODE_STRING;
 | 
			
		||||
			code->value.string = tty_term_strip(s);
 | 
			
		||||
				code->value.string = tty_term_strip(value);
 | 
			
		||||
				break;
 | 
			
		||||
			case TTYCODE_NUMBER:
 | 
			
		||||
			n = tigetnum((char *) ent->name);
 | 
			
		||||
			if (n == -1 || n == -2)
 | 
			
		||||
				break;
 | 
			
		||||
				code->type = TTYCODE_NUMBER;
 | 
			
		||||
			code->value.number = n;
 | 
			
		||||
				code->value.number = atoi(value);
 | 
			
		||||
				break;
 | 
			
		||||
			case TTYCODE_FLAG:
 | 
			
		||||
			n = tigetflag((char *) ent->name);
 | 
			
		||||
			if (n == -1)
 | 
			
		||||
				break;
 | 
			
		||||
				code->type = TTYCODE_FLAG;
 | 
			
		||||
			code->value.flag = n;
 | 
			
		||||
				code->value.flag = (*value == '1');
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Apply terminal features. */
 | 
			
		||||
	o = options_get_only(global_options, "terminal-features");
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user