xref: /minix/external/bsd/tmux/dist/cfg.c (revision e3b78ef1)
1 /* $Id: cfg.c,v 1.1.1.2 2011/08/17 18:40:04 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 	int		 retval;
84 
85 	if ((f = fopen(path, "rb")) == NULL) {
86 		cfg_add_cause(causes, "%s: %s", path, strerror(errno));
87 		return (-1);
88 	}
89 	n = 0;
90 
91 	line = NULL;
92 	retval = 0;
93 	while ((buf = fgetln(f, &len))) {
94 		if (buf[len - 1] == '\n')
95 			buf[len - 1] = '\0';
96 		else {
97 			line = xrealloc(line, 1, len + 1);
98 			memcpy(line, buf, len);
99 			line[len] = '\0';
100 			buf = line;
101 		}
102 		n++;
103 
104 		if (cmd_string_parse(buf, &cmdlist, &cause) != 0) {
105 			if (cause == NULL)
106 				continue;
107 			cfg_add_cause(causes, "%s: %u: %s", path, n, cause);
108 			xfree(cause);
109 			continue;
110 		}
111 		if (cmdlist == NULL)
112 			continue;
113 		cfg_cause = NULL;
114 
115 		if (ctxin == NULL) {
116 			ctx.msgdata = NULL;
117 			ctx.curclient = NULL;
118 			ctx.cmdclient = NULL;
119 		} else {
120 			ctx.msgdata = ctxin->msgdata;
121 			ctx.curclient = ctxin->curclient;
122 			ctx.cmdclient = ctxin->cmdclient;
123 		}
124 
125 		ctx.error = cfg_error;
126 		ctx.print = cfg_print;
127 		ctx.info = cfg_print;
128 
129 		cfg_cause = NULL;
130 		if (cmd_list_exec(cmdlist, &ctx) == 1)
131 			retval = 1;
132 		cmd_list_free(cmdlist);
133 		if (cfg_cause != NULL) {
134 			cfg_add_cause(causes, "%s: %d: %s", path, n, cfg_cause);
135 			xfree(cfg_cause);
136 		}
137 	}
138 	if (line != NULL)
139 		xfree(line);
140 	fclose(f);
141 
142 	return (retval);
143 }
144