int bus_set_address_machine(sd_bus *b, RuntimeScope runtime_scope, const char *machine) {
_cleanup_free_ char *a = NULL;
- const char *rhs;
assert(b);
assert(machine);
- rhs = strchr(machine, '@');
- if (rhs || runtime_scope == RUNTIME_SCOPE_USER) {
- _cleanup_free_ char *u = NULL, *eu = NULL, *erhs = NULL;
+ _cleanup_free_ char *u = NULL, *h = NULL;
+ int with_at;
+ with_at = split_user_at_host(machine, &u, &h);
+ if (with_at < 0)
+ return with_at;
+
+ if (with_at || runtime_scope == RUNTIME_SCOPE_USER) {
+ _cleanup_free_ char *eu = NULL, *eh = NULL;
/* If there's an "@" in the container specification, we'll connect as a user specified at its
* left hand side, which is useful in combination with user=true. This isn't as trivial as it
* into the container and acquire a PAM session there, and then invoke systemd-stdio-bridge
* in it, which propagates the bus transport to us. */
- if (rhs) {
- if (rhs > machine)
- u = strndup(machine, rhs - machine);
- else
+ if (with_at) {
+ if (!u) {
u = getusername_malloc(); /* Empty user name, let's use the local one */
- if (!u)
- return -ENOMEM;
+ if (!u)
+ return -ENOMEM;
+ }
eu = bus_address_escape(u);
if (!eu)
return -ENOMEM;
-
- rhs++;
- } else {
- /* No "@" specified but we shall connect to the user instance? Then assume root (and
- * not a user named identically to the calling one). This means:
- *
- * --machine=foobar --user → connect to user bus of root user in container "foobar"
- * --machine=@foobar --user → connect to user bus of user named like the calling user in container "foobar"
- *
- * Why? so that behaviour for "--machine=foobar --system" is roughly similar to
- * "--machine=foobar --user": both times we unconditionally connect as root user
- * regardless what the calling user is. */
-
- rhs = machine;
}
- if (!isempty(rhs)) {
- erhs = bus_address_escape(rhs);
- if (!erhs)
+ /* No "@" specified but we shall connect to the user instance? Then assume root (and
+ * not a user named identically to the calling one). This means:
+ *
+ * --machine=foobar --user → connect to user bus of root user in container "foobar"
+ * --machine=@foobar --user → connect to user bus of user named like the calling user in container "foobar"
+ *
+ * Why? so that behaviour for "--machine=foobar --system" is roughly similar to
+ * "--machine=foobar --user": both times we unconditionally connect as root user
+ * regardless what the calling user is. */
+
+ if (h) {
+ eh = bus_address_escape(h);
+ if (!eh)
return -ENOMEM;
}
/* systemd-run -M… -PGq --wait -pUser=… -pPAMName=login systemd-stdio-bridge */
a = strjoin("unixexec:path=systemd-run,"
- "argv1=-M", erhs ?: ".host", ","
+ "argv1=-M", eh ?: ".host", ","
"argv2=-PGq,"
"argv3=--wait,"
"argv4=-pUser%3d", eu ?: "root", ",",
/* Just a container name, we can go the simple way, and just join the container, and connect
* to the well-known path of the system bus there. */
- e = bus_address_escape(machine);
+ e = bus_address_escape(h ?: ".host");
if (!e)
return -ENOMEM;