1 /* GDBus - GLib D-Bus Library
3 * Copyright (C) 2008-2010 Red Hat, Inc.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Author: David Zeuthen <davidz@redhat.com>
31 #include "gdbusutils.h"
32 #include "gdbusaddress.h"
33 #include "gdbuserror.h"
34 #include "gioenumtypes.h"
35 #include "gnetworkaddress.h"
36 #include "gsocketclient.h"
37 #include "giostream.h"
38 #include "gasyncresult.h"
39 #include "gsimpleasyncresult.h"
40 #include "gdbusprivate.h"
41 #include "giomodule-priv.h"
42 #include "gdbusdaemon.h"
45 #include <gio/gunixsocketaddress.h>
57 * SECTION:gdbusaddress
58 * @title: D-Bus Addresses
59 * @short_description: D-Bus connection endpoints
62 * Routines for working with D-Bus addresses. A D-Bus address is a string
63 * like "unix:tmpdir=/tmp/my-app-name". The exact format of addresses
64 * is explained in detail in the <link linkend="http://dbus.freedesktop.org/doc/dbus-specification.html#addresses">D-Bus specification</link>.
67 static gchar
*get_session_address_platform_specific (GError
**error
);
69 /* ---------------------------------------------------------------------------------------------------- */
75 * Checks if @string is a D-Bus address.
77 * This doesn't check if @string is actually supported by #GDBusServer
78 * or #GDBusConnection - use g_dbus_is_supported_address() to do more
81 * Returns: %TRUE if @string is a valid D-Bus address, %FALSE otherwise.
86 g_dbus_is_address (const gchar
*string
)
94 g_return_val_if_fail (string
!= NULL
, FALSE
);
96 a
= g_strsplit (string
, ";", 0);
100 for (n
= 0; a
[n
] != NULL
; n
++)
102 if (!_g_dbus_address_parse_entry (a
[n
],
117 is_valid_unix (const gchar
*address_entry
,
118 GHashTable
*key_value_pairs
,
126 const gchar
*abstract
;
134 keys
= g_hash_table_get_keys (key_value_pairs
);
135 for (l
= keys
; l
!= NULL
; l
= l
->next
)
137 const gchar
*key
= l
->data
;
138 if (g_strcmp0 (key
, "path") == 0)
139 path
= g_hash_table_lookup (key_value_pairs
, key
);
140 else if (g_strcmp0 (key
, "tmpdir") == 0)
141 tmpdir
= g_hash_table_lookup (key_value_pairs
, key
);
142 else if (g_strcmp0 (key
, "abstract") == 0)
143 abstract
= g_hash_table_lookup (key_value_pairs
, key
);
148 G_IO_ERROR_INVALID_ARGUMENT
,
149 _("Unsupported key `%s' in address entry `%s'"),
158 if (tmpdir
!= NULL
|| abstract
!= NULL
)
161 else if (tmpdir
!= NULL
)
163 if (path
!= NULL
|| abstract
!= NULL
)
166 else if (abstract
!= NULL
)
168 if (path
!= NULL
|| tmpdir
!= NULL
)
175 G_IO_ERROR_INVALID_ARGUMENT
,
176 _("Address `%s' is invalid (need exactly one of path, tmpdir or abstract keys)"),
188 G_IO_ERROR_INVALID_ARGUMENT
,
189 _("Meaningless key/value pair combination in address entry `%s'"),
199 is_valid_nonce_tcp (const gchar
*address_entry
,
200 GHashTable
*key_value_pairs
,
209 const gchar
*nonce_file
;
220 keys
= g_hash_table_get_keys (key_value_pairs
);
221 for (l
= keys
; l
!= NULL
; l
= l
->next
)
223 const gchar
*key
= l
->data
;
224 if (g_strcmp0 (key
, "host") == 0)
225 host
= g_hash_table_lookup (key_value_pairs
, key
);
226 else if (g_strcmp0 (key
, "port") == 0)
227 port
= g_hash_table_lookup (key_value_pairs
, key
);
228 else if (g_strcmp0 (key
, "family") == 0)
229 family
= g_hash_table_lookup (key_value_pairs
, key
);
230 else if (g_strcmp0 (key
, "noncefile") == 0)
231 nonce_file
= g_hash_table_lookup (key_value_pairs
, key
);
236 G_IO_ERROR_INVALID_ARGUMENT
,
237 _("Unsupported key `%s' in address entry `%s'"),
246 port_num
= strtol (port
, &endp
, 10);
247 if ((*port
== '\0' || *endp
!= '\0') || port_num
< 0 || port_num
>= 65536)
251 G_IO_ERROR_INVALID_ARGUMENT
,
252 _("Error in address `%s' - the port attribute is malformed"),
258 if (family
!= NULL
&& !(g_strcmp0 (family
, "ipv4") == 0 || g_strcmp0 (family
, "ipv6") == 0))
262 G_IO_ERROR_INVALID_ARGUMENT
,
263 _("Error in address `%s' - the family attribute is malformed"),
270 /* TODO: validate host */
273 nonce_file
= nonce_file
; /* To avoid -Wunused-but-set-variable */
284 is_valid_tcp (const gchar
*address_entry
,
285 GHashTable
*key_value_pairs
,
303 keys
= g_hash_table_get_keys (key_value_pairs
);
304 for (l
= keys
; l
!= NULL
; l
= l
->next
)
306 const gchar
*key
= l
->data
;
307 if (g_strcmp0 (key
, "host") == 0)
308 host
= g_hash_table_lookup (key_value_pairs
, key
);
309 else if (g_strcmp0 (key
, "port") == 0)
310 port
= g_hash_table_lookup (key_value_pairs
, key
);
311 else if (g_strcmp0 (key
, "family") == 0)
312 family
= g_hash_table_lookup (key_value_pairs
, key
);
317 G_IO_ERROR_INVALID_ARGUMENT
,
318 _("Unsupported key `%s' in address entry `%s'"),
327 port_num
= strtol (port
, &endp
, 10);
328 if ((*port
== '\0' || *endp
!= '\0') || port_num
< 0 || port_num
>= 65536)
332 G_IO_ERROR_INVALID_ARGUMENT
,
333 _("Error in address `%s' - the port attribute is malformed"),
339 if (family
!= NULL
&& !(g_strcmp0 (family
, "ipv4") == 0 || g_strcmp0 (family
, "ipv6") == 0))
343 G_IO_ERROR_INVALID_ARGUMENT
,
344 _("Error in address `%s' - the family attribute is malformed"),
351 /* TODO: validate host */
363 * g_dbus_is_supported_address:
365 * @error: Return location for error or %NULL.
367 * Like g_dbus_is_address() but also checks if the library suppors the
368 * transports in @string and that key/value pairs for each transport
371 * Returns: %TRUE if @string is a valid D-Bus address that is
372 * supported by this library, %FALSE if @error is set.
377 g_dbus_is_supported_address (const gchar
*string
,
386 g_return_val_if_fail (string
!= NULL
, FALSE
);
387 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, FALSE
);
389 a
= g_strsplit (string
, ";", 0);
390 for (n
= 0; a
[n
] != NULL
; n
++)
392 gchar
*transport_name
;
393 GHashTable
*key_value_pairs
;
396 if (!_g_dbus_address_parse_entry (a
[n
],
403 if (g_strcmp0 (transport_name
, "unix") == 0)
404 supported
= is_valid_unix (a
[n
], key_value_pairs
, error
);
405 else if (g_strcmp0 (transport_name
, "tcp") == 0)
406 supported
= is_valid_tcp (a
[n
], key_value_pairs
, error
);
407 else if (g_strcmp0 (transport_name
, "nonce-tcp") == 0)
408 supported
= is_valid_nonce_tcp (a
[n
], key_value_pairs
, error
);
409 else if (g_strcmp0 (a
[n
], "autolaunch:") == 0)
412 g_free (transport_name
);
413 g_hash_table_unref (key_value_pairs
);
424 g_assert (ret
|| (!ret
&& (error
== NULL
|| *error
!= NULL
)));
430 _g_dbus_address_parse_entry (const gchar
*address_entry
,
431 gchar
**out_transport_name
,
432 GHashTable
**out_key_value_pairs
,
436 GHashTable
*key_value_pairs
;
437 gchar
*transport_name
;
444 transport_name
= NULL
;
445 key_value_pairs
= NULL
;
447 s
= strchr (address_entry
, ':');
452 G_IO_ERROR_INVALID_ARGUMENT
,
453 _("Address element `%s' does not contain a colon (:)"),
458 transport_name
= g_strndup (address_entry
, s
- address_entry
);
459 key_value_pairs
= g_hash_table_new_full (g_str_hash
, g_str_equal
, g_free
, g_free
);
461 kv_pairs
= g_strsplit (s
+ 1, ",", 0);
462 for (n
= 0; kv_pairs
!= NULL
&& kv_pairs
[n
] != NULL
; n
++)
464 const gchar
*kv_pair
= kv_pairs
[n
];
468 s
= strchr (kv_pair
, '=');
473 G_IO_ERROR_INVALID_ARGUMENT
,
474 _("Key/Value pair %d, `%s', in address element `%s' does not contain an equal sign"),
481 key
= g_uri_unescape_segment (kv_pair
, s
, NULL
);
482 value
= g_uri_unescape_segment (s
+ 1, kv_pair
+ strlen (kv_pair
), NULL
);
483 if (key
== NULL
|| value
== NULL
)
487 G_IO_ERROR_INVALID_ARGUMENT
,
488 _("Error unescaping key or value in Key/Value pair %d, `%s', in address element `%s'"),
496 g_hash_table_insert (key_value_pairs
, key
, value
);
502 g_strfreev (kv_pairs
);
505 if (out_transport_name
!= NULL
)
506 *out_transport_name
= transport_name
;
508 g_free (transport_name
);
509 if (out_key_value_pairs
!= NULL
)
510 *out_key_value_pairs
= key_value_pairs
;
511 else if (key_value_pairs
!= NULL
)
512 g_hash_table_unref (key_value_pairs
);
516 g_free (transport_name
);
517 if (key_value_pairs
!= NULL
)
518 g_hash_table_unref (key_value_pairs
);
523 /* ---------------------------------------------------------------------------------------------------- */
526 g_dbus_address_try_connect_one (const gchar
*address_entry
,
528 GCancellable
*cancellable
,
531 /* TODO: Declare an extension point called GDBusTransport (or similar)
532 * and move code below to extensions implementing said extension
533 * point. That way we can implement a D-Bus transport over X11 without
534 * making libgio link to libX11...
537 g_dbus_address_connect (const gchar
*address_entry
,
538 const gchar
*transport_name
,
539 GHashTable
*key_value_pairs
,
540 GCancellable
*cancellable
,
544 GSocketConnectable
*connectable
;
545 const gchar
*nonce_file
;
555 else if (g_strcmp0 (transport_name
, "unix") == 0)
558 const gchar
*abstract
;
559 path
= g_hash_table_lookup (key_value_pairs
, "path");
560 abstract
= g_hash_table_lookup (key_value_pairs
, "abstract");
561 if ((path
== NULL
&& abstract
== NULL
) || (path
!= NULL
&& abstract
!= NULL
))
565 G_IO_ERROR_INVALID_ARGUMENT
,
566 _("Error in address `%s' - the unix transport requires exactly one of the "
567 "keys `path' or `abstract' to be set"),
570 else if (path
!= NULL
)
572 connectable
= G_SOCKET_CONNECTABLE (g_unix_socket_address_new (path
));
574 else if (abstract
!= NULL
)
576 connectable
= G_SOCKET_CONNECTABLE (g_unix_socket_address_new_with_type (abstract
,
578 G_UNIX_SOCKET_ADDRESS_ABSTRACT
));
582 g_assert_not_reached ();
586 else if (g_strcmp0 (transport_name
, "tcp") == 0 || g_strcmp0 (transport_name
, "nonce-tcp") == 0)
594 is_nonce
= (g_strcmp0 (transport_name
, "nonce-tcp") == 0);
596 host
= g_hash_table_lookup (key_value_pairs
, "host");
601 G_IO_ERROR_INVALID_ARGUMENT
,
602 _("Error in address `%s' - the host attribute is missing or malformed"),
607 s
= g_hash_table_lookup (key_value_pairs
, "port");
610 port
= strtol (s
, &endp
, 10);
611 if ((*s
== '\0' || *endp
!= '\0') || port
< 0 || port
>= 65536)
615 G_IO_ERROR_INVALID_ARGUMENT
,
616 _("Error in address `%s' - the port attribute is missing or malformed"),
624 nonce_file
= g_hash_table_lookup (key_value_pairs
, "noncefile");
625 if (nonce_file
== NULL
)
629 G_IO_ERROR_INVALID_ARGUMENT
,
630 _("Error in address `%s' - the noncefile attribute is missing or malformed"),
636 /* TODO: deal with family key/value-pair */
637 connectable
= g_network_address_new (host
, port
);
639 else if (g_strcmp0 (address_entry
, "autolaunch:") == 0)
641 gchar
*autolaunch_address
;
642 autolaunch_address
= get_session_address_platform_specific (error
);
643 if (autolaunch_address
!= NULL
)
645 ret
= g_dbus_address_try_connect_one (autolaunch_address
, NULL
, cancellable
, error
);
646 g_free (autolaunch_address
);
651 g_prefix_error (error
, _("Error auto-launching: "));
658 G_IO_ERROR_INVALID_ARGUMENT
,
659 _("Unknown or unsupported transport `%s' for address `%s'"),
664 if (connectable
!= NULL
)
666 GSocketClient
*client
;
667 GSocketConnection
*connection
;
669 g_assert (ret
== NULL
);
670 client
= g_socket_client_new ();
671 connection
= g_socket_client_connect (client
,
675 g_object_unref (connectable
);
676 g_object_unref (client
);
677 if (connection
== NULL
)
680 ret
= G_IO_STREAM (connection
);
682 if (nonce_file
!= NULL
)
684 gchar nonce_contents
[16 + 1];
685 size_t num_bytes_read
;
688 /* be careful to read only 16 bytes - we also check that the file is only 16 bytes long */
689 f
= fopen (nonce_file
, "rb");
694 G_IO_ERROR_INVALID_ARGUMENT
,
695 _("Error opening nonce file `%s': %s"),
698 g_object_unref (ret
);
702 num_bytes_read
= fread (nonce_contents
,
706 if (num_bytes_read
!= 16)
708 if (num_bytes_read
== 0)
712 G_IO_ERROR_INVALID_ARGUMENT
,
713 _("Error reading from nonce file `%s': %s"),
721 G_IO_ERROR_INVALID_ARGUMENT
,
722 _("Error reading from nonce file `%s', expected 16 bytes, got %d"),
724 (gint
) num_bytes_read
);
726 g_object_unref (ret
);
733 if (!g_output_stream_write_all (g_io_stream_get_output_stream (ret
),
740 g_prefix_error (error
, _("Error writing contents of nonce file `%s' to stream:"), nonce_file
);
741 g_object_unref (ret
);
754 g_dbus_address_try_connect_one (const gchar
*address_entry
,
756 GCancellable
*cancellable
,
760 GHashTable
*key_value_pairs
;
761 gchar
*transport_name
;
765 transport_name
= NULL
;
766 key_value_pairs
= NULL
;
768 if (!_g_dbus_address_parse_entry (address_entry
,
774 ret
= g_dbus_address_connect (address_entry
,
782 guid
= g_hash_table_lookup (key_value_pairs
, "guid");
783 if (guid
!= NULL
&& out_guid
!= NULL
)
784 *out_guid
= g_strdup (guid
);
787 g_free (transport_name
);
788 if (key_value_pairs
!= NULL
)
789 g_hash_table_unref (key_value_pairs
);
794 /* ---------------------------------------------------------------------------------------------------- */
803 get_stream_data_free (GetStreamData
*data
)
805 g_free (data
->address
);
806 if (data
->stream
!= NULL
)
807 g_object_unref (data
->stream
);
813 get_stream_thread_func (GSimpleAsyncResult
*res
,
815 GCancellable
*cancellable
)
820 data
= g_simple_async_result_get_op_res_gpointer (res
);
823 data
->stream
= g_dbus_address_get_stream_sync (data
->address
,
827 if (data
->stream
== NULL
)
828 g_simple_async_result_take_error (res
, error
);
832 * g_dbus_address_get_stream:
833 * @address: A valid D-Bus address.
834 * @cancellable: (allow-none): A #GCancellable or %NULL.
835 * @callback: A #GAsyncReadyCallback to call when the request is satisfied.
836 * @user_data: Data to pass to @callback.
838 * Asynchronously connects to an endpoint specified by @address and
839 * sets up the connection so it is in a state to run the client-side
840 * of the D-Bus authentication conversation.
842 * When the operation is finished, @callback will be invoked. You can
843 * then call g_dbus_address_get_stream_finish() to get the result of
846 * This is an asynchronous failable function. See
847 * g_dbus_address_get_stream_sync() for the synchronous version.
852 g_dbus_address_get_stream (const gchar
*address
,
853 GCancellable
*cancellable
,
854 GAsyncReadyCallback callback
,
857 GSimpleAsyncResult
*res
;
860 g_return_if_fail (address
!= NULL
);
862 res
= g_simple_async_result_new (NULL
,
865 g_dbus_address_get_stream
);
866 g_simple_async_result_set_check_cancellable (res
, cancellable
);
867 data
= g_new0 (GetStreamData
, 1);
868 data
->address
= g_strdup (address
);
869 g_simple_async_result_set_op_res_gpointer (res
,
871 (GDestroyNotify
) get_stream_data_free
);
872 g_simple_async_result_run_in_thread (res
,
873 get_stream_thread_func
,
876 g_object_unref (res
);
880 * g_dbus_address_get_stream_finish:
881 * @res: A #GAsyncResult obtained from the GAsyncReadyCallback passed to g_dbus_address_get_stream().
882 * @out_guid: %NULL or return location to store the GUID extracted from @address, if any.
883 * @error: Return location for error or %NULL.
885 * Finishes an operation started with g_dbus_address_get_stream().
887 * Returns: (transfer full): A #GIOStream or %NULL if @error is set.
892 g_dbus_address_get_stream_finish (GAsyncResult
*res
,
896 GSimpleAsyncResult
*simple
= G_SIMPLE_ASYNC_RESULT (res
);
900 g_return_val_if_fail (G_IS_ASYNC_RESULT (res
), NULL
);
901 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
903 g_warn_if_fail (g_simple_async_result_get_source_tag (simple
) == g_dbus_address_get_stream
);
907 data
= g_simple_async_result_get_op_res_gpointer (simple
);
908 if (g_simple_async_result_propagate_error (simple
, error
))
911 ret
= g_object_ref (data
->stream
);
912 if (out_guid
!= NULL
)
913 *out_guid
= g_strdup (data
->guid
);
920 * g_dbus_address_get_stream_sync:
921 * @address: A valid D-Bus address.
922 * @out_guid: %NULL or return location to store the GUID extracted from @address, if any.
923 * @cancellable: (allow-none): A #GCancellable or %NULL.
924 * @error: Return location for error or %NULL.
926 * Synchronously connects to an endpoint specified by @address and
927 * sets up the connection so it is in a state to run the client-side
928 * of the D-Bus authentication conversation.
930 * This is a synchronous failable function. See
931 * g_dbus_address_get_stream() for the asynchronous version.
933 * Returns: (transfer full): A #GIOStream or %NULL if @error is set.
938 g_dbus_address_get_stream_sync (const gchar
*address
,
940 GCancellable
*cancellable
,
948 g_return_val_if_fail (address
!= NULL
, NULL
);
949 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
954 addr_array
= g_strsplit (address
, ";", 0);
955 if (addr_array
!= NULL
&& addr_array
[0] == NULL
)
957 last_error
= g_error_new_literal (G_IO_ERROR
,
958 G_IO_ERROR_INVALID_ARGUMENT
,
959 _("The given address is empty"));
963 for (n
= 0; addr_array
!= NULL
&& addr_array
[n
] != NULL
; n
++)
965 const gchar
*addr
= addr_array
[n
];
969 ret
= g_dbus_address_try_connect_one (addr
,
979 g_assert (this_error
!= NULL
);
980 if (last_error
!= NULL
)
981 g_error_free (last_error
);
982 last_error
= this_error
;
989 if (last_error
!= NULL
)
990 g_error_free (last_error
);
994 g_assert (last_error
!= NULL
);
995 g_propagate_error (error
, last_error
);
998 g_strfreev (addr_array
);
1002 /* ---------------------------------------------------------------------------------------------------- */
1006 get_session_address_dbus_launch (GError
**error
)
1010 gchar
*command_line
;
1011 gchar
*launch_stdout
;
1012 gchar
*launch_stderr
;
1014 gchar
*old_dbus_verbose
;
1015 gboolean restore_dbus_verbose
;
1019 command_line
= NULL
;
1020 launch_stdout
= NULL
;
1021 launch_stderr
= NULL
;
1022 restore_dbus_verbose
= FALSE
;
1023 old_dbus_verbose
= NULL
;
1025 machine_id
= _g_dbus_get_machine_id (error
);
1026 if (machine_id
== NULL
)
1028 g_prefix_error (error
, _("Cannot spawn a message bus without a machine-id: "));
1032 /* We're using private libdbus facilities here. When everything
1033 * (X11, Mac OS X, Windows) is spec'ed out correctly (not even the
1034 * X11 property is correctly documented right now) we should
1035 * consider using the spec instead of dbus-launch.
1037 * --autolaunch=MACHINEID
1038 * This option implies that dbus-launch should scan for a previ‐
1039 * ously-started session and reuse the values found there. If no
1040 * session is found, it will start a new session. The --exit-with-
1041 * session option is implied if --autolaunch is given. This option
1042 * is for the exclusive use of libdbus, you do not want to use it
1043 * manually. It may change in the future.
1046 /* TODO: maybe provide a variable for where to look for the dbus-launch binary? */
1047 command_line
= g_strdup_printf ("dbus-launch --autolaunch=%s --binary-syntax --close-stderr", machine_id
);
1049 if (G_UNLIKELY (_g_dbus_debug_address ()))
1051 _g_dbus_debug_print_lock ();
1052 g_print ("GDBus-debug:Address: Running `%s' to get bus address (possibly autolaunching)\n", command_line
);
1053 old_dbus_verbose
= g_strdup (g_getenv ("DBUS_VERBOSE"));
1054 restore_dbus_verbose
= TRUE
;
1055 g_setenv ("DBUS_VERBOSE", "1", TRUE
);
1056 _g_dbus_debug_print_unlock ();
1059 if (!g_spawn_command_line_sync (command_line
,
1068 if (!g_spawn_check_exit_status (exit_status
, error
))
1070 g_prefix_error (error
, _("Error spawning command line `%s': "), command_line
);
1074 /* From the dbus-launch(1) man page:
1076 * --binary-syntax Write to stdout a nul-terminated bus address,
1077 * then the bus PID as a binary integer of size sizeof(pid_t),
1078 * then the bus X window ID as a binary integer of size
1079 * sizeof(long). Integers are in the machine's byte order, not
1080 * network byte order or any other canonical byte order.
1082 ret
= g_strdup (launch_stdout
);
1085 if (G_UNLIKELY (_g_dbus_debug_address ()))
1088 _g_dbus_debug_print_lock ();
1089 g_print ("GDBus-debug:Address: dbus-launch output:");
1090 if (launch_stdout
!= NULL
)
1092 s
= _g_dbus_hexdump (launch_stdout
, strlen (launch_stdout
) + 1 + sizeof (pid_t
) + sizeof (long), 2);
1093 g_print ("\n%s", s
);
1098 g_print (" (none)\n");
1100 g_print ("GDBus-debug:Address: dbus-launch stderr output:");
1101 if (launch_stderr
!= NULL
)
1102 g_print ("\n%s", launch_stderr
);
1104 g_print (" (none)\n");
1105 _g_dbus_debug_print_unlock ();
1108 g_free (machine_id
);
1109 g_free (command_line
);
1110 g_free (launch_stdout
);
1111 g_free (launch_stderr
);
1112 if (G_UNLIKELY (restore_dbus_verbose
))
1114 if (old_dbus_verbose
!= NULL
)
1115 g_setenv ("DBUS_VERBOSE", old_dbus_verbose
, TRUE
);
1117 g_unsetenv ("DBUS_VERBOSE");
1119 g_free (old_dbus_verbose
);
1126 #define DBUS_DAEMON_ADDRESS_INFO "DBusDaemonAddressInfo"
1127 #define DBUS_DAEMON_MUTEX "DBusDaemonMutex"
1128 #define UNIQUE_DBUS_INIT_MUTEX "UniqueDBusInitMutex"
1129 #define DBUS_AUTOLAUNCH_MUTEX "DBusAutolaunchMutex"
1132 release_mutex (HANDLE mutex
)
1134 ReleaseMutex (mutex
);
1135 CloseHandle (mutex
);
1139 acquire_mutex (const char *mutexname
)
1144 mutex
= CreateMutexA (NULL
, FALSE
, mutexname
);
1148 res
= WaitForSingleObject (mutex
, INFINITE
);
1151 case WAIT_ABANDONED
:
1152 release_mutex (mutex
);
1163 is_mutex_owned (const char *mutexname
)
1166 gboolean res
= FALSE
;
1168 mutex
= CreateMutexA (NULL
, FALSE
, mutexname
);
1169 if (WaitForSingleObject (mutex
, 10) == WAIT_TIMEOUT
)
1172 ReleaseMutex (mutex
);
1173 CloseHandle (mutex
);
1179 read_shm (const char *shm_name
)
1188 for (i
= 0; i
< 20; i
++)
1190 shared_mem
= OpenFileMappingA (FILE_MAP_READ
, FALSE
, shm_name
);
1191 if (shared_mem
!= 0)
1196 if (shared_mem
!= 0)
1198 shared_data
= MapViewOfFile (shared_mem
, FILE_MAP_READ
, 0, 0, 0);
1199 if (shared_data
!= NULL
)
1201 res
= g_strdup (shared_data
);
1202 UnmapViewOfFile (shared_data
);
1204 CloseHandle (shared_mem
);
1211 set_shm (const char *shm_name
, const char *value
)
1216 shared_mem
= CreateFileMappingA (INVALID_HANDLE_VALUE
, NULL
, PAGE_READWRITE
,
1217 0, strlen (value
) + 1, shm_name
);
1218 if (shared_mem
== 0)
1221 shared_data
= MapViewOfFile (shared_mem
, FILE_MAP_WRITE
, 0, 0, 0 );
1222 if (shared_data
== NULL
)
1225 strcpy (shared_data
, value
);
1227 UnmapViewOfFile (shared_data
);
1232 /* These keep state between publish_session_bus and unpublish_session_bus */
1233 static HANDLE published_daemon_mutex
;
1234 static HANDLE published_shared_mem
;
1237 publish_session_bus (const char *address
)
1241 init_mutex
= acquire_mutex (UNIQUE_DBUS_INIT_MUTEX
);
1243 published_daemon_mutex
= CreateMutexA (NULL
, FALSE
, DBUS_DAEMON_MUTEX
);
1244 if (WaitForSingleObject (published_daemon_mutex
, 10 ) != WAIT_OBJECT_0
)
1246 release_mutex (init_mutex
);
1247 CloseHandle (published_daemon_mutex
);
1248 published_daemon_mutex
= NULL
;
1252 published_shared_mem
= set_shm (DBUS_DAEMON_ADDRESS_INFO
, address
);
1253 if (!published_shared_mem
)
1255 release_mutex (init_mutex
);
1256 CloseHandle (published_daemon_mutex
);
1257 published_daemon_mutex
= NULL
;
1261 release_mutex (init_mutex
);
1266 unpublish_session_bus ()
1270 init_mutex
= acquire_mutex (UNIQUE_DBUS_INIT_MUTEX
);
1272 CloseHandle (published_shared_mem
);
1273 published_shared_mem
= NULL
;
1275 release_mutex (published_daemon_mutex
);
1276 published_daemon_mutex
= NULL
;
1278 release_mutex (init_mutex
);
1282 wait_console_window (void)
1284 FILE *console
= fopen ("CONOUT$", "w");
1286 SetConsoleTitleW (L
"gdbus-daemon output. Type any character to close this window.");
1287 fprintf (console
, _("(Type any character to close this window)\n"));
1293 open_console_window (void)
1295 if (((HANDLE
) _get_osfhandle (fileno (stdout
)) == INVALID_HANDLE_VALUE
||
1296 (HANDLE
) _get_osfhandle (fileno (stderr
)) == INVALID_HANDLE_VALUE
) && AllocConsole ())
1298 if ((HANDLE
) _get_osfhandle (fileno (stdout
)) == INVALID_HANDLE_VALUE
)
1299 freopen ("CONOUT$", "w", stdout
);
1301 if ((HANDLE
) _get_osfhandle (fileno (stderr
)) == INVALID_HANDLE_VALUE
)
1302 freopen ("CONOUT$", "w", stderr
);
1304 SetConsoleTitleW (L
"gdbus-daemon debug output.");
1306 atexit (wait_console_window
);
1310 idle_timeout_cb (GDBusDaemon
*daemon
, gpointer user_data
)
1312 GMainLoop
*loop
= user_data
;
1313 g_main_loop_quit (loop
);
1316 __declspec(dllexport
) void CALLBACK
1317 g_win32_run_session_bus (HWND hwnd
, HINSTANCE hinst
, char *cmdline
, int nCmdShow
)
1319 GDBusDaemon
*daemon
;
1321 const char *address
;
1322 GError
*error
= NULL
;
1324 if (g_getenv ("GDBUS_DAEMON_DEBUG") != NULL
)
1325 open_console_window ();
1329 loop
= g_main_loop_new (NULL
, FALSE
);
1331 address
= "nonce-tcp:";
1332 daemon
= _g_dbus_daemon_new (address
, NULL
, &error
);
1335 g_printerr ("Can't init bus: %s\n", error
->message
);
1339 g_signal_connect (daemon
, "idle-timeout", G_CALLBACK (idle_timeout_cb
), loop
);
1341 if ( publish_session_bus (_g_dbus_daemon_get_address (daemon
)))
1343 g_main_loop_run (loop
);
1345 unpublish_session_bus ();
1348 g_main_loop_unref (loop
);
1349 g_object_unref (daemon
);
1353 get_session_address_dbus_launch (GError
**error
)
1355 HANDLE autolaunch_mutex
, init_mutex
;
1356 char *address
= NULL
;
1357 wchar_t gio_path
[MAX_PATH
+1+200];
1359 autolaunch_mutex
= acquire_mutex (DBUS_AUTOLAUNCH_MUTEX
);
1361 init_mutex
= acquire_mutex (UNIQUE_DBUS_INIT_MUTEX
);
1363 if (is_mutex_owned (DBUS_DAEMON_MUTEX
))
1364 address
= read_shm (DBUS_DAEMON_ADDRESS_INFO
);
1366 release_mutex (init_mutex
);
1368 if (address
== NULL
)
1370 gio_path
[MAX_PATH
] = 0;
1371 if (GetModuleFileNameW (_g_io_win32_get_module (), gio_path
, MAX_PATH
))
1373 PROCESS_INFORMATION pi
= { 0 };
1374 STARTUPINFOW si
= { 0 };
1376 wchar_t gio_path_short
[MAX_PATH
];
1377 wchar_t rundll_path
[MAX_PATH
*2];
1378 wchar_t args
[MAX_PATH
*4];
1380 GetShortPathNameW (gio_path
, gio_path_short
, MAX_PATH
);
1382 GetWindowsDirectoryW (rundll_path
, MAX_PATH
);
1383 wcscat (rundll_path
, L
"\\rundll32.exe");
1384 if (GetFileAttributesW (rundll_path
) == INVALID_FILE_ATTRIBUTES
)
1386 GetSystemDirectoryW (rundll_path
, MAX_PATH
);
1387 wcscat (rundll_path
, L
"\\rundll32.exe");
1390 wcscpy (args
, L
"\"");
1391 wcscat (args
, rundll_path
);
1392 wcscat (args
, L
"\" ");
1393 wcscat (args
, gio_path_short
);
1394 wcscat (args
, L
",g_win32_run_session_bus@16");
1396 res
= CreateProcessW (rundll_path
, args
,
1398 NORMAL_PRIORITY_CLASS
| CREATE_NO_WINDOW
| DETACHED_PROCESS
,
1399 0, NULL
/* TODO: Should be root */,
1402 address
= read_shm (DBUS_DAEMON_ADDRESS_INFO
);
1406 release_mutex (autolaunch_mutex
);
1408 if (address
== NULL
)
1412 _("Session dbus not running, and autolaunch failed"));
1418 /* ---------------------------------------------------------------------------------------------------- */
1421 get_session_address_platform_specific (GError
**error
)
1424 #if defined (G_OS_UNIX) || defined(G_OS_WIN32)
1425 /* need to handle OS X in a different way since `dbus-launch --autolaunch' probably won't work there */
1426 ret
= get_session_address_dbus_launch (error
);
1428 /* TODO: implement for OS X */
1433 _("Cannot determine session bus address (not implemented for this OS)"));
1438 /* ---------------------------------------------------------------------------------------------------- */
1441 * g_dbus_address_get_for_bus_sync:
1442 * @bus_type: A #GBusType.
1443 * @cancellable: (allow-none): A #GCancellable or %NULL.
1444 * @error: Return location for error or %NULL.
1446 * Synchronously looks up the D-Bus address for the well-known message
1447 * bus instance specified by @bus_type. This may involve using various
1448 * platform specific mechanisms.
1450 * Returns: A valid D-Bus address string for @bus_type or %NULL if @error is set.
1455 g_dbus_address_get_for_bus_sync (GBusType bus_type
,
1456 GCancellable
*cancellable
,
1460 const gchar
*starter_bus
;
1461 GError
*local_error
;
1463 g_return_val_if_fail (error
== NULL
|| *error
== NULL
, NULL
);
1468 if (G_UNLIKELY (_g_dbus_debug_address ()))
1471 _g_dbus_debug_print_lock ();
1472 g_print ("GDBus-debug:Address: In g_dbus_address_get_for_bus_sync() for bus type `%s'\n",
1473 _g_dbus_enum_to_string (G_TYPE_BUS_TYPE
, bus_type
));
1474 for (n
= 0; n
< 3; n
++)
1480 case 0: k
= "DBUS_SESSION_BUS_ADDRESS"; break;
1481 case 1: k
= "DBUS_SYSTEM_BUS_ADDRESS"; break;
1482 case 2: k
= "DBUS_STARTER_BUS_TYPE"; break;
1483 default: g_assert_not_reached ();
1486 g_print ("GDBus-debug:Address: env var %s", k
);
1488 g_print ("=`%s'\n", v
);
1490 g_print (" is not set\n");
1492 _g_dbus_debug_print_unlock ();
1497 case G_BUS_TYPE_SYSTEM
:
1498 ret
= g_strdup (g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
1501 ret
= g_strdup ("unix:path=/var/run/dbus/system_bus_socket");
1505 case G_BUS_TYPE_SESSION
:
1506 ret
= g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
1509 ret
= get_session_address_platform_specific (&local_error
);
1513 case G_BUS_TYPE_STARTER
:
1514 starter_bus
= g_getenv ("DBUS_STARTER_BUS_TYPE");
1515 if (g_strcmp0 (starter_bus
, "session") == 0)
1517 ret
= g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION
, cancellable
, &local_error
);
1520 else if (g_strcmp0 (starter_bus
, "system") == 0)
1522 ret
= g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SYSTEM
, cancellable
, &local_error
);
1527 if (starter_bus
!= NULL
)
1529 g_set_error (&local_error
,
1532 _("Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable"
1533 " - unknown value `%s'"),
1538 g_set_error_literal (&local_error
,
1541 _("Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment "
1542 "variable is not set"));
1548 g_set_error (&local_error
,
1551 _("Unknown bus type %d"),
1557 if (G_UNLIKELY (_g_dbus_debug_address ()))
1559 _g_dbus_debug_print_lock ();
1562 g_print ("GDBus-debug:Address: Returning address `%s' for bus type `%s'\n",
1564 _g_dbus_enum_to_string (G_TYPE_BUS_TYPE
, bus_type
));
1568 g_print ("GDBus-debug:Address: Cannot look-up address bus type `%s': %s\n",
1569 _g_dbus_enum_to_string (G_TYPE_BUS_TYPE
, bus_type
),
1570 local_error
? local_error
->message
: "");
1572 _g_dbus_debug_print_unlock ();
1575 if (local_error
!= NULL
)
1576 g_propagate_error (error
, local_error
);