aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/tru/tinyradutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tru/tinyradutil.c')
-rw-r--r--src/tru/tinyradutil.c460
1 files changed, 460 insertions, 0 deletions
diff --git a/src/tru/tinyradutil.c b/src/tru/tinyradutil.c
new file mode 100644
index 0000000..5524931
--- /dev/null
+++ b/src/tru/tinyradutil.c
@@ -0,0 +1,460 @@
1/*
2 * Tiny RADIUS Client Library
3 * Copyright (C) 2021 David M. Syzdek <david@syzdek.net>.
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * * Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * * Neither the name of David M. Syzdek nor the
16 * names of its contributors may be used to endorse or promote products
17 * derived from this software without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL DAVID M. SYZDEK BE LIABLE FOR
23 * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 */
31#define _SRC_TRU_TINYRADUTIL_C 1
32
33///////////////
34// //
35// Headers //
36// //
37///////////////
38#pragma mark - Headers
39
40#include "tinyradutil.h"
41
42#include <tinyrad_utils.h>
43
44#include <stdio.h>
45#include <stdarg.h>
46#include <stdlib.h>
47#include <string.h>
48#include <strings.h>
49#include <unistd.h>
50#include <getopt.h>
51#include <sys/types.h>
52#include <sys/stat.h>
53#include <sys/uio.h>
54#include <unistd.h>
55#include <assert.h>
56#include <fcntl.h>
57#include <errno.h>
58
59
60///////////////////
61// //
62// Definitions //
63// //
64///////////////////
65#pragma mark - Definitions
66
67
68//////////////////
69// //
70// Data Types //
71// //
72//////////////////
73#pragma mark - Data Types
74
75
76//////////////////
77// //
78// Prototypes //
79// //
80//////////////////
81#pragma mark - Prototypes
82
83static const TinyRadUtilWidget *
84tru_widget_lookup(
85 const char * wname,
86 int exact );
87
88
89/////////////////
90// //
91// Variables //
92// //
93/////////////////
94#pragma mark - Variables
95
96#pragma mark tinyrad_cmdmap[]
97const TinyRadUtilWidget tru_widget_map[] =
98{
99 {
100 .name = "configuration",
101 .func = &tru_widget_config,
102 .shortopts = TRU_COMMON_SHORT TRU_DICT_SHORT,
103 .longopts = (struct option []) { TRU_DICT_LONG TRU_COMMON_LONG },
104 .min_arg = 0,
105 .max_arg = 0,
106 .usage = NULL,
107 .desc = "print configuration"
108 },
109 {
110 .name = "dictionary",
111 .func = &tru_widget_dict,
112 .shortopts = TRU_COMMON_SHORT TRU_DICT_SHORT,
113 .longopts = (struct option []) { TRU_DICT_LONG TRU_COMMON_LONG },
114 .min_arg = 0,
115 .max_arg = 0,
116 .usage = NULL,
117 .desc = "print processed dictionary"
118 },
119 {
120 .name = "help",
121 .func = &tru_usage,
122 .shortopts = TRU_COMMON_SHORT,
123 .longopts = (struct option []) { TRU_COMMON_LONG },
124 .min_arg = 0,
125 .max_arg = 0,
126 .usage = NULL,
127 .desc = "print command usage"
128 },
129 {
130 .name = NULL,
131 .func = NULL,
132 .shortopts = NULL,
133 .longopts = NULL,
134 .min_arg = -1,
135 .max_arg = -1,
136 .usage = NULL,
137 .desc = NULL
138 }
139};
140
141
142/////////////////
143// //
144// Functions //
145// //
146/////////////////
147#pragma mark - Functions
148
149int main(int argc, char * argv[])
150{
151 int c;
152 int opt_index;
153 int rc;
154 TinyRadDict * dict;
155 TinyRadUtilConf cnfdata;
156 TinyRadUtilConf * cnf;
157
158 // getopt options
159 static char short_opt[] = "+" TRU_COMMON_SHORT;
160 static struct option long_opt[] = { TRU_COMMON_LONG };
161
162 trutils_initialize(PROGRAM_NAME);
163
164 memset(&cnfdata, 0, sizeof(cnfdata));
165 cnf = &cnfdata;
166 dict = NULL;
167
168 while((c = tru_getopt(cnf, argc, argv, short_opt, long_opt, &opt_index)) != -1)
169 {
170 switch(c)
171 {
172 case TRU_GETOPT_MATCHED: /* captured by common options */
173 case -1: /* no more arguments */
174 case 0: /* long options toggles */
175 break;
176
177 case TRU_GETOPT_EXIT:
178 tru_cleanup(cnf);
179 return(0);
180
181 case TRU_GETOPT_ERROR:
182 tru_cleanup(cnf);
183 return(1);
184
185 case '?':
186 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
187 return(1);
188
189 default:
190 fprintf(stderr, "%s: unrecognized option `--%c'\n", PROGRAM_NAME, c);
191 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
192 return(1);
193 };
194 };
195 if ((argc - optind) < 1)
196 {
197 fprintf(stderr, "%s: missing required argument\n", PROGRAM_NAME);
198 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
199 return(1);
200 };
201 cnf->cmd_argc = (argc - optind);
202 cnf->cmd_argv = &argv[optind];
203 cnf->cmd_name = cnf->cmd_argv[0];
204
205 // looks up widget
206 if ((cnf->cmd = tru_widget_lookup(cnf->cmd_argv[0], TRAD_NO)) == NULL)
207 {
208 fprintf(stderr, "%s: unknown or ambiguous widget -- \"%s\"\n", PROGRAM_NAME, cnf->cmd_argv[0]);
209 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
210 return(1);
211 };
212
213 // process widget cli options
214 optind = 1;
215 opt_index = 0;
216 while((c = tru_getopt(cnf, cnf->cmd_argc, cnf->cmd_argv, cnf->cmd->shortopts, cnf->cmd->longopts, &opt_index)) != -1)
217 {
218 switch(c)
219 {
220 case -2: /* captured by common options */
221 case -1: /* no more arguments */
222 case 0: /* long options toggles */
223 break;
224
225 case TRU_GETOPT_EXIT:
226 tru_cleanup(cnf);
227 return(0);
228
229 case TRU_GETOPT_ERROR:
230 tru_cleanup(cnf);
231 return(1);
232
233 case '?':
234 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->cmd_name);
235 return(1);
236
237 default:
238 fprintf(stderr, "%s: %s: unrecognized option `--%c'\n", PROGRAM_NAME, cnf->cmd_name, c);
239 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->cmd_name);
240 return(1);
241 };
242 };
243 if ((cnf->cmd_argc - optind) < cnf->cmd->min_arg)
244 {
245 fprintf(stderr, "%s: missing required argument\n", PROGRAM_NAME);
246 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->cmd_name);
247 return(1);
248 };
249 if ((optind+cnf->cmd->max_arg) > cnf->cmd_argc)
250 {
251 fprintf(stderr, "%s: unrecognized argument `-- %s'\n", PROGRAM_NAME, cnf->cmd_argv[optind+1]);
252 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->cmd_name);
253 return(1);
254 };
255
256 // call widget
257 rc = cnf->cmd->func(cnf);
258 tru_cleanup(cnf);
259 return(trutils_exit_code(rc));
260}
261
262
263void
264tru_cleanup(
265 TinyRadUtilConf * cnf )
266{
267 tinyrad_free(cnf->tr);
268 tinyrad_strsfree(cnf->dict_files);
269 tinyrad_strsfree(cnf->dict_paths);
270 return;
271}
272
273
274int
275tru_getopt(
276 TinyRadUtilConf * cnf,
277 int argc,
278 char * const * argv,
279 const char * short_opt,
280 const struct option * long_opt,
281 int * opt_index )
282{
283 int c;
284 int opt;
285
286 switch(c = getopt_long(argc, argv, short_opt, long_opt, opt_index))
287 {
288 case 'b':
289 cnf->tr_opts |= TRAD_BUILTIN_DICT;
290 return(TRU_GETOPT_MATCHED);
291
292 case 'D':
293 if (tinyrad_strsadd(&cnf->dict_files, optarg) != TRAD_SUCCESS)
294 {
295 trutils_error(cnf->opts, NULL, "out of virtual memory");
296 return(TRU_GETOPT_ERROR);
297 };
298 return(TRU_GETOPT_MATCHED);
299
300 case 'd':
301 opt = ((optarg)) ? (int)strtol(optarg, NULL, 0) : TRAD_DEBUG_ANY;
302 tinyrad_set_option(NULL, TRAD_OPT_DEBUG_LEVEL, &opt);
303 return(TRU_GETOPT_MATCHED);
304
305 case 'h':
306 tru_usage(cnf);
307 return(TRU_GETOPT_EXIT);
308
309 case 'I':
310 if (tinyrad_strsadd(&cnf->dict_paths, optarg) != TRAD_SUCCESS)
311 {
312 trutils_error(cnf->opts, NULL, "out of virtual memory");
313 return(TRU_GETOPT_ERROR);
314 };
315 return(TRU_GETOPT_MATCHED);
316
317 case 'q':
318 cnf->opts |= TRUTILS_OPT_QUIET;
319 cnf->opts &= ~TRUTILS_OPT_VERBOSE;
320 return(TRU_GETOPT_MATCHED);
321
322 case 'V':
323 trutils_version();
324 return(TRU_GETOPT_EXIT);
325
326 case 'v':
327 cnf->opts |= TRUTILS_OPT_VERBOSE;
328 cnf->opts &= ~TRUTILS_OPT_QUIET;
329 return(TRU_GETOPT_MATCHED);
330
331 default:
332 break;
333 };
334
335 return(c);
336}
337
338
339int
340tru_load_tinyrad(
341 TinyRadUtilConf * cnf )
342{
343 int rc;
344 char ** errs;
345 size_t pos;
346 TinyRadDict * dict;
347
348 errs = NULL;
349 dict = NULL;
350
351 if ((cnf->dict_files))
352 {
353 // initialize dictionary
354 if ((rc = tinyrad_dict_initialize(&dict, cnf->tr_opts)) != TRAD_SUCCESS)
355 {
356 trutils_error(cnf->opts, NULL, "out of virtual memory");
357 return(rc);
358 };
359
360 // set paths
361 if ((cnf->dict_paths))
362 {
363 if ((rc = tinyrad_dict_set_option(dict, TRAD_DICT_OPT_PATHS, cnf->dict_paths)) != TRAD_SUCCESS)
364 {
365 trutils_error(cnf->opts, NULL, "tinyrad_dict_set_option(TRAD_DICT_OPT_PATHS): %s", tinyrad_strerror(rc));
366 tinyrad_free(dict);
367 return(rc);
368 };
369 };
370
371 // parse dictionary files
372 for(pos = 0; ( ((cnf->dict_files)) && ((cnf->dict_files[pos])) ); pos++)
373 {
374 if ((rc = tinyrad_dict_parse(dict, cnf->dict_files[pos], &errs, 0)) != TRAD_SUCCESS)
375 {
376 trutils_error(cnf->opts, errs, NULL);
377 tinyrad_strsfree(errs);
378 tinyrad_free(dict);
379 return(rc);
380 };
381 };
382 };
383
384 // initialize tinyrad handle
385 rc = tinyrad_initialize(&cnf->tr, dict, cnf->url, cnf->tr_opts);
386 tinyrad_free(dict);
387 return(rc);
388}
389
390
391int
392tru_usage(
393 TinyRadUtilConf * cnf )
394{
395 int i;
396 const char * name;
397 const char * help;
398 const char * s;
399
400 name = (!(cnf->cmd)) ? "widget" : cnf->cmd->name;
401 help = (!(cnf->cmd)) ? " ..." : (((cnf->cmd->usage)) ? cnf->cmd->usage : "");
402 s = (!(cnf->cmd)) ? TRU_COMMON_SHORT : (((cnf->cmd->shortopts)) ? cnf->cmd->shortopts : TRU_COMMON_SHORT);
403
404 printf("Usage: %s %s [OPTIONS]%s\n", PROGRAM_NAME, name, help);
405 printf("OPTIONS:\n");
406 if ((strchr(s, 'b'))) printf(" -b, --builtin-dict load built-in dictionary\n");
407 if ((strchr(s, 'D'))) printf(" -D dictionary include dictionary\n");
408 if ((strchr(s, 'd'))) printf(" -d level, --debug=level print debug messages\n");
409 if ((strchr(s, 'f'))) printf(" -f file, --file=file attribute list\n");
410 if ((strchr(s, 'h'))) printf(" -h, --help print this help and exit\n");
411 if ((strchr(s, 'I'))) printf(" -I path add path to dictionary search paths\n");
412 if ((strchr(s, 'q'))) printf(" -q, --quiet, --silent do not print messages\n");
413 if ((strchr(s, 'V'))) printf(" -V, --version print version number and exit\n");
414 if ((strchr(s, 'v'))) printf(" -v, --verbose print verbose messages\n");
415 if (!(cnf->cmd))
416 {
417 printf("COMMANDS:\n");
418 for(i = 0; tru_widget_map[i].name != NULL; i++)
419 if ((tru_widget_map[i].desc))
420 printf(" %-25s %s\n", tru_widget_map[i].name, tru_widget_map[i].desc);
421 };
422 printf("\n");
423 return(0);
424}
425
426
427static const TinyRadUtilWidget *
428tru_widget_lookup(
429 const char * wname,
430 int exact )
431{
432 size_t wname_len;
433 size_t x;
434 const TinyRadUtilWidget * widget;
435 const TinyRadUtilWidget * match;
436
437 match = NULL;
438 wname_len = strlen(wname);
439
440 for(x = 0; ((tru_widget_map[x].name)); x++)
441 {
442 widget = &tru_widget_map[x];
443 if (widget->func == NULL)
444 continue;
445
446 if (!(strncmp(widget->name, wname, wname_len)))
447 {
448 if (widget->name[wname_len] == '\0')
449 return(widget);
450 if ((match))
451 return(NULL);
452 if (exact == TRAD_NO)
453 match = widget;
454 };
455 };
456
457 return(match);
458}
459
460/* end of source */