Annotation of src/usr.bin/tmux/cfg.c, Revision 1.31
1.31 ! nicm 1: /* $OpenBSD: cfg.c,v 1.30 2013/10/20 17:28:43 nicm Exp $ */
1.1 nicm 2:
3: /*
4: * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
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.21 nicm 21: #include <ctype.h>
1.1 nicm 22: #include <errno.h>
23: #include <stdio.h>
1.15 nicm 24: #include <stdlib.h>
1.1 nicm 25: #include <string.h>
26:
27: #include "tmux.h"
28:
1.28 nicm 29: struct cmd_q *cfg_cmd_q;
1.18 nicm 30: int cfg_finished;
1.28 nicm 31: int cfg_references;
1.18 nicm 32: struct causelist cfg_causes;
1.30 nicm 33: struct client *cfg_client;
1.1 nicm 34:
1.28 nicm 35: int
36: load_cfg(const char *path, struct cmd_q *cmdq, char **cause)
1.1 nicm 37: {
1.7 deraadt 38: FILE *f;
1.28 nicm 39: u_int n, found;
40: char *buf, *copy, *line, *cause1, *msg;
1.21 nicm 41: size_t len, oldlen;
1.1 nicm 42: struct cmd_list *cmdlist;
43:
1.29 nicm 44: log_debug("loading %s", path);
1.1 nicm 45: if ((f = fopen(path, "rb")) == NULL) {
1.28 nicm 46: xasprintf(cause, "%s: %s", path, strerror(errno));
47: return (-1);
1.25 nicm 48: }
49:
1.28 nicm 50: n = found = 0;
1.1 nicm 51: line = NULL;
52: while ((buf = fgetln(f, &len))) {
1.21 nicm 53: /* Trim \n. */
1.1 nicm 54: if (buf[len - 1] == '\n')
1.13 nicm 55: len--;
1.24 nicm 56: log_debug("%s: %.*s", path, (int)len, buf);
1.13 nicm 57:
1.20 nicm 58: /* Current line is the continuation of the previous one. */
59: if (line != NULL) {
1.21 nicm 60: oldlen = strlen(line);
61: line = xrealloc(line, 1, oldlen + len + 1);
1.20 nicm 62: } else {
1.21 nicm 63: oldlen = 0;
64: line = xmalloc(len + 1);
1.1 nicm 65: }
1.13 nicm 66:
1.20 nicm 67: /* Append current line to the previous. */
1.21 nicm 68: memcpy(line + oldlen, buf, len);
69: line[oldlen + len] = '\0';
1.1 nicm 70: n++;
71:
1.13 nicm 72: /* Continuation: get next line? */
73: len = strlen(line);
74: if (len > 0 && line[len - 1] == '\\') {
75: line[len - 1] = '\0';
1.20 nicm 76:
1.14 nicm 77: /* Ignore escaped backslash at EOL. */
78: if (len > 1 && line[len - 2] != '\\')
79: continue;
1.13 nicm 80: }
1.21 nicm 81: copy = line;
1.13 nicm 82: line = NULL;
83:
1.21 nicm 84: /* Skip empty lines. */
85: buf = copy;
86: while (isspace((u_char)*buf))
87: buf++;
1.22 nicm 88: if (*buf == '\0') {
89: free(copy);
1.21 nicm 90: continue;
1.22 nicm 91: }
1.21 nicm 92:
1.28 nicm 93: /* Parse and run the command. */
94: if (cmd_string_parse(buf, &cmdlist, path, n, &cause1) != 0) {
1.21 nicm 95: free(copy);
1.28 nicm 96: if (cause1 == NULL)
1.1 nicm 97: continue;
1.28 nicm 98: xasprintf(&msg, "%s:%u: %s", path, n, cause1);
99: ARRAY_ADD(&cfg_causes, msg);
100: free(cause1);
1.9 nicm 101: continue;
1.20 nicm 102: }
1.21 nicm 103: free(copy);
1.28 nicm 104:
1.1 nicm 105: if (cmdlist == NULL)
106: continue;
1.28 nicm 107: cmdq_append(cmdq, cmdlist);
1.1 nicm 108: cmd_list_free(cmdlist);
1.28 nicm 109: found++;
1.1 nicm 110: }
1.28 nicm 111: if (line != NULL)
1.15 nicm 112: free(line);
1.1 nicm 113: fclose(f);
1.25 nicm 114:
1.28 nicm 115: return (found);
116: }
117:
118: void
119: cfg_default_done(unused struct cmd_q *cmdq)
120: {
121: if (--cfg_references != 0)
122: return;
123: cfg_finished = 1;
1.18 nicm 124:
1.28 nicm 125: if (!RB_EMPTY(&sessions))
126: cfg_show_causes(RB_MIN(sessions, &sessions));
1.1 nicm 127:
1.28 nicm 128: cmdq_free(cfg_cmd_q);
129: cfg_cmd_q = NULL;
1.30 nicm 130:
131: if (cfg_client != NULL) {
132: /*
133: * The client command queue starts with client_exit set to 1 so
134: * only continue if not empty (that is, we have been delayed
135: * during configuration parsing for long enough that the
136: * MSG_COMMAND has arrived), else the client will exit before
137: * the MSG_COMMAND which might tell it not to.
138: */
139: if (!TAILQ_EMPTY(&cfg_client->cmdq->queue))
140: cmdq_continue(cfg_client->cmdq);
141: cfg_client->references--;
142: cfg_client = NULL;
143: }
1.17 nicm 144: }
145:
146: void
1.28 nicm 147: cfg_show_causes(struct session *s)
1.17 nicm 148: {
149: struct window_pane *wp;
150: char *cause;
151: u_int i;
152:
153: if (s == NULL || ARRAY_EMPTY(&cfg_causes))
154: return;
155: wp = s->curw->window->active;
156:
157: window_pane_set_mode(wp, &window_copy_mode);
158: window_copy_init_for_output(wp);
159: for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
160: cause = ARRAY_ITEM(&cfg_causes, i);
161: window_copy_add(wp, "%s", cause);
162: free(cause);
163: }
164: ARRAY_FREE(&cfg_causes);
1.1 nicm 165: }