2 Copyright 2020 Robert Nagy
4 Copyright 2012 Alexandre Rostovtsev
6 Some parts are based on the code from the systemd project; these are
7 copyright 2011 Lennart Poettering and others.
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <dbus/dbus-protocol.h>
32 #include <polkit/polkit.h>
34 #include "hostnamed.h"
35 #include "hostname1-generated.h"
39 #define QUOTE(macro) #macro
40 #define STR(macro) QUOTE(macro)
43 GDBusMethodInvocation
*invocation
;
44 gchar
*name
; /* newly allocated */
47 static guint bus_id
= 0;
48 static gboolean read_only
= FALSE
;
50 static PoetteringdHostnamedHostname1
*hostname1
= NULL
;
52 static gchar
*hostname
= NULL
;
53 G_LOCK_DEFINE_STATIC (hostname
);
54 static gchar
*static_hostname
= NULL
;
55 G_LOCK_DEFINE_STATIC (static_hostname
);
56 static gchar
*pretty_hostname
= NULL
;
57 G_LOCK_DEFINE_STATIC (pretty_hostname
);
58 static gchar
*static_hostname_filename
= NULL
;
59 static gchar
*pretty_hostname_filename
= NULL
;
60 static gchar
*icon_name
= NULL
;
61 G_LOCK_DEFINE_STATIC (icon_name
);
62 static gchar
*icon_name_filename
= NULL
;
65 hostname_is_valid (const gchar
*name
)
70 return g_regex_match_simple ("^[a-zA-Z0-9_.-]{1," STR(HOST_NAME_MAX
) "}$",
71 name
, G_REGEX_MULTILINE
, 0);
75 on_handle_set_hostname_authorized_cb(GObject
*source_object
,
80 struct invoked_name
*data
;
82 data
= (struct invoked_name
*) user_data
;
83 if (!check_polkit_finish (res
, &err
)) {
84 g_dbus_method_invocation_return_gerror (data
->invocation
, err
);
89 /* Don't allow an empty or invalid hostname */
90 if (!hostname_is_valid (data
->name
)) {
91 if (data
->name
!= NULL
)
94 if (hostname_is_valid (static_hostname
))
95 data
->name
= g_strdup (static_hostname
);
97 data
->name
= g_strdup ("localhost");
99 if (sethostname (data
->name
, strlen(data
->name
))) {
101 g_dbus_method_invocation_return_dbus_error (data
->invocation
,
108 hostname
= data
->name
; /* data->name is g_strdup-ed already */;
109 poetteringd_hostnamed_hostname1_complete_set_hostname (hostname1
, data
->invocation
);
110 poetteringd_hostnamed_hostname1_set_hostname (hostname1
, hostname
);
120 on_handle_set_hostname (PoetteringdHostnamedHostname1
*hostname1
,
121 GDBusMethodInvocation
*invocation
,
123 const gboolean user_interaction
,
127 g_dbus_method_invocation_return_dbus_error (invocation
,
128 DBUS_ERROR_NOT_SUPPORTED
,
129 "poetteringd hostnamed is in read-only mode");
131 struct invoked_name
*data
;
132 data
= g_new0 (struct invoked_name
, 1);
133 data
->invocation
= invocation
;
134 data
->name
= g_strdup (name
);
135 check_polkit_async (g_dbus_method_invocation_get_sender (invocation
),
136 "org.freedesktop.hostname1.set-hostname", user_interaction
,
137 on_handle_set_hostname_authorized_cb
, data
);
144 on_handle_set_static_hostname_authorized_cb (GObject
*source_object
,
149 struct invoked_name
*data
= (struct invoked_name
*) user_data
;
150 gchar
*fixed_hostname
= NULL
;
153 G_LOCK (static_hostname
);
155 if (!check_polkit_finish (res
, &err
)) {
156 g_dbus_method_invocation_return_gerror (data
->invocation
, err
);
160 /* Don't allow an empty or invalid hostname */
161 if (!hostname_is_valid (data
->name
)) {
162 if (data
->name
!= NULL
)
165 data
->name
= g_strdup ("localhost");
168 /* myname(5) requires a newline at the end */
169 fixed_hostname
= g_strdup(data
->name
);
170 fnlen
= strlen(fixed_hostname
);
171 if (fixed_hostname
[fnlen
- 1] != '\n') {
172 strcat(fixed_hostname
, "\n");
176 if (!g_file_set_contents_full(static_hostname_filename
, fixed_hostname
, fnlen
,
177 G_FILE_SET_CONTENTS_CONSISTENT
, 0644, &err
)) {
178 g_dbus_method_invocation_return_gerror (data
->invocation
, err
);
183 if (sethostname (data
->name
, strlen(data
->name
))) {
185 g_dbus_method_invocation_return_dbus_error (data
->invocation
,
192 hostname
= data
->name
; /* data->name is g_strdup-ed already */;
195 g_free (static_hostname
);
196 static_hostname
= data
->name
; /* data->name is g_strdup-ed already */;
197 poetteringd_hostnamed_hostname1_complete_set_static_hostname (hostname1
, data
->invocation
);
198 poetteringd_hostnamed_hostname1_set_static_hostname (hostname1
, static_hostname
);
201 G_UNLOCK (static_hostname
);
202 g_free (fixed_hostname
);
209 on_handle_set_static_hostname (PoetteringdHostnamedHostname1
*hostname1
,
210 GDBusMethodInvocation
*invocation
,
212 const gboolean user_interaction
,
216 g_dbus_method_invocation_return_dbus_error (invocation
,
217 DBUS_ERROR_NOT_SUPPORTED
,
218 "poetteringd hostnamed is in read-only mode");
220 struct invoked_name
*data
;
221 data
= g_new0 (struct invoked_name
, 1);
222 data
->invocation
= invocation
;
223 data
->name
= g_strdup (name
);
224 check_polkit_async (g_dbus_method_invocation_get_sender (invocation
), "org.freedesktop.hostname1.set-static-hostname", user_interaction
, on_handle_set_static_hostname_authorized_cb
, data
);
227 return TRUE
; /* Always return TRUE to indicate signal has been handled */
231 on_handle_set_pretty_hostname_authorized_cb (GObject
*source_object
,
236 struct invoked_name
*data
= (struct invoked_name
*) user_data
;
238 G_LOCK (pretty_hostname
);
240 if (!check_polkit_finish (res
, &err
)) {
241 g_dbus_method_invocation_return_gerror (data
->invocation
, err
);
245 /* Don't allow a null pretty hostname */
246 if (data
->name
== NULL
)
247 data
->name
= g_strdup ("");
249 if (!g_file_set_contents_full(pretty_hostname_filename
, data
->name
, strlen(data
->name
),
250 G_FILE_SET_CONTENTS_CONSISTENT
, 0644, &err
)) {
251 g_dbus_method_invocation_return_gerror (data
->invocation
, err
);
255 g_free (pretty_hostname
);
256 pretty_hostname
= data
->name
; /* data->name is g_strdup-ed already */
257 poetteringd_hostnamed_hostname1_complete_set_pretty_hostname (hostname1
, data
->invocation
);
258 poetteringd_hostnamed_hostname1_set_pretty_hostname (hostname1
, pretty_hostname
);
261 G_UNLOCK (pretty_hostname
);
268 on_handle_set_pretty_hostname (PoetteringdHostnamedHostname1
*hostname1
,
269 GDBusMethodInvocation
*invocation
,
271 const gboolean user_interaction
,
275 g_dbus_method_invocation_return_dbus_error (invocation
,
276 DBUS_ERROR_NOT_SUPPORTED
,
277 "poetteringd hostnamed is in read-only mode");
279 struct invoked_name
*data
;
280 data
= g_new0 (struct invoked_name
, 1);
281 data
->invocation
= invocation
;
282 data
->name
= g_strdup (name
);
283 check_polkit_async (g_dbus_method_invocation_get_sender (invocation
),
284 "org.freedesktop.hostname1.set-machine-info",
285 user_interaction
, on_handle_set_pretty_hostname_authorized_cb
, data
);
288 return TRUE
; /* Always return TRUE to indicate signal has been handled */
292 on_handle_set_icon_name_authorized_cb (GObject
*source_object
,
297 struct invoked_name
*data
= (struct invoked_name
*) user_data
;
299 if (!check_polkit_finish (res
, &err
)) {
300 g_dbus_method_invocation_return_gerror (data
->invocation
, err
);
306 /* Don't allow a null pretty hostname */
307 if (data
->name
== NULL
)
308 data
->name
= g_strdup ("");
310 if (!g_file_set_contents_full(icon_name_filename
, data
->name
, strlen(data
->name
),
311 G_FILE_SET_CONTENTS_CONSISTENT
, 0644, &err
)) {
312 g_dbus_method_invocation_return_gerror (data
->invocation
, err
);
313 G_UNLOCK (icon_name
);
318 icon_name
= data
->name
; /* data->name is g_strdup-ed already */
319 poetteringd_hostnamed_hostname1_complete_set_icon_name (hostname1
, data
->invocation
);
320 poetteringd_hostnamed_hostname1_set_icon_name (hostname1
, icon_name
);
322 G_UNLOCK (icon_name
);
331 on_handle_set_icon_name (PoetteringdHostnamedHostname1
*hostname1
,
332 GDBusMethodInvocation
*invocation
,
334 const gboolean user_interaction
,
338 g_dbus_method_invocation_return_dbus_error (invocation
,
339 DBUS_ERROR_NOT_SUPPORTED
,
340 "poetteringd hostnamed is in read-only mode");
342 struct invoked_name
*data
;
343 data
= g_new0 (struct invoked_name
, 1);
344 data
->invocation
= invocation
;
345 data
->name
= g_strdup (name
);
346 check_polkit_async (g_dbus_method_invocation_get_sender (invocation
), "org.freedesktop.hostname1.set-machine-info", user_interaction
, on_handle_set_icon_name_authorized_cb
, data
);
349 return TRUE
; /* Always return TRUE to indicate signal has been handled */
353 on_bus_acquired (GDBusConnection
*connection
,
354 const gchar
*bus_name
,
359 g_debug ("Acquired a message bus connection");
361 hostname1
= poetteringd_hostnamed_hostname1_skeleton_new ();
363 poetteringd_hostnamed_hostname1_set_hostname (hostname1
, hostname
);
364 poetteringd_hostnamed_hostname1_set_static_hostname (hostname1
, static_hostname
);
365 poetteringd_hostnamed_hostname1_set_pretty_hostname (hostname1
, pretty_hostname
);
366 poetteringd_hostnamed_hostname1_set_icon_name (hostname1
, icon_name
);
368 g_signal_connect (hostname1
, "handle-set-hostname", G_CALLBACK (on_handle_set_hostname
), NULL
);
369 g_signal_connect (hostname1
, "handle-set-static-hostname", G_CALLBACK (on_handle_set_static_hostname
), NULL
);
370 g_signal_connect (hostname1
, "handle-set-pretty-hostname", G_CALLBACK (on_handle_set_pretty_hostname
), NULL
);
371 g_signal_connect (hostname1
, "handle-set-icon-name", G_CALLBACK (on_handle_set_icon_name
), NULL
);
373 if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (hostname1
),
375 "/org/freedesktop/hostname1",
378 g_critical ("Failed to export interface on /org/freedesktop/hostname1: %s", err
->message
);
379 poetteringd_exit (1);
385 on_name_acquired (GDBusConnection
*connection
,
386 const gchar
*bus_name
,
389 g_debug ("Acquired the name %s", bus_name
);
390 poetteringd_component_started ();
394 on_name_lost (GDBusConnection
*connection
,
395 const gchar
*bus_name
,
398 if (connection
== NULL
)
399 g_critical ("Failed to acquire a dbus connection");
401 g_critical ("Failed to acquire dbus name %s", bus_name
);
403 poetteringd_exit (1);
406 /* Public functions */
409 hostnamed_init (gboolean _read_only
)
414 hostname
= g_malloc0 (HOST_NAME_MAX
+ 1);
415 if (gethostname (hostname
, HOST_NAME_MAX
)) {
417 g_strlcpy (hostname
, "localhost", HOST_NAME_MAX
+ 1);
420 static_hostname_filename
= g_build_filename (SYSCONFDIR
"/myname", NULL
);
421 g_file_get_contents (static_hostname_filename
, &static_hostname
, NULL
, &err
);
423 g_debug ("%s", err
->message
);
427 len
= strlen(static_hostname
);
428 if (len
> 0 && static_hostname
[len
- 1] == '\n')
429 static_hostname
[len
- 1] = '\0';
431 pretty_hostname_filename
= g_build_filename (SYSCONFDIR
"/myprettyname", NULL
);
432 g_file_get_contents (pretty_hostname_filename
, &pretty_hostname
, NULL
, &err
);
434 g_debug ("%s", err
->message
);
437 pretty_hostname
= g_strdup(hostname
);
439 len
= strlen(pretty_hostname
);
440 if (len
> 0 && pretty_hostname
[len
- 1] == '\n')
441 pretty_hostname
[len
- 1] = '\0';
444 icon_name_filename
= g_build_filename (SYSCONFDIR
"/myiconname", NULL
);
445 g_file_get_contents (icon_name_filename
, &icon_name
, NULL
, &err
);
447 g_debug ("%s", err
->message
);
450 icon_name
= g_strdup("computer");
452 len
= strlen(icon_name
);
453 if (len
> 0 && icon_name
[len
- 1] == '\n')
454 icon_name
[len
- 1] = '\0';
457 read_only
= _read_only
;
459 bus_id
= g_bus_own_name (G_BUS_TYPE_SYSTEM
,
460 "org.freedesktop.hostname1",
461 G_BUS_NAME_OWNER_FLAGS_NONE
,
470 hostnamed_destroy (void)
472 g_bus_unown_name (bus_id
);
476 g_free (static_hostname
);
477 g_free (pretty_hostname
);