X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fafb-config.c;h=fcc69a418c0f9ad1383a49b144c28105c1342a3f;hb=refs%2Fheads%2Fsandbox%2FDDTLK%2Fpakage;hp=a791969f98b3175234bb986dbbbd41f3ac88f453;hpb=9c2e6e45d4c9745c4702ac1992a0cb086e99fb0b;p=src%2Fapp-framework-binder.git diff --git a/src/afb-config.c b/src/afb-config.c index a791969f..fcc69a41 100644 --- a/src/afb-config.c +++ b/src/afb-config.c @@ -107,17 +107,17 @@ #define SET_TRACEDITF 25 #define SET_TRACESVC 26 #endif - +#define SET_TRAP_FAULTS 27 +#define ADD_CALL 28 #if defined(WITH_DBUS_TRANSPARENCY) # define ADD_DBUS_CLIENT 30 # define ADD_DBUS_SERVICE 31 #endif - #define ADD_AUTO_API 'A' #define ADD_BINDING 'b' #define SET_CONFIG 'C' -#define ADD_CALL 'c' +#define SET_COLOR 'c' #define SET_DAEMON 'D' #define SET_EXEC 'e' #define GET_HELP 'h' @@ -130,11 +130,13 @@ #define SET_PORT 'p' #define SET_QUIET 'q' #define SET_RANDOM_TOKEN 'r' +#define ADD_SET 's' #define SET_TOKEN 't' #define SET_UPLOAD_DIR 'u' #define GET_VERSION 'V' #define SET_VERBOSE 'v' #define SET_WORK_DIR 'w' +#define DUMP_CONFIG 'Z' /* structure for defining of options */ struct option_desc { @@ -148,6 +150,7 @@ struct option_desc { static struct option_desc optdefs[] = { /* *INDENT-OFF* */ {SET_VERBOSE, 0, "verbose", "Verbose Mode, repeat to increase verbosity"}, + {SET_COLOR, 0, "color", "Colorize the ouput"}, {SET_QUIET, 0, "quiet", "Quiet Mode, repeat to decrease verbosity"}, {SET_LOG, 1, "log", "Tune log level"}, @@ -168,8 +171,8 @@ static struct option_desc optdefs[] = { {SET_CACHE_TIMEOUT, 1, "cache-eol", "Client cache end of live [default " d2s(DEFAULT_CACHE_TIMEOUT) "]"}, {SET_WORK_DIR, 1, "workdir", "Set the working directory [default: $PWD or current working directory]"}, - {SET_UPLOAD_DIR, 1, "uploaddir", "Directory for uploading files [default: workdir]"}, - {SET_ROOT_DIR, 1, "rootdir", "Root Directory of the application [default: workdir]"}, + {SET_UPLOAD_DIR, 1, "uploaddir", "Directory for uploading files [default: workdir] relative to workdir"}, + {SET_ROOT_DIR, 1, "rootdir", "Root Directory of the application [default: workdir] relative to workdir"}, {ADD_LDPATH, 1, "ldpaths", "Load bindings from dir1:dir2:... [default = " BINDING_INSTALL_DIR "]"}, {ADD_BINDING, 1, "binding", "Load the binding of path"}, @@ -213,8 +216,13 @@ static struct option_desc optdefs[] = { #endif {SET_CONFIG, 1, "config", "Load options from the given config file"}, + {DUMP_CONFIG, 0, "dump-config", "Dump the config to stdout and exit"}, + + {ADD_SET, 1, "set", "Set parameters ([API]/[KEY]:JSON or {\"API\":{\"KEY\":JSON}}" }, {SET_OUTPUT, 1, "output", "Redirect stdout and stderr to output file (when --daemon)"}, + {SET_TRAP_FAULTS, 1, "trap-faults", "Trap faults: on, off, yes, no, true, false, 1, 0 (default: true)"}, + {0, 0, NULL, NULL} /* *INDENT-ON* */ }; @@ -396,6 +404,30 @@ static void printHelp(FILE * file, const char *name) name); } +static void dump(struct json_object *config, FILE *file, const char *prefix, const char *title) +{ + const char *head, *tail; + + if (title) + fprintf(file, "%s----BEGIN OF %s-----\n", prefix ?: "", title); + + head = json_object_to_json_string_ext(config, JSON_C_TO_STRING_PRETTY + |JSON_C_TO_STRING_SPACED|JSON_C_TO_STRING_NOSLASHESCAPE); + + if (!prefix) + fprintf(file, "%s\n", head); + else { + while(*head) { + for (tail = head ; *tail && *tail != '\n' ; tail++); + fprintf(file, "%s %.*s\n", prefix, (int)(tail - head), head); + head = tail + !!*tail; + } + } + + if (title) + fprintf(file, "%s----END OF %s-----\n", prefix ?: "", title); +} + /********************************** * json helpers ***********************************/ @@ -424,6 +456,29 @@ static struct json_object *to_jbool(int value) * arguments helpers ***********************************/ +static int string_to_bool(const char *value) +{ + static const char true_names[] = "1\0yes\0true\0on"; + static const char false_names[] = "0\0no\0false\0off"; + size_t pos; + + pos = 0; + while (pos < sizeof true_names) + if (strcasecmp(value, &true_names[pos])) + pos += 1 + strlen(&true_names[pos]); + else + return 1; + + pos = 0; + while (pos < sizeof false_names) + if (strcasecmp(value, &false_names[pos])) + pos += 1 + strlen(&false_names[pos]); + else + return 0; + + return -1; +} + static void noarg(int optid) { if (optarg) { @@ -442,6 +497,17 @@ static const char *get_arg(int optid) return optarg; } +static int get_arg_bool(int optid) +{ + int value = string_to_bool(get_arg(optid)); + if (value < 0) { + ERROR("option [--%s] needs a boolean value: yes/no, true/false, on/off, 1/0", + name_of_optid(optid)); + exit(1); + } + return value; +} + static void config_del(struct json_object *config, int optid) { return json_object_object_del(config, name_of_optid(optid)); @@ -539,8 +605,7 @@ static void config_add(struct json_object *config, int optid, struct json_object { struct json_object *a; if (!json_object_object_get_ex(config, name_of_optid(optid), &a)) { - a = json_object_new_array(); - oomchk(a); + a = joomchk(json_object_new_array()); json_object_object_add(config, name_of_optid(optid), a); } json_object_array_add(a, val); @@ -556,6 +621,73 @@ static void config_add_optstr(struct json_object *config, int optid) config_add_str(config, optid, get_arg(optid)); } +static void config_mix2_cb(void *closure, struct json_object *obj, const char *name) +{ + struct json_object *dest, *base = closure; + + if (!name) + name = ""; + + if (!json_object_object_get_ex(base, name, &dest)) { + dest = joomchk(json_object_new_object()); + json_object_object_add(base, name, dest); + } + if (json_object_is_type(obj, json_type_object)) + wrap_json_object_add(dest, obj); + else + json_object_object_add(dest, "", json_object_get(obj)); +} + +static void config_mix2(struct json_object *config, int optid, struct json_object *val) +{ + struct json_object *obj; + + if (!json_object_object_get_ex(config, name_of_optid(optid), &obj)) { + obj = joomchk(json_object_new_object()); + json_object_object_add(config, name_of_optid(optid), obj); + } + wrap_json_for_all(val, config_mix2_cb, obj); +} + +static void config_mix2_str(struct json_object *config, int optid, const char *val) +{ + size_t st1, st2; + const char *api, *key; + struct json_object *obj, *sub; + enum json_tokener_error jerr; + + st1 = strcspn(val, "/:{[\""); + st2 = strcspn(&val[st1], ":{[\""); + if (val[st1] != '/' || val[st1 + st2] != ':') { + obj = json_tokener_parse_verbose(val, &jerr); + if (jerr != json_tokener_success) + obj = json_object_new_string(val); + } else { + api = st1 == 0 ? "*" : strndupa(val, st1); + val += st1 + 1; + key = st2 <= 1 || (st2 == 2 && *val == '*') ? NULL : strndupa(val, st2 - 1); + val += st2; + sub = json_tokener_parse_verbose(val, &jerr); + if (jerr != json_tokener_success) + sub = json_object_new_string(val); + + if (key) { + obj = json_object_new_object(); + json_object_object_add(obj, key, sub); + sub = obj; + } + obj = json_object_new_object(); + json_object_object_add(obj, api, sub); + } + config_mix2(config, optid, obj); + json_object_put(obj); +} + +static void config_mix2_optstr(struct json_object *config, int optid) +{ + config_mix2_str(config, optid, get_arg(optid)); +} + /*--------------------------------------------------------- | set the log levels +--------------------------------------------------------- */ @@ -610,7 +742,7 @@ static void set_log(const char *args) static void parse_arguments_inner(int argc, char **argv, struct json_object *config, struct option *options) { struct json_object *conf; - int optid, cind; + int optid, cind, dodump = 0; for (;;) { cind = optind; @@ -624,6 +756,10 @@ static void parse_arguments_inner(int argc, char **argv, struct json_object *con verbose_inc(); break; + case SET_COLOR: + verbose_colorize(); + break; + case SET_QUIET: verbose_dec(); break; @@ -672,6 +808,10 @@ static void parse_arguments_inner(int argc, char **argv, struct json_object *con config_add_optstr(config, optid); break; + case ADD_SET: + config_mix2_optstr(config, optid); + break; + #if defined(WITH_MONITORING_OPTION) case SET_MONITORING: #endif @@ -690,6 +830,11 @@ static void parse_arguments_inner(int argc, char **argv, struct json_object *con config_set_bool(config, SET_DAEMON, optid != SET_FOREGROUND); break; + case SET_TRAP_FAULTS: + config_set_bool(config, optid, get_arg_bool(optid)); + break; + + case SET_TRACEREQ: config_set_optenum(config, optid, afb_hook_flags_xreq_from_text); break; @@ -739,6 +884,11 @@ static void parse_arguments_inner(int argc, char **argv, struct json_object *con json_object_put(conf); break; + case DUMP_CONFIG: + noarg(optid); + dodump = 1; + break; + case GET_VERSION: noarg(optid); printVersion(stdout); @@ -754,6 +904,11 @@ static void parse_arguments_inner(int argc, char **argv, struct json_object *con } } /* TODO: check for extra value */ + + if (dodump) { + dump(config, stdout, NULL, NULL); + exit(0); + } } static void parse_arguments(int argc, char **argv, struct json_object *config) @@ -807,45 +962,17 @@ static void fulfill_config(struct json_object *config) #endif } -static void dump(struct json_object *config, FILE *file, const char *prefix, const char *title) -{ - char z; - const char *head, *tail; - - if (!prefix) { - z = 0; - prefix = &z; - } - - if (title) - fprintf(file, "%s----BEGIN OF %s-----\n", prefix, title); - - head = json_object_to_json_string_ext(config, JSON_C_TO_STRING_PRETTY - |JSON_C_TO_STRING_SPACED|JSON_C_TO_STRING_NOSLASHESCAPE); - - if (head) { - while(*head) { - for (tail = head ; *tail && *tail != '\n' ; tail++); - fprintf(file, "%s %.*s\n", prefix, (int)(tail - head), head); - head = tail + !!*tail; - } - } - - if (title) - fprintf(file, "%s----END OF %s-----\n", prefix, title); -} - void afb_config_dump(struct json_object *config) { dump(config, stderr, "--", "CONFIG"); } -static void on_environment_add(struct json_object *config, int optid, const char *name) +static void on_environment(struct json_object *config, int optid, const char *name, void (*func)(struct json_object*, int, const char*)) { char *value = getenv(name); if (value && *value) - config_add_str(config, optid, value); + func(config, optid, value); } static void on_environment_enum(struct json_object *config, int optid, const char *name, int (*func)(const char*)) @@ -860,6 +987,20 @@ static void on_environment_enum(struct json_object *config, int optid, const cha } } +static void on_environment_bool(struct json_object *config, int optid, const char *name) +{ + char *value = getenv(name); + int asbool; + + if (value) { + asbool = string_to_bool(value); + if (asbool < 0) + WARNING("Unknown value %s for environment variable %s, ignored", value, name); + else + config_set_bool(config, optid, asbool); + } +} + static void parse_environment(struct json_object *config) { on_environment_enum(config, SET_TRACEREQ, "AFB_TRACEREQ", afb_hook_flags_xreq_from_text); @@ -867,11 +1008,13 @@ static void parse_environment(struct json_object *config) on_environment_enum(config, SET_TRACESES, "AFB_TRACESES", afb_hook_flags_session_from_text); on_environment_enum(config, SET_TRACEAPI, "AFB_TRACEAPI", afb_hook_flags_api_from_text); on_environment_enum(config, SET_TRACEGLOB, "AFB_TRACEGLOB", afb_hook_flags_global_from_text); - on_environment_add(config, ADD_LDPATH, "AFB_LDPATHS"); + on_environment(config, ADD_LDPATH, "AFB_LDPATHS", config_add_str); + on_environment(config, ADD_SET, "AFB_SET", config_mix2_str); #if !defined(REMOVE_LEGACY_TRACE) on_environment_enum(config, SET_TRACEDITF, "AFB_TRACEDITF", afb_hook_flags_legacy_ditf_from_text); on_environment_enum(config, SET_TRACESVC, "AFB_TRACESVC", afb_hook_flags_legacy_svc_from_text); #endif + on_environment_bool(config, SET_TRAP_FAULTS, "AFB_TRAP_FAULTS"); } struct json_object *afb_config_parse_arguments(int argc, char **argv)