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 cfg_show_causes(NULL
);
58 cmdq_continue(cfg_item
);
60 status_prompt_load_history();
62 return (CMD_RETURN_NORMAL
);
72 * Configuration files are loaded without a client, so commands are run
73 * in the global queue with item->client NULL.
75 * However, we must block the initial client (but just the initial
76 * client) so that its command runs after the configuration is loaded.
77 * Because start_cfg() is called so early, we can be sure the client's
78 * command queue is currently empty and our callback will be at the
79 * front - we need to get in before MSG_COMMAND.
81 cfg_client
= c
= TAILQ_FIRST(&clients
);
83 cfg_item
= cmdq_get_callback(cfg_client_done
, NULL
);
84 cmdq_append(c
, cfg_item
);
87 for (i
= 0; i
< cfg_nfiles
; i
++) {
89 load_cfg(cfg_files
[i
], c
, NULL
, CMD_PARSE_QUIET
, NULL
);
91 load_cfg(cfg_files
[i
], c
, NULL
, 0, NULL
);
94 cmdq_append(NULL
, cmdq_get_callback(cfg_done
, NULL
));
98 load_cfg(const char *path
, struct client
*c
, struct cmdq_item
*item
, int flags
,
99 struct cmdq_item
**new_item
)
102 struct cmd_parse_input pi
;
103 struct cmd_parse_result
*pr
;
104 struct cmdq_item
*new_item0
;
105 struct cmdq_state
*state
;
107 if (new_item
!= NULL
)
110 log_debug("loading %s", path
);
111 if ((f
= fopen(path
, "rb")) == NULL
) {
112 if (errno
== ENOENT
&& (flags
& CMD_PARSE_QUIET
))
114 cfg_add_cause("%s: %s", path
, strerror(errno
));
118 memset(&pi
, 0, sizeof pi
);
125 pr
= cmd_parse_from_file(f
, &pi
);
127 if (pr
->status
== CMD_PARSE_ERROR
) {
128 cfg_add_cause("%s", pr
->error
);
132 if (flags
& CMD_PARSE_PARSEONLY
) {
133 cmd_list_free(pr
->cmdlist
);
138 state
= cmdq_copy_state(cmdq_get_state(item
));
140 state
= cmdq_new_state(NULL
, NULL
, 0);
141 cmdq_add_format(state
, "current_file", "%s", pi
.file
);
143 new_item0
= cmdq_get_command(pr
->cmdlist
, state
);
145 new_item0
= cmdq_insert_after(item
, new_item0
);
147 new_item0
= cmdq_append(NULL
, new_item0
);
148 cmd_list_free(pr
->cmdlist
);
149 cmdq_free_state(state
);
151 if (new_item
!= NULL
)
152 *new_item
= new_item0
;
157 load_cfg_from_buffer(const void *buf
, size_t len
, const char *path
,
158 struct client
*c
, struct cmdq_item
*item
, int flags
,
159 struct cmdq_item
**new_item
)
161 struct cmd_parse_input pi
;
162 struct cmd_parse_result
*pr
;
163 struct cmdq_item
*new_item0
;
164 struct cmdq_state
*state
;
166 if (new_item
!= NULL
)
169 log_debug("loading %s", path
);
171 memset(&pi
, 0, sizeof pi
);
178 pr
= cmd_parse_from_buffer(buf
, len
, &pi
);
179 if (pr
->status
== CMD_PARSE_ERROR
) {
180 cfg_add_cause("%s", pr
->error
);
184 if (flags
& CMD_PARSE_PARSEONLY
) {
185 cmd_list_free(pr
->cmdlist
);
190 state
= cmdq_copy_state(cmdq_get_state(item
));
192 state
= cmdq_new_state(NULL
, NULL
, 0);
193 cmdq_add_format(state
, "current_file", "%s", pi
.file
);
195 new_item0
= cmdq_get_command(pr
->cmdlist
, state
);
197 new_item0
= cmdq_insert_after(item
, new_item0
);
199 new_item0
= cmdq_append(NULL
, new_item0
);
200 cmd_list_free(pr
->cmdlist
);
201 cmdq_free_state(state
);
203 if (new_item
!= NULL
)
204 *new_item
= new_item0
;
209 cfg_add_cause(const char *fmt
, ...)
215 xvasprintf(&msg
, fmt
, ap
);
219 cfg_causes
= xreallocarray(cfg_causes
, cfg_ncauses
, sizeof *cfg_causes
);
220 cfg_causes
[cfg_ncauses
- 1] = msg
;
224 cfg_print_causes(struct cmdq_item
*item
)
228 for (i
= 0; i
< cfg_ncauses
; i
++) {
229 cmdq_print(item
, "%s", cfg_causes
[i
]);
239 cfg_show_causes(struct session
*s
)
241 struct client
*c
= TAILQ_FIRST(&clients
);
242 struct window_pane
*wp
;
243 struct window_mode_entry
*wme
;
246 if (cfg_ncauses
== 0)
249 if (c
!= NULL
&& (c
->flags
& CLIENT_CONTROL
)) {
250 for (i
= 0; i
< cfg_ncauses
; i
++) {
251 control_write(c
, "%%config-error %s", cfg_causes
[i
]);
258 if (c
!= NULL
&& c
->session
!= NULL
)
261 s
= RB_MIN(sessions
, &sessions
);
263 if (s
== NULL
|| s
->attached
== 0) /* wait for an attached session */
265 wp
= s
->curw
->window
->active
;
267 wme
= TAILQ_FIRST(&wp
->modes
);
268 if (wme
== NULL
|| wme
->mode
!= &window_view_mode
)
269 window_pane_set_mode(wp
, NULL
, &window_view_mode
, NULL
, NULL
);
270 for (i
= 0; i
< cfg_ncauses
; i
++) {
271 window_copy_add(wp
, 0, "%s", cfg_causes
[i
]);