diff options
author | Toni Uhlig <matzeton@googlemail.com> | 2018-05-30 23:32:01 +0200 |
---|---|---|
committer | Toni Uhlig <matzeton@googlemail.com> | 2018-05-30 23:32:01 +0200 |
commit | 9badf738fcd67ff8b61c56f28cdb15ac614eff7a (patch) | |
tree | 56464361155f6081843662b77ef6df5a9f921589 | |
parent | 1c9022f075387e86269a79ac71f61dd4ac32c421 (diff) |
POTD skeleton #84.
Signed-off-by: Toni Uhlig <matzeton@googlemail.com>
-rw-r--r-- | configure.ac | 4 | ||||
-rw-r--r-- | src/Makefile.am | 2 | ||||
-rw-r--r-- | src/main.c | 16 | ||||
-rw-r--r-- | src/options.c | 134 | ||||
-rw-r--r-- | src/options.h | 18 |
5 files changed, 168 insertions, 6 deletions
diff --git a/configure.ac b/configure.ac index 34bd487..a124a8c 100644 --- a/configure.ac +++ b/configure.ac @@ -168,10 +168,10 @@ dnl minimum required functions AC_CHECK_FUNCS([open read write close malloc free memset memcpy fork unshare \ getpwnam getgrnam setreuid setregid \ wait waitpid isprint remove unlink mkdir access stat chroot chdir mount umount mknod \ - strncat strncpy snprintf vsnprintf printf fprintf getpid \ + strdup strncat strncpy snprintf vsnprintf printf fprintf getpid \ prctl signal signalfd fcntl getenv kill exit \ setsockopt socket connect accept bind listen \ - time difftime], [], + time difftime strtol strtoll getopt_long_only], [], [ AC_MSG_ERROR([required function not available]) ]) dnl GAI functions AC_CHECK_FUNCS([getaddrinfo getnameinfo freeaddrinfo], [], diff --git a/src/Makefile.am b/src/Makefile.am index 7718218..b6e48f3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -2,4 +2,4 @@ AM_CFLAGS = -pedantic -Wall -std=gnu99 -fstrict-aliasing -D_GNU_SOURCE=1 $(libss AM_LDFLAGS = $(libssh_LIBS) $(libseccomp_LIBS) $(valgrind_LIBS) sbin_PROGRAMS = potd -potd_SOURCES = utils.c log.c log_colored.c log_file.c socket.c pevent.c capabilities.c pseccomp.c jail.c forward.c redirector.c protocol.c protocol_ssh.c main.c +potd_SOURCES = utils.c options.c log.c log_colored.c log_file.c socket.c pevent.c capabilities.c pseccomp.c jail.c forward.c redirector.c protocol.c protocol_ssh.c main.c @@ -12,6 +12,7 @@ #include "log.h" #include "log_colored.h" #include "log_file.h" +#include "options.h" #include "utils.h" #include "redirector.h" #include "protocol_ssh.h" @@ -129,12 +130,21 @@ int main(int argc, char *argv[]) (void) argv; arg0 = argv[0]; - //LOG_SET_FUNCS_VA(LOG_COLORED_FUNCS); - log_file = strdup("./potd.log"); - LOG_SET_FUNCS_VA(LOG_FILE_FUNCS); + if (options_cmdline(argc, argv)) { + fprintf(stderr, "%s: parsing command line failed\n", argv[0]); + exit(EXIT_FAILURE); + } + + if (getopt_used(OPT_LOGFILE)) { + log_file = getopt_str(OPT_LOGFILE); + LOG_SET_FUNCS_VA(LOG_FILE_FUNCS); + } else { + LOG_SET_FUNCS_VA(LOG_COLORED_FUNCS); + } //log_prio = DEBUG; if (log_open()) exit(EXIT_FAILURE); + #ifdef HAVE_CONFIG_H N("%s (C) 2018 Toni Uhlig (%s)", PACKAGE_STRING, PACKAGE_BUGREPORT); #endif diff --git a/src/options.c b/src/options.c new file mode 100644 index 0000000..8d2248a --- /dev/null +++ b/src/options.c @@ -0,0 +1,134 @@ +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <assert.h> +#include <getopt.h> + +#include "options.h" + +typedef enum opt_type { + OT_INVALID = 0, OT_NOARG, OT_L, OT_LL, OT_STR +} opt_type; + +typedef union opt_ptr { + long int l; + long long int ll; + const char *str; + char *str_dup; +} opt_ptr; + +struct opt { + opt_type type; + opt_ptr value; + opt_ptr def_value; + int used; + int is_list; + + const char *arg_name; + const char *short_help; + const char *help; +}; + +#define OPT(type, def_value, is_list, arg, short_help, help) \ + { type, {0}, {def_value}, 0, is_list, arg, short_help, help } +#define OPT_STR(def_value, is_list, arg, short_help, help) \ + OPT(OT_STR, .str = def_value, is_list, arg, short_help, help) +#define OPT_NOARG(arg, short_help, help) \ + OPT(OT_NOARG, .ll = 0, 0, arg, short_help, help) +static struct opt options[OPT_MAX+1] = { + OPT_STR("./potd.log", 0, "log", "short help", "help"), + OPT_STR(NULL, 0, "log-level", "short help", "help"), + + OPT(OT_INVALID, .ll = 0, 0, NULL, NULL, NULL) +}; + +static int setopt(struct opt *o, const char *optarg); + + +static int setopt(struct opt *o, const char *optarg) +{ + char *endptr = NULL; + + if (o->used && !o->is_list) + return 1; + + switch (o->type) { + case OT_L: + o->value.l = strtol(optarg, &endptr, 10); + break; + case OT_LL: + o->value.ll = strtoll(optarg, &endptr, 10); + break; + case OT_STR: + o->value.str_dup = strdup(optarg); + break; + case OT_NOARG: + case OT_INVALID: + return 1; + } + + if (endptr && *endptr != 0) + return 1; + + return 0; +} + +int options_cmdline(int argc, char **argv) +{ + int i, option, option_index; + struct option *o = (struct option *) calloc(OPT_MAX+1, sizeof *o); + + assert(o); + for (i = 0; i < OPT_MAX; ++i) { + o[i].name = options[i].arg_name; + o[i].has_arg = + (options[i].type == OT_NOARG ? no_argument : optional_argument); + } + + while (1) { + option_index = -1; + option = getopt_long_only(argc, argv, "", o, &option_index); + if (option == -1 || option_index == -1) + break; + + if (!option) { + options[option_index].used = 1; + + if (optarg && options[option_index].type != OT_INVALID && + options[option_index].type != OT_NOARG) + { + if (setopt(&options[option_index], optarg)) { + goto error; + } + } else goto error; + } else { + fprintf(stderr, "%s: unknown option '%c' [0x%X]\n", + argv[0], option, option); + } + } + +error: + free(o); + + return 0; +} + +int getopt_used(opt_name on) +{ + return options[on].used; +} + +char * +getopt_str(opt_name on) +{ + char *str; + + assert(options[on].type == OT_STR); + assert(getopt_used(on) || options[on].def_value.str); + str = options[on].value.str_dup; + if (!str) + str = options[on].def_value.str_dup; + + return str; +} diff --git a/src/options.h b/src/options.h new file mode 100644 index 0000000..bd6c139 --- /dev/null +++ b/src/options.h @@ -0,0 +1,18 @@ +#ifndef POTD_OPTIONS_H +#define POTD_OPTIONS_H 1 + +typedef enum opt_name { + OPT_LOGFILE = 0, OPT_LOGLEVEL, + + OPT_MAX +} opt_name; + + +int options_cmdline(int argc, char **argv); + +int getopt_used(opt_name on); + +char * +getopt_str(opt_name on); + +#endif |