Merge pull request #15906 from keszybz/busctl-stdout-stderr

Make busctl stdout/stderr split consistent
This commit is contained in:
Lennart Poettering 2020-05-26 15:38:14 +02:00 committed by GitHub
commit cf3317f63a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 200 additions and 85 deletions

3
TODO
View File

@ -4,9 +4,6 @@ Bugfixes:
manager or system manager can be always set. It would be better to reject
them when parsing config.
* busctl prints errors to stdout:
busctl tree org.freedesktop.systemd1 /org/freedesktop/systemd1
External:
* Fedora: add an rpmlint check that verifies that all unit files in the RPM are listed in %systemd_post macros.

View File

@ -267,6 +267,12 @@ manpages = [
['sd_bus_get_n_queued_read', '3', ['sd_bus_get_n_queued_write'], ''],
['sd_bus_get_name_creds', '3', ['sd_bus_get_owner_creds'], ''],
['sd_bus_get_name_machine_id', '3', [], ''],
['sd_bus_interface_name_is_valid',
'3',
['sd_bus_member_name_is_valid',
'sd_bus_object_path_is_valid',
'sd_bus_service_name_is_valid'],
''],
['sd_bus_is_open', '3', ['sd_bus_is_ready'], ''],
['sd_bus_list_names', '3', [], ''],
['sd_bus_message_append', '3', ['sd_bus_message_appendv'], ''],

View File

@ -89,6 +89,7 @@
<citerefentry><refentrytitle>sd_bus_get_scope</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_tid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_get_unique_name</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_interface_name_is_valid</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_is_monitor</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_is_bus_client</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_is_server</refentrytitle><manvolnum>3</manvolnum></citerefentry>,

View File

@ -0,0 +1,98 @@
<?xml version='1.0'?>
<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
<refentry id="sd_bus_interface_name_is_valid" xmlns:xi="http://www.w3.org/2001/XInclude">
<refentryinfo>
<title>sd_bus_interface_name_is_valid</title>
<productname>systemd</productname>
</refentryinfo>
<refmeta>
<refentrytitle>sd_bus_interface_name_is_valid</refentrytitle>
<manvolnum>3</manvolnum>
</refmeta>
<refnamediv>
<refname>sd_bus_interface_name_is_valid</refname>
<refname>sd_bus_service_name_is_valid</refname>
<refname>sd_bus_member_name_is_valid</refname>
<refname>sd_bus_object_path_is_valid</refname>
<refpurpose>Check if a string is a valid bus name or object path</refpurpose>
</refnamediv>
<refsynopsisdiv>
<funcsynopsis>
<funcsynopsisinfo>#include &lt;systemd/sd-bus.h&gt;</funcsynopsisinfo>
<funcprototype>
<funcdef>int <function>sd_bus_interface_name_is_valid</function></funcdef>
<paramdef>const char* <parameter>p</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_bus_service_name_is_valid</function></funcdef>
<paramdef>const char* <parameter>p</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_bus_member_name_is_valid</function></funcdef>
<paramdef>const char* <parameter>p</parameter></paramdef>
</funcprototype>
<funcprototype>
<funcdef>int <function>sd_bus_object_path_is_valid</function></funcdef>
<paramdef>const char* <parameter>p</parameter></paramdef>
</funcprototype>
</funcsynopsis>
</refsynopsisdiv>
<refsect1>
<title>Description</title>
<para><function>sd_bus_interface_name_is_valid()</function> checks if a given string
<parameter>p</parameter> is a syntactically valid bus interface name. Similarly,
<function>sd_bus_service_name_is_valid()</function> checks if the argument is a valid bus service name,
<function>sd_bus_member_name_is_valid()</function> checks if the argument is a valid bus interface member
name, and <function>sd_bus_object_path_is_valid()</function> checks if the argument is a valid bus object
path. Those functions generally check that only allowed characters are used and that the length of the
string is within limits.</para>
</refsect1>
<refsect1>
<title>Return Value</title>
<para>Those functions return 1 if the argument is a valid interface / service / member name or object
path, and 0 if it is not. If the argument is NULL, an error is returned.</para>
<refsect2>
<title>Errors</title>
<para>Returned errors may indicate the following problems:</para>
<variablelist>
<varlistentry>
<term><constant>-EINVAL</constant></term>
<listitem><para>The <parameter>p</parameter> parameter is
<constant>NULL</constant>.</para></listitem>
</varlistentry>
</variablelist>
</refsect2>
</refsect1>
<xi:include href="libsystemd-pkgconfig.xml" />
<refsect1>
<title>See Also</title>
<para>
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd-bus</refentrytitle><manvolnum>3</manvolnum></citerefentry>,
<citerefentry><refentrytitle>sd_bus_message_call_method</refentrytitle><manvolnum>3</manvolnum></citerefentry>
</para>
</refsect1>
</refentry>

View File

@ -110,13 +110,10 @@ static int acquire_bus(bool set_monitor, sd_bus **ret) {
switch (arg_transport) {
case BUS_TRANSPORT_LOCAL:
if (arg_user) {
bus->is_user = true;
if (arg_user)
r = bus_set_address_user(bus);
} else {
bus->is_system = true;
else
r = bus_set_address_system(bus);
}
break;
case BUS_TRANSPORT_REMOTE:
@ -427,29 +424,15 @@ static void print_subtree(const char *prefix, const char *path, char **l) {
}
}
static void print_tree(const char *prefix, char **l) {
prefix = strempty(prefix);
if (arg_list) {
char **i;
STRV_FOREACH(i, l)
printf("%s%s\n", prefix, *i);
return;
}
if (strv_isempty(l)) {
static void print_tree(char **l) {
if (arg_list)
strv_print(l);
else if (strv_isempty(l))
printf("No objects discovered.\n");
return;
}
if (streq(l[0], "/") && !l[1]) {
else if (streq(l[0], "/") && !l[1])
printf("Only root object discovered.\n");
return;
}
print_subtree(prefix, "/", l);
else
print_subtree("", "/", l);
}
static int on_path(const char *path, void *userdata) {
@ -465,7 +448,7 @@ static int on_path(const char *path, void *userdata) {
return 0;
}
static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths, bool many) {
static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *paths) {
static const XMLIntrospectOps ops = {
.on_path = on_path,
};
@ -479,12 +462,10 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p
"org.freedesktop.DBus.Introspectable", "Introspect",
&error, &reply, "");
if (r < 0) {
if (many)
printf("Failed to introspect object %s of service %s: %s\n",
path, service, bus_error_message(&error, r));
else
log_error_errno(r, "Failed to introspect object %s of service %s: %s",
path, service, bus_error_message(&error, r));
printf("%sFailed to introspect object %s of service %s: %s%s\n",
ansi_highlight_red(),
path, service, bus_error_message(&error, r),
ansi_normal());
return r;
}
@ -495,34 +476,23 @@ static int find_nodes(sd_bus *bus, const char *service, const char *path, Set *p
return parse_xml_introspect(path, xml, &ops, paths);
}
static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool many) {
_cleanup_set_free_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
static int tree_one(sd_bus *bus, const char *service) {
_cleanup_set_free_ Set *paths = NULL, *done = NULL, *failed = NULL;
_cleanup_free_ char **l = NULL;
char *m;
int r;
paths = set_new(&string_hash_ops);
if (!paths)
r = set_put_strdup(&paths, "/");
if (r < 0)
return log_oom();
done = set_new(&string_hash_ops);
done = set_new(&string_hash_ops_free);
if (!done)
return log_oom();
failed = set_new(&string_hash_ops);
failed = set_new(&string_hash_ops_free);
if (!failed)
return log_oom();
m = strdup("/");
if (!m)
return log_oom();
r = set_put(paths, m);
if (r < 0) {
free(m);
return log_oom();
}
for (;;) {
_cleanup_free_ char *p = NULL;
int q;
@ -535,20 +505,14 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
set_contains(failed, p))
continue;
q = find_nodes(bus, service, p, paths, many);
if (q < 0) {
if (r >= 0)
r = q;
q = set_put(failed, p);
} else
q = set_put(done, p);
q = find_nodes(bus, service, p, paths);
if (q < 0 && r >= 0)
r = q;
q = set_consume(q < 0 ? failed : done, TAKE_PTR(p));
assert(q != 0);
if (q < 0)
return log_oom();
assert(q != 0);
p = NULL;
}
(void) pager_open(arg_pager_flags);
@ -558,7 +522,7 @@ static int tree_one(sd_bus *bus, const char *service, const char *prefix, bool m
return log_oom();
strv_sort(l);
print_tree(prefix, l);
print_tree(l);
fflush(stdout);
@ -570,6 +534,12 @@ static int tree(int argc, char **argv, void *userdata) {
char **i;
int r = 0;
/* Do superficial verification of arguments before even opening the bus */
STRV_FOREACH(i, strv_skip(argv, 1))
if (!sd_bus_service_name_is_valid(*i))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid bus service name: %s", *i);
if (!arg_unique && !arg_acquired)
arg_acquired = true;
@ -601,14 +571,14 @@ static int tree(int argc, char **argv, void *userdata) {
printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
q = tree_one(bus, *i, NULL, true);
q = tree_one(bus, *i);
if (q < 0 && r >= 0)
r = q;
not_first = true;
}
} else {
STRV_FOREACH(i, argv+1) {
} else
STRV_FOREACH(i, strv_skip(argv, 1)) {
int q;
if (i > argv+1)
@ -619,11 +589,10 @@ static int tree(int argc, char **argv, void *userdata) {
printf("Service %s%s%s:\n", ansi_highlight(), *i, ansi_normal());
}
q = tree_one(bus, *i, NULL, !!argv[2]);
q = tree_one(bus, *i);
if (q < 0 && r >= 0)
r = q;
}
}
return r;
}
@ -1291,7 +1260,7 @@ static int monitor(int argc, char **argv, int (*dump)(sd_bus_message *m, FILE *f
STRV_FOREACH(i, argv+1) {
_cleanup_free_ char *m = NULL;
if (!service_name_is_valid(*i))
if (!sd_bus_service_name_is_valid(*i))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid service name '%s'", *i);
m = strjoin("sender='", *i, "'");
@ -2608,7 +2577,6 @@ static int parse_argv(int argc, char *argv[]) {
}
static int busctl_main(int argc, char *argv[]) {
static const Verb verbs[] = {
{ "list", VERB_ANY, 1, VERB_DEFAULT, list_bus_names },
{ "status", VERB_ANY, 2, 0, status },

View File

@ -2,7 +2,6 @@
#include "alloc-util.h"
#include "bus-common-errors.h"
#include "bus-internal.h"
#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-kill.h"
@ -140,7 +139,7 @@ static int bus_scope_set_transient_property(
if (r < 0)
return r;
if (!isempty(controller) && !service_name_is_valid(controller))
if (!isempty(controller) && !sd_bus_service_name_is_valid(controller))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Controller '%s' is not a valid bus name.", controller);
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {

View File

@ -4,7 +4,6 @@
#include "alloc-util.h"
#include "async.h"
#include "bus-internal.h"
#include "bus-util.h"
#include "dbus-cgroup.h"
#include "dbus-execute.h"
@ -258,7 +257,7 @@ static BUS_DEFINE_SET_TRANSIENT_PARSE(notify_access, NotifyAccess, notify_access
static BUS_DEFINE_SET_TRANSIENT_PARSE(service_type, ServiceType, service_type_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(service_restart, ServiceRestart, service_restart_from_string);
static BUS_DEFINE_SET_TRANSIENT_PARSE(oom_policy, OOMPolicy, oom_policy_from_string);
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, service_name_is_valid);
static BUS_DEFINE_SET_TRANSIENT_STRING_WITH_CHECK(bus_name, sd_bus_service_name_is_valid);
static int bus_service_set_transient_property(
Service *s,

View File

@ -1948,7 +1948,7 @@ int config_parse_bus_name(
return 0;
}
if (!service_name_is_valid(k)) {
if (!sd_bus_service_name_is_valid(k)) {
log_syntax(unit, LOG_ERR, filename, line, 0, "Invalid bus name, ignoring: %s", k);
return 0;
}

View File

@ -700,6 +700,11 @@ global:
LIBSYSTEMD_246 {
global:
sd_bus_interface_name_is_valid;
sd_bus_service_name_is_valid;
sd_bus_member_name_is_valid;
sd_bus_object_path_is_valid;
sd_bus_call_methodv;
sd_bus_call_method_asyncv;
sd_bus_emit_signalv;
@ -707,6 +712,7 @@ global:
sd_bus_reply_method_errorfv;
sd_bus_reply_method_returnv;
sd_bus_set_propertyv;
sd_path_lookup;
sd_path_lookup_strv;
} LIBSYSTEMD_245;

View File

@ -354,6 +354,7 @@ bool interface_name_is_valid(const char *p) _pure_;
bool service_name_is_valid(const char *p) _pure_;
bool member_name_is_valid(const char *p) _pure_;
bool object_path_is_valid(const char *p) _pure_;
char *object_path_startswith(const char *a, const char *b) _pure_;
bool namespace_complex_pattern(const char *pattern, const char *value) _pure_;

View File

@ -4,6 +4,7 @@
#include "sd-bus.h"
#include "bus-internal.h"
#include "bus-type.h"
bool bus_type_is_valid(char c) {
@ -135,3 +136,27 @@ int bus_type_get_size(char c) {
return -EINVAL;
}
_public_ int sd_bus_interface_name_is_valid(const char *p) {
assert_return(p, -EINVAL);
return interface_name_is_valid(p);
}
_public_ int sd_bus_service_name_is_valid(const char *p) {
assert_return(p, -EINVAL);
return service_name_is_valid(p);
}
_public_ int sd_bus_member_name_is_valid(const char *p) {
assert_return(p, -EINVAL);
return member_name_is_valid(p);
}
_public_ int sd_bus_object_path_is_valid(const char *p) {
assert_return(p, -EINVAL);
return object_path_is_valid(p);
}

View File

@ -1266,10 +1266,16 @@ _public_ int sd_bus_open(sd_bus **ret) {
int bus_set_address_system(sd_bus *b) {
const char *e;
int r;
assert(b);
e = secure_getenv("DBUS_SYSTEM_BUS_ADDRESS");
return sd_bus_set_address(b, e ?: DEFAULT_SYSTEM_BUS_ADDRESS);
r = sd_bus_set_address(b, e ?: DEFAULT_SYSTEM_BUS_ADDRESS);
if (r >= 0)
b->is_system = true;
return r;
}
_public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *description) {
@ -1293,7 +1299,6 @@ _public_ int sd_bus_open_system_with_description(sd_bus **ret, const char *descr
return r;
b->bus_client = true;
b->is_system = true;
/* Let's do per-method access control on the system bus. We
* need the caller's UID and capability set for that. */
@ -1316,6 +1321,7 @@ _public_ int sd_bus_open_system(sd_bus **ret) {
int bus_set_address_user(sd_bus *b) {
const char *a;
_cleanup_free_ char *_a = NULL;
int r;
assert(b);
@ -1337,7 +1343,10 @@ int bus_set_address_user(sd_bus *b) {
a = _a;
}
return sd_bus_set_address(b, a);
r = sd_bus_set_address(b, a);
if (r >= 0)
b->is_user = true;
return r;
}
_public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *description) {
@ -1361,7 +1370,6 @@ _public_ int sd_bus_open_user_with_description(sd_bus **ret, const char *descrip
return r;
b->bus_client = true;
b->is_user = true;
/* We don't do any per-method access control on the user bus. */
b->trusted = true;

View File

@ -1156,7 +1156,7 @@ int bus_path_encode_unique(sd_bus *b, const char *prefix, const char *sender_id,
int r;
assert_return(b || (sender_id && external_id), -EINVAL);
assert_return(object_path_is_valid(prefix), -EINVAL);
assert_return(sd_bus_object_path_is_valid(prefix), -EINVAL);
assert_return(ret_path, -EINVAL);
if (!sender_id) {
@ -1208,8 +1208,8 @@ int bus_path_decode_unique(const char *path, const char *prefix, char **ret_send
const char *p, *q;
char *sender, *external;
assert(object_path_is_valid(path));
assert(object_path_is_valid(prefix));
assert(sd_bus_object_path_is_valid(path));
assert(sd_bus_object_path_is_valid(prefix));
assert(ret_sender);
assert(ret_external);
@ -1670,7 +1670,7 @@ int bus_introspect_implementations(
}
struct introspect intro = {};
bool is_interface = interface_name_is_valid(pattern);
bool is_interface = sd_bus_interface_name_is_valid(pattern);
impl = find_implementation(pattern, bus_objects);
if (!impl)

View File

@ -124,6 +124,13 @@ typedef _sd_destroy_t sd_bus_destroy_t;
#include "sd-bus-protocol.h"
#include "sd-bus-vtable.h"
/* Naming */
int sd_bus_interface_name_is_valid(const char *p);
int sd_bus_service_name_is_valid(const char *p);
int sd_bus_member_name_is_valid(const char *p);
int sd_bus_object_path_is_valid(const char *p);
/* Connections */
int sd_bus_default(sd_bus **ret);