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.
pull/1/head
Nicholas Marriott 2010-02-06 17:15:33 +00:00
parent 5e6a7c85cc
commit 8aba77b7be
8 changed files with 112 additions and 61 deletions

57
cfg.c
View File

@ -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;
goto error;
cfg_add_cause(
ncauses, causes, "%s: %u: %s", path, n, cause);
xfree(cause);
continue;
}
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);
}

View File

@ -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 */
}

View File

@ -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);

View File

@ -113,10 +113,11 @@ server_create_socket(void)
int
server_start(char *path)
{
struct client *c;
int pair[2];
char *cause, rpathbuf[MAXPATHLEN];
struct timeval tv;
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
View File

@ -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
View File

@ -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 */

View File

@ -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)
{

View File

@ -657,9 +657,6 @@ window_pane_parse(struct window_pane *wp)
char *data;
size_t new_size;
if (wp->mode != NULL)
return;
new_size = EVBUFFER_LENGTH(wp->event->input) - wp->pipe_off;
if (wp->pipe_fd != -1 && new_size > 0) {
data = EVBUFFER_DATA(wp->event->input);