diff options
Diffstat (limited to 'src/varlinkctl')
-rw-r--r-- | src/varlinkctl/varlinkctl.c | 66 |
1 files changed, 50 insertions, 16 deletions
diff --git a/src/varlinkctl/varlinkctl.c b/src/varlinkctl/varlinkctl.c index 64105c7..9da484d 100644 --- a/src/varlinkctl/varlinkctl.c +++ b/src/varlinkctl/varlinkctl.c @@ -19,6 +19,7 @@ static JsonFormatFlags arg_json_format_flags = JSON_FORMAT_OFF; static PagerFlags arg_pager_flags = 0; static VarlinkMethodFlags arg_method_flags = 0; +static bool arg_collect = false; static int help(void) { _cleanup_free_ char *link = NULL; @@ -47,6 +48,7 @@ static int help(void) { " --version Show package version\n" " --no-pager Do not pipe output into a pager\n" " --more Request multiple responses\n" + " --collect Collect multiple responses in a JSON array\n" " --oneway Do not request response\n" " --json=MODE Output as JSON\n" " -j Same as --json=pretty on tty, --json=short otherwise\n" @@ -73,6 +75,7 @@ static int parse_argv(int argc, char *argv[]) { ARG_MORE, ARG_ONEWAY, ARG_JSON, + ARG_COLLECT, }; static const struct option options[] = { @@ -82,6 +85,7 @@ static int parse_argv(int argc, char *argv[]) { { "more", no_argument, NULL, ARG_MORE }, { "oneway", no_argument, NULL, ARG_ONEWAY }, { "json", required_argument, NULL, ARG_JSON }, + { "collect", no_argument, NULL, ARG_COLLECT }, {}, }; @@ -112,6 +116,10 @@ static int parse_argv(int argc, char *argv[]) { arg_method_flags = (arg_method_flags & ~VARLINK_METHOD_MORE) | VARLINK_METHOD_ONEWAY; break; + case ARG_COLLECT: + arg_collect = true; + break; + case ARG_JSON: r = parse_json_argument(optarg, &arg_json_format_flags); if (r <= 0) @@ -210,12 +218,9 @@ static int verb_info(int argc, char *argv[], void *userdata) { return r; JsonVariant *reply = NULL; - const char *error = NULL; - r = varlink_call(vl, "org.varlink.service.GetInfo", NULL, &reply, &error, NULL); + r = varlink_call_and_log(vl, "org.varlink.service.GetInfo", /* parameters= */ NULL, &reply); if (r < 0) - return log_error_errno(r, "Failed to issue GetInfo() call: %m"); - if (error) - return log_error_errno(SYNTHETIC_ERRNO(EBADE), "Method call GetInfo() failed: %s", error); + return r; pager_open(arg_pager_flags); @@ -296,12 +301,13 @@ static int verb_introspect(int argc, char *argv[], void *userdata) { return r; JsonVariant *reply = NULL; - const char *error = NULL; - r = varlink_callb(vl, "org.varlink.service.GetInterfaceDescription", &reply, &error, NULL, JSON_BUILD_OBJECT(JSON_BUILD_PAIR_STRING("interface", interface))); + r = varlink_callb_and_log( + vl, + "org.varlink.service.GetInterfaceDescription", + &reply, + JSON_BUILD_OBJECT(JSON_BUILD_PAIR_STRING("interface", interface))); if (r < 0) - return log_error_errno(r, "Failed to issue GetInterfaceDescription() call: %m"); - if (error) - return log_error_errno(SYNTHETIC_ERRNO(EBADE), "Method call GetInterfaceDescription() failed: %s", error); + return r; pager_open(arg_pager_flags); @@ -344,7 +350,7 @@ static int reply_callback( VarlinkReplyFlags flags, void *userdata) { - int r; + int *ret = ASSERT_PTR(userdata), r; assert(link); @@ -352,7 +358,7 @@ static int reply_callback( /* Propagate the error we received via sd_notify() */ (void) sd_notifyf(/* unset_environment= */ false, "VARLINKERROR=%s", error); - r = log_error_errno(SYNTHETIC_ERRNO(EBADE), "Method call failed: %s", error); + r = *ret = log_error_errno(SYNTHETIC_ERRNO(EBADE), "Method call failed: %s", error); } else r = 0; @@ -373,7 +379,13 @@ static int verb_call(int argc, char *argv[], void *userdata) { method = argv[2]; parameter = argc > 3 && !streq(argv[3], "-") ? argv[3] : NULL; - arg_json_format_flags &= ~JSON_FORMAT_OFF; + /* No JSON mode explicitly configured? Then default to the same as -j */ + if (FLAGS_SET(arg_json_format_flags, JSON_FORMAT_OFF)) + arg_json_format_flags = JSON_FORMAT_PRETTY_AUTO|JSON_FORMAT_COLOR_AUTO; + + /* For pipeable text tools it's kinda customary to finish output off in a newline character, and not + * leave incomplete lines hanging around. */ + arg_json_format_flags |= JSON_FORMAT_NEWLINE; if (parameter) { /* <argv[4]> is correct, as dispatch_verb() shifts arguments by one for the verb. */ @@ -390,7 +402,26 @@ static int verb_call(int argc, char *argv[], void *userdata) { if (r < 0) return r; - if (arg_method_flags & VARLINK_METHOD_ONEWAY) { + if (arg_collect) { + JsonVariant *reply = NULL; + const char *error = NULL; + + r = varlink_collect(vl, method, jp, &reply, &error); + if (r < 0) + return log_error_errno(r, "Failed to issue %s() call: %m", method); + if (error) { + /* Propagate the error we received via sd_notify() */ + (void) sd_notifyf(/* unset_environment= */ false, "VARLINKERROR=%s", error); + + r = log_error_errno(SYNTHETIC_ERRNO(EBADE), "Method call %s() failed: %s", method, error); + } else + r = 0; + + pager_open(arg_pager_flags); + json_variant_dump(reply, arg_json_format_flags, stdout, NULL); + return r; + + } else if (arg_method_flags & VARLINK_METHOD_ONEWAY) { r = varlink_send(vl, method, jp); if (r < 0) return log_error_errno(r, "Failed to issue %s() call: %m", method); @@ -401,7 +432,8 @@ static int verb_call(int argc, char *argv[], void *userdata) { } else if (arg_method_flags & VARLINK_METHOD_MORE) { - varlink_set_userdata(vl, (void*) method); + int ret = 0; + varlink_set_userdata(vl, &ret); r = varlink_bind_reply(vl, reply_callback); if (r < 0) @@ -428,11 +460,13 @@ static int verb_call(int argc, char *argv[], void *userdata) { if (r < 0) return log_error_errno(r, "Failed to wait for varlink connection events: %m"); } + + return ret; } else { JsonVariant *reply = NULL; const char *error = NULL; - r = varlink_call(vl, method, jp, &reply, &error, NULL); + r = varlink_call(vl, method, jp, &reply, &error); if (r < 0) return log_error_errno(r, "Failed to issue %s() call: %m", method); |