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
= { "Fnqv", 1, -1, NULL
},
40 .usage
= "[-Fnqv] path ...",
43 .exec
= cmd_source_file_exec
46 struct cmd_source_file_data
{
47 struct cmdq_item
*item
;
50 struct cmdq_item
*after
;
51 enum cmd_retval retval
;
58 static enum cmd_retval
59 cmd_source_file_complete_cb(struct cmdq_item
*item
, __unused
void *data
)
61 cfg_print_causes(item
);
62 return (CMD_RETURN_NORMAL
);
66 cmd_source_file_complete(struct client
*c
, struct cmd_source_file_data
*cdata
)
68 struct cmdq_item
*new_item
;
72 if (cdata
->retval
== CMD_RETURN_ERROR
&&
76 new_item
= cmdq_get_callback(cmd_source_file_complete_cb
, NULL
);
77 cmdq_insert_after(cdata
->after
, new_item
);
80 for (i
= 0; i
< cdata
->nfiles
; i
++)
81 free(cdata
->files
[i
]);
87 cmd_source_file_done(struct client
*c
, const char *path
, int error
,
88 int closed
, struct evbuffer
*buffer
, void *data
)
90 struct cmd_source_file_data
*cdata
= data
;
91 struct cmdq_item
*item
= cdata
->item
;
92 void *bdata
= EVBUFFER_DATA(buffer
);
93 size_t bsize
= EVBUFFER_LENGTH(buffer
);
95 struct cmdq_item
*new_item
;
101 cmdq_error(item
, "%s: %s", path
, strerror(error
));
102 else if (bsize
!= 0) {
103 if (load_cfg_from_buffer(bdata
, bsize
, path
, c
, cdata
->after
,
104 cdata
->flags
, &new_item
) < 0)
105 cdata
->retval
= CMD_RETURN_ERROR
;
106 else if (new_item
!= NULL
)
107 cdata
->after
= new_item
;
110 n
= ++cdata
->current
;
111 if (n
< cdata
->nfiles
)
112 file_read(c
, cdata
->files
[n
], cmd_source_file_done
, cdata
);
114 cmd_source_file_complete(c
, cdata
);
120 cmd_source_file_add(struct cmd_source_file_data
*cdata
, const char *path
)
122 log_debug("%s: %s", __func__
, path
);
123 cdata
->files
= xreallocarray(cdata
->files
, cdata
->nfiles
+ 1,
124 sizeof *cdata
->files
);
125 cdata
->files
[cdata
->nfiles
++] = xstrdup(path
);
128 static enum cmd_retval
129 cmd_source_file_exec(struct cmd
*self
, struct cmdq_item
*item
)
131 struct args
*args
= cmd_get_args(self
);
132 struct cmd_source_file_data
*cdata
;
133 struct client
*c
= cmdq_get_client(item
);
134 enum cmd_retval retval
= CMD_RETURN_NORMAL
;
135 char *pattern
, *cwd
, *expanded
= NULL
;
136 const char *path
, *error
;
141 cdata
= xcalloc(1, sizeof *cdata
);
144 if (args_has(args
, 'q'))
145 cdata
->flags
|= CMD_PARSE_QUIET
;
146 if (args_has(args
, 'n'))
147 cdata
->flags
|= CMD_PARSE_PARSEONLY
;
148 if (args_has(args
, 'v'))
149 cdata
->flags
|= CMD_PARSE_VERBOSE
;
151 utf8_stravis(&cwd
, server_client_get_cwd(c
, NULL
), VIS_GLOB
);
153 for (i
= 0; i
< args_count(args
); i
++) {
154 path
= args_string(args
, i
);
155 if (args_has(args
, 'F')) {
157 expanded
= format_single_from_target(item
, path
);
160 if (strcmp(path
, "-") == 0) {
161 cmd_source_file_add(cdata
, "-");
166 pattern
= xstrdup(path
);
168 xasprintf(&pattern
, "%s/%s", cwd
, path
);
169 log_debug("%s: %s", __func__
, pattern
);
171 if ((result
= glob(pattern
, 0, NULL
, &g
)) != 0) {
172 if (result
!= GLOB_NOMATCH
||
173 (~cdata
->flags
& CMD_PARSE_QUIET
)) {
174 if (result
== GLOB_NOMATCH
)
175 error
= strerror(ENOENT
);
176 else if (result
== GLOB_NOSPACE
)
177 error
= strerror(ENOMEM
);
179 error
= strerror(EINVAL
);
180 cmdq_error(item
, "%s: %s", path
, error
);
181 retval
= CMD_RETURN_ERROR
;
189 for (j
= 0; j
< g
.gl_pathc
; j
++)
190 cmd_source_file_add(cdata
, g
.gl_pathv
[j
]);
196 cdata
->retval
= retval
;
198 if (cdata
->nfiles
!= 0) {
199 file_read(c
, cdata
->files
[0], cmd_source_file_done
, cdata
);
200 retval
= CMD_RETURN_WAIT
;
202 cmd_source_file_complete(c
, cdata
);