Don't die if fail to get root directory, from Ben Boeckel.
[tmux-openbsd.git] / cfg.c
blobd49bfa6126ba56ed1c182b7458bc23e94bed062c
1 /* $OpenBSD$ */
3 /*
4 * Copyright (c) 2008 Nicholas Marriott <nicm@users.sourceforge.net>
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>
20 #include <sys/stat.h>
22 #include <errno.h>
23 #include <stdio.h>
24 #include <string.h>
26 #include "tmux.h"
29 * Config file parser. Pretty quick and simple, each line is parsed into a
30 * argv array and executed as a command.
33 void printflike2 cfg_print(struct cmd_ctx *, const char *, ...);
34 void printflike2 cfg_error(struct cmd_ctx *, const char *, ...);
36 char *cfg_cause;
37 int cfg_finished;
38 struct causelist cfg_causes = ARRAY_INITIALIZER;
40 /* ARGSUSED */
41 void printflike2
42 cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...)
46 /* ARGSUSED */
47 void printflike2
48 cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
50 va_list ap;
52 va_start(ap, fmt);
53 xvasprintf(&cfg_cause, fmt, ap);
54 va_end(ap);
57 void printflike2
58 cfg_add_cause(struct causelist *causes, const char *fmt, ...)
60 char *cause;
61 va_list ap;
63 va_start(ap, fmt);
64 xvasprintf(&cause, fmt, ap);
65 va_end(ap);
67 ARRAY_ADD(causes, cause);
71 * Load configuration file. Returns -1 for an error with a list of messages in
72 * causes. Note that causes must be initialised by the caller!
74 int
75 load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
77 FILE *f;
78 u_int n;
79 char *buf, *line, *cause;
80 size_t len;
81 struct cmd_list *cmdlist;
82 struct cmd_ctx ctx;
83 int retval;
85 if ((f = fopen(path, "rb")) == NULL) {
86 cfg_add_cause(causes, "%s: %s", path, strerror(errno));
87 return (-1);
89 n = 0;
91 line = NULL;
92 retval = 0;
93 while ((buf = fgetln(f, &len))) {
94 if (buf[len - 1] == '\n')
95 len--;
97 if (line != NULL)
98 line = xrealloc(line, 1, strlen(line) + len + 1);
99 else {
100 line = xmalloc(len + 1);
101 *line = '\0';
104 /* Append buffer to line. strncat will terminate. */
105 strncat(line, buf, len);
106 n++;
108 /* Continuation: get next line? */
109 len = strlen(line);
110 if (len > 0 && line[len - 1] == '\\') {
111 line[len - 1] = '\0';
112 continue;
114 buf = line;
115 line = NULL;
117 if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
118 xfree(buf);
119 if (cause == NULL)
120 continue;
121 cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
122 xfree(cause);
123 continue;
124 } else
125 xfree(buf);
126 if (cmdlist == NULL)
127 continue;
128 cfg_cause = NULL;
130 if (ctxin == NULL) {
131 ctx.msgdata = NULL;
132 ctx.curclient = NULL;
133 ctx.cmdclient = NULL;
134 } else {
135 ctx.msgdata = ctxin->msgdata;
136 ctx.curclient = ctxin->curclient;
137 ctx.cmdclient = ctxin->cmdclient;
140 ctx.error = cfg_error;
141 ctx.print = cfg_print;
142 ctx.info = cfg_print;
144 cfg_cause = NULL;
145 if (cmd_list_exec(cmdlist, &ctx) == 1)
146 retval = 1;
147 cmd_list_free(cmdlist);
148 if (cfg_cause != NULL) {
149 cfg_add_cause(
150 causes, "%s: %d: %s", path, n, cfg_cause);
151 xfree(cfg_cause);
154 if (line != NULL) {
155 cfg_add_cause(causes,
156 "%s: %d: line continuation at end of file", path, n);
157 xfree(line);
159 fclose(f);
161 return (retval);