set /etc/myname when setStaticHostname is called
[systembsd.git] / src / interfaces / hostnamed / hostnamed.c
index 162cf5d212104b726a86718edeb9b1b97a30e367..81200e73a92ab0fec3958c80f883e7fbe79cfc7b 100644 (file)
@@ -110,6 +110,9 @@ const gchar *server_archs[] = {
     "sparc64"
 };
 
+static const gchar *DEFAULT_DOMAIN   = ".home.network";
+static const gchar *OS_HOSTNAME_PATH = "/etc/myname";
+
 /* --- begin method/property/dbus signal code --- */
 
 /* TODO free some strings here */
@@ -133,7 +136,7 @@ on_handle_set_hostname(Hostname1 *hn1_passed_interf,
     bus_name = g_dbus_method_invocation_get_sender(invoc);
 
     /* verify caller has correct permissions via polkit */
-    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.SetHostname", policykit_auth);
+    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.set-hostname", policykit_auth);
 
     switch(is_authed) {
 
@@ -196,11 +199,12 @@ on_handle_set_static_hostname(Hostname1 *hn1_passed_interf,
                               gpointer data) {
 
     GVariant *params;
-    gchar *proposed_static_hostname, *valid_static_hostname_buf;
+    gchar *proposed_static_hostname, *valid_static_hostname_buf, *bsd_hostname_try;
     const gchar *bus_name;
     gboolean policykit_auth, ret, try_to_set;
     size_t check_length;
     check_auth_result is_authed;
+    
 
     proposed_static_hostname = NULL;
     ret = try_to_set = FALSE;
@@ -210,7 +214,7 @@ on_handle_set_static_hostname(Hostname1 *hn1_passed_interf,
     bus_name = g_dbus_method_invocation_get_sender(invoc);
 
     /* verify caller has correct permissions via polkit */
-    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.SetStaticHostname", policykit_auth);
+    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.set-static-hostname", policykit_auth);
 
     switch(is_authed) {
 
@@ -256,9 +260,20 @@ on_handle_set_static_hostname(Hostname1 *hn1_passed_interf,
         } else { 
 
             g_strdelimit(STATIC_HOSTNAME, " ", '-');
-            hostname1_set_static_hostname(hn1_passed_interf, STATIC_HOSTNAME);
+            hostname1_set_static_hostname(hn1_passed_interf, STATIC_HOSTNAME); 
             g_ptr_array_add(hostnamed_freeable, valid_static_hostname_buf);
-            ret = TRUE;
+
+            /* set string in OS_HOSTNAME_PATH ("/etc/myname" on bsd) */
+            bsd_hostname_try = get_bsd_hostname(STATIC_HOSTNAME);
+            GError *debug_error;
+            if(!bsd_hostname_try || !g_file_set_contents(OS_HOSTNAME_PATH, bsd_hostname_try, -1, &debug_error))
+                g_printf("failed to write to %s! are you root?\n", OS_HOSTNAME_PATH);
+            
+            if(bsd_hostname_try)
+                g_free(bsd_hostname_try);
+
+            /* call sethostname(3) too */
+            ret = (!sethostname(valid_static_hostname_buf, MAXHOSTNAMELEN)) ? TRUE : FALSE; /* TODO set /etc/myname, guarantee domain or substitue .home.network" */
             hostname1_complete_set_static_hostname(hn1_passed_interf, invoc);
         }
     }
@@ -289,7 +304,7 @@ on_handle_set_pretty_hostname(Hostname1 *hn1_passed_interf,
     bus_name = g_dbus_method_invocation_get_sender(invoc);
 
     /* verify caller has correct permissions via polkit */
-    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.SetPrettyHostname", policykit_auth);
+    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.set-pretty-hostname", policykit_auth);
 
     switch(is_authed) {
 
@@ -339,11 +354,11 @@ on_handle_set_pretty_hostname(Hostname1 *hn1_passed_interf,
             hostname1_complete_set_pretty_hostname(hn1_passed_interf, invoc);
             ret = TRUE;
 
-            if(g_key_file_load_from_file(config, "/etc/systemd_compat.conf", G_KEY_FILE_NONE, NULL)) {
+            if(g_key_file_load_from_file(config, "/etc/machine-info", G_KEY_FILE_NONE, NULL)) {
  
-                g_key_file_set_string(config, "hostnamed", "PrettyHostname", valid_pretty_hostname_buf);
+                g_key_file_set_string(config, "hostnamed", "PRETTY_HOSTNAME", valid_pretty_hostname_buf);
 
-                if((computed_static_hostname = g_hostname_to_ascii(PRETTY_HOSTNAME))) {
+                /* if((computed_static_hostname = g_hostname_to_ascii(PRETTY_HOSTNAME))) {
 
                     g_strdelimit(computed_static_hostname, " ", '-');
                     hostname1_set_static_hostname(hn1_passed_interf, computed_static_hostname);
@@ -351,14 +366,12 @@ on_handle_set_pretty_hostname(Hostname1 *hn1_passed_interf,
                     g_ptr_array_add(hostnamed_freeable, computed_static_hostname);
                     g_key_file_set_string(config, "hostnamed", "StaticHostname", computed_static_hostname);
 
-                } else
-                    g_free(computed_static_hostname);
+                } */
             }
-
         }
     }
 
-    g_key_file_save_to_file(config, "/etc/systemd_compat.conf", NULL);
+    g_key_file_save_to_file(config, "/etc/machine-info", NULL);
     g_key_file_unref(config);
 
     return ret;
@@ -389,7 +402,7 @@ on_handle_set_chassis(Hostname1 *hn1_passed_interf,
     g_strlcpy(valid_chassis_name_buf, proposed_chassis_name, (gsize)64);
 
     /* verify caller has correct permissions via polkit */
-    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.SetChassis", policykit_auth);
+    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.set-chassis", policykit_auth);
 
     switch(is_authed) {
 
@@ -436,7 +449,7 @@ on_handle_set_chassis(Hostname1 *hn1_passed_interf,
             g_ptr_array_add(hostnamed_freeable, valid_chassis_name_buf);
             hostname1_complete_set_chassis(hn1_passed_interf, invoc);
 
-            if(g_key_file_load_from_file(config, "/etc/systemd_compat.conf", G_KEY_FILE_NONE, NULL)) {
+            if(g_key_file_load_from_file(config, "/etc/machine-info", G_KEY_FILE_NONE, NULL)) {
 
                 ret = TRUE;
                 g_key_file_set_string(config, "hostnamed", "ChassisType", valid_chassis_name_buf);
@@ -445,7 +458,7 @@ on_handle_set_chassis(Hostname1 *hn1_passed_interf,
         }
     }
 
-    g_key_file_save_to_file(config, "/etc/systemd_compat.conf", NULL);
+    g_key_file_save_to_file(config, "/etc/machine-info", NULL);
     g_key_file_unref(config);
 
     return ret;
@@ -473,7 +486,7 @@ on_handle_set_icon_name(Hostname1 *hn1_passed_interf,
     bus_name = g_dbus_method_invocation_get_sender(invoc);
 
     /* verify caller has correct permissions via polkit */
-    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.SetIconName", policykit_auth);
+    is_authed = polkit_try_auth(bus_name, "org.freedesktop.hostname1.set-icon-name", policykit_auth);
 
     switch(is_authed) {
 
@@ -517,7 +530,7 @@ on_handle_set_icon_name(Hostname1 *hn1_passed_interf,
             g_ptr_array_add(hostnamed_freeable, valid_icon_name_buf);
             hostname1_complete_set_icon_name(hn1_passed_interf, invoc);
 
-            if(g_key_file_load_from_file(config, "/etc/systemd_compat.conf", G_KEY_FILE_NONE, NULL)) {
+            if(g_key_file_load_from_file(config, "/etc/machine-info", G_KEY_FILE_NONE, NULL)) {
 
                 ret = TRUE;
                 g_key_file_set_string(config, "hostnamed", "IconName", valid_icon_name_buf);
@@ -526,7 +539,7 @@ on_handle_set_icon_name(Hostname1 *hn1_passed_interf,
         }
     }
 
-    g_key_file_save_to_file(config, "/etc/systemd_compat.conf", NULL);
+    g_key_file_save_to_file(config, "/etc/machine-info", NULL);
     g_key_file_unref(config);
 
     return ret;
@@ -628,7 +641,8 @@ our_get_kernel_release() {
 const gchar *
 our_get_os_cpename() {
 
-    return "ONEDAY";
+    /* XXX needs to parse /etc/os-release (fallback to /usr/local/lib/os-release) */
+    return "";
 }
 
 const gchar *
@@ -746,6 +760,8 @@ int main() {
   
     /* TODO: check for valid, writable config at init. if no, complain to `make install` */
 
+    get_bsd_hostname("adsf"); /* TODO KILL ME */
+
     CHASSIS = ICON = OS_CPENAME = 0;
     KERN_NAME = KERN_RELEASE = KERN_VERS = 0;
     HOSTNAME = STATIC_HOSTNAME = PRETTY_HOSTNAME = NULL;
@@ -807,24 +823,24 @@ gboolean set_names() {
     strncpy(ret, hostname_buf, hostname_divider); */
 
     /* (3) set PRETTY_HOSTNAME */
-    if(g_key_file_load_from_file(config, "/etc/systemd_compat.conf", G_KEY_FILE_NONE, NULL)
-        && (pretty_hostname_buf = g_key_file_get_value(config, "hostnamed", "PrettyHostname", NULL)))
+    if(g_key_file_load_from_file(config, "/etc/machine-info", G_KEY_FILE_NONE, NULL)
+        && (pretty_hostname_buf = g_key_file_get_value(config, "hostnamed", "PRETTY_HOSTNAME", NULL)))
         PRETTY_HOSTNAME = pretty_hostname_buf;
     else
         PRETTY_HOSTNAME = "";
  
-    if(config)
-        g_key_file_unref(config);
+    
+    /* (4) set STATIC_HOSTNAME */
+    if((static_hostname_buf = g_key_file_get_value(config, "hostnamed", "STATIC_HOSTNAME", NULL)))
+        STATIC_HOSTNAME = static_hostname_buf;
 
-    /* (4) set STATIC_HOSTNAME */ 
-    if(!g_strcmp0(PRETTY_HOSTNAME, ""))
-        STATIC_HOSTNAME = HOSTNAME;
+    else
+        STATIC_HOSTNAME = "";
 
-    else if((static_hostname_buf = g_hostname_to_ascii(PRETTY_HOSTNAME)))
-        STATIC_HOSTNAME = static_hostname_buf;
+    if(config)
+        g_key_file_unref(config);
 
     return (HOSTNAME && STATIC_HOSTNAME && PRETTY_HOSTNAME) ? TRUE : FALSE;
-
 }
 
 gboolean set_uname_properties() {
@@ -1023,4 +1039,101 @@ static gboolean is_valid_chassis_type(gchar *test) {
         return TRUE;
 
     return FALSE;
-} 
+}
+
+/* returns a proper, bsd-style FQDN hostname safe to write to /etc/myname
+ * if proposed_hostname does not contain an appended domain, the one in /etc/myname is substituted.
+ * failing that, DEFAULT_DOMAIN is used. NULL if proposed_hostname is invalid
+ * returns string that should be g_free()'d, or NULL if passed an invalid hostname */
+static gchar *get_bsd_hostname(gchar *proposed_hostname) {
+
+    gchar *bsd_hostname, *ascii_translated_hostname, **myname_contents, *passed_domain, *temp_buf;
+    size_t domain_len, check_len;
+    gboolean read_result;
+
+    g_strdelimit(proposed_hostname, "`~!@#$%^&*()_=+[{]}|:;'\"\\", '-');
+
+    ascii_translated_hostname = g_hostname_to_ascii(proposed_hostname);
+    check_len = strnlen(ascii_translated_hostname, MAXHOSTNAMELEN);
+
+    if(!ascii_translated_hostname || !check_len || check_len > MAXHOSTNAMELEN || !g_strcmp0("", ascii_translated_hostname) || !g_strcmp0(".", ascii_translated_hostname)) {
+        
+        bsd_hostname = NULL;
+        passed_domain = NULL;
+        myname_contents = NULL;
+
+    } else if((passed_domain = has_domain(ascii_translated_hostname))) {
+
+        bsd_hostname    = (gchar *) g_malloc0(MAXHOSTNAMELEN); 
+        g_strlcpy(bsd_hostname, ascii_translated_hostname, MAXHOSTNAMELEN);
+        
+        passed_domain = NULL;
+        myname_contents = NULL;
+
+    } else {
+
+        myname_contents = (gchar **) g_malloc0(MAXHOSTNAMELEN * 2);
+        read_result = g_file_get_contents(OS_HOSTNAME_PATH, myname_contents, NULL, NULL);
+
+        if(read_result && (passed_domain = has_domain(myname_contents[0]))) {
+
+            domain_len = strnlen(passed_domain, MAXHOSTNAMELEN);
+
+            if((domain_len + check_len) > MAXHOSTNAMELEN)
+                bsd_hostname = NULL;
+            else
+                bsd_hostname = g_strconcat(ascii_translated_hostname, passed_domain, NULL);
+
+        } else if(myname_contents[0]) {
+
+            g_printf("%s does not contain a proper FQDN! this is a significant error on BSD machines, otherwise OK.\nfalling back to default domain, '%s'\n", OS_HOSTNAME_PATH, DEFAULT_DOMAIN);
+
+            domain_len = strnlen(DEFAULT_DOMAIN, MAXHOSTNAMELEN);
+
+            if((domain_len + check_len) > MAXHOSTNAMELEN)
+                bsd_hostname = NULL;
+            else
+                bsd_hostname = g_strconcat(ascii_translated_hostname, DEFAULT_DOMAIN, NULL);
+
+        } else {
+
+            g_printf("could not read hostname at %s, this is a major error\n", OS_HOSTNAME_PATH);
+            bsd_hostname = NULL;
+            passed_domain = (gchar *) g_malloc0(MAXHOSTNAMELEN);
+        }
+    }
+
+    if(passed_domain)
+        g_free(passed_domain);
+    if(myname_contents)
+        g_free(myname_contents);
+
+    if(bsd_hostname && !strchr(bsd_hostname, '\n')) {
+
+        temp_buf = bsd_hostname;
+        bsd_hostname = g_strconcat(bsd_hostname, "\n", NULL);
+        g_free(temp_buf);
+    }
+
+    return bsd_hostname;
+}
+
+/* returns NULL if no domain, otherwise append-appropriate domain string you must g_free()
+ * i.e. has_domain("foo.bar.com") returns ".bar.com"
+ * only pass g_hostname_to_ascii'd strings */
+static gchar *has_domain(const gchar *test) {
+
+    size_t hostname_len, full_len;
+    gchar *ret;
+    
+    hostname_len = strcspn(test, ".");
+    full_len     = strnlen(test, MAXHOSTNAMELEN);
+
+    if(full_len == hostname_len)
+        return NULL;
+
+    ret = (gchar *) g_malloc0(MAXHOSTNAMELEN);
+    g_strlcpy(ret, &test[hostname_len], MAXHOSTNAMELEN);
+
+    return ret;
+}