4 * Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
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 * Sources a configuration file.
33 static enum cmd_retval
cmd_source_file_exec(struct cmd
*, struct cmdq_item
*);
35 const struct cmd_entry cmd_source_file_entry
= {
36 .name
= "source-file",
39 .args
= { "t:Fnqv", 1, -1, NULL
},
40 .usage
= "[-Fnqv] " CMD_TARGET_PANE_USAGE
" path ...",
42 .target
= { 't', CMD_FIND_PANE
, CMD_FIND_CANFAIL
},
45 .exec
= cmd_source_file_exec
48 struct cmd_source_file_data
{
49 struct cmdq_item
*item
;
52 struct cmdq_item
*after
;
53 enum cmd_retval retval
;
60 static enum cmd_retval
61 cmd_source_file_complete_cb(struct cmdq_item
*item
, __unused
void *data
)
63 cfg_print_causes(item
);
64 return (CMD_RETURN_NORMAL
);
68 cmd_source_file_complete(struct client
*c
, struct cmd_source_file_data
*cdata
)
70 struct cmdq_item
*new_item
;
74 if (cdata
->retval
== CMD_RETURN_ERROR
&&
78 new_item
= cmdq_get_callback(cmd_source_file_complete_cb
, NULL
);
79 cmdq_insert_after(cdata
->after
, new_item
);
82 for (i
= 0; i
< cdata
->nfiles
; i
++)
83 free(cdata
->files
[i
]);
89 cmd_source_file_done(struct client
*c
, const char *path
, int error
,
90 int closed
, struct evbuffer
*buffer
, void *data
)
92 struct cmd_source_file_data
*cdata
= data
;
93 struct cmdq_item
*item
= cdata
->item
;
94 void *bdata
= EVBUFFER_DATA(buffer
);
95 size_t bsize
= EVBUFFER_LENGTH(buffer
);
97 struct cmdq_item
*new_item
;
98 struct cmd_find_state
*target
= cmdq_get_target(item
);
104 cmdq_error(item
, "%s: %s", path
, strerror(error
));
105 else if (bsize
!= 0) {
106 if (load_cfg_from_buffer(bdata
, bsize
, path
, c
, cdata
->after
,
107 target
, cdata
->flags
, &new_item
) < 0)
108 cdata
->retval
= CMD_RETURN_ERROR
;
109 else if (new_item
!= NULL
)
110 cdata
->after
= new_item
;
113 n
= ++cdata
->current
;
114 if (n
< cdata
->nfiles
)
115 file_read(c
, cdata
->files
[n
], cmd_source_file_done
, cdata
);
117 cmd_source_file_complete(c
, cdata
);
123 cmd_source_file_add(struct cmd_source_file_data
*cdata
, const char *path
)
125 log_debug("%s: %s", __func__
, path
);
126 cdata
->files
= xreallocarray(cdata
->files
, cdata
->nfiles
+ 1,
127 sizeof *cdata
->files
);
128 cdata
->files
[cdata
->nfiles
++] = xstrdup(path
);
131 static enum cmd_retval
132 cmd_source_file_exec(struct cmd
*self
, struct cmdq_item
*item
)
134 struct args
*args
= cmd_get_args(self
);
135 struct cmd_source_file_data
*cdata
;
136 struct client
*c
= cmdq_get_client(item
);
137 enum cmd_retval retval
= CMD_RETURN_NORMAL
;
138 char *pattern
, *cwd
, *expanded
= NULL
;
139 const char *path
, *error
;
144 cdata
= xcalloc(1, sizeof *cdata
);
147 if (args_has(args
, 'q'))
148 cdata
->flags
|= CMD_PARSE_QUIET
;
149 if (args_has(args
, 'n'))
150 cdata
->flags
|= CMD_PARSE_PARSEONLY
;
151 if (args_has(args
, 'v'))
152 cdata
->flags
|= CMD_PARSE_VERBOSE
;
154 utf8_stravis(&cwd
, server_client_get_cwd(c
, NULL
), VIS_GLOB
);
156 for (i
= 0; i
< args_count(args
); i
++) {
157 path
= args_string(args
, i
);
158 if (args_has(args
, 'F')) {
160 expanded
= format_single_from_target(item
, path
);
163 if (strcmp(path
, "-") == 0) {
164 cmd_source_file_add(cdata
, "-");
169 pattern
= xstrdup(path
);
171 xasprintf(&pattern
, "%s/%s", cwd
, path
);
172 log_debug("%s: %s", __func__
, pattern
);
174 if ((result
= glob(pattern
, 0, NULL
, &g
)) != 0) {
175 if (result
!= GLOB_NOMATCH
||
176 (~cdata
->flags
& CMD_PARSE_QUIET
)) {
177 if (result
== GLOB_NOMATCH
)
178 error
= strerror(ENOENT
);
179 else if (result
== GLOB_NOSPACE
)
180 error
= strerror(ENOMEM
);
182 error
= strerror(EINVAL
);
183 cmdq_error(item
, "%s: %s", path
, error
);
184 retval
= CMD_RETURN_ERROR
;
192 for (j
= 0; j
< g
.gl_pathc
; j
++)
193 cmd_source_file_add(cdata
, g
.gl_pathv
[j
]);
199 cdata
->retval
= retval
;
201 if (cdata
->nfiles
!= 0) {
202 file_read(c
, cdata
->files
[0], cmd_source_file_done
, cdata
);
203 retval
= CMD_RETURN_WAIT
;
205 cmd_source_file_complete(c
, cdata
);