]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
hostname-util: add new helper split_user_at_host()
authorLennart Poettering <lennart@poettering.net>
Thu, 5 Jun 2025 09:17:22 +0000 (11:17 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 5 Jun 2025 10:44:08 +0000 (12:44 +0200)
Let's introduce a common helper for splitting user@host specifications
like we use them for --machine=.

src/basic/hostname-util.c
src/basic/hostname-util.h
src/test/test-hostname-util.c

index 673e1de3d42c4b8218a85e02e6a26fd6e67eecbc..1372dec0b2f7f5c4af3b08bdd8c75fc952c1ad97 100644 (file)
@@ -172,3 +172,36 @@ int get_pretty_hostname(char **ret) {
         *ret = TAKE_PTR(n);
         return 0;
 }
+
+int split_user_at_host(const char *s, char **ret_user, char **ret_host) {
+        _cleanup_free_ char *u = NULL, *h = NULL;
+
+        /* Splits a user@host expression (one of those we accept on --machine= and similar). Returns NULL in
+         * each of the two return parameters if that part was left empty. */
+
+        const char *rhs = strchr(s, '@');
+        if (rhs) {
+                if (ret_user && rhs > s) {
+                        u = strndup(s, rhs - s);
+                        if (!u)
+                                return -ENOMEM;
+                }
+
+                if (ret_host && rhs[1] != 0) {
+                        h = strdup(rhs + 1);
+                        if (!h)
+                                return -ENOMEM;
+                }
+        } else if (!isempty(s) && ret_host) {
+                h = strdup(s);
+                if (!h)
+                        return -ENOMEM;
+        }
+
+        if (ret_user)
+                *ret_user = TAKE_PTR(u);
+        if (ret_host)
+                *ret_host = TAKE_PTR(h);
+
+        return !!rhs; /* return > 0 if '@' was specified, 0 otherwise */
+}
index d85391e59fcd40549fb9a5d8fecbfb70f748e5eb..4abdfdd76a1bdb010154344ab96992f3f1433108 100644 (file)
@@ -38,3 +38,5 @@ static inline bool is_dns_proxy_stub_hostname(const char *hostname) {
 }
 
 int get_pretty_hostname(char **ret);
+
+int split_user_at_host(const char *s, char **ret_user, char **ret_host);
index f9f24e0e03c073853d010f5ea6521ab31e04b32c..4abac5ca3a95b50f4b1729008e7da4e28e94b471 100644 (file)
@@ -89,4 +89,31 @@ TEST(hostname_cleanup) {
         ASSERT_STREQ(hostname_cleanup(s), "xxxx.xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx");
 }
 
+static void test_split_user_at_host_one(const char *s, const char *expected_user, const char *expected_host, int ret) {
+        _cleanup_free_ char *u = NULL, *h = NULL;
+
+        ASSERT_OK_EQ(split_user_at_host(s, &u, &h), ret);
+        ASSERT_STREQ(u, expected_user);
+        ASSERT_STREQ(h, expected_host);
+
+        u = mfree(u);
+        h = mfree(h);
+
+        ASSERT_OK_EQ(split_user_at_host(s, &u, NULL), ret);
+        ASSERT_STREQ(u, expected_user);
+
+        ASSERT_OK_EQ(split_user_at_host(s, NULL, &h), ret);
+        ASSERT_STREQ(h, expected_host);
+}
+
+TEST(split_user_at_host) {
+        test_split_user_at_host_one("", NULL, NULL, 0);
+        test_split_user_at_host_one("@", NULL, NULL, 1);
+        test_split_user_at_host_one("a", NULL, "a", 0);
+        test_split_user_at_host_one("a@b", "a", "b", 1);
+        test_split_user_at_host_one("@b", NULL, "b", 1);
+        test_split_user_at_host_one("a@", "a", NULL, 1);
+        test_split_user_at_host_one("aa@@@bb", "aa", "@@bb", 1);
+}
+
 DEFINE_TEST_MAIN(LOG_DEBUG);