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