4 * Copyright (c) 2008 Nicholas Marriott <nicholas.marriott@gmail.com>
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF MIND, USE, DATA OR PROFITS, WHETHER
15 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <sys/types.h>
30 struct client
*cfg_client
;
32 static char **cfg_causes
;
33 static u_int cfg_ncauses
;
34 static struct cmdq_item
*cfg_item
;
40 static enum cmd_retval
41 cfg_client_done(__unused
struct cmdq_item
*item
, __unused
void *data
)
44 return (CMD_RETURN_WAIT
);
45 return (CMD_RETURN_NORMAL
);
48 static enum cmd_retval
49 cfg_done(__unused
struct cmdq_item
*item
, __unused
void *data
)
52 return (CMD_RETURN_NORMAL
);
55 if (!RB_EMPTY(&sessions
))
56 cfg_show_causes(RB_MIN(sessions
, &sessions
));
59 cmdq_continue(cfg_item
);
61 status_prompt_load_history();
63 return (CMD_RETURN_NORMAL
);
73 * Configuration files are loaded without a client, so commands are run
74 * in the global queue with item->client NULL.
76 * However, we must block the initial client (but just the initial
77 * client) so that its command runs after the configuration is loaded.
78 * Because start_cfg() is called so early, we can be sure the client's
79 * command queue is currently empty and our callback will be at the
80 * front - we need to get in before MSG_COMMAND.
82 cfg_client
= c
= TAILQ_FIRST(&clients
);
84 cfg_item
= cmdq_get_callback(cfg_client_done
, NULL
);
85 cmdq_append(c
, cfg_item
);
88 for (i
= 0; i
< cfg_nfiles
; i
++) {
90 load_cfg(cfg_files
[i
], c
, NULL
, CMD_PARSE_QUIET
, NULL
);
92 load_cfg(cfg_files
[i
], c
, NULL
, 0, NULL
);
95 cmdq_append(NULL
, cmdq_get_callback(cfg_done
, NULL
));
99 load_cfg(const char *path
, struct client
*c
, struct cmdq_item
*item
, int flags
,
100 struct cmdq_item
**new_item
)
103 struct cmd_parse_input pi
;
104 struct cmd_parse_result
*pr
;
105 struct cmdq_item
*new_item0
;
106 struct cmdq_state
*state
;
108 if (new_item
!= NULL
)
111 log_debug("loading %s", path
);
112 if ((f
= fopen(path
, "rb")) == NULL
) {
113 if (errno
== ENOENT
&& (flags
& CMD_PARSE_QUIET
))
115 cfg_add_cause("%s: %s", path
, strerror(errno
));
119 memset(&pi
, 0, sizeof pi
);
126 pr
= cmd_parse_from_file(f
, &pi
);
128 if (pr
->status
== CMD_PARSE_ERROR
) {
129 cfg_add_cause("%s", pr
->error
);
133 if (flags
& CMD_PARSE_PARSEONLY
) {
134 cmd_list_free(pr
->cmdlist
);
139 state
= cmdq_copy_state(cmdq_get_state(item
));
141 state
= cmdq_new_state(NULL
, NULL
, 0);
142 cmdq_add_format(state
, "current_file", "%s", pi
.file
);
144 new_item0
= cmdq_get_command(pr
->cmdlist
, state
);
146 new_item0
= cmdq_insert_after(item
, new_item0
);
148 new_item0
= cmdq_append(NULL
, new_item0
);
149 cmd_list_free(pr
->cmdlist
);
150 cmdq_free_state(state
);
152 if (new_item
!= NULL
)
153 *new_item
= new_item0
;
158 load_cfg_from_buffer(const void *buf
, size_t len
, const char *path
,
159 struct client
*c
, struct cmdq_item
*item
, int flags
,
160 struct cmdq_item
**new_item
)
162 struct cmd_parse_input pi
;
163 struct cmd_parse_result
*pr
;
164 struct cmdq_item
*new_item0
;
165 struct cmdq_state
*state
;
167 if (new_item
!= NULL
)
170 log_debug("loading %s", path
);
172 memset(&pi
, 0, sizeof pi
);
179 pr
= cmd_parse_from_buffer(buf
, len
, &pi
);
180 if (pr
->status
== CMD_PARSE_ERROR
) {
181 cfg_add_cause("%s", pr
->error
);
185 if (flags
& CMD_PARSE_PARSEONLY
) {
186 cmd_list_free(pr
->cmdlist
);
191 state
= cmdq_copy_state(cmdq_get_state(item
));
193 state
= cmdq_new_state(NULL
, NULL
, 0);
194 cmdq_add_format(state
, "current_file", "%s", pi
.file
);
196 new_item0
= cmdq_get_command(pr
->cmdlist
, state
);
198 new_item0
= cmdq_insert_after(item
, new_item0
);
200 new_item0
= cmdq_append(NULL
, new_item0
);
201 cmd_list_free(pr
->cmdlist
);
202 cmdq_free_state(state
);
204 if (new_item
!= NULL
)
205 *new_item
= new_item0
;
210 cfg_add_cause(const char *fmt
, ...)
216 xvasprintf(&msg
, fmt
, ap
);
220 cfg_causes
= xreallocarray(cfg_causes
, cfg_ncauses
, sizeof *cfg_causes
);
221 cfg_causes
[cfg_ncauses
- 1] = msg
;
225 cfg_print_causes(struct cmdq_item
*item
)
229 for (i
= 0; i
< cfg_ncauses
; i
++) {
230 cmdq_print(item
, "%s", cfg_causes
[i
]);
240 cfg_show_causes(struct session
*s
)
242 struct window_pane
*wp
;
243 struct window_mode_entry
*wme
;
246 if (s
== NULL
|| cfg_ncauses
== 0)
248 wp
= s
->curw
->window
->active
;
250 wme
= TAILQ_FIRST(&wp
->modes
);
251 if (wme
== NULL
|| wme
->mode
!= &window_view_mode
)
252 window_pane_set_mode(wp
, NULL
, &window_view_mode
, NULL
, NULL
);
253 for (i
= 0; i
< cfg_ncauses
; i
++) {
254 window_copy_add(wp
, 0, "%s", cfg_causes
[i
]);