ctdb-common: Return script_list for zero scripts
[vlendec/samba-autobuild/.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 "cluster/cluster_conf.h"
33 #include "database/database_conf.h"
34 #include "event/event_conf.h"
35 #include "server/legacy_conf.h"
36
37 #include "common/conf_tool.h"
38
39 struct conf_tool_context {
40         struct cmdline_context *cmdline;
41         const char *conf_file;
42         struct conf_context *conf;
43 };
44
45 static int conf_tool_dump(TALLOC_CTX *mem_ctx,
46                           int argc,
47                           const char **argv,
48                           void *private_data)
49 {
50         struct conf_tool_context *ctx = talloc_get_type_abort(
51                 private_data, struct conf_tool_context);
52         int ret;
53
54         if (argc != 0) {
55                 cmdline_usage(ctx->cmdline, "dump");
56                 return EINVAL;
57         }
58
59         ret = conf_load(ctx->conf, ctx->conf_file, true);
60         if (ret != 0 && ret != ENOENT) {
61                 D_ERR("Failed to load config file %s\n", ctx->conf_file);
62                 return ret;
63         }
64
65         conf_dump(ctx->conf, stdout);
66         return 0;
67 }
68
69 static int conf_tool_get(TALLOC_CTX *mem_ctx,
70                          int argc,
71                          const char **argv,
72                          void *private_data)
73 {
74         struct conf_tool_context *ctx = talloc_get_type_abort(
75                 private_data, struct conf_tool_context);
76         const char *section, *option;
77         enum conf_type type;
78         int ret;
79         bool ok;
80         const char *s_val = NULL;
81         int i_val;
82         bool b_val;
83
84         if (argc != 2) {
85                 cmdline_usage(ctx->cmdline, "get");
86                 return EINVAL;
87         }
88
89         section = argv[0];
90         option = argv[1];
91
92         ok = conf_query(ctx->conf, section, option, &type);
93         if (!ok) {
94                 D_ERR("Configuration option [%s] -> \"%s\" not defined\n",
95                       section, option);
96                 return ENOENT;
97         }
98
99         ret = conf_load(ctx->conf, ctx->conf_file, true);
100         if (ret != 0 && ret != ENOENT) {
101                 D_ERR("Failed to load config file %s\n", ctx->conf_file);
102                 return ret;
103         }
104
105         switch (type) {
106         case CONF_STRING:
107                 ret = conf_get_string(ctx->conf,
108                                       section,
109                                       option,
110                                       &s_val,
111                                       NULL);
112                 break;
113
114         case CONF_INTEGER:
115                 ret = conf_get_integer(ctx->conf,
116                                        section,
117                                        option,
118                                        &i_val,
119                                        NULL);
120                 break;
121
122         case CONF_BOOLEAN:
123                 ret = conf_get_boolean(ctx->conf,
124                                        section,
125                                        option,
126                                        &b_val,
127                                        NULL);
128                 break;
129
130         default:
131                 D_ERR("Unknown configuration option type\n");
132                 return EINVAL;
133         }
134
135         if (ret != 0) {
136                 D_ERR("Failed to get configuration option value\n");
137                 return ret;
138         }
139
140         switch (type) {
141         case CONF_STRING:
142                 printf("%s\n", s_val == NULL ? "" : s_val);
143                 break;
144
145         case CONF_INTEGER:
146                 printf("%d\n", i_val);
147                 break;
148
149         case CONF_BOOLEAN:
150                 printf("%s\n", b_val ? "true" : "false");
151                 break;
152         }
153
154         return 0;
155 }
156
157 static int conf_tool_validate(TALLOC_CTX *mem_ctx,
158                               int argc,
159                               const char **argv,
160                               void *private_data)
161 {
162         struct conf_tool_context *ctx = talloc_get_type_abort(
163                 private_data, struct conf_tool_context);
164         int ret;
165
166         if (argc != 0) {
167                 cmdline_usage(ctx->cmdline, "validate");
168                 return EINVAL;
169         }
170
171         ret = conf_load(ctx->conf, ctx->conf_file, false);
172         if (ret != 0) {
173                 D_ERR("Failed to load config file %s\n", ctx->conf_file);
174                 return ret;
175         }
176
177         return 0;
178 }
179
180 struct cmdline_command conf_commands[] = {
181         { "dump", conf_tool_dump,
182                 "Dump configuration", NULL },
183         { "get", conf_tool_get,
184                 "Get a config value", "<section> <key>" },
185         { "validate", conf_tool_validate,
186                 "Validate configuration file", NULL },
187         CMDLINE_TABLEEND
188 };
189
190 int conf_tool_init(TALLOC_CTX *mem_ctx,
191                    const char *prog,
192                    struct poptOption *options,
193                    int argc,
194                    const char **argv,
195                    bool parse_options,
196                    struct conf_tool_context **result)
197 {
198         struct conf_tool_context *ctx;
199         int ret;
200
201         ctx = talloc_zero(mem_ctx, struct conf_tool_context);
202         if (ctx == NULL) {
203                 D_ERR("Memory allocation error\n");
204                 return ENOMEM;
205         }
206
207         ret = cmdline_init(ctx, prog, options, conf_commands, &ctx->cmdline);
208         if (ret != 0) {
209                 D_ERR("Failed to initialize cmdline, ret=%d\n", ret);
210                 talloc_free(ctx);
211                 return ret;
212         }
213
214         ret = cmdline_parse(ctx->cmdline, argc, argv, parse_options);
215         if (ret != 0) {
216                 cmdline_usage(ctx->cmdline, NULL);
217                 talloc_free(ctx);
218                 return ret;
219         }
220
221         *result = ctx;
222         return 0;
223 }
224
225 int conf_tool_run(struct conf_tool_context *ctx, int *result)
226 {
227         int ret;
228
229         ctx->conf_file = path_config(ctx);
230         if (ctx->conf_file == NULL) {
231                 D_ERR("Memory allocation error\n");
232                 return ENOMEM;
233         }
234
235         ret = conf_init(ctx, &ctx->conf);
236         if (ret != 0) {
237                 D_ERR("Failed to initialize config\n");
238                 return ret;
239         }
240
241         /* Call functions to initialize config sections/variables */
242         logging_conf_init(ctx->conf, NULL);
243         cluster_conf_init(ctx->conf);
244         database_conf_init(ctx->conf);
245         event_conf_init(ctx->conf);
246         legacy_conf_init(ctx->conf);
247
248         if (! conf_valid(ctx->conf)) {
249                 D_ERR("Failed to define configuration options\n");
250                 return EINVAL;
251         }
252
253         ret = cmdline_run(ctx->cmdline, ctx, result);
254         return ret;
255 }
256
257 #ifdef CTDB_CONF_TOOL
258
259 static struct {
260         const char *debug;
261 } conf_data = {
262         .debug = "ERROR",
263 };
264
265 struct poptOption conf_options[] = {
266         POPT_AUTOHELP
267         { "debug", 'd', POPT_ARG_STRING, &conf_data.debug, 0,
268                 "debug level", "ERROR|WARNING|NOTICE|INFO|DEBUG" },
269         POPT_TABLEEND
270 };
271
272 int main(int argc, const char **argv)
273 {
274         TALLOC_CTX *mem_ctx;
275         struct conf_tool_context *ctx;
276         int ret, result;
277         bool ok;
278
279         mem_ctx = talloc_new(NULL);
280         if (mem_ctx == NULL) {
281                 fprintf(stderr, "Memory allocation error\n");
282                 exit(1);
283         }
284
285         ret = conf_tool_init(mem_ctx,
286                              "ctdb-config",
287                              conf_options,
288                              argc,
289                              argv,
290                              true,
291                              &ctx);
292         if (ret != 0) {
293                 talloc_free(mem_ctx);
294                 exit(1);
295         }
296
297         setup_logging("ctdb-config", DEBUG_STDERR);
298         ok = debug_level_parse(conf_data.debug, &DEBUGLEVEL);
299         if (!ok) {
300                 DEBUGLEVEL = DEBUG_ERR;
301         }
302
303         ret = conf_tool_run(ctx, &result);
304         if (ret != 0) {
305                 result = 1;
306         }
307
308         talloc_free(mem_ctx);
309         exit(result);
310 }
311
312 #endif /* CTDB_CONF_TOOL */