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 char resolved
[PATH_MAX
];
127 if (realpath(path
, resolved
) == NULL
) {
128 log_debug("%s: realpath(\"%s\") failed: %s", __func__
,
129 path
, strerror(errno
));
133 log_debug("%s: %s", __func__
, path
);
134 cdata
->files
= xreallocarray(cdata
->files
, cdata
->nfiles
+ 1,
135 sizeof *cdata
->files
);
136 cdata
->files
[cdata
->nfiles
++] = xstrdup(path
);
139 static enum cmd_retval
140 cmd_source_file_exec(struct cmd
*self
, struct cmdq_item
*item
)
142 struct args
*args
= cmd_get_args(self
);
143 struct cmd_source_file_data
*cdata
;
144 struct client
*c
= cmdq_get_client(item
);
145 enum cmd_retval retval
= CMD_RETURN_NORMAL
;
146 char *pattern
, *cwd
, *expanded
= NULL
;
147 const char *path
, *error
;
152 cdata
= xcalloc(1, sizeof *cdata
);
155 if (args_has(args
, 'q'))
156 cdata
->flags
|= CMD_PARSE_QUIET
;
157 if (args_has(args
, 'n'))
158 cdata
->flags
|= CMD_PARSE_PARSEONLY
;
159 if (args_has(args
, 'v'))
160 cdata
->flags
|= CMD_PARSE_VERBOSE
;
162 utf8_stravis(&cwd
, server_client_get_cwd(c
, NULL
), VIS_GLOB
);
164 for (i
= 0; i
< args_count(args
); i
++) {
165 path
= args_string(args
, i
);
166 if (args_has(args
, 'F')) {
168 expanded
= format_single_from_target(item
, path
);
171 if (strcmp(path
, "-") == 0) {
172 cmd_source_file_add(cdata
, "-");
177 pattern
= xstrdup(path
);
179 xasprintf(&pattern
, "%s/%s", cwd
, path
);
180 log_debug("%s: %s", __func__
, pattern
);
182 if ((result
= glob(pattern
, 0, NULL
, &g
)) != 0) {
183 if (result
!= GLOB_NOMATCH
||
184 (~cdata
->flags
& CMD_PARSE_QUIET
)) {
185 if (result
== GLOB_NOMATCH
)
186 error
= strerror(ENOENT
);
187 else if (result
== GLOB_NOSPACE
)
188 error
= strerror(ENOMEM
);
190 error
= strerror(EINVAL
);
191 cmdq_error(item
, "%s: %s", path
, error
);
192 retval
= CMD_RETURN_ERROR
;
200 for (j
= 0; j
< g
.gl_pathc
; j
++)
201 cmd_source_file_add(cdata
, g
.gl_pathv
[j
]);
207 cdata
->retval
= retval
;
209 if (cdata
->nfiles
!= 0) {
210 file_read(c
, cdata
->files
[0], cmd_source_file_done
, cdata
);
211 retval
= CMD_RETURN_WAIT
;
213 cmd_source_file_complete(c
, cdata
);