mirror of
				https://github.com/tmux/tmux.git
				synced 2025-10-26 12:27:15 +00:00 
			
		
		
		
	Sync OpenBSD patchset 350:
Support -c like sh(1) to execute a command, useful when tmux is a login shell. Suggested by halex@. This includes another protocol version increase (the last for now) so again restart the tmux server before upgrading.
This commit is contained in:
		
							
								
								
									
										4
									
								
								client.c
									
									
									
									
									
								
							
							
						
						
									
										4
									
								
								client.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: client.c,v 1.74 2009-09-23 15:00:08 tcunha Exp $ */ | ||||
| /* $Id: client.c,v 1.75 2009-09-23 15:18:56 tcunha Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -95,6 +95,8 @@ server_started: | ||||
| 		fatal("fcntl failed"); | ||||
| 	if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) | ||||
| 		fatal("fcntl failed"); | ||||
| 	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) | ||||
| 		fatal("fcntl failed"); | ||||
| 	imsg_init(&cctx->ibuf, fd); | ||||
|  | ||||
| 	if (cmdflags & CMD_SENDENVIRON) | ||||
|   | ||||
							
								
								
									
										27
									
								
								server-msg.c
									
									
									
									
									
								
							
							
						
						
									
										27
									
								
								server-msg.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: server-msg.c,v 1.87 2009-09-23 15:00:08 tcunha Exp $ */ | ||||
