Fedora 30 packaging fix issu
[src/app-framework-binder.git] / src / afb-config.c
index a791969..fcc69a4 100644 (file)
 #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'
 #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)