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>
29 * Sources a configuration file.
32 static enum cmd_retval
cmd_source_file_exec(struct cmd
*, struct cmdq_item
*);
34 const struct cmd_entry cmd_source_file_entry
= {
35 .name
= "source-file",
38 .args
= { "t:Fnqv", 1, -1, NULL
},
39 .usage
= "[-Fnqv] " CMD_TARGET_PANE_USAGE
" path ...",
41 .target
= { 't', CMD_FIND_PANE
, CMD_FIND_CANFAIL
},
44 .exec
= cmd_source_file_exec
47 struct cmd_source_file_data
{
48 struct cmdq_item
*item
;
51 struct cmdq_item
*after
;
52 enum cmd_retval retval
;
59 static enum cmd_retval
60 cmd_source_file_complete_cb(struct cmdq_item
*item
, __unused
void *data
)
62 cfg_print_causes(item
);
63 return (CMD_RETURN_NORMAL
);
67 cmd_source_file_complete(struct client
*c
, struct cmd_source_file_data
*cdata
)
69 struct cmdq_item
*new_item
;
73 if (cdata
->retval
== CMD_RETURN_ERROR
&&
77 new_item
= cmdq_get_callback(cmd_source_file_complete_cb
, NULL
);
78 cmdq_insert_after(cdata
->after
, new_item
);
81 for (i
= 0; i
< cdata
->nfiles
; i
++)
82 free(cdata
->files
[i
]);
88 cmd_source_file_done(struct client
*c
, const char *path
, int error
,
89 int closed
, struct evbuffer
*buffer
, void *data
)
91 struct cmd_source_file_data
*cdata
= data
;
92 struct cmdq_item
*item
= cdata
->item
;
93 void *bdata
= EVBUFFER_DATA(buffer
);
94 size_t bsize
= EVBUFFER_LENGTH(buffer
);
96 struct cmdq_item
*new_item
;
97 struct cmd_find_state
*target
= cmdq_get_target(item
);
103 cmdq_error(item
, "%s: %s", path
, strerror(error
));
104 else if (bsize
!= 0) {
105 if (load_cfg_from_buffer(bdata
, bsize
, path
, c
, cdata
->after
,
106 target
, cdata
->flags
, &new_item
) < 0)
107 cdata
->retval
= CMD_RETURN_ERROR
;
108 else if (new_item
!= NULL
)
109 cdata
->after
= new_item
;
112 n
= ++cdata
->current
;
113 if (n
< cdata
->nfiles
)
114 file_read(c
, cdata
->files
[n
], cmd_source_file_done
, cdata
);
116 cmd_source_file_complete(c
, cdata
);
122 cmd_source_file_add(struct cmd_source_file_data
*cdata
, const char *path
)
124 char resolved
[PATH_MAX
];
126 if (realpath(path
, resolved
) == NULL
) {
127 log_debug("%s: realpath(\"%s\") failed: %s", __func__
,
128 path
, strerror(errno
));
132 log_debug("%s: %s", __func__
, path
);
133 cdata
->files
= xreallocarray(cdata
->files
, cdata
->nfiles
+ 1,
134 sizeof *cdata
->files
);
135 cdata
->files
[cdata
->nfiles
++] = xstrdup(path
);
138 static enum cmd_retval
139 cmd_source_file_exec(struct cmd
*self
, struct cmdq_item
*item
)
141 struct args
*args
= cmd_get_args(self
);
142 struct cmd_source_file_data
*cdata
;
143 struct client
*c
= cmdq_get_client(item
);
144 enum cmd_retval retval
= CMD_RETURN_NORMAL
;
145 char *pattern
, *cwd
, *expanded
= NULL
;
146 const char *path
, *error
;
151 cdata
= xcalloc(1, sizeof *cdata
);
154 if (args_has(args
, 'q'))
155 cdata
->flags
|= CMD_PARSE_QUIET
;
156 if (args_has(args
, 'n'))
157 cdata
->flags
|= CMD_PARSE_PARSEONLY
;
158 if (args_has(args
, 'v'))
159 cdata
->flags
|= CMD_PARSE_VERBOSE
;
161 utf8_stravis(&cwd
, server_client_get_cwd(c
, NULL
), VIS_GLOB
);
163 for (i
= 0; i
< args_count(args
); i
++) {
164 path
= args_string(args
, i
);
165 if (args_has(args
, 'F')) {
167 expanded
= format_single_from_target(item
, path
);
170 if (strcmp(path
, "-") == 0) {
171 cmd_source_file_add(cdata
, "-");
176 pattern
= xstrdup(path
);
178 xasprintf(&pattern
, "%s/%s", cwd
, path
);
179 log_debug("%s: %s", __func__
, pattern
);
181 if ((result
= glob(pattern
, 0, NULL
, &g
)) != 0) {
182 if (result
!= GLOB_NOMATCH
||
183 (~cdata
->flags
& CMD_PARSE_QUIET
)) {
184 if (result
== GLOB_NOMATCH
)
185 error
= strerror(ENOENT
);
186 else if (result
== GLOB_NOSPACE
)
187 error
= strerror(ENOMEM
);
189 error
= strerror(EINVAL
);
190 cmdq_error(item
, "%s: %s", path
, error
);
191 retval
= CMD_RETURN_ERROR
;
199 for (j
= 0; j
< g
.gl_pathc
; j
++)
200 cmd_source_file_add(cdata
, g
.gl_pathv
[j
]);
206 cdata
->retval
= retval
;
208 if (cdata
->nfiles
!= 0) {
209 file_read(c
, cdata
->files
[0], cmd_source_file_done
, cdata
);
210 retval
= CMD_RETURN_WAIT
;
212 cmd_source_file_complete(c
, cdata
);