d37f973637697a56de96127b606d766b09933cc3
[metze/samba/wip.git] / ctdb / common / conf_tool.c
1 /*
2    Config options tool
3
4    Copyright (C) Amitay Isaacs  2018
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21
22 #include <talloc.h>
23
24 #include "lib/util/debug.h"
25
26 #include "common/logging.h"
27 #include "common/cmdline.h"
28 #include "common/conf.h"
29 #include "common/path.h"
30
31 #include "common/logging_conf.h"
32 #include "event/event_conf.h"
33
34 #include "common/conf_tool.h"
35
36 struct conf_tool_context {
37         struct cmdline_context *cmdline;
38         const char *conf_file;
39         struct conf_context *conf;
40 };
41
42 static int conf_tool_dump(TALLOC_CTX *mem_ctx,
43                           int argc,
44                           const char **argv,
45                           void *private_data)
46 {
47         struct conf_tool_context *ctx = talloc_get_type_abort(
48                 private_data, struct conf_tool_context);
49         int ret;
50
51         if (argc != 0) {
52                 cmdline_usage(ctx->cmdline, "dump");
53                 return EINVAL;
54         }
55
56         ret = conf_load(ctx->conf, ctx->conf_file, true);
57         if (ret != 0 && ret != ENOENT) {
58                 D_ERR("Failed to load config file %s\n", ctx->conf_file);
59                 return ret;
60         }
61
62         conf_dump(ctx->conf, stdout);
63         return 0;
64 }
65
66 static int conf_tool_get(TALLOC_CTX *mem_ctx,
67                          int argc,
68                          const char **argv,
69                          void *private_data)
70 {
71         struct conf_tool_context *ctx = talloc_get_type_abort(
72                 private_data, struct conf_tool_context);
73         const char *section, *option;
74         enum conf_type type;
75         int ret;
76         bool ok;
77         const char *s_val = NULL;
78         int i_val;
79         bool b_val;
80
81         if (argc != 2) {
82                 cmdline_usage(ctx->cmdline, "get");
83                 return EINVAL;
84         }
85
86         section = argv[0];
87         option = argv[1];
88
89         ok = conf_query(ctx->conf, section, option, &type);
90         if (!ok) {
91                 D_ERR("Configuration option [%s] -> \"%s\" not defined\n",
92                       section, option);
93                 return ENOENT;
94         }
95
96         ret = conf_load(ctx->conf, ctx->conf_file, true);
97         if (ret != 0 && ret != ENOENT) {
98                 D_ERR("Failed to load config file %s\n", ctx->conf_file);
99                 return ret;
100         }
101
102         switch (type) {
103         case CONF_STRING:
104                 ret = conf_get_string(ctx->conf,
105                                       section,
106                                       option,
107                                       &s_val,
108                                       NULL);
109                 break;
110
111         case CONF_INTEGER:
112                 ret = conf_get_integer(ctx->conf,
113                                        section,
114                                        option,
115                                        &i_val,
116                                        NULL);
117                 break;
118
119         case CONF_BOOLEAN:
120                 ret = conf_get_boolean(ctx->conf,
121                                        section,
122                                        option,
123                                        &b_val,
124                                        NULL);
125                 break;
126
127         default:
128                 D_ERR("Unknown configuration option type\n");
129                 return EINVAL;
130         }
131
132         if (ret != 0) {
133                 D_ERR("Failed to get configuration option value\n");
134                 return ret;
135         }
136
137         switch (type) {
138         case CONF_STRING:
139                 printf("%s\n", s_val == NULL ? "" : s_val);
140                 break;
141
142         case CONF_INTEGER:
143                 printf("%d\n", i_val);
144                 break;
145
146         case CONF_BOOLEAN:
147                 printf("%s\n", b_val ? "true" : "false");
148                 break;
149         }
150
151         return 0;
152 }
153
154 static int conf_tool_validate(TALLOC_CTX *mem_ctx,
155                               int argc,
156                               const char **argv,
157                               void *private_data)
158 {
159         struct conf_tool_context *ctx = talloc_get_type_abort(
160                 private_data, struct conf_tool_context);
161         int ret;
162
163         if (argc != 0) {
164                 cmdline_usage(ctx->cmdline, "validate");
165                 return EINVAL;
166         }
167
168         ret = conf_load(ctx->conf, ctx->conf_file, false);
169         if (ret != 0) {
170                 D_ERR("Failed to load config file %s\n", ctx->conf_file);
171                 return ret;
172         }
173
174         return 0;
175 }
176
177 struct cmdline_command conf_commands[] = {
178         { "dump", conf_tool_dump,
179                 "Dump configuration", NULL },
180         { "get", conf_tool_get,
181                 "Get a config value", "<section> <key>" },
182         { "validate", conf_tool_validate,
183                 "Validate configuration file", NULL },
184         CMDLINE_TABLEEND
185 };
186
187 int conf_tool_init(TALLOC_CTX *mem_ctx,
188                    const char *prog,
189                    struct poptOption *options,
190                    int argc,
191                    const char **argv,
192                    bool parse_options,
193                    struct conf_tool_context **result)
194 {
195         struct conf_tool_context *ctx;
196         int ret;
197
198         ctx = talloc_zero(mem_ctx, struct conf_tool_context);
199         if (ctx == NULL) {
200                 D_ERR("Memory allocation error\n");
201                 return ENOMEM;
202         }
203
204         ret = cmdline_init(ctx, prog, options, conf_commands, &ctx->cmdline);
205         if (ret != 0) {
206                 D_ERR("Failed to initialize cmdline, ret=%d\n", ret);
207                 talloc_free(ctx);
208                 return ret;
209         }
210
211         ret = cmdline_parse(ctx->cmdline, argc, argv, parse_options);
212         if (ret != 0) {
213                 cmdline_usage(ctx->cmdline, NULL);
214                 talloc_free(ctx);
215                 return ret;
216         }
217
218         *result = ctx;
219         return 0;
220 }
221
222 int conf_tool_run(struct conf_tool_context *ctx, int *result)
223 {
224         int ret;
225
226         ctx->conf_file = path_config(ctx);
227         if (ctx->conf_file == NULL) {
228                 D_ERR("Memory allocation error\n");
229                 return ENOMEM;
230         }
231
232         ret = conf_init(ctx, &ctx->conf);
233         if (ret != 0) {
234                 D_ERR("Failed to initialize config\n");
235                 return ret;
236         }
237
238         /* Call functions to initialize config sections/variables */
239         logging_conf_init(ctx->conf, NULL);
240         event_conf_init(ctx->conf);
241
242         if (! conf_valid(ctx->conf)) {
243                 D_ERR("Failed to define configuration options\n");
244                 return EINVAL;
245         }
246
247         ret = cmdline_run(ctx->cmdline, ctx, result);
248         return ret;
249 }
250
251 #ifdef CTDB_CONF_TOOL
252
253 static struct {
254         const char *debug;
255 } conf_data = {
256         .debug = "ERROR",
257 };
258
259 struct poptOption conf_options[] = {
260         POPT_AUTOHELP
261         { "debug", 'd', POPT_ARG_STRING, &conf_data.debug, 0,
262                 "debug level", "ERROR|WARNING|NOTICE|INFO|DEBUG" },
263         POPT_TABLEEND
264 };
265
266 int main(int argc, const char **argv)
267 {
268         TALLOC_CTX *mem_ctx;
269         struct conf_tool_context *ctx;
270         int ret, result;
271         bool ok;
272
273         mem_ctx = talloc_new(NULL);
274         if (mem_ctx == NULL) {
275                 fprintf(stderr, "Memory allocation error\n");
276                 exit(1);
277         }
278
279         ret = conf_tool_init(mem_ctx,
280                              "ctdb-config",
281                              conf_options,
282                              argc,
283                              argv,
284                              true,
285                              &ctx);
286         if (ret != 0) {
287                 talloc_free(mem_ctx);
288                 exit(1);
289         }
290
291         setup_logging("ctdb-config", DEBUG_STDERR);
292         ok = debug_level_parse(conf_data.debug, &DEBUGLEVEL);
293         if (!ok) {
294                 DEBUGLEVEL = DEBUG_ERR;
295         }
296
297         ret = conf_tool_run(ctx, &result);
298         if (ret != 0) {
299                 result = 1;
300         }
301
302         talloc_free(mem_ctx);
303         exit(result);
304 }
305
306 #endif /* CTDB_CONF_TOOL */