| /* $Id: server-msg.c,v 1.88 2009-09-23 15:18:56 tcunha Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -20,6 +20,7 @@ | ||||
| #include <sys/ioctl.h> | ||||
|  | ||||
| #include <errno.h> | ||||
| #include <paths.h> | ||||
| #include <stdlib.h> | ||||
| #include <string.h> | ||||
| #include <time.h> | ||||
| @@ -29,6 +30,7 @@ | ||||
|  | ||||
| void	server_msg_command(struct client *, struct msg_command_data *); | ||||
| void	server_msg_identify(struct client *, struct msg_identify_data *, int); | ||||
| void	server_msg_shell(struct client *); | ||||
|  | ||||
| void printflike2 server_msg_command_error(struct cmd_ctx *, const char *, ...); | ||||
| void printflike2 server_msg_command_print(struct cmd_ctx *, const char *, ...); | ||||
| @@ -113,6 +115,12 @@ server_msg_dispatch(struct client *c) | ||||
| 			if (strchr(environdata.var, '=') != NULL) | ||||
| 				environ_put(&c->environ, environdata.var); | ||||
| 			break; | ||||
| 		case MSG_SHELL: | ||||
| 			if (datalen != 0) | ||||
| 				fatalx("bad MSG_SHELL size"); | ||||
|  | ||||
| 			server_msg_shell(c); | ||||
| 			break; | ||||
| 		default: | ||||
| 			fatalx("unexpected message"); | ||||
| 		} | ||||
| @@ -248,3 +256,20 @@ server_msg_identify(struct client *c, struct msg_identify_data *data, int fd) | ||||
|  | ||||
| 	c->flags |= CLIENT_TERMINAL; | ||||
| } | ||||
|  | ||||
| void | ||||
| server_msg_shell(struct client *c) | ||||
| { | ||||
| 	struct msg_shell_data	 data; | ||||
| 	const char		*shell; | ||||
| 	 | ||||
| 	shell = options_get_string(&global_s_options, "default-shell"); | ||||
|  | ||||
| 	if (*shell == '\0' || areshell(shell)) | ||||
| 		shell = _PATH_BSHELL; | ||||
| 	if (strlcpy(data.shell, shell, sizeof data.shell) >= sizeof data.shell) | ||||
| 		strlcpy(data.shell, _PATH_BSHELL, sizeof data.shell); | ||||
| 	 | ||||
| 	server_write_client(c, MSG_SHELL, &data, sizeof data); | ||||
| 	c->flags |= CLIENT_BAD;	/* it will die after exec */ | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								tmux.1
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								tmux.1
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| .\" $Id: tmux.1,v 1.172 2009-09-23 15:00:09 tcunha Exp $ | ||||
| .\" $Id: tmux.1,v 1.173 2009-09-23 15:18:56 tcunha Exp $ | ||||
| .\" | ||||
| .\" Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| .\" | ||||
| @@ -24,6 +24,7 @@ | ||||
| .Nm tmux | ||||
| .Bk -words | ||||
| .Op Fl 28dlquv | ||||
| .Op Fl c Ar shell-command | ||||
| .Op Fl f Ar file | ||||
| .Op Fl L Ar socket-name | ||||
| .Op Fl S Ar socket-path | ||||
| @@ -101,6 +102,15 @@ to assume the terminal supports 256 colours. | ||||
| Like | ||||
| .Fl 2 , | ||||
| but indicates that the terminal supports 88 colours. | ||||
| .It Fl c Ar shell-command | ||||
| Execute | ||||
| .Ar shell-command | ||||
| using the default shell. | ||||
| If necessary, the | ||||
| .Nm | ||||
| server will be started to retrieve the | ||||
| .Ic default-shell | ||||
| option. | ||||
| .It Fl d | ||||
| Force | ||||
| .Nm | ||||
|   | ||||
							
								
								
									
										68
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								tmux.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tmux.c,v 1.174 2009-09-23 15:00:09 tcunha Exp $ */ | ||||
| /* $Id: tmux.c,v 1.175 2009-09-23 15:18:56 tcunha Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -62,7 +62,8 @@ int		 login_shell; | ||||
| __dead void	 usage(void); | ||||
| char 		*makesockpath(const char *); | ||||
| int		 prepare_cmd(enum msgtype *, void **, size_t *, int, char **); | ||||
| int		 dispatch_imsg(struct client_ctx *, int *); | ||||
| int		 dispatch_imsg(struct client_ctx *, const char *, int *); | ||||
| __dead void	 shell_exec(const char *, const char *); | ||||
|  | ||||
| #ifndef HAVE_PROGNAME | ||||
| char      *__progname = (char *) "tmux"; | ||||
| @@ -72,7 +73,7 @@ __dead void | ||||
| usage(void) | ||||
| { | ||||
| 	fprintf(stderr, | ||||
| 	    "usage: %s [-28dlquv] [-f file] [-L socket-name]\n" | ||||
| 	    "usage: %s [-28dlquv] [-c shell-command] [-f file] [-L socket-name]\n" | ||||
| 	    "            [-S socket-path] [command [flags]]\n", | ||||
| 	    __progname); | ||||
| 	exit(1); | ||||
| @@ -284,17 +285,17 @@ main(int argc, char **argv) | ||||
| 	struct passwd		*pw; | ||||
| 	struct options		*so, *wo; | ||||
| 	struct keylist		*keylist; | ||||
| 	char			*s, *path, *label, *home, *cause, **var; | ||||
| 	char			 cwd[MAXPATHLEN]; | ||||
| 	char			*s, *shellcmd, *path, *label, *home, *cause; | ||||
| 	char			 cwd[MAXPATHLEN], **var; | ||||
| 	void			*buf; | ||||
| 	size_t			 len; | ||||
| 	int	 		 retcode, opt, flags, cmdflags = 0; | ||||
| 	int			 nfds; | ||||
|  | ||||
| 	flags = 0; | ||||
| 	label = path = NULL; | ||||
| 	shellcmd = label = path = NULL; | ||||
| 	login_shell = (**argv == '-'); | ||||
| 	while ((opt = getopt(argc, argv, "28df:lL:qS:uUv")) != -1) { | ||||
| 	while ((opt = getopt(argc, argv, "28c:df:lL:qS:uUv")) != -1) { | ||||
| 		switch (opt) { | ||||
| 		case '2': | ||||
| 			flags |= IDENTIFY_256COLOURS; | ||||
| @@ -304,6 +305,11 @@ main(int argc, char **argv) | ||||
| 			flags |= IDENTIFY_88COLOURS; | ||||
| 			flags &= ~IDENTIFY_256COLOURS; | ||||
| 			break; | ||||
| 		case 'c': | ||||
| 			if (shellcmd != NULL) | ||||
| 				xfree(shellcmd); | ||||
| 			shellcmd = xstrdup(optarg); | ||||
| 			break; | ||||
| 		case 'd': | ||||
| 			flags |= IDENTIFY_HASDEFAULTS; | ||||
| 			break; | ||||
| @@ -341,6 +347,9 @@ main(int argc, char **argv) | ||||
| 	argc -= optind; | ||||
| 	argv += optind; | ||||
|  | ||||
| 	if (shellcmd != NULL && argc != 0) | ||||
| 		usage(); | ||||
|  | ||||
| 	log_open_tty(debug_level); | ||||
| 	siginit(); | ||||
|  | ||||
| @@ -486,10 +495,16 @@ main(int argc, char **argv) | ||||
| 	} | ||||
| 	xfree(label); | ||||
|  | ||||
| 	if (prepare_cmd(&msg, &buf, &len, argc, argv) != 0) | ||||
| 	if (shellcmd != NULL) { | ||||
| 		msg = MSG_SHELL; | ||||
| 		buf = NULL; | ||||
| 		len = 0; | ||||
| 	} else if (prepare_cmd(&msg, &buf, &len, argc, argv) != 0) | ||||
| 		exit(1); | ||||
|  | ||||
| 	if (argc == 0)	/* new-session is the default */ | ||||
| 	if (shellcmd != NULL) | ||||
| 		cmdflags |= CMD_STARTSERVER; | ||||
| 	else if (argc == 0)	/* new-session is the default */ | ||||
| 		cmdflags |= CMD_STARTSERVER|CMD_SENDENVIRON; | ||||
| 	else { | ||||
| 		/* | ||||
| @@ -538,7 +553,7 @@ main(int argc, char **argv) | ||||
| 			fatalx("socket error"); | ||||
|  | ||||
|                 if (pfd.revents & POLLIN) { | ||||
| 			if (dispatch_imsg(&cctx, &retcode) != 0) | ||||
| 			if (dispatch_imsg(&cctx, shellcmd, &retcode) != 0) | ||||
| 				break; | ||||
| 		} | ||||
|  | ||||
| @@ -555,11 +570,12 @@ main(int argc, char **argv) | ||||
| } | ||||
|  | ||||
| int | ||||
| dispatch_imsg(struct client_ctx *cctx, int *retcode) | ||||
| dispatch_imsg(struct client_ctx *cctx, const char *shellcmd, int *retcode) | ||||
| { | ||||
| 	struct imsg		imsg; | ||||
| 	ssize_t			n, datalen; | ||||
| 	struct msg_print_data	printdata; | ||||
| 	struct msg_shell_data	shelldata; | ||||
|  | ||||
|         if ((n = imsg_read(&cctx->ibuf)) == -1 || n == 0) | ||||
| 		fatalx("imsg_read failed"); | ||||
| @@ -603,6 +619,13 @@ dispatch_imsg(struct client_ctx *cctx, int *retcode) | ||||
| 			    "server %u)", PROTOCOL_VERSION, imsg.hdr.peerid); | ||||
| 			*retcode = 1; | ||||
| 			return (-1); | ||||
| 		case MSG_SHELL: | ||||
| 			if (datalen != sizeof shelldata) | ||||
| 				fatalx("bad MSG_SHELL size"); | ||||
| 			memcpy(&shelldata, imsg.data, sizeof shelldata); | ||||
| 			shelldata.shell[(sizeof shelldata.shell) - 1] = '\0'; | ||||
| 			 | ||||
| 			shell_exec(shelldata.shell, shellcmd); | ||||
| 		default: | ||||
| 			fatalx("unexpected message"); | ||||
| 		} | ||||
| @@ -610,3 +633,26 @@ dispatch_imsg(struct client_ctx *cctx, int *retcode) | ||||
| 		imsg_free(&imsg); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| __dead void | ||||
| shell_exec(const char *shell, const char *shellcmd) | ||||
| { | ||||
| 	const char	*shellname, *ptr; | ||||
| 	char		*argv0; | ||||
|  | ||||
| 	sigreset(); | ||||
| 				 | ||||
| 	ptr = strrchr(shell, '/'); | ||||
| 	if (ptr != NULL && *(ptr + 1) != '\0') | ||||
| 		shellname = ptr + 1; | ||||
| 	else | ||||
| 		shellname = shell; | ||||
| 	if (login_shell) | ||||
| 		xasprintf(&argv0, "-%s", shellname); | ||||
| 	else | ||||
| 		xasprintf(&argv0, "%s", shellname); | ||||
| 	setenv("SHELL", shell, 1); | ||||
|  | ||||
| 	execl(shell, argv0, "-c", shellcmd, (char *) NULL); | ||||
| 	fatal("execl failed"); | ||||
| } | ||||
|   | ||||
							
								
								
									
										12
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								tmux.h
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tmux.h,v 1.453 2009-09-23 15:00:09 tcunha Exp $ */ | ||||
| /* $Id: tmux.h,v 1.454 2009-09-23 15:18:56 tcunha Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -21,7 +21,7 @@ | ||||
|  | ||||
| #include "config.h" | ||||
|  | ||||
| #define PROTOCOL_VERSION 4 | ||||
| #define PROTOCOL_VERSION 5 | ||||
|  | ||||
| #include <sys/param.h> | ||||
| #include <sys/time.h> | ||||
| @@ -128,6 +128,7 @@ enum key_code { | ||||
|  | ||||
| 	/* Function keys. */ | ||||
| 	KEYC_F1, | ||||
|  | ||||
| 	KEYC_F2, | ||||
| 	KEYC_F3, | ||||
| 	KEYC_F4, | ||||
| @@ -306,7 +307,8 @@ enum msgtype { | ||||
| 	MSG_WAKEUP, | ||||
| 	MSG_ENVIRON, | ||||
| 	MSG_UNLOCK, | ||||
| 	MSG_LOCK | ||||
| 	MSG_LOCK, | ||||
| 	MSG_SHELL | ||||
| }; | ||||
|  | ||||
| /* | ||||
| @@ -346,6 +348,10 @@ struct msg_environ_data { | ||||
| 	char	     	var[ENVIRON_LENGTH]; | ||||
| }; | ||||
|  | ||||
| struct msg_shell_data { | ||||
| 	char	       	shell[MAXPATHLEN]; | ||||
| }; | ||||
|  | ||||
| /* Mode key commands. */ | ||||
| enum mode_key_cmd { | ||||
| 	MODEKEY_NONE, | ||||
|   | ||||
							
								
								
									
										18
									
								
								tty.c
									
									
									
									
									
								
							
							
						
						
									
										18
									
								
								tty.c
									
									
									
									
									
								
							| @@ -1,4 +1,4 @@ | ||||
| /* $Id: tty.c,v 1.137 2009-09-23 15:08:21 tcunha Exp $ */ | ||||
| /* $Id: tty.c,v 1.138 2009-09-23 15:18:56 tcunha Exp $ */ | ||||
|  | ||||
| /* | ||||
|  * Copyright (c) 2007 Nicholas Marriott <nicm@users.sourceforge.net> | ||||
| @@ -44,7 +44,6 @@ void	tty_cell(struct tty *, | ||||
| void | ||||
| tty_init(struct tty *tty, int fd, char *term) | ||||
| { | ||||
| 	int	 mode; | ||||
| 	char	*path; | ||||
|  | ||||
| 	memset(tty, 0, sizeof *tty); | ||||
| @@ -55,10 +54,6 @@ tty_init(struct tty *tty, int fd, char *term) | ||||
| 	else | ||||
| 		tty->termname = xstrdup(term); | ||||
|  | ||||
| 	if ((mode = fcntl(fd, F_GETFL)) == -1) | ||||
| 		fatal("fcntl failed"); | ||||
| 	if (fcntl(fd, F_SETFL, mode|O_NONBLOCK) == -1) | ||||
| 		fatal("fcntl failed"); | ||||
| 	if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) | ||||
| 		fatal("fcntl failed"); | ||||
| 	tty->fd = fd; | ||||
| @@ -129,6 +124,7 @@ void | ||||
| tty_start_tty(struct tty *tty) | ||||
| { | ||||
| 	struct termios	 tio; | ||||
| 	int		 mode; | ||||
| #ifdef TIOCFLUSH | ||||
| 	int		 what; | ||||
| #endif | ||||
| @@ -136,6 +132,11 @@ tty_start_tty(struct tty *tty) | ||||
| 	if (tty->fd == -1) | ||||
| 		return; | ||||
|  | ||||
| 	if ((mode = fcntl(tty->fd, F_GETFL)) == -1) | ||||
| 		fatal("fcntl failed"); | ||||
| 	if (fcntl(tty->fd, F_SETFL, mode|O_NONBLOCK) == -1) | ||||
| 		fatal("fcntl failed"); | ||||
|  | ||||
| #if 0 | ||||
| 	tty_detect_utf8(tty); | ||||
| #endif | ||||
| @@ -187,6 +188,7 @@ void | ||||
| tty_stop_tty(struct tty *tty) | ||||
| { | ||||
| 	struct winsize	ws; | ||||
| 	int		mode; | ||||
|  | ||||
| 	if (!(tty->flags & TTY_STARTED)) | ||||
| 		return; | ||||
| @@ -197,6 +199,10 @@ tty_stop_tty(struct tty *tty) | ||||
| 	 * because the fd is invalid. Things like ssh -t can easily leave us | ||||
| 	 * with a dead tty. | ||||
| 	 */ | ||||
| 	if ((mode = fcntl(tty->fd, F_GETFL)) == -1) | ||||
| 		return; | ||||
| 	if (fcntl(tty->fd, F_SETFL, mode & ~O_NONBLOCK) == -1) | ||||
| 		return; | ||||
| 	if (ioctl(tty->fd, TIOCGWINSZ, &ws) == -1) | ||||
| 		return; | ||||
| 	if (tcsetattr(tty->fd, TCSANOW, &tty->tio) == -1) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Tiago Cunha
					Tiago Cunha