Annotation of src/usr.bin/tmux/cmd-source-file.c, Revision 1.54
1.54 ! nicm 1: /* $OpenBSD: cmd-source-file.c,v 1.53 2021/08/23 11:04:21 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2008 Tiago Cunha <me@tiagocunha.org>
5: *
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.
9: *
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.
17: */
18:
19: #include <sys/types.h>
20:
1.31 nicm 21: #include <errno.h>
22: #include <glob.h>
1.12 nicm 23: #include <stdlib.h>
1.31 nicm 24: #include <string.h>
1.34 nicm 25: #include <vis.h>
1.12 nicm 26:
1.1 nicm 27: #include "tmux.h"
28:
29: /*
30: * Sources a configuration file.
31: */
32:
1.30 nicm 33: static enum cmd_retval cmd_source_file_exec(struct cmd *, struct cmdq_item *);
1.15 nicm 34:
1.1 nicm 35: const struct cmd_entry cmd_source_file_entry = {
1.23 nicm 36: .name = "source-file",
37: .alias = "source",
38:
1.54 ! nicm 39: .args = { "t:Fnqv", 1, -1, NULL },
! 40: .usage = "[-Fnqv] " CMD_TARGET_PANE_USAGE " path ...",
! 41:
! 42: .target = { 't', CMD_FIND_PANE, CMD_FIND_CANFAIL },
1.23 nicm 43:
44: .flags = 0,
45: .exec = cmd_source_file_exec
1.1 nicm 46: };
47:
1.42 nicm 48: struct cmd_source_file_data {
49: struct cmdq_item *item;
50: int flags;
51:
52: struct cmdq_item *after;
53: enum cmd_retval retval;
54:
55: u_int current;
56: char **files;
57: u_int nfiles;
58: };
59:
60: static enum cmd_retval
61: cmd_source_file_complete_cb(struct cmdq_item *item, __unused void *data)
62: {
63: cfg_print_causes(item);
64: return (CMD_RETURN_NORMAL);
65: }
66:
67: static void
68: cmd_source_file_complete(struct client *c, struct cmd_source_file_data *cdata)
69: {
70: struct cmdq_item *new_item;
1.53 nicm 71: u_int i;
1.42 nicm 72:
73: if (cfg_finished) {
1.49 nicm 74: if (cdata->retval == CMD_RETURN_ERROR &&
75: c != NULL &&
76: c->session == NULL)
1.42 nicm 77: c->retval = 1;
78: new_item = cmdq_get_callback(cmd_source_file_complete_cb, NULL);
79: cmdq_insert_after(cdata->after, new_item);
80: }
81:
1.53 nicm 82: for (i = 0; i < cdata->nfiles; i++)
83: free(cdata->files[i]);
1.42 nicm 84: free(cdata->files);
85: free(cdata);
86: }
87:
88: static void
89: cmd_source_file_done(struct client *c, const char *path, int error,
90: int closed, struct evbuffer *buffer, void *data)
91: {
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);
96: u_int n;
97: struct cmdq_item *new_item;
1.54 ! nicm 98: struct cmd_find_state *target = cmdq_get_target(item);
1.42 nicm 99:
100: if (!closed)
101: return;
102:
103: if (error != 0)
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,
1.54 ! nicm 107: target, cdata->flags, &new_item) < 0)
1.42 nicm 108: cdata->retval = CMD_RETURN_ERROR;
109: else if (new_item != NULL)
110: cdata->after = new_item;
111: }
112:
113: n = ++cdata->current;
114: if (n < cdata->nfiles)
115: file_read(c, cdata->files[n], cmd_source_file_done, cdata);
116: else {
117: cmd_source_file_complete(c, cdata);
118: cmdq_continue(item);
119: }
120: }
121:
122: static void
123: cmd_source_file_add(struct cmd_source_file_data *cdata, const char *path)
124: {
1.44 nicm 125: log_debug("%s: %s", __func__, path);
1.42 nicm 126: cdata->files = xreallocarray(cdata->files, cdata->nfiles + 1,
127: sizeof *cdata->files);
128: cdata->files[cdata->nfiles++] = xstrdup(path);
129: }
130:
1.26 nicm 131: static enum cmd_retval
1.30 nicm 132: cmd_source_file_exec(struct cmd *self, struct cmdq_item *item)
1.15 nicm 133: {
1.46 nicm 134: struct args *args = cmd_get_args(self);
1.42 nicm 135: struct cmd_source_file_data *cdata;
1.47 nicm 136: struct client *c = cmdq_get_client(item);
1.42 nicm 137: enum cmd_retval retval = CMD_RETURN_NORMAL;
1.50 nicm 138: char *pattern, *cwd, *expanded = NULL;
1.42 nicm 139: const char *path, *error;
140: glob_t g;
1.50 nicm 141: int result;
142: u_int i, j;
1.42 nicm 143:
144: cdata = xcalloc(1, sizeof *cdata);
145: cdata->item = item;
1.15 nicm 146:
1.37 nicm 147: if (args_has(args, 'q'))
1.42 nicm 148: cdata->flags |= CMD_PARSE_QUIET;
1.38 nicm 149: if (args_has(args, 'n'))
1.42 nicm 150: cdata->flags |= CMD_PARSE_PARSEONLY;
1.41 nicm 151: if (args_has(args, 'v'))
1.42 nicm 152: cdata->flags |= CMD_PARSE_VERBOSE;
153:
1.39 nicm 154: utf8_stravis(&cwd, server_client_get_cwd(c, NULL), VIS_GLOB);
1.31 nicm 155:
1.50 nicm 156: for (i = 0; i < args_count(args); i++) {
157: path = args_string(args, i);
1.48 nicm 158: if (args_has(args, 'F')) {
1.50 nicm 159: free(expanded);
160: expanded = format_single_from_target(item, path);
161: path = expanded;
162: }
1.42 nicm 163: if (strcmp(path, "-") == 0) {
164: cmd_source_file_add(cdata, "-");
165: continue;
166: }
167:
1.39 nicm 168: if (*path == '/')
169: pattern = xstrdup(path);
170: else
171: xasprintf(&pattern, "%s/%s", cwd, path);
172: log_debug("%s: %s", __func__, pattern);
173:
1.43 nicm 174: if ((result = glob(pattern, 0, NULL, &g)) != 0) {
175: if (result != GLOB_NOMATCH ||
1.45 tim 176: (~cdata->flags & CMD_PARSE_QUIET)) {
1.43 nicm 177: if (result == GLOB_NOMATCH)
178: error = strerror(ENOENT);
179: else if (result == GLOB_NOSPACE)
180: error = strerror(ENOMEM);
181: else
182: error = strerror(EINVAL);
1.39 nicm 183: cmdq_error(item, "%s: %s", path, error);
184: retval = CMD_RETURN_ERROR;
185: }
1.53 nicm 186: globfree(&g);
1.39 nicm 187: free(pattern);
188: continue;
1.34 nicm 189: }
190: free(pattern);
191:
1.42 nicm 192: for (j = 0; j < g.gl_pathc; j++)
193: cmd_source_file_add(cdata, g.gl_pathv[j]);
1.53 nicm 194: globfree(&g);
1.29 nicm 195: }
1.52 nicm 196: free(expanded);
1.42 nicm 197:
198: cdata->after = item;
199: cdata->retval = retval;
200:
201: if (cdata->nfiles != 0) {
202: file_read(c, cdata->files[0], cmd_source_file_done, cdata);
203: retval = CMD_RETURN_WAIT;
204: } else
205: cmd_source_file_complete(c, cdata);
1.31 nicm 206:
1.39 nicm 207: free(cwd);
1.31 nicm 208: return (retval);
1.1 nicm 209: }