aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/tru/tru.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/tru/tru.c')
-rw-r--r--src/tru/tru.c473
1 files changed, 473 insertions, 0 deletions
diff --git a/src/tru/tru.c b/src/tru/tru.c
new file mode 100644
index 0000000..0e86f6d
--- /dev/null
+++ b/src/tru/tru.c
@@ -0,0 +1,473 @@
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_TINYRADUTIL_TINYRADUTIL_C 1
32
33///////////////
34// //
35// Headers //
36// //
37///////////////
38#pragma mark - Headers
39
40#include "tru.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 = TINYRAD_DICT_GETOPT_SHORT TINYRAD_GETOPT_SHORT,
103 .longopts = (struct option [])
104 { TINYRAD_DICT_GETOPT_LONG
105 TINYRAD_GETOPT_LONG
106 },
107 .min_arg = 0,
108 .max_arg = 0,
109 .usage = NULL,
110 .desc = "print configuration"
111 },
112 {
113 .name = "dictionary",
114 .func = &tru_widget_dict,
115 .shortopts = TINYRAD_DICT_GETOPT_SHORT TINYRAD_GETOPT_SHORT,
116 .longopts = (struct option [])
117 { TINYRAD_DICT_GETOPT_LONG
118 TINYRAD_GETOPT_LONG
119 },
120 .min_arg = 0,
121 .max_arg = 0,
122 .usage = NULL,
123 .desc = "print processed dictionary"
124 },
125 {
126 .name = "help",
127 .func = &tru_usage,
128 .shortopts = TINYRAD_GETOPT_SHORT,
129 .longopts = (struct option []) { TINYRAD_GETOPT_LONG },
130 .min_arg = 0,
131 .max_arg = 0,
132 .usage = NULL,
133 .desc = "print command usage"
134 },
135 {
136 .name = NULL,
137 .func = NULL,
138 .shortopts = NULL,
139 .longopts = NULL,
140 .min_arg = -1,
141 .max_arg = -1,
142 .usage = NULL,
143 .desc = NULL
144 }
145};
146
147
148/////////////////
149// //
150// Functions //
151// //
152/////////////////
153#pragma mark - Functions
154
155int main(int argc, char * argv[])
156{
157 int c;
158 int opt_index;
159 int rc;
160 TinyRadDict * dict;
161 TinyRadUtilConf cnfdata;
162 TinyRadUtilConf * cnf;
163
164 // getopt options
165 static char short_opt[] = "+" TINYRAD_GETOPT_SHORT;
166 static struct option long_opt[] = { TINYRAD_GETOPT_LONG };
167
168 trutils_initialize(PROGRAM_NAME);
169
170 memset(&cnfdata, 0, sizeof(cnfdata));
171 cnf = &cnfdata;
172 dict = NULL;
173
174 while((c = tru_getopt(cnf, argc, argv, short_opt, long_opt, &opt_index)) != -1)
175 {
176 switch(c)
177 {
178 case MY_GETOPT_MATCHED: /* captured by common options */
179 case -1: /* no more arguments */
180 case 0: /* long options toggles */
181 break;
182
183 case MY_GETOPT_EXIT:
184 tru_cleanup(cnf);
185 return(0);
186
187 case MY_GETOPT_ERROR:
188 tru_cleanup(cnf);
189 return(1);
190
191 case '?':
192 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
193 return(1);
194
195 default:
196 fprintf(stderr, "%s: unrecognized option `--%c'\n", PROGRAM_NAME, c);
197 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
198 return(1);
199 };
200 };
201 if ((argc - optind) < 1)
202 {
203 fprintf(stderr, "%s: missing required argument\n", PROGRAM_NAME);
204 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
205 return(1);
206 };
207 cnf->cmd_argc = (argc - optind);
208 cnf->cmd_argv = &argv[optind];
209 cnf->cmd_name = cnf->cmd_argv[0];
210
211 // looks up widget
212 if ((cnf->cmd = tru_widget_lookup(cnf->cmd_argv[0], TRAD_NO)) == NULL)
213 {
214 fprintf(stderr, "%s: unknown or ambiguous widget -- \"%s\"\n", PROGRAM_NAME, cnf->cmd_argv[0]);
215 fprintf(stderr, "Try `%s --help' for more information.\n", PROGRAM_NAME);
216 return(1);
217 };
218
219 // process widget cli options
220 optind = 1;
221 opt_index = 0;
222 while((c = tru_getopt(cnf, cnf->cmd_argc, cnf->cmd_argv, cnf->cmd->shortopts, cnf->cmd->longopts, &opt_index)) != -1)
223 {
224 switch(c)
225 {
226 case -2: /* captured by common options */
227 case -1: /* no more arguments */
228 case 0: /* long options toggles */
229 break;
230
231 case MY_GETOPT_EXIT:
232 tru_cleanup(cnf);
233 return(0);
234
235 case MY_GETOPT_ERROR:
236 tru_cleanup(cnf);
237 return(1);
238
239 case '?':
240 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->cmd_name);
241 return(1);
242
243 default:
244 fprintf(stderr, "%s: %s: unrecognized option `--%c'\n", PROGRAM_NAME, cnf->cmd_name, c);
245 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->cmd_name);
246 return(1);
247 };
248 };
249 if ((cnf->cmd_argc - optind) < cnf->cmd->min_arg)
250 {
251 fprintf(stderr, "%s: missing required argument\n", PROGRAM_NAME);
252 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->cmd_name);
253 return(1);
254 };
255 if ((optind+cnf->cmd->max_arg) > cnf->cmd_argc)
256 {
257 fprintf(stderr, "%s: unrecognized argument `-- %s'\n", PROGRAM_NAME, cnf->cmd_argv[optind+1]);
258 fprintf(stderr, "Try `%s %s --help' for more information.\n", PROGRAM_NAME, cnf->cmd_name);
259 return(1);
260 };
261
262 // call widget
263 rc = cnf->cmd->func(cnf);
264 tru_cleanup(cnf);
265 return(trutils_exit_code(rc));
266}
267
268
269void
270tru_cleanup(
271 TinyRadUtilConf * cnf )
272{
273 tinyrad_free(cnf->tr);
274 tinyrad_strsfree(cnf->dict_files);
275 tinyrad_strsfree(cnf->dict_paths);
276 return;
277}
278
279
280int
281tru_getopt(
282 TinyRadUtilConf * cnf,
283 int argc,
284 char * const * argv,
285 const char * short_opt,
286 const struct option * long_opt,
287 int * opt_index )
288{
289 int c;
290 int opt;
291
292 switch(c = getopt_long(argc, argv, short_opt, long_opt, opt_index))
293 {
294 case 'b':
295 cnf->tr_opts |= TRAD_BUILTIN_DICT;
296 return(MY_GETOPT_MATCHED);
297
298 case 'D':
299 if (tinyrad_strsadd(&cnf->dict_files, optarg) != TRAD_SUCCESS)
300 {
301 trutils_error(cnf->opts, NULL, "out of virtual memory");
302 return(MY_GETOPT_ERROR);
303 };
304 return(MY_GETOPT_MATCHED);
305
306 case 'd':
307 opt = ((optarg)) ? (int)strtol(optarg, NULL, 0) : TRAD_DEBUG_ANY;
308 tinyrad_set_option(NULL, TRAD_OPT_DEBUG_LEVEL, &opt);
309 return(MY_GETOPT_MATCHED);
310
311 case 'h':
312 tru_usage(cnf);
313 return(MY_GETOPT_EXIT);
314
315 case 'I':
316 if (tinyrad_strsadd(&cnf->dict_paths, optarg) != TRAD_SUCCESS)
317 {
318 trutils_error(cnf->opts, NULL, "out of virtual memory");
319 return(MY_GETOPT_ERROR);
320 };
321 return(MY_GETOPT_MATCHED);
322
323 case 'q':
324 cnf->opts |= TRUTILS_OPT_QUIET;
325 cnf->opts &= ~TRUTILS_OPT_VERBOSE;
326 return(MY_GETOPT_MATCHED);
327
328 case 'V':
329 trutils_version();
330 return(MY_GETOPT_EXIT);
331
332 case 'v':
333 cnf->opts |= TRUTILS_OPT_VERBOSE;
334 cnf->opts &= ~TRUTILS_OPT_QUIET;
335 return(MY_GETOPT_MATCHED);
336
337 default:
338 break;
339 };
340
341 return(c);
342}
343
344
345int
346tru_load_tinyrad(
347 TinyRadUtilConf * cnf )
348{
349 int rc;
350 char ** errs;
351 size_t pos;
352 TinyRadDict * dict;
353
354 errs = NULL;
355 dict = NULL;
356
357 if ((cnf->dict_files))
358 {
359 // initialize dictionary
360 if ((rc = tinyrad_dict_initialize(&dict, cnf->tr_opts)) != TRAD_SUCCESS)
361 {
362 trutils_error(cnf->opts, NULL, "out of virtual memory");
363 return(rc);
364 };
365
366 // set paths
367 if ((cnf->dict_paths))
368 {
369 if ((rc = tinyrad_dict_set_option(dict, TRAD_DICT_OPT_PATHS, cnf->dict_paths)) != TRAD_SUCCESS)
370 {
371 trutils_error(cnf->opts, NULL, "tinyrad_dict_set_option(TRAD_DICT_OPT_PATHS): %s", tinyrad_strerror(rc));
372 tinyrad_free(dict);
373 return(rc);
374 };
375 };
376
377 // parse dictionary files
378 for(pos = 0; ( ((cnf->dict_files)) && ((cnf->dict_files[pos])) ); pos++)
379 {
380 if ((rc = tinyrad_dict_parse(dict, cnf->dict_files[pos], &errs, 0)) != TRAD_SUCCESS)
381 {
382 trutils_error(cnf->opts, errs, NULL);
383 tinyrad_strsfree(errs);
384 tinyrad_free(dict);
385 return(rc);
386 };
387 };
388 };
389
390 // initialize tinyrad handle
391 rc = tinyrad_initialize(&cnf->tr, dict, cnf->url, cnf->tr_opts);
392 tinyrad_free(dict);
393 return(rc);
394}
395
396
397int
398tru_usage(
399 TinyRadUtilConf * cnf )
400{
401 int i;
402 const char * name;
403 const char * help;
404 const char * s;
405
406 name = "COMMAND";
407 help = " ...";
408 s = TINYRAD_GETOPT_SHORT;
409
410 if ((cnf->cmd))
411 {
412 name = cnf->cmd->name;
413 help = ((cnf->cmd->usage)) ? cnf->cmd->usage : "";
414 s = ((cnf->cmd->shortopts)) ? cnf->cmd->shortopts : TINYRAD_GETOPT_SHORT;
415 };
416
417 printf("Usage: %s %s [OPTIONS]%s\n", PROGRAM_NAME, name, help);
418 printf("OPTIONS:\n");
419 if ((strchr(s, 'b'))) printf(" -b, --builtin-dict load built-in dictionary\n");
420 if ((strchr(s, 'D'))) printf(" -D dictionary include dictionary\n");
421 if ((strchr(s, 'd'))) printf(" -d level, --debug=level print debug messages\n");
422 if ((strchr(s, 'f'))) printf(" -f file, --file=file attribute list\n");
423 if ((strchr(s, 'h'))) printf(" -h, --help print this help and exit\n");
424 if ((strchr(s, 'I'))) printf(" -I path add path to dictionary search paths\n");
425 if ((strchr(s, 'q'))) printf(" -q, --quiet, --silent do not print messages\n");
426 if ((strchr(s, 'V'))) printf(" -V, --version print version number and exit\n");
427 if ((strchr(s, 'v'))) printf(" -v, --verbose print verbose messages\n");
428 if (!(cnf->cmd))
429 {
430 printf("COMMANDS:\n");
431 for(i = 0; tru_widget_map[i].name != NULL; i++)
432 if ((tru_widget_map[i].desc))
433 printf(" %-25s %s\n", tru_widget_map[i].name, tru_widget_map[i].desc);
434 };
435 printf("\n");
436 return(0);
437}
438
439
440static const TinyRadUtilWidget *
441tru_widget_lookup(
442 const char * wname,
443 int exact )
444{
445 size_t wname_len;
446 size_t x;
447 const TinyRadUtilWidget * widget;
448 const TinyRadUtilWidget * match;
449
450 match = NULL;
451 wname_len = strlen(wname);
452
453 for(x = 0; ((tru_widget_map[x].name)); x++)
454 {
455 widget = &tru_widget_map[x];
456 if (widget->func == NULL)
457 continue;
458
459 if (!(strncmp(widget->name, wname, wname_len)))
460 {
461 if (widget->name[wname_len] == '\0')
462 return(widget);
463 if ((match))
464 return(NULL);
465 if (exact == TRAD_NO)
466 match = widget;
467 };
468 };
469
470 return(NULL);
471}
472
473/* end of source */