diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index 7e293e47e5..276cae1b8b 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -31,11 +31,7 @@ #include "user-util.h" #include "verbs.h" -static enum { - JSON_OFF, - JSON_SHORT, - JSON_PRETTY, -} arg_json = JSON_OFF; +static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static PagerFlags arg_pager_flags = 0; static bool arg_legend = true; static bool arg_full = false; @@ -67,7 +63,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_matches, strv_freep); #define NAME_IS_ACTIVATABLE INT_TO_PTR(2) static int json_transform_message(sd_bus_message *m, JsonVariant **ret); -static void json_dump_with_flags(JsonVariant *v, FILE *f); static int acquire_bus(bool set_monitor, sd_bus **ret) { _cleanup_(sd_bus_close_unrefp) sd_bus *bus = NULL; @@ -362,13 +357,10 @@ static int list_bus_names(int argc, char **argv, void *userdata) { return log_error_errno(r, "Failed to fill line: %m"); } - (void) pager_open(arg_pager_flags); + if (arg_json_format_flags & (JSON_FORMAT_OFF|JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO)) + (void) pager_open(arg_pager_flags); - if (arg_json) - r = table_print_json(table, stdout, - (arg_json == JSON_PRETTY ? JSON_FORMAT_PRETTY : JSON_FORMAT_NEWLINE) | JSON_FORMAT_COLOR_AUTO); - else - r = table_print(table, stdout); + r = table_print_json(table, NULL, arg_json_format_flags); if (r < 0) return table_log_print_error(r); @@ -1228,7 +1220,7 @@ static int message_json(sd_bus_message *m, FILE *f) { if (r < 0) return log_error_errno(r, "Failed to build JSON object: %m"); - json_dump_with_flags(w, f); + json_variant_dump(w, arg_json_format_flags, f, NULL); return 0; } @@ -1355,7 +1347,7 @@ static int monitor(int argc, char **argv, int (*dump)(sd_bus_message *m, FILE *f } static int verb_monitor(int argc, char **argv, void *userdata) { - return monitor(argc, argv, arg_json != JSON_OFF ? message_json : message_dump); + return monitor(argc, argv, (arg_json_format_flags & JSON_FORMAT_OFF) ? message_dump : message_json); } static int verb_capture(int argc, char **argv, void *userdata) { @@ -2006,14 +1998,6 @@ static int json_transform_message(sd_bus_message *m, JsonVariant **ret) { return 0; } -static void json_dump_with_flags(JsonVariant *v, FILE *f) { - - json_variant_dump(v, - (arg_json == JSON_PRETTY ? JSON_FORMAT_PRETTY : JSON_FORMAT_NEWLINE) | - JSON_FORMAT_COLOR_AUTO, - f, NULL); -} - static int call(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_flush_close_unrefp) sd_bus *bus = NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; @@ -2072,17 +2056,17 @@ static int call(int argc, char **argv, void *userdata) { if (r == 0 && !arg_quiet) { - if (arg_json != JSON_OFF) { + if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) { _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; - if (arg_json != JSON_SHORT) + if (arg_json_format_flags & (JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO)) (void) pager_open(arg_pager_flags); r = json_transform_message(reply, &v); if (r < 0) return r; - json_dump_with_flags(v, stdout); + json_variant_dump(v, arg_json_format_flags, NULL, NULL); } else if (arg_verbose) { (void) pager_open(arg_pager_flags); @@ -2181,17 +2165,17 @@ static int get_property(int argc, char **argv, void *userdata) { if (r < 0) return bus_log_parse_error(r); - if (arg_json != JSON_OFF) { + if (!FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) { _cleanup_(json_variant_unrefp) JsonVariant *v = NULL; - if (arg_json != JSON_SHORT) + if (arg_json_format_flags & (JSON_FORMAT_PRETTY|JSON_FORMAT_PRETTY_AUTO)) (void) pager_open(arg_pager_flags); r = json_transform_variant(reply, contents, &v); if (r < 0) return r; - json_dump_with_flags(v, stdout); + json_variant_dump(v, arg_json_format_flags, NULL, NULL); } else if (arg_verbose) { (void) pager_open(arg_pager_flags); @@ -2543,25 +2527,13 @@ static int parse_argv(int argc, char *argv[]) { break; case 'j': - if (on_tty()) - arg_json = JSON_PRETTY; - else - arg_json = JSON_SHORT; + arg_json_format_flags = JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO; break; case ARG_JSON: - if (streq(optarg, "short")) - arg_json = JSON_SHORT; - else if (streq(optarg, "pretty")) - arg_json = JSON_PRETTY; - else if (streq(optarg, "help")) { - fputs("short\n" - "pretty\n", stdout); - return 0; - } else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Unknown JSON out mode: %s", - optarg); + r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags); + if (r <= 0) + return r; break; diff --git a/src/dissect/dissect.c b/src/dissect/dissect.c index dc7e9dc626..c5d161b2b5 100644 --- a/src/dissect/dissect.c +++ b/src/dissect/dissect.c @@ -45,8 +45,7 @@ static const char *arg_source = NULL; static const char *arg_target = NULL; static DissectImageFlags arg_flags = DISSECT_IMAGE_REQUIRE_ROOT|DISSECT_IMAGE_DISCARD_ON_LOOP|DISSECT_IMAGE_RELAX_VAR_CHECK|DISSECT_IMAGE_FSCK; static VeritySettings arg_verity_settings = VERITY_SETTINGS_DEFAULT; -static bool arg_json = false; -static JsonFormatFlags arg_json_format_flags = 0; +static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; STATIC_DESTRUCTOR_REGISTER(arg_verity_settings, verity_settings_done); @@ -242,22 +241,9 @@ static int parse_argv(int argc, char *argv[]) { break; case ARG_JSON: - if (streq(optarg, "pretty")) { - arg_json = true; - arg_json_format_flags = JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR_AUTO; - } else if (streq(optarg, "short")) { - arg_json = true; - arg_json_format_flags = JSON_FORMAT_NEWLINE; - } else if (streq(optarg, "off")) { - arg_json = false; - arg_json_format_flags = 0; - } else if (streq(optarg, "help")) { - puts("pretty\n" - "short\n" - "off"); - return 0; - } else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown argument to --json=: %s", optarg); + r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags); + if (r <= 0) + return r; break; @@ -353,17 +339,17 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { assert(m); assert(d); - if (!arg_json) + if (arg_json_format_flags & JSON_FORMAT_OFF) printf(" Name: %s\n", basename(arg_image)); if (ioctl(d->fd, BLKGETSIZE64, &size) < 0) log_debug_errno(errno, "Failed to query size of loopback device: %m"); - else if (!arg_json) { + else if (arg_json_format_flags & JSON_FORMAT_OFF) { char s[FORMAT_BYTES_MAX]; printf(" Size: %s\n", format_bytes(s, sizeof(s), size)); } - if (!arg_json) + if (arg_json_format_flags & JSON_FORMAT_OFF) putc('\n', stdout); r = dissected_image_acquire_metadata(m); @@ -379,7 +365,7 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { log_warning_errno(r, "OS image is currently in use, proceeding without showing OS image metadata."); else if (r < 0) return log_error_errno(r, "Failed to acquire image metadata: %m"); - else if (!arg_json) { + else if (arg_json_format_flags & JSON_FORMAT_OFF) { if (m->hostname) printf(" Hostname: %s\n", m->hostname); @@ -495,7 +481,11 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { return table_log_add_error(r); } - if (arg_json) { + if (arg_json_format_flags & JSON_FORMAT_OFF) { + r = table_print(t, stdout); + if (r < 0) + return table_log_print_error(r); + } else { _cleanup_(json_variant_unrefp) JsonVariant *jt = NULL; r = table_to_json(t, &jt); @@ -507,10 +497,6 @@ static int action_dissect(DissectedImage *m, LoopDevice *d) { return log_oom(); json_variant_dump(v, arg_json_format_flags, stdout, NULL); - } else { - r = table_print(t, stdout); - if (r < 0) - return log_error_errno(r, "Failed to dump table: %m"); } return 0; diff --git a/src/home/homectl.c b/src/home/homectl.c index c9e54b1e67..f9c07dfec7 100644 --- a/src/home/homectl.c +++ b/src/home/homectl.c @@ -56,8 +56,7 @@ static uint64_t arg_disk_size_relative = UINT64_MAX; static char **arg_pkcs11_token_uri = NULL; static char **arg_fido2_device = NULL; static bool arg_recovery_key = false; -static bool arg_json = false; -static JsonFormatFlags arg_json_format_flags = 0; +static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static bool arg_and_resize = false; static bool arg_and_change_password = false; static enum { @@ -171,22 +170,19 @@ static int list_homes(int argc, char *argv[], void *userdata) { if (r < 0) return bus_log_parse_error(r); - if (table_get_rows(table) > 1 || arg_json) { + if (table_get_rows(table) > 1 || !FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) { r = table_set_sort(table, (size_t) 0, (size_t) -1); if (r < 0) return table_log_sort_error(r); table_set_header(table, arg_legend); - if (arg_json) - r = table_print_json(table, stdout, arg_json_format_flags); - else - r = table_print(table, NULL); + r = table_print_json(table, stdout, arg_json_format_flags); if (r < 0) return table_log_print_error(r); } - if (arg_legend && !arg_json) { + if (arg_legend && (arg_json_format_flags & JSON_FORMAT_OFF)) { if (table_get_rows(table) > 1) printf("\n%zu home areas listed.\n", table_get_rows(table) - 1); else @@ -462,7 +458,9 @@ static void dump_home_record(UserRecord *hr) { log_warning("Warning: lacking rights to acquire privileged fields of user record of '%s', output incomplete.", hr->user_name); } - if (arg_json) { + if (arg_json_format_flags & JSON_FORMAT_OFF) + user_record_show(hr, true); + else { _cleanup_(user_record_unrefp) UserRecord *stripped = NULL; if (arg_export_format == EXPORT_FORMAT_STRIPPED) @@ -477,8 +475,7 @@ static void dump_home_record(UserRecord *hr) { hr = stripped; json_variant_dump(hr->json, arg_json_format_flags, stdout, NULL); - } else - user_record_show(hr, true); + } } static char **mangle_user_list(char **list, char ***ret_allocated) { @@ -3235,27 +3232,13 @@ static int parse_argv(int argc, char *argv[]) { } case 'j': - arg_json = true; arg_json_format_flags = JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO; break; case ARG_JSON: - if (streq(optarg, "pretty")) { - arg_json = true; - arg_json_format_flags = JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR_AUTO; - } else if (streq(optarg, "short")) { - arg_json = true; - arg_json_format_flags = JSON_FORMAT_NEWLINE; - } else if (streq(optarg, "off")) { - arg_json = false; - arg_json_format_flags = 0; - } else if (streq(optarg, "help")) { - puts("pretty\n" - "short\n" - "off"); - return 0; - } else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown argument to --json=: %s", optarg); + r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags); + if (r <= 0) + return r; break; @@ -3267,7 +3250,7 @@ static int parse_argv(int argc, char *argv[]) { else return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Specifying -E more than twice is not supported."); - arg_json = true; + arg_json_format_flags &= ~JSON_FORMAT_OFF; if (arg_json_format_flags == 0) arg_json_format_flags = JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO; break; diff --git a/src/partition/repart.c b/src/partition/repart.c index 02d7f227f8..d98051d134 100644 --- a/src/partition/repart.c +++ b/src/partition/repart.c @@ -106,8 +106,7 @@ static bool arg_randomize = false; static int arg_pretty = -1; static uint64_t arg_size = UINT64_MAX; static bool arg_size_auto = false; -static bool arg_json = false; -static JsonFormatFlags arg_json_format_flags = 0; +static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static void *arg_key = NULL; static size_t arg_key_size = 0; static char *arg_tpm2_device = NULL; @@ -1824,7 +1823,7 @@ static int context_dump_partitions(Context *context, const char *node) { Partition *p; int r; - if (!arg_json && context->n_partitions == 0) { + if ((arg_json_format_flags & JSON_FORMAT_OFF) && context->n_partitions == 0) { log_info("Empty partition table."); return 0; } @@ -1834,12 +1833,12 @@ static int context_dump_partitions(Context *context, const char *node) { return log_oom(); if (!DEBUG_LOGGING) { - if (arg_json) - (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, - (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, (size_t) 12, (size_t) -1); - else + if (arg_json_format_flags & JSON_FORMAT_OFF) (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, (size_t) 8, (size_t) 11, (size_t) -1); + else + (void) table_set_display(t, (size_t) 0, (size_t) 1, (size_t) 2, (size_t) 3, (size_t) 4, + (size_t) 5, (size_t) 6, (size_t) 7, (size_t) 9, (size_t) 10, (size_t) 12, (size_t) -1); } (void) table_set_align_percent(t, table_get_cell(t, 0, 4), 100); @@ -1893,7 +1892,7 @@ static int context_dump_partitions(Context *context, const char *node) { return table_log_add_error(r); } - if (!arg_json && (sum_padding > 0 || sum_size > 0)) { + if ((arg_json_format_flags & JSON_FORMAT_OFF) && (sum_padding > 0 || sum_size > 0)) { char s[FORMAT_BYTES_MAX]; const char *a, *b; @@ -1919,12 +1918,9 @@ static int context_dump_partitions(Context *context, const char *node) { return table_log_add_error(r); } - if (arg_json) - r = table_print_json(t, stdout, arg_json_format_flags); - else - r = table_print(t, stdout); + r = table_print_json(t, stdout, arg_json_format_flags); if (r < 0) - return log_error_errno(r, "Failed to dump table: %m"); + return table_log_print_error(r); return 0; } @@ -3203,13 +3199,13 @@ static int context_write_partition_table( if (arg_pretty > 0 || (arg_pretty < 0 && isatty(STDOUT_FILENO) > 0) || - arg_json) { + !FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) { (void) context_dump_partitions(context, node); putc('\n', stdout); - if (!arg_json) + if (arg_json_format_flags & JSON_FORMAT_OFF) (void) context_dump_partition_bar(context, node); putc('\n', stdout); fflush(stdout); @@ -3679,22 +3675,9 @@ static int parse_argv(int argc, char *argv[]) { } case ARG_JSON: - if (streq(optarg, "pretty")) { - arg_json = true; - arg_json_format_flags = JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR_AUTO; - } else if (streq(optarg, "short")) { - arg_json = true; - arg_json_format_flags = JSON_FORMAT_NEWLINE; - } else if (streq(optarg, "off")) { - arg_json = false; - arg_json_format_flags = 0; - } else if (streq(optarg, "help")) { - puts("pretty\n" - "short\n" - "off"); - return 0; - } else - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown argument to --json=: %s", optarg); + r = json_parse_cmdline_parameter_and_warn(optarg, &arg_json_format_flags); + if (r <= 0) + return r; break; diff --git a/src/shared/format-table.c b/src/shared/format-table.c index a13a198b7a..645e5b9afa 100644 --- a/src/shared/format-table.c +++ b/src/shared/format-table.c @@ -2536,6 +2536,9 @@ int table_print_json(Table *t, FILE *f, JsonFormatFlags flags) { assert(t); + if (flags & JSON_FORMAT_OFF) /* If JSON output is turned off, use regular output */ + return table_print(t, f); + if (!f) f = stdout; diff --git a/src/shared/json.c b/src/shared/json.c index 6beb56cfa0..d559111248 100644 --- a/src/shared/json.c +++ b/src/shared/json.c @@ -1766,6 +1766,9 @@ int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret) { assert_return(v, -EINVAL); assert_return(ret, -EINVAL); + if (flags & JSON_FORMAT_OFF) + return -ENOEXEC; + { _cleanup_fclose_ FILE *f = NULL; @@ -4456,6 +4459,27 @@ int json_variant_unhex(JsonVariant *v, void **ret, size_t *ret_size) { return unhexmem(json_variant_string(v), (size_t) -1, ret, ret_size); } +int json_parse_cmdline_parameter_and_warn(const char *s, JsonFormatFlags *ret) { + assert(s); + assert(ret); + + if (streq(s, "pretty")) + *ret = JSON_FORMAT_PRETTY|JSON_FORMAT_COLOR_AUTO; + else if (streq(s, "short")) + *ret = JSON_FORMAT_NEWLINE; + else if (streq(s, "off")) + *ret = JSON_FORMAT_OFF; + else if (streq(s, "help")) { + puts("pretty\n" + "short\n" + "off"); + return 0; /* 0 means → we showed a brief help, exit now */ + } else + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Unknown argument to --json= switch: %s", s); + + return 1; /* 1 means → properly parsed */ +} + static const char* const json_variant_type_table[_JSON_VARIANT_TYPE_MAX] = { [JSON_VARIANT_STRING] = "string", [JSON_VARIANT_INTEGER] = "integer", diff --git a/src/shared/json.h b/src/shared/json.h index abc0dccddb..aad7326513 100644 --- a/src/shared/json.h +++ b/src/shared/json.h @@ -175,6 +175,7 @@ typedef enum JsonFormatFlags { JSON_FORMAT_SSE = 1 << 6, /* prefix/suffix with W3C server-sent events */ JSON_FORMAT_SEQ = 1 << 7, /* prefix/suffix with RFC 7464 application/json-seq */ JSON_FORMAT_FLUSH = 1 << 8, /* call fflush() after dumping JSON */ + JSON_FORMAT_OFF = 1 << 9, /* make json_variant_format() fail with -ENOEXEC */ } JsonFormatFlags; int json_variant_format(JsonVariant *v, JsonFormatFlags flags, char **ret); @@ -356,5 +357,7 @@ int json_log_internal(JsonVariant *variant, int level, int error, const char *fi int json_variant_unbase64(JsonVariant *v, void **ret, size_t *ret_size); int json_variant_unhex(JsonVariant *v, void **ret, size_t *ret_size); +int json_parse_cmdline_parameter_and_warn(const char *s, JsonFormatFlags *ret); + const char *json_variant_type_to_string(JsonVariantType t); JsonVariantType json_variant_type_from_string(const char *s);