xref: /netbsd-src/external/bsd/tmux/dist/cfg.c (revision 1b9578b8c2c1f848eeb16dabbfd7d1f0d9fdefbd)
1 /* $Id: cfg.c,v 1.1.1.1 2011/03/10 09:15:36 jmmv Exp $ */
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>
24 #include <string.h>
25 
26 #include "tmux.h"
27 
28 /*
29  * Config file parser. Pretty quick and simple, each line is parsed into a
30  * argv array and executed as a command.
31  */
32 
33 void printflike2 cfg_print(struct cmd_ctx *, const char *, ...);
34 void printflike2 cfg_error(struct cmd_ctx *, const char *, ...);
35 
36 char	 	       *cfg_cause;
37 int     	 	cfg_finished;
38 struct causelist	cfg_causes = ARRAY_INITIALIZER;
39 
40 /* ARGSUSED */
41 void printflike2
42 cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...)
43 {
44 }
45 
46 /* ARGSUSED */
47 void printflike2
48 cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
49 {
50 	va_list	ap;
51 
52 	va_start(ap, fmt);
53 	xvasprintf(&cfg_cause, fmt, ap);
54 	va_end(ap);
55 }
56 
57 void printflike2
58 cfg_add_cause(struct causelist *causes, const char *fmt, ...)
59 {
60 	char	*cause;
61 	va_list	 ap;
62 
63 	va_start(ap, fmt);
64 	xvasprintf(&cause, fmt, ap);
65 	va_end(ap);
66 
67 	ARRAY_ADD(causes, cause);
68 }
69 
70 /*
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!
73  */
74 int
75 load_cfg(const char *path, struct cmd_ctx *ctxin, struct causelist *causes)
76 {
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 
84 	if ((f = fopen(path, "rb")) == NULL) {
85 		cfg_add_cause(causes, "%s: %s", path, strerror(errno));
86 		return (-1);
87 	}
88 	n = 0;
89 
90 	line = NULL;
91 	while ((buf = fgetln(f, &len))) {
92 		if (buf[len - 1] == '\n')
93 			buf[len - 1] = '\0';
94 		else {
95 			line = xrealloc(line, 1, len + 1);
96 			memcpy(line, buf, len);
97 			line[len] = '\0';
98 			buf = line;
99 		}
100 		n++;
101 
102 		if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
103 			if (cause == NULL)
104 				continue;
105 			cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
106 			xfree(cause);
107 			continue;
108 		}
109 		if (cmdlist == NULL)
110 			continue;
111 		cfg_cause = NULL;
112 
113 		if (ctxin == NULL) {
114 			ctx.msgdata = NULL;
115 			ctx.curclient = NULL;
116 			ctx.cmdclient = NULL;
117 		} else {
118 			ctx.msgdata = ctxin->msgdata;
119 			ctx.curclient = ctxin->curclient;
120 			ctx.cmdclient = ctxin->cmdclient;
121 		}
122 
123 		ctx.error = cfg_error;
124 		ctx.print = cfg_print;
125 		ctx.info = cfg_print;
126 
127 		cfg_cause = NULL;
128 		cmd_list_exec(cmdlist, &ctx);
129 		cmd_list_free(cmdlist);
130 		if (cfg_cause != NULL) {
131 			cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause);
132 			xfree(cfg_cause);
133 			continue;
134 		}
135 	}
136 	if (line != NULL)
137 		xfree(line);
138 	fclose(f);
139 
140 	if (ARRAY_LENGTH(causes) != 0)
141 		return (-1);
142 	return (0);
143 }
144