xref: /openbsd-src/usr.bin/tmux/cfg.c (revision 43003dfe3ad45d1698bed8a37f2b0f5b14f20d4f)
1 /* $OpenBSD: cfg.c,v 1.6 2009/08/23 17:29:51 nicm 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 
38 void printflike2
39 cfg_print(unused struct cmd_ctx *ctx, unused const char *fmt, ...)
40 {
41 }
42 
43 void printflike2
44 cfg_error(unused struct cmd_ctx *ctx, const char *fmt, ...)
45 {
46 	va_list	ap;
47 
48 	va_start(ap, fmt);
49 	xvasprintf(&cfg_cause, fmt, ap);
50 	va_end(ap);
51 }
52 
53 int
54 load_cfg(const char *path, struct cmd_ctx *ctxin, char **cause)
55 {
56 	FILE   	        *f;
57 	u_int		 n;
58 	char	        *buf, *line, *ptr;
59 	size_t		 len;
60 	struct cmd_list	*cmdlist;
61 	struct cmd_ctx	 ctx;
62 
63 	if ((f = fopen(path, "rb")) == NULL) {
64 		xasprintf(cause, "%s: %s", path, strerror(errno));
65 		return (1);
66 	}
67 	n = 0;
68 
69 	line = NULL;
70 	while ((buf = fgetln(f, &len))) {
71 		if (buf[len - 1] == '\n')
72 			buf[len - 1] = '\0';
73 		else {
74 			line = xrealloc(line, 1, len + 1);
75 			memcpy(line, buf, len);
76 			line[len] = '\0';
77 			buf = line;
78 		}
79 		n++;
80 
81 		if (cmd_string_parse(buf, &cmdlist, cause) != 0) {
82 			if (*cause == NULL)
83 				continue;
84 			goto error;
85 		}
86 		if (cmdlist == NULL)
87 			continue;
88 		cfg_cause = NULL;
89 
90 		if (ctxin == NULL) {
91 			ctx.msgdata = NULL;
92 			ctx.curclient = NULL;
93 			ctx.cmdclient = NULL;
94 		} else {
95 			ctx.msgdata = ctxin->msgdata;
96 			ctx.curclient = ctxin->curclient;
97 			ctx.cmdclient = ctxin->cmdclient;
98 		}
99 
100 		ctx.error = cfg_error;
101 		ctx.print = cfg_print;
102 		ctx.info = cfg_print;
103 
104 		cfg_cause = NULL;
105 		cmd_list_exec(cmdlist, &ctx);
106 		cmd_list_free(cmdlist);
107 		if (cfg_cause != NULL) {
108 			*cause = cfg_cause;
109 			goto error;
110 		}
111 	}
112 	if (line != NULL)
113 		xfree(line);
114 	fclose(f);
115 
116 	return (0);
117 
118 error:
119 	if (line != NULL)
120 		xfree(line);
121 	fclose(f);
122 
123 	xasprintf(&ptr, "%s: %s at line %u", path, *cause, n);
124 	xfree(*cause);
125 	*cause = ptr;
126 	return (1);
127 }
128