mirror of
				https://github.com/tmux/tmux.git
				synced 2025-11-04 09:26:05 +00:00 
			
		
		
		
	Instead of bailing out on the first configuration file error, carry on,
collecting all the errors, then start with the active window in more mode displaying them.
This commit is contained in:
		
							
								
								
									
										57
									
								
								cfg.c
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								cfg.c
									
									
									
									
									
								
							@@ -34,6 +34,9 @@ void printflike2 cfg_print(struct cmd_ctx *, const char *, ...);
 | 
			
		||||
void printflike2 cfg_error(struct cmd_ctx *, const char *, ...);
 | 
			
		||||
 | 
			
		||||
char	 *cfg_cause;
 | 
			
		||||
int       cfg_finished;
 | 
			
		||||
char    **cfg_causes;
 | 
			
		||||
u_int     cfg_ncauses;
 | 
			
		||||
 | 
			
		||||
/* ARGSUSED */
 | 
			
		||||
void printflike2
 | 
			
		||||
@@ -52,19 +55,38 @@ cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void printflike3
 | 
			
		||||
cfg_add_cause(u_int *ncauses, char ***causes, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	char	*cause;
 | 
			
		||||
	va_list	 ap;
 | 
			
		||||
 | 
			
		||||
	va_start(ap, fmt);
 | 
			
		||||
	xvasprintf(&cause, fmt, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
 | 
			
		||||
	*causes = xrealloc(*causes, *ncauses + 1, sizeof **causes);
 | 
			
		||||
	(*causes)[(*ncauses)++] = cause;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Load configuration file. Returns -1 for an error with a list of messages in
 | 
			
		||||
 * causes. Note that causes and ncauses must be initialised by the caller!
 | 
			
		||||
 */
 | 
			
		||||
int
 | 
			
		||||
load_cfg(const char *path, struct cmd_ctx *ctxin, char **cause)
 | 
			
		||||
load_cfg(
 | 
			
		||||
    const char *path, struct cmd_ctx *ctxin, u_int *ncauses, char ***causes)
 | 
			
		||||
{
 | 
			
		||||
	FILE		*f;
 | 
			
		||||
	u_int		 n;
 | 
			
		||||
	char		*buf, *line, *ptr;
 | 
			
		||||
	char		*buf, *line, *cause;
 | 
			
		||||
	size_t		 len;
 | 
			
		||||
	struct cmd_list	*cmdlist;
 | 
			
		||||
	struct cmd_ctx	 ctx;
 | 
			
		||||
 | 
			
		||||
	if ((f = fopen(path, "rb")) == NULL) {
 | 
			
		||||
		xasprintf(cause, "%s: %s", path, strerror(errno));
 | 
			
		||||
		return (1);
 | 
			
		||||
		cfg_add_cause(ncauses, causes, "%s: %s", path, strerror(errno));
 | 
			
		||||
		return (-1);
 | 
			
		||||
	}
 | 
			
		||||
	n = 0;
 | 
			
		||||
 | 
			
		||||
@@ -80,10 +102,13 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, char **cause)
 | 
			
		||||
		}
 | 
			
		||||
		n++;
 | 
			
		||||
 | 
			
		||||
		if (cmd_string_parse(buf, &cmdlist, cause) != 0) {
 | 
			
		||||
			if (*cause == NULL)
 | 
			
		||||
		if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
 | 
			
		||||
			if (cause == NULL)
 | 
			
		||||
				continue;
 | 
			
		||||
			cfg_add_cause(
 | 
			
		||||
			    ncauses, causes, "%s: %u: %s", path, n, cause);
 | 
			
		||||
			xfree(cause);
 | 
			
		||||
			continue;
 | 
			
		||||
			goto error;
 | 
			
		||||
		}
 | 
			
		||||
		if (cmdlist == NULL)
 | 
			
		||||
			continue;
 | 
			
		||||
@@ -107,23 +132,17 @@ load_cfg(const char *path, struct cmd_ctx *ctxin, char **cause)
 | 
			
		||||
		cmd_list_exec(cmdlist, &ctx);
 | 
			
		||||
		cmd_list_free(cmdlist);
 | 
			
		||||
		if (cfg_cause != NULL) {
 | 
			
		||||
			*cause = cfg_cause;
 | 
			
		||||
			goto error;
 | 
			
		||||
			cfg_add_cause(
 | 
			
		||||
			    ncauses, causes, "%s: %d: %s", path, n, cfg_cause);
 | 
			
		||||
			xfree(cfg_cause);
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	if (line != NULL)
 | 
			
		||||
		xfree(line);
 | 
			
		||||
	fclose(f);
 | 
			
		||||
 | 
			
		||||
	if (*ncauses != 0)
 | 
			
		||||
		return (-1);
 | 
			
		||||
	return (0);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	if (line != NULL)
 | 
			
		||||
		xfree(line);
 | 
			
		||||
	fclose(f);
 | 
			
		||||
 | 
			
		||||
	xasprintf(&ptr, "%s: %s at line %u", path, *cause, n);
 | 
			
		||||
	xfree(*cause);
 | 
			
		||||
	*cause = ptr;
 | 
			
		||||
	return (1);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -122,12 +122,13 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	struct cmd_new_session_data	*data = self->data;
 | 
			
		||||
	struct session			*s, *groupwith;
 | 
			
		||||
	struct window			*w;
 | 
			
		||||
	struct window_pane		*wp;
 | 
			
		||||
	struct environ			 env;
 | 
			
		||||
	struct termios			 tio, *tiop;
 | 
			
		||||
	const char			*update;
 | 
			
		||||
	char				*overrides, *cmd, *cwd, *cause;
 | 
			
		||||
	int				 detached, idx;
 | 
			
		||||
	u_int				 sx, sy;
 | 
			
		||||
	u_int				 sx, sy, i;
 | 
			
		||||
 | 
			
		||||
	if (data->newname != NULL && session_find(data->newname) != NULL) {
 | 
			
		||||
		ctx->error(ctx, "duplicate session: %s", data->newname);
 | 
			
		||||
@@ -280,6 +281,21 @@ cmd_new_session_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
	recalculate_sizes();
 | 
			
		||||
	server_update_socket();
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If there are still configuration file errors to display, put the new
 | 
			
		||||
	 * session's current window into more mode and display them now.
 | 
			
		||||
	 */
 | 
			
		||||
	if (cfg_finished && cfg_ncauses != 0) {
 | 
			
		||||
		wp = s->curw->window->active;
 | 
			
		||||
		window_pane_set_mode(wp, &window_more_mode);
 | 
			
		||||
		for (i = 0; i < cfg_ncauses; i++) {
 | 
			
		||||
			window_more_add(wp, "%s", cfg_causes[i]);
 | 
			
		||||
			xfree(cfg_causes[i]);
 | 
			
		||||
		}
 | 
			
		||||
		xfree(cfg_causes);
 | 
			
		||||
		cfg_ncauses = 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (!detached);	/* 1 means don't tell command client to exit */
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -89,12 +89,18 @@ int
 | 
			
		||||
cmd_source_file_exec(struct cmd *self, struct cmd_ctx *ctx)
 | 
			
		||||
{
 | 
			
		||||
	struct cmd_source_file_data	*data = self->data;
 | 
			
		||||
	char				*cause;
 | 
			
		||||
	char			       **causes;
 | 
			
		||||
	u_int				 i, ncauses;
 | 
			
		||||
 | 
			
		||||
	if (load_cfg(data->path, ctx, &cause) != 0) {
 | 
			
		||||
		ctx->error(ctx, "%s", cause);
 | 
			
		||||
		xfree(cause);
 | 
			
		||||
		return (-1);
 | 
			
		||||
	causes = NULL;
 | 
			
		||||
	ncauses = 0;
 | 
			
		||||
 | 
			
		||||
	if (load_cfg(data->path, ctx, &ncauses, &causes) != 0) {
 | 
			
		||||
		for (i = 0; i < ncauses; i++) {
 | 
			
		||||
			ctx->print(ctx, "%s", causes[i]);
 | 
			
		||||
			xfree(causes[i]);
 | 
			
		||||
		}
 | 
			
		||||
		xfree(causes);
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return (0);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										53
									
								
								server.c
									
									
									
									
									
								
							
							
						
						
									
										53
									
								
								server.c
									
									
									
									
									
								
							@@ -113,10 +113,11 @@ server_create_socket(void)
 | 
			
		||||
int
 | 
			
		||||
server_start(char *path)
 | 
			
		||||
{
 | 
			
		||||
	struct client	*c;
 | 
			
		||||
	int		 pair[2];
 | 
			
		||||
	char		*cause, rpathbuf[MAXPATHLEN];
 | 
			
		||||
	struct window_pane	*wp;
 | 
			
		||||
	int	 		 pair[2], retval;
 | 
			
		||||
	char			 rpathbuf[MAXPATHLEN];
 | 
			
		||||
	struct timeval		 tv;
 | 
			
		||||
	u_int			 i;
 | 
			
		||||
 | 
			
		||||
	/* The first client is special and gets a socketpair; create it. */
 | 
			
		||||
	if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pair) != 0)
 | 
			
		||||
@@ -166,15 +167,31 @@ server_start(char *path)
 | 
			
		||||
	server_fd = server_create_socket();
 | 
			
		||||
	server_client_create(pair[1]);
 | 
			
		||||
 | 
			
		||||
	if (access(SYSTEM_CFG, R_OK) == 0) {
 | 
			
		||||
		if (load_cfg(SYSTEM_CFG, NULL, &cause) != 0)
 | 
			
		||||
			goto error;
 | 
			
		||||
	} else if (errno != ENOENT) {
 | 
			
		||||
		xasprintf(&cause, "%s: %s", strerror(errno), SYSTEM_CFG);
 | 
			
		||||
		goto error;
 | 
			
		||||
	retval = 0;
 | 
			
		||||
	if (access(SYSTEM_CFG, R_OK) == 0)
 | 
			
		||||
		load_cfg(SYSTEM_CFG, NULL, &cfg_ncauses, &cfg_causes);
 | 
			
		||||
	else if (errno != ENOENT) {
 | 
			
		||||
		cfg_add_cause(&cfg_ncauses, &cfg_causes,
 | 
			
		||||
		    "%s: %s", strerror(errno), SYSTEM_CFG);
 | 
			
		||||
	}
 | 
			
		||||
	if (cfg_file != NULL && load_cfg(cfg_file, NULL, &cause) != 0)
 | 
			
		||||
		goto error;
 | 
			
		||||
	if (cfg_file != NULL)
 | 
			
		||||
		load_cfg(cfg_file, NULL, &cfg_ncauses, &cfg_causes);
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
	 * If there is a session already, put the current window and pane into
 | 
			
		||||
	 * more mode.
 | 
			
		||||
	 */
 | 
			
		||||
	if (!ARRAY_EMPTY(&sessions) && cfg_ncauses != 0) {
 | 
			
		||||
		wp = ARRAY_FIRST(&sessions)->curw->window->active;
 | 
			
		||||
		window_pane_set_mode(wp, &window_more_mode);
 | 
			
		||||
		for (i = 0; i < cfg_ncauses; i++) {
 | 
			
		||||
			window_more_add(wp, "%s", cfg_causes[i]);
 | 
			
		||||
			xfree(cfg_causes[i]);
 | 
			
		||||
		}
 | 
			
		||||
		xfree(cfg_causes);
 | 
			
		||||
		cfg_ncauses = 0;
 | 
			
		||||
	}
 | 
			
		||||
	cfg_finished = 1;
 | 
			
		||||
 | 
			
		||||
	event_set(&server_ev_accept,
 | 
			
		||||
	    server_fd, EV_READ|EV_PERSIST, server_accept_callback, NULL);
 | 
			
		||||
@@ -188,20 +205,6 @@ server_start(char *path)
 | 
			
		||||
	server_signal_set();
 | 
			
		||||
	server_loop();
 | 
			
		||||
	exit(0);
 | 
			
		||||
 | 
			
		||||
error:
 | 
			
		||||
	/* Write the error and shutdown the server. */
 | 
			
		||||
	c = ARRAY_FIRST(&clients);
 | 
			
		||||
 | 
			
		||||
	server_write_error(c, cause);
 | 
			
		||||
	server_write_client(c, MSG_EXIT, NULL, 0);
 | 
			
		||||
	xfree(cause);
 | 
			
		||||
 | 
			
		||||
	server_shutdown = 1;
 | 
			
		||||
 | 
			
		||||
	server_signal_set();
 | 
			
		||||
	server_loop();
 | 
			
		||||
	exit(1);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Main server loop. */
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								tmux.c
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								tmux.c
									
									
									
									
									
								
							@@ -432,15 +432,10 @@ main(int argc, char **argv)
 | 
			
		||||
				home = pw->pw_dir;
 | 
			
		||||
		}
 | 
			
		||||
		xasprintf(&cfg_file, "%s/%s", home, DEFAULT_CFG);
 | 
			
		||||
		if (access(cfg_file, R_OK) != 0) {
 | 
			
		||||
		if (access(cfg_file, R_OK) != 0 && errno == ENOENT) {
 | 
			
		||||
			xfree(cfg_file);
 | 
			
		||||
			cfg_file = NULL;
 | 
			
		||||
		}
 | 
			
		||||
	} else {
 | 
			
		||||
		if (access(cfg_file, R_OK) != 0) {
 | 
			
		||||
			log_warn("%s", cfg_file);
 | 
			
		||||
			exit(1);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/*
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								tmux.h
									
									
									
									
									
								
							
							
						
						
									
										7
									
								
								tmux.h
									
									
									
									
									
								
							@@ -1257,7 +1257,11 @@ int		 checkshell(const char *);
 | 
			
		||||
int		 areshell(const char *);
 | 
			
		||||
 | 
			
		||||
/* cfg.c */
 | 
			
		||||
int		 load_cfg(const char *, struct cmd_ctx *, char **);
 | 
			
		||||
extern int       cfg_finished;
 | 
			
		||||
extern char    **cfg_causes;
 | 
			
		||||
extern u_int     cfg_ncauses;
 | 
			
		||||
void printflike3 cfg_add_cause(u_int *, char ***, const char *, ...);
 | 
			
		||||
int		 load_cfg(const char *, struct cmd_ctx *, u_int *, char ***);
 | 
			
		||||
 | 
			
		||||
/* mode-key.c */
 | 
			
		||||
extern const struct mode_key_table mode_key_tables[];
 | 
			
		||||
@@ -1867,6 +1871,7 @@ void		 window_copy_pageup(struct window_pane *);
 | 
			
		||||
 | 
			
		||||
/* window-more.c */
 | 
			
		||||
extern const struct window_mode window_more_mode;
 | 
			
		||||
void		 window_more_add(struct window_pane *, const char *, ...);
 | 
			
		||||
void		 window_more_vadd(struct window_pane *, const char *, va_list);
 | 
			
		||||
 | 
			
		||||
/* window-choose.c */
 | 
			
		||||
 
 | 
			
		||||
@@ -52,6 +52,16 @@ struct window_more_mode_data {
 | 
			
		||||
	u_int			top;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_more_add(struct window_pane *wp, const char *fmt, ...)
 | 
			
		||||
{
 | 
			
		||||
	va_list	ap;
 | 
			
		||||
 | 
			
		||||
	va_start(ap, fmt);
 | 
			
		||||
	window_more_vadd(wp, fmt, ap);
 | 
			
		||||
	va_end(ap);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void
 | 
			
		||||
window_more_vadd(struct window_pane *wp, const char *fmt, va_list ap)
 | 
			
		||||
{
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user