Annotation of src/usr.bin/tmux/cfg.c, Revision 1.17
1.17 ! nicm 1: /* $OpenBSD: cfg.c,v 1.16 2012/07/11 07:10:15 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: #include <sys/stat.h>
21:
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:
29: /*
30: * Config file parser. Pretty quick and simple, each line is parsed into a
31: * argv array and executed as a command.
32: */
33:
34: void printflike2 cfg_print(struct cmd_ctx *, const char *, ...);
35: void printflike2 cfg_error(struct cmd_ctx *, const char *, ...);
36:
1.10 nicm 37: char *cfg_cause;
38: int cfg_finished;
39: struct causelist cfg_causes = ARRAY_INITIALIZER;
1.1 nicm 40:
1.8 nicm 41: /* ARGSUSED */
1.1 nicm 42: void printflike2
43: cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...)
44: {
45: }
46:
1.8 nicm 47: /* ARGSUSED */
1.1 nicm 48: void printflike2
49: cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
50: {
51: va_list ap;
52:
53: va_start(ap, fmt);
54: xvasprintf(&cfg_cause, fmt, ap);
55: va_end(ap);
56: }
57:
1.10 nicm 58: void printflike2
59: cfg_add_cause(struct causelist *causes, const char *fmt, ...)
1.9 nicm 60: {
61: char *cause;
62: va_list ap;
63:
64: va_start(ap, fmt);
65: xvasprintf(&cause, fmt, ap);
66: va_end(ap);
67:
1.10 nicm 68: ARRAY_ADD(causes, cause);
1.9 nicm 69: }
70:
71: /*
72: * Load configuration file. Returns -1 for an error with a list of messages in
1.11 nicm 73: * causes. Note that causes must be initialised by the caller!
1.9 nicm 74: */
1.1 nicm 75: int
1.10 nicm 76: load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
1.1 nicm 77: {
1.7 deraadt 78: FILE *f;
1.1 nicm 79: u_int n;
1.9 nicm 80: char *buf, *line, *cause;
1.1 nicm 81: size_t len;
82: struct cmd_list *cmdlist;
83: struct cmd_ctx ctx;
1.16 nicm 84: enum cmd_retval retval;
1.1 nicm 85:
86: if ((f = fopen(path, "rb")) == NULL) {
1.10 nicm 87: cfg_add_cause(causes, "%s: %s", path, strerror(errno));
1.9 nicm 88: return (-1);
1.1 nicm 89: }
90: n = 0;
91:
92: line = NULL;
1.16 nicm 93: retval = CMD_RETURN_NORMAL;
1.1 nicm 94: while ((buf = fgetln(f, &len))) {
95: if (buf[len - 1] == '\n')
1.13 nicm 96: len--;
97:
98: if (line != NULL)
99: line = xrealloc(line, 1, strlen(line) + len + 1);
1.1 nicm 100: else {
1.13 nicm 101: line = xmalloc(len + 1);
102: *line = '\0';
1.1 nicm 103: }
1.13 nicm 104:
105: /* Append buffer to line. strncat will terminate. */
106: strncat(line, buf, len);
1.1 nicm 107: n++;
108:
1.13 nicm 109: /* Continuation: get next line? */
110: len = strlen(line);
111: if (len > 0 && line[len - 1] == '\\') {
112: line[len - 1] = '\0';
1.14 nicm 113: /* Ignore escaped backslash at EOL. */
114: if (len > 1 && line[len - 2] != '\\')
115: continue;
1.13 nicm 116: }
117: buf = line;
118: line = NULL;
119:
1.9 nicm 120: if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
1.15 nicm 121: free(buf);
1.9 nicm 122: if (cause == NULL)
1.1 nicm 123: continue;
1.10 nicm 124: cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
1.15 nicm 125: free(cause);
1.9 nicm 126: continue;
1.13 nicm 127: } else
1.15 nicm 128: free(buf);
1.1 nicm 129: if (cmdlist == NULL)
130: continue;
131: cfg_cause = NULL;
132:
1.6 nicm 133: if (ctxin == NULL) {
134: ctx.msgdata = NULL;
135: ctx.curclient = NULL;
136: ctx.cmdclient = NULL;
137: } else {
138: ctx.msgdata = ctxin->msgdata;
139: ctx.curclient = ctxin->curclient;
140: ctx.cmdclient = ctxin->cmdclient;
141: }
1.1 nicm 142:
143: ctx.error = cfg_error;
144: ctx.print = cfg_print;
145: ctx.info = cfg_print;
146:
147: cfg_cause = NULL;
1.16 nicm 148: switch (cmd_list_exec(cmdlist, &ctx)) {
149: case CMD_RETURN_YIELD:
150: if (retval != CMD_RETURN_ATTACH)
151: retval = CMD_RETURN_YIELD;
152: break;
153: case CMD_RETURN_ATTACH:
154: retval = CMD_RETURN_ATTACH;
155: break;
156: case CMD_RETURN_ERROR:
157: case CMD_RETURN_NORMAL:
158: break;
159: }
1.1 nicm 160: cmd_list_free(cmdlist);
161: if (cfg_cause != NULL) {
1.13 nicm 162: cfg_add_cause(
163: causes, "%s: %d: %s", path, n, cfg_cause);
1.15 nicm 164: free(cfg_cause);
1.1 nicm 165: }
166: }
1.13 nicm 167: if (line != NULL) {
168: cfg_add_cause(causes,
169: "%s: %d: line continuation at end of file", path, n);
1.15 nicm 170: free(line);
1.13 nicm 171: }
1.1 nicm 172: fclose(f);
173:
1.12 nicm 174: return (retval);
1.17 ! nicm 175: }
! 176:
! 177: void
! 178: show_cfg_causes(struct session *s)
! 179: {
! 180: struct window_pane *wp;
! 181: char *cause;
! 182: u_int i;
! 183:
! 184: if (s == NULL || ARRAY_EMPTY(&cfg_causes))
! 185: return;
! 186:
! 187: wp = s->curw->window->active;
! 188:
! 189: window_pane_set_mode(wp, &window_copy_mode);
! 190: window_copy_init_for_output(wp);
! 191: for (i = 0; i < ARRAY_LENGTH(&cfg_causes); i++) {
! 192: cause = ARRAY_ITEM(&cfg_causes, i);
! 193: window_copy_add(wp, "%s", cause);
! 194: free(cause);
! 195: }
! 196: ARRAY_FREE(&cfg_causes);
1.1 nicm 197: }