Avoid calls to strlen in miscellaneous functions.
[bpt/emacs.git] / src / dbusbind.c
CommitLineData
033b73e2 1/* Elisp bindings for D-Bus.
acaf905b 2 Copyright (C) 2007-2012 Free Software Foundation, Inc.
033b73e2
MA
3
4This file is part of GNU Emacs.
5
9ec0b715 6GNU Emacs is free software: you can redistribute it and/or modify
033b73e2 7it under the terms of the GNU General Public License as published by
9ec0b715
GM
8the Free Software Foundation, either version 3 of the License, or
9(at your option) any later version.
033b73e2
MA
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
9ec0b715 17along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
033b73e2 18
08a494a3 19#include <config.h>
033b73e2
MA
20
21#ifdef HAVE_DBUS
f5306ca3 22#include <stdio.h>
033b73e2 23#include <dbus/dbus.h>
d7306fe6 24#include <setjmp.h>
033b73e2
MA
25#include "lisp.h"
26#include "frame.h"
27#include "termhooks.h"
28#include "keyboard.h"
3fad2ad2 29#include "process.h"
033b73e2 30
dcbf5805
MA
31#ifndef DBUS_NUM_MESSAGE_TYPES
32#define DBUS_NUM_MESSAGE_TYPES 5
33#endif
34
033b73e2
MA
35\f
36/* Subroutines. */
955cbe7b 37static Lisp_Object Qdbus_init_bus;
955cbe7b 38static Lisp_Object Qdbus_get_unique_name;
dcbf5805 39static Lisp_Object Qdbus_message_internal;
033b73e2
MA
40
41/* D-Bus error symbol. */
955cbe7b 42static Lisp_Object Qdbus_error;
033b73e2
MA
43
44/* Lisp symbols of the system and session buses. */
955cbe7b 45static Lisp_Object QCdbus_system_bus, QCdbus_session_bus;
033b73e2 46
90b3fc84 47/* Lisp symbol for method call timeout. */
955cbe7b 48static Lisp_Object QCdbus_timeout;
90b3fc84 49
54371585 50/* Lisp symbols of D-Bus types. */
955cbe7b
PE
51static Lisp_Object QCdbus_type_byte, QCdbus_type_boolean;
52static Lisp_Object QCdbus_type_int16, QCdbus_type_uint16;
53static Lisp_Object QCdbus_type_int32, QCdbus_type_uint32;
54static Lisp_Object QCdbus_type_int64, QCdbus_type_uint64;
55static Lisp_Object QCdbus_type_double, QCdbus_type_string;
56static Lisp_Object QCdbus_type_object_path, QCdbus_type_signature;
da1fec2b 57#ifdef DBUS_TYPE_UNIX_FD
b4289b64 58static Lisp_Object QCdbus_type_unix_fd;
da1fec2b 59#endif
955cbe7b
PE
60static Lisp_Object QCdbus_type_array, QCdbus_type_variant;
61static Lisp_Object QCdbus_type_struct, QCdbus_type_dict_entry;
54371585 62
dcbf5805
MA
63/* Lisp symbols of objects in `dbus-registered-objects-table'. */
64static Lisp_Object QCdbus_registered_serial, QCdbus_registered_method;
65static Lisp_Object QCdbus_registered_signal;
66
5cb67954
MA
67/* Alist of D-Bus buses we are polling for messages.
68 The key is the symbol or string of the bus, and the value is the
69 connection address. */
70static Lisp_Object xd_registered_buses;
71
1dae9197 72/* Whether we are reading a D-Bus event. */
16390cd2 73static int xd_in_read_queued_messages = 0;
1dae9197 74
033b73e2
MA
75\f
76/* We use "xd_" and "XD_" as prefix for all internal symbols, because
77 we don't want to poison other namespaces with "dbus_". */
78
1dae9197
MA
79/* Raise a signal. If we are reading events, we cannot signal; we
80 throw to xd_read_queued_messages then. */
81#define XD_SIGNAL1(arg) \
82 do { \
83 if (xd_in_read_queued_messages) \
84 Fthrow (Qdbus_error, Qnil); \
85 else \
86 xsignal1 (Qdbus_error, arg); \
87 } while (0)
88
89#define XD_SIGNAL2(arg1, arg2) \
90 do { \
91 if (xd_in_read_queued_messages) \
92 Fthrow (Qdbus_error, Qnil); \
93 else \
94 xsignal2 (Qdbus_error, arg1, arg2); \
95 } while (0)
96
97#define XD_SIGNAL3(arg1, arg2, arg3) \
98 do { \
99 if (xd_in_read_queued_messages) \
100 Fthrow (Qdbus_error, Qnil); \
101 else \
102 xsignal3 (Qdbus_error, arg1, arg2, arg3); \
103 } while (0)
104
54371585 105/* Raise a Lisp error from a D-Bus ERROR. */
033b73e2 106#define XD_ERROR(error) \
17bc8f94 107 do { \
033b73e2 108 /* Remove the trailing newline. */ \
573f4b54
PE
109 char const *mess = error.message; \
110 char const *nl = strchr (mess, '\n'); \
111 Lisp_Object err = make_string (mess, nl ? nl - mess : strlen (mess)); \
112 dbus_error_free (&error); \
113 XD_SIGNAL1 (err); \
17bc8f94 114 } while (0)
033b73e2
MA
115
116/* Macros for debugging. In order to enable them, build with
dcbf5805 117 "env MYCPPFLAGS='-DDBUS_DEBUG -Wall' make". */
033b73e2 118#ifdef DBUS_DEBUG
9a4b36f8
MA
119#define XD_DEBUG_MESSAGE(...) \
120 do { \
121 char s[1024]; \
122 snprintf (s, sizeof s, __VA_ARGS__); \
123 if (!noninteractive) \
124 printf ("%s: %s\n", __func__, s); \
125 message ("%s: %s", __func__, s); \
17bc8f94 126 } while (0)
033b73e2 127#define XD_DEBUG_VALID_LISP_OBJECT_P(object) \
17bc8f94
MA
128 do { \
129 if (!valid_lisp_object_p (object)) \
130 { \
131 XD_DEBUG_MESSAGE ("%d Assertion failure", __LINE__); \
1dae9197 132 XD_SIGNAL1 (build_string ("Assertion failure")); \
17bc8f94
MA
133 } \
134 } while (0)
033b73e2
MA
135
136#else /* !DBUS_DEBUG */
17bc8f94
MA
137#define XD_DEBUG_MESSAGE(...) \
138 do { \
139 if (!NILP (Vdbus_debug)) \
140 { \
141 char s[1024]; \
dcbf5805 142 snprintf (s, sizeof s, __VA_ARGS__); \
17bc8f94 143 message ("%s: %s", __func__, s); \
80f9d13b 144 } \
17bc8f94 145 } while (0)
033b73e2
MA
146#define XD_DEBUG_VALID_LISP_OBJECT_P(object)
147#endif
148
87cf1a39 149/* Check whether TYPE is a basic DBusType. */
ff88beb8
MA
150#ifdef HAVE_DBUS_TYPE_IS_VALID
151#define XD_BASIC_DBUS_TYPE(type) \
152 (dbus_type_is_valid (type) && dbus_type_is_basic (type))
153#else
da1fec2b
MA
154#ifdef DBUS_TYPE_UNIX_FD
155#define XD_BASIC_DBUS_TYPE(type) \
156 ((type == DBUS_TYPE_BYTE) \
157 || (type == DBUS_TYPE_BOOLEAN) \
158 || (type == DBUS_TYPE_INT16) \
159 || (type == DBUS_TYPE_UINT16) \
160 || (type == DBUS_TYPE_INT32) \
161 || (type == DBUS_TYPE_UINT32) \
162 || (type == DBUS_TYPE_INT64) \
163 || (type == DBUS_TYPE_UINT64) \
164 || (type == DBUS_TYPE_DOUBLE) \
165 || (type == DBUS_TYPE_STRING) \
166 || (type == DBUS_TYPE_OBJECT_PATH) \
01768686 167 || (type == DBUS_TYPE_SIGNATURE) \
da1fec2b
MA
168 || (type == DBUS_TYPE_UNIX_FD))
169#else
87cf1a39
MA
170#define XD_BASIC_DBUS_TYPE(type) \
171 ((type == DBUS_TYPE_BYTE) \
172 || (type == DBUS_TYPE_BOOLEAN) \
173 || (type == DBUS_TYPE_INT16) \
174 || (type == DBUS_TYPE_UINT16) \
175 || (type == DBUS_TYPE_INT32) \
176 || (type == DBUS_TYPE_UINT32) \
177 || (type == DBUS_TYPE_INT64) \
178 || (type == DBUS_TYPE_UINT64) \
179 || (type == DBUS_TYPE_DOUBLE) \
180 || (type == DBUS_TYPE_STRING) \
181 || (type == DBUS_TYPE_OBJECT_PATH) \
182 || (type == DBUS_TYPE_SIGNATURE))
da1fec2b 183#endif
ff88beb8 184#endif
87cf1a39 185
78c38319 186/* This was a macro. On Solaris 2.11 it was said to compile for
e1dbe924 187 hours, when optimization is enabled. So we have transferred it into
78c38319 188 a function. */
54371585
MA
189/* Determine the DBusType of a given Lisp symbol. OBJECT must be one
190 of the predefined D-Bus type symbols. */
78c38319 191static int
971de7fb 192xd_symbol_to_dbus_type (Lisp_Object object)
78c38319
MA
193{
194 return
195 ((EQ (object, QCdbus_type_byte)) ? DBUS_TYPE_BYTE
196 : (EQ (object, QCdbus_type_boolean)) ? DBUS_TYPE_BOOLEAN
197 : (EQ (object, QCdbus_type_int16)) ? DBUS_TYPE_INT16
198 : (EQ (object, QCdbus_type_uint16)) ? DBUS_TYPE_UINT16
199 : (EQ (object, QCdbus_type_int32)) ? DBUS_TYPE_INT32
200 : (EQ (object, QCdbus_type_uint32)) ? DBUS_TYPE_UINT32
201 : (EQ (object, QCdbus_type_int64)) ? DBUS_TYPE_INT64
202 : (EQ (object, QCdbus_type_uint64)) ? DBUS_TYPE_UINT64
203 : (EQ (object, QCdbus_type_double)) ? DBUS_TYPE_DOUBLE
204 : (EQ (object, QCdbus_type_string)) ? DBUS_TYPE_STRING
205 : (EQ (object, QCdbus_type_object_path)) ? DBUS_TYPE_OBJECT_PATH
206 : (EQ (object, QCdbus_type_signature)) ? DBUS_TYPE_SIGNATURE
da1fec2b
MA
207#ifdef DBUS_TYPE_UNIX_FD
208 : (EQ (object, QCdbus_type_unix_fd)) ? DBUS_TYPE_UNIX_FD
209#endif
78c38319
MA
210 : (EQ (object, QCdbus_type_array)) ? DBUS_TYPE_ARRAY
211 : (EQ (object, QCdbus_type_variant)) ? DBUS_TYPE_VARIANT
212 : (EQ (object, QCdbus_type_struct)) ? DBUS_TYPE_STRUCT
213 : (EQ (object, QCdbus_type_dict_entry)) ? DBUS_TYPE_DICT_ENTRY
214 : DBUS_TYPE_INVALID);
215}
87cf1a39
MA
216
217/* Check whether a Lisp symbol is a predefined D-Bus type symbol. */
218#define XD_DBUS_TYPE_P(object) \
78c38319 219 (SYMBOLP (object) && ((xd_symbol_to_dbus_type (object) != DBUS_TYPE_INVALID)))
54371585
MA
220
221/* Determine the DBusType of a given Lisp OBJECT. It is used to
033b73e2
MA
222 convert Lisp objects, being arguments of `dbus-call-method' or
223 `dbus-send-signal', into corresponding C values appended as
224 arguments to a D-Bus message. */
87cf1a39
MA
225#define XD_OBJECT_TO_DBUS_TYPE(object) \
226 ((EQ (object, Qt) || EQ (object, Qnil)) ? DBUS_TYPE_BOOLEAN \
227 : (NATNUMP (object)) ? DBUS_TYPE_UINT32 \
228 : (INTEGERP (object)) ? DBUS_TYPE_INT32 \
229 : (FLOATP (object)) ? DBUS_TYPE_DOUBLE \
230 : (STRINGP (object)) ? DBUS_TYPE_STRING \
78c38319 231 : (XD_DBUS_TYPE_P (object)) ? xd_symbol_to_dbus_type (object) \
07a4cb03
MA
232 : (CONSP (object)) \
233 ? ((XD_DBUS_TYPE_P (CAR_SAFE (object))) \
78c38319 234 ? ((XD_BASIC_DBUS_TYPE (xd_symbol_to_dbus_type (CAR_SAFE (object)))) \
07a4cb03 235 ? DBUS_TYPE_ARRAY \
78c38319 236 : xd_symbol_to_dbus_type (CAR_SAFE (object))) \
07a4cb03 237 : DBUS_TYPE_ARRAY) \
87cf1a39
MA
238 : DBUS_TYPE_INVALID)
239
240/* Return a list pointer which does not have a Lisp symbol as car. */
a8e72f4f 241#define XD_NEXT_VALUE(object) \
5125905e 242 ((XD_DBUS_TYPE_P (CAR_SAFE (object))) ? CDR_SAFE (object) : object)
87cf1a39 243
dcbf5805
MA
244/* Transform the message type to its string representation for debug
245 messages. */
246#define XD_MESSAGE_TYPE_TO_STRING(mtype) \
247 ((mtype == DBUS_MESSAGE_TYPE_INVALID) \
248 ? "DBUS_MESSAGE_TYPE_INVALID" \
249 : (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL) \
250 ? "DBUS_MESSAGE_TYPE_METHOD_CALL" \
251 : (mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN) \
252 ? "DBUS_MESSAGE_TYPE_METHOD_RETURN" \
253 : (mtype == DBUS_MESSAGE_TYPE_ERROR) \
254 ? "DBUS_MESSAGE_TYPE_ERROR" \
255 : "DBUS_MESSAGE_TYPE_SIGNAL")
256
257/* Transform the object to its string representation for debug
258 messages. */
259#define XD_OBJECT_TO_STRING(object) \
260 SDATA (format2 ("%s", object, Qnil))
261
dcbf5805
MA
262#define XD_DBUS_VALIDATE_BUS_ADDRESS(bus) \
263 do { \
264 if (STRINGP (bus)) \
265 { \
266 DBusAddressEntry **entries; \
267 int len; \
268 DBusError derror; \
269 dbus_error_init (&derror); \
270 if (!dbus_parse_address (SSDATA (bus), &entries, &len, &derror)) \
271 XD_ERROR (derror); \
272 /* Cleanup. */ \
273 dbus_error_free (&derror); \
274 dbus_address_entries_free (entries); \
275 } \
276 \
277 else \
278 { \
279 CHECK_SYMBOL (bus); \
280 if (!(EQ (bus, QCdbus_system_bus) || EQ (bus, QCdbus_session_bus))) \
281 XD_SIGNAL2 (build_string ("Wrong bus name"), bus); \
282 /* We do not want to have an autolaunch for the session bus. */ \
283 if (EQ (bus, QCdbus_session_bus) \
284 && getenv ("DBUS_SESSION_BUS_ADDRESS") == NULL) \
285 XD_SIGNAL2 (build_string ("No connection to bus"), bus); \
286 } \
287 } while (0)
288
de85e130
PE
289#if (HAVE_DBUS_VALIDATE_BUS_NAME || HAVE_DBUS_VALIDATE_PATH \
290 || XD_DBUS_VALIDATE_OBJECT || HAVE_DBUS_VALIDATE_MEMBER)
dcbf5805
MA
291#define XD_DBUS_VALIDATE_OBJECT(object, func) \
292 do { \
293 if (!NILP (object)) \
294 { \
295 DBusError derror; \
296 CHECK_STRING (object); \
297 dbus_error_init (&derror); \
298 if (!func (SSDATA (object), &derror)) \
299 XD_ERROR (derror); \
300 /* Cleanup. */ \
301 dbus_error_free (&derror); \
302 } \
303 } while (0)
de85e130 304#endif
dcbf5805
MA
305
306#if HAVE_DBUS_VALIDATE_BUS_NAME
307#define XD_DBUS_VALIDATE_BUS_NAME(bus_name) \
308 XD_DBUS_VALIDATE_OBJECT(bus_name, dbus_validate_bus_name);
309#else
310#define XD_DBUS_VALIDATE_BUS_NAME(bus_name) \
311 if (!NILP (bus_name)) CHECK_STRING (bus_name);
312#endif
313
314#if HAVE_DBUS_VALIDATE_PATH
315#define XD_DBUS_VALIDATE_PATH(path) \
316 XD_DBUS_VALIDATE_OBJECT(path, dbus_validate_path);
317#else
318#define XD_DBUS_VALIDATE_PATH(path) \
319 if (!NILP (path)) CHECK_STRING (path);
320#endif
321
322#if HAVE_DBUS_VALIDATE_INTERFACE
323#define XD_DBUS_VALIDATE_INTERFACE(interface) \
324 XD_DBUS_VALIDATE_OBJECT(interface, dbus_validate_interface);
325#else
326#define XD_DBUS_VALIDATE_INTERFACE(interface) \
327 if (!NILP (interface)) CHECK_STRING (interface);
328#endif
329
330#if HAVE_DBUS_VALIDATE_MEMBER
331#define XD_DBUS_VALIDATE_MEMBER(member) \
332 XD_DBUS_VALIDATE_OBJECT(member, dbus_validate_member);
333#else
334#define XD_DBUS_VALIDATE_MEMBER(member) \
335 if (!NILP (member)) CHECK_STRING (member);
336#endif
08686060 337
e936e76e 338/* Append to SIGNATURE a copy of X, making sure SIGNATURE does
2be7d702
PE
339 not become too long. */
340static void
ecfc0a49 341xd_signature_cat (char *signature, char const *x)
2be7d702
PE
342{
343 ptrdiff_t siglen = strlen (signature);
344 ptrdiff_t xlen = strlen (x);
345 if (DBUS_MAXIMUM_SIGNATURE_LENGTH - xlen <= siglen)
346 string_overflow ();
347 strcat (signature, x);
348}
349
87cf1a39
MA
350/* Compute SIGNATURE of OBJECT. It must have a form that it can be
351 used in dbus_message_iter_open_container. DTYPE is the DBusType
352 the object is related to. It is passed as argument, because it
353 cannot be detected in basic type objects, when they are preceded by
354 a type symbol. PARENT_TYPE is the DBusType of a container this
355 signature is embedded, or DBUS_TYPE_INVALID. It is needed for the
356 check that DBUS_TYPE_DICT_ENTRY occurs only as array element. */
78c38319 357static void
243e0530 358xd_signature (char *signature, int dtype, int parent_type, Lisp_Object object)
033b73e2 359{
243e0530 360 int subtype;
87cf1a39 361 Lisp_Object elt;
2ea16b89 362 char const *subsig;
8666506e 363 int subsiglen;
87cf1a39
MA
364 char x[DBUS_MAXIMUM_SIGNATURE_LENGTH];
365
366 elt = object;
033b73e2 367
033b73e2
MA
368 switch (dtype)
369 {
54371585
MA
370 case DBUS_TYPE_BYTE:
371 case DBUS_TYPE_UINT16:
54371585 372 CHECK_NATNUM (object);
87cf1a39 373 sprintf (signature, "%c", dtype);
54371585 374 break;
87cf1a39 375
54371585
MA
376 case DBUS_TYPE_BOOLEAN:
377 if (!EQ (object, Qt) && !EQ (object, Qnil))
378 wrong_type_argument (intern ("booleanp"), object);
87cf1a39 379 sprintf (signature, "%c", dtype);
54371585 380 break;
87cf1a39 381
54371585 382 case DBUS_TYPE_INT16:
54371585 383 CHECK_NUMBER (object);
87cf1a39 384 sprintf (signature, "%c", dtype);
54371585 385 break;
87cf1a39 386
dcbf5805
MA
387 case DBUS_TYPE_UINT32:
388 case DBUS_TYPE_UINT64:
389#ifdef DBUS_TYPE_UNIX_FD
390 case DBUS_TYPE_UNIX_FD:
391#endif
392 case DBUS_TYPE_INT32:
393 case DBUS_TYPE_INT64:
033b73e2 394 case DBUS_TYPE_DOUBLE:
dcbf5805 395 CHECK_NUMBER_OR_FLOAT (object);
87cf1a39 396 sprintf (signature, "%c", dtype);
54371585 397 break;
87cf1a39 398
033b73e2 399 case DBUS_TYPE_STRING:
54371585
MA
400 case DBUS_TYPE_OBJECT_PATH:
401 case DBUS_TYPE_SIGNATURE:
402 CHECK_STRING (object);
87cf1a39 403 sprintf (signature, "%c", dtype);
54371585 404 break;
87cf1a39 405
54371585 406 case DBUS_TYPE_ARRAY:
9af5078b 407 /* Check that all list elements have the same D-Bus type. For
87cf1a39
MA
408 complex element types, we just check the container type, not
409 the whole element's signature. */
54371585 410 CHECK_CONS (object);
87cf1a39 411
5125905e
MA
412 /* Type symbol is optional. */
413 if (EQ (QCdbus_type_array, CAR_SAFE (elt)))
87cf1a39 414 elt = XD_NEXT_VALUE (elt);
5125905e
MA
415
416 /* If the array is empty, DBUS_TYPE_STRING is the default
417 element type. */
418 if (NILP (elt))
419 {
420 subtype = DBUS_TYPE_STRING;
2ea16b89 421 subsig = DBUS_TYPE_STRING_AS_STRING;
5125905e
MA
422 }
423 else
424 {
425 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
426 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
2ea16b89 427 subsig = x;
5125905e
MA
428 }
429
430 /* If the element type is DBUS_TYPE_SIGNATURE, and this is the
dcbf5805
MA
431 only element, the value of this element is used as the
432 array's element signature. */
5125905e
MA
433 if ((subtype == DBUS_TYPE_SIGNATURE)
434 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (elt)))
435 && NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
2ea16b89 436 subsig = SSDATA (CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39
MA
437
438 while (!NILP (elt))
439 {
5125905e
MA
440 if (subtype != XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt)))
441 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (elt));
442 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39
MA
443 }
444
8666506e
PE
445 subsiglen = snprintf (signature, DBUS_MAXIMUM_SIGNATURE_LENGTH,
446 "%c%s", dtype, subsig);
447 if (! (0 <= subsiglen && subsiglen < DBUS_MAXIMUM_SIGNATURE_LENGTH))
2ea16b89 448 string_overflow ();
54371585 449 break;
87cf1a39 450
54371585 451 case DBUS_TYPE_VARIANT:
9af5078b 452 /* Check that there is exactly one list element. */
54371585 453 CHECK_CONS (object);
87cf1a39
MA
454
455 elt = XD_NEXT_VALUE (elt);
5125905e
MA
456 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
457 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
87cf1a39 458
5125905e 459 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 460 wrong_type_argument (intern ("D-Bus"),
5125905e 461 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
87cf1a39 462
a271e124 463 sprintf (signature, "%c", dtype);
54371585 464 break;
87cf1a39 465
54371585 466 case DBUS_TYPE_STRUCT:
9af5078b
MA
467 /* A struct list might contain any number of elements with
468 different types. No further check needed. */
87cf1a39
MA
469 CHECK_CONS (object);
470
471 elt = XD_NEXT_VALUE (elt);
472
473 /* Compose the signature from the elements. It is enclosed by
474 parentheses. */
475 sprintf (signature, "%c", DBUS_STRUCT_BEGIN_CHAR );
476 while (!NILP (elt))
477 {
5125905e
MA
478 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
479 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
ecfc0a49 480 xd_signature_cat (signature, x);
5125905e 481 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
87cf1a39 482 }
ecfc0a49 483 xd_signature_cat (signature, DBUS_STRUCT_END_CHAR_AS_STRING);
54371585 484 break;
54371585 485
87cf1a39 486 case DBUS_TYPE_DICT_ENTRY:
9af5078b
MA
487 /* Check that there are exactly two list elements, and the first
488 one is of basic type. The dictionary entry itself must be an
489 element of an array. */
87cf1a39 490 CHECK_CONS (object);
54371585 491
9af5078b 492 /* Check the parent object type. */
87cf1a39
MA
493 if (parent_type != DBUS_TYPE_ARRAY)
494 wrong_type_argument (intern ("D-Bus"), object);
54371585 495
87cf1a39
MA
496 /* Compose the signature from the elements. It is enclosed by
497 curly braces. */
498 sprintf (signature, "%c", DBUS_DICT_ENTRY_BEGIN_CHAR);
54371585 499
87cf1a39
MA
500 /* First element. */
501 elt = XD_NEXT_VALUE (elt);
5125905e
MA
502 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
503 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
ecfc0a49 504 xd_signature_cat (signature, x);
54371585 505
87cf1a39 506 if (!XD_BASIC_DBUS_TYPE (subtype))
5125905e 507 wrong_type_argument (intern ("D-Bus"), CAR_SAFE (XD_NEXT_VALUE (elt)));
54371585 508
87cf1a39 509 /* Second element. */
5125905e
MA
510 elt = CDR_SAFE (XD_NEXT_VALUE (elt));
511 subtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (elt));
512 xd_signature (x, subtype, dtype, CAR_SAFE (XD_NEXT_VALUE (elt)));
ecfc0a49 513 xd_signature_cat (signature, x);
54371585 514
5125905e 515 if (!NILP (CDR_SAFE (XD_NEXT_VALUE (elt))))
87cf1a39 516 wrong_type_argument (intern ("D-Bus"),
5125905e 517 CAR_SAFE (CDR_SAFE (XD_NEXT_VALUE (elt))));
54371585 518
87cf1a39 519 /* Closing signature. */
ecfc0a49 520 xd_signature_cat (signature, DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
87cf1a39 521 break;
54371585 522
87cf1a39
MA
523 default:
524 wrong_type_argument (intern ("D-Bus"), object);
54371585
MA
525 }
526
87cf1a39
MA
527 XD_DEBUG_MESSAGE ("%s", signature);
528}
54371585 529
42b2a986
PE
530/* Convert X to a signed integer with bounds LO and HI. */
531static intmax_t
ff88beb8 532xd_extract_signed (Lisp_Object x, intmax_t lo, intmax_t hi)
42b2a986
PE
533{
534 CHECK_NUMBER_OR_FLOAT (x);
535 if (INTEGERP (x))
536 {
537 if (lo <= XINT (x) && XINT (x) <= hi)
538 return XINT (x);
539 }
540 else
541 {
542 double d = XFLOAT_DATA (x);
543 if (lo <= d && d <= hi)
544 {
545 intmax_t n = d;
546 if (n == d)
547 return n;
548 }
549 }
243e0530
PE
550 if (xd_in_read_queued_messages)
551 Fthrow (Qdbus_error, Qnil);
552 else
553 args_out_of_range_3 (x,
554 make_fixnum_or_float (lo),
555 make_fixnum_or_float (hi));
42b2a986
PE
556}
557
558/* Convert X to an unsigned integer with bounds 0 and HI. */
559static uintmax_t
ff88beb8 560xd_extract_unsigned (Lisp_Object x, uintmax_t hi)
42b2a986
PE
561{
562 CHECK_NUMBER_OR_FLOAT (x);
563 if (INTEGERP (x))
564 {
565 if (0 <= XINT (x) && XINT (x) <= hi)
566 return XINT (x);
567 }
568 else
569 {
570 double d = XFLOAT_DATA (x);
571 if (0 <= d && d <= hi)
572 {
573 uintmax_t n = d;
574 if (n == d)
575 return n;
576 }
577 }
243e0530
PE
578 if (xd_in_read_queued_messages)
579 Fthrow (Qdbus_error, Qnil);
580 else
581 args_out_of_range_3 (x, make_number (0), make_fixnum_or_float (hi));
42b2a986
PE
582}
583
87cf1a39
MA
584/* Append C value, extracted from Lisp OBJECT, to iteration ITER.
585 DTYPE must be a valid DBusType. It is used to convert Lisp
586 objects, being arguments of `dbus-call-method' or
587 `dbus-send-signal', into corresponding C values appended as
588 arguments to a D-Bus message. */
78c38319 589static void
243e0530 590xd_append_arg (int dtype, Lisp_Object object, DBusMessageIter *iter)
87cf1a39 591{
87cf1a39
MA
592 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
593 DBusMessageIter subiter;
87cf1a39
MA
594
595 if (XD_BASIC_DBUS_TYPE (dtype))
17bc8f94
MA
596 switch (dtype)
597 {
598 case DBUS_TYPE_BYTE:
2d1fc3c7 599 CHECK_NATNUM (object);
54371585 600 {
2d1fc3c7 601 unsigned char val = XFASTINT (object) & 0xFF;
3478ec45 602 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
17bc8f94 603 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 604 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
605 return;
606 }
87cf1a39 607
17bc8f94
MA
608 case DBUS_TYPE_BOOLEAN:
609 {
610 dbus_bool_t val = (NILP (object)) ? FALSE : TRUE;
611 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
612 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 613 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
614 return;
615 }
87cf1a39 616
17bc8f94
MA
617 case DBUS_TYPE_INT16:
618 {
ff88beb8
MA
619 dbus_int16_t val =
620 xd_extract_signed (object,
621 TYPE_MINIMUM (dbus_int16_t),
622 TYPE_MAXIMUM (dbus_int16_t));
3478ec45
PE
623 int pval = val;
624 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
17bc8f94 625 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 626 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
627 return;
628 }
87cf1a39 629
17bc8f94
MA
630 case DBUS_TYPE_UINT16:
631 {
ff88beb8
MA
632 dbus_uint16_t val =
633 xd_extract_unsigned (object,
634 TYPE_MAXIMUM (dbus_uint16_t));
3478ec45
PE
635 unsigned int pval = val;
636 XD_DEBUG_MESSAGE ("%c %u", dtype, pval);
17bc8f94 637 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 638 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
639 return;
640 }
87cf1a39 641
17bc8f94
MA
642 case DBUS_TYPE_INT32:
643 {
ff88beb8
MA
644 dbus_int32_t val =
645 xd_extract_signed (object,
646 TYPE_MINIMUM (dbus_int32_t),
647 TYPE_MAXIMUM (dbus_int32_t));
3478ec45
PE
648 int pval = val;
649 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
17bc8f94 650 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 651 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
652 return;
653 }
87cf1a39 654
17bc8f94 655 case DBUS_TYPE_UINT32:
da1fec2b
MA
656#ifdef DBUS_TYPE_UNIX_FD
657 case DBUS_TYPE_UNIX_FD:
658#endif
17bc8f94 659 {
ff88beb8
MA
660 dbus_uint32_t val =
661 xd_extract_unsigned (object,
662 TYPE_MAXIMUM (dbus_uint32_t));
3478ec45
PE
663 unsigned int pval = val;
664 XD_DEBUG_MESSAGE ("%c %u", dtype, pval);
17bc8f94 665 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 666 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
667 return;
668 }
87cf1a39 669
17bc8f94
MA
670 case DBUS_TYPE_INT64:
671 {
ff88beb8
MA
672 dbus_int64_t val =
673 xd_extract_signed (object,
674 TYPE_MINIMUM (dbus_int64_t),
675 TYPE_MAXIMUM (dbus_int64_t));
3478ec45
PE
676 printmax_t pval = val;
677 XD_DEBUG_MESSAGE ("%c %"pMd, dtype, pval);
17bc8f94 678 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 679 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
680 return;
681 }
87cf1a39 682
17bc8f94
MA
683 case DBUS_TYPE_UINT64:
684 {
ff88beb8
MA
685 dbus_uint64_t val =
686 xd_extract_unsigned (object,
687 TYPE_MAXIMUM (dbus_uint64_t));
3478ec45
PE
688 uprintmax_t pval = val;
689 XD_DEBUG_MESSAGE ("%c %"pMu, dtype, pval);
17bc8f94 690 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 691 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94 692 return;
54371585 693 }
87cf1a39 694
17bc8f94 695 case DBUS_TYPE_DOUBLE:
f601cdf3 696 {
dcbf5805 697 double val = extract_float (object);
f601cdf3
KR
698 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
699 if (!dbus_message_iter_append_basic (iter, dtype, &val))
700 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
701 return;
702 }
17bc8f94
MA
703
704 case DBUS_TYPE_STRING:
705 case DBUS_TYPE_OBJECT_PATH:
706 case DBUS_TYPE_SIGNATURE:
e454a4a3 707 CHECK_STRING (object);
17bc8f94 708 {
e454a4a3
SM
709 /* We need to send a valid UTF-8 string. We could encode `object'
710 but by not encoding it, we guarantee it's valid utf-8, even if
711 it contains eight-bit-bytes. Of course, you can still send
712 manually-crafted junk by passing a unibyte string. */
59d6fe83 713 char *val = SSDATA (object);
17bc8f94
MA
714 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
715 if (!dbus_message_iter_append_basic (iter, dtype, &val))
1dae9197 716 XD_SIGNAL2 (build_string ("Unable to append argument"), object);
17bc8f94
MA
717 return;
718 }
719 }
87cf1a39
MA
720
721 else /* Compound types. */
722 {
723
724 /* All compound types except array have a type symbol. For
725 array, it is optional. Skip it. */
5125905e 726 if (!XD_BASIC_DBUS_TYPE (XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))))
87cf1a39
MA
727 object = XD_NEXT_VALUE (object);
728
729 /* Open new subiteration. */
730 switch (dtype)
731 {
732 case DBUS_TYPE_ARRAY:
5125905e
MA
733 /* An array has only elements of the same type. So it is
734 sufficient to check the first element's signature
735 only. */
736
737 if (NILP (object))
738 /* If the array is empty, DBUS_TYPE_STRING is the default
739 element type. */
740 strcpy (signature, DBUS_TYPE_STRING_AS_STRING);
741
742 else
743 /* If the element type is DBUS_TYPE_SIGNATURE, and this is
744 the only element, the value of this element is used as
745 the array's element signature. */
746 if ((XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object))
747 == DBUS_TYPE_SIGNATURE)
748 && STRINGP (CAR_SAFE (XD_NEXT_VALUE (object)))
749 && NILP (CDR_SAFE (XD_NEXT_VALUE (object))))
750 {
59d6fe83 751 strcpy (signature, SSDATA (CAR_SAFE (XD_NEXT_VALUE (object))));
5125905e
MA
752 object = CDR_SAFE (XD_NEXT_VALUE (object));
753 }
754
755 else
756 xd_signature (signature,
757 XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
758 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
759
760 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
dcbf5805 761 XD_OBJECT_TO_STRING (object));
5125905e
MA
762 if (!dbus_message_iter_open_container (iter, dtype,
763 signature, &subiter))
1dae9197
MA
764 XD_SIGNAL3 (build_string ("Cannot open container"),
765 make_number (dtype), build_string (signature));
5125905e
MA
766 break;
767
87cf1a39 768 case DBUS_TYPE_VARIANT:
5125905e
MA
769 /* A variant has just one element. */
770 xd_signature (signature, XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object)),
771 dtype, CAR_SAFE (XD_NEXT_VALUE (object)));
772
87cf1a39 773 XD_DEBUG_MESSAGE ("%c %s %s", dtype, signature,
dcbf5805 774 XD_OBJECT_TO_STRING (object));
87cf1a39
MA
775 if (!dbus_message_iter_open_container (iter, dtype,
776 signature, &subiter))
1dae9197
MA
777 XD_SIGNAL3 (build_string ("Cannot open container"),
778 make_number (dtype), build_string (signature));
87cf1a39
MA
779 break;
780
781 case DBUS_TYPE_STRUCT:
782 case DBUS_TYPE_DICT_ENTRY:
9af5078b 783 /* These containers do not require a signature. */
dcbf5805 784 XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (object));
87cf1a39 785 if (!dbus_message_iter_open_container (iter, dtype, NULL, &subiter))
1dae9197
MA
786 XD_SIGNAL2 (build_string ("Cannot open container"),
787 make_number (dtype));
87cf1a39
MA
788 break;
789 }
790
791 /* Loop over list elements. */
792 while (!NILP (object))
793 {
5125905e 794 dtype = XD_OBJECT_TO_DBUS_TYPE (CAR_SAFE (object));
87cf1a39
MA
795 object = XD_NEXT_VALUE (object);
796
5125905e 797 xd_append_arg (dtype, CAR_SAFE (object), &subiter);
87cf1a39 798
5125905e 799 object = CDR_SAFE (object);
87cf1a39
MA
800 }
801
9af5078b 802 /* Close the subiteration. */
87cf1a39 803 if (!dbus_message_iter_close_container (iter, &subiter))
1dae9197
MA
804 XD_SIGNAL2 (build_string ("Cannot close container"),
805 make_number (dtype));
87cf1a39 806 }
033b73e2
MA
807}
808
809/* Retrieve C value from a DBusMessageIter structure ITER, and return
810 a converted Lisp object. The type DTYPE of the argument of the
9af5078b
MA
811 D-Bus message must be a valid DBusType. Compound D-Bus types
812 result always in a Lisp list. */
78c38319 813static Lisp_Object
243e0530 814xd_retrieve_arg (int dtype, DBusMessageIter *iter)
033b73e2
MA
815{
816
817 switch (dtype)
818 {
9af5078b 819 case DBUS_TYPE_BYTE:
9af5078b 820 {
17bc8f94 821 unsigned int val;
9af5078b 822 dbus_message_iter_get_basic (iter, &val);
17bc8f94 823 val = val & 0xFF;
3478ec45 824 XD_DEBUG_MESSAGE ("%c %u", dtype, val);
9af5078b
MA
825 return make_number (val);
826 }
827
033b73e2
MA
828 case DBUS_TYPE_BOOLEAN:
829 {
830 dbus_bool_t val;
831 dbus_message_iter_get_basic (iter, &val);
87cf1a39 832 XD_DEBUG_MESSAGE ("%c %s", dtype, (val == FALSE) ? "false" : "true");
033b73e2
MA
833 return (val == FALSE) ? Qnil : Qt;
834 }
87cf1a39 835
17bc8f94 836 case DBUS_TYPE_INT16:
1cae01f7
AS
837 {
838 dbus_int16_t val;
3478ec45 839 int pval;
1cae01f7 840 dbus_message_iter_get_basic (iter, &val);
3478ec45
PE
841 pval = val;
842 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
1cae01f7
AS
843 return make_number (val);
844 }
845
17bc8f94
MA
846 case DBUS_TYPE_UINT16:
847 {
848 dbus_uint16_t val;
3478ec45 849 int pval;
17bc8f94 850 dbus_message_iter_get_basic (iter, &val);
3478ec45
PE
851 pval = val;
852 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
17bc8f94
MA
853 return make_number (val);
854 }
855
033b73e2 856 case DBUS_TYPE_INT32:
1cae01f7
AS
857 {
858 dbus_int32_t val;
3478ec45 859 int pval;
1cae01f7 860 dbus_message_iter_get_basic (iter, &val);
3478ec45
PE
861 pval = val;
862 XD_DEBUG_MESSAGE ("%c %d", dtype, pval);
1cae01f7
AS
863 return make_fixnum_or_float (val);
864 }
865
033b73e2 866 case DBUS_TYPE_UINT32:
da1fec2b
MA
867#ifdef DBUS_TYPE_UNIX_FD
868 case DBUS_TYPE_UNIX_FD:
869#endif
033b73e2
MA
870 {
871 dbus_uint32_t val;
3478ec45 872 unsigned int pval = val;
033b73e2 873 dbus_message_iter_get_basic (iter, &val);
3478ec45
PE
874 pval = val;
875 XD_DEBUG_MESSAGE ("%c %u", dtype, pval);
1cae01f7 876 return make_fixnum_or_float (val);
9af5078b
MA
877 }
878
879 case DBUS_TYPE_INT64:
1cae01f7
AS
880 {
881 dbus_int64_t val;
3478ec45 882 printmax_t pval;
1cae01f7 883 dbus_message_iter_get_basic (iter, &val);
3478ec45
PE
884 pval = val;
885 XD_DEBUG_MESSAGE ("%c %"pMd, dtype, pval);
1cae01f7
AS
886 return make_fixnum_or_float (val);
887 }
888
9af5078b
MA
889 case DBUS_TYPE_UINT64:
890 {
891 dbus_uint64_t val;
3478ec45 892 uprintmax_t pval;
9af5078b 893 dbus_message_iter_get_basic (iter, &val);
3478ec45
PE
894 pval = val;
895 XD_DEBUG_MESSAGE ("%c %"pMd, dtype, pval);
9af5078b
MA
896 return make_fixnum_or_float (val);
897 }
898
899 case DBUS_TYPE_DOUBLE:
900 {
901 double val;
902 dbus_message_iter_get_basic (iter, &val);
903 XD_DEBUG_MESSAGE ("%c %f", dtype, val);
904 return make_float (val);
033b73e2 905 }
87cf1a39 906
033b73e2
MA
907 case DBUS_TYPE_STRING:
908 case DBUS_TYPE_OBJECT_PATH:
9af5078b 909 case DBUS_TYPE_SIGNATURE:
033b73e2
MA
910 {
911 char *val;
912 dbus_message_iter_get_basic (iter, &val);
87cf1a39 913 XD_DEBUG_MESSAGE ("%c %s", dtype, val);
033b73e2
MA
914 return build_string (val);
915 }
87cf1a39 916
033b73e2
MA
917 case DBUS_TYPE_ARRAY:
918 case DBUS_TYPE_VARIANT:
919 case DBUS_TYPE_STRUCT:
920 case DBUS_TYPE_DICT_ENTRY:
921 {
922 Lisp_Object result;
923 struct gcpro gcpro1;
033b73e2
MA
924 DBusMessageIter subiter;
925 int subtype;
fa8e045a
MA
926 result = Qnil;
927 GCPRO1 (result);
033b73e2
MA
928 dbus_message_iter_recurse (iter, &subiter);
929 while ((subtype = dbus_message_iter_get_arg_type (&subiter))
930 != DBUS_TYPE_INVALID)
931 {
932 result = Fcons (xd_retrieve_arg (subtype, &subiter), result);
933 dbus_message_iter_next (&subiter);
934 }
dcbf5805 935 XD_DEBUG_MESSAGE ("%c %s", dtype, XD_OBJECT_TO_STRING (result));
033b73e2
MA
936 RETURN_UNGCPRO (Fnreverse (result));
937 }
87cf1a39 938
033b73e2 939 default:
87cf1a39 940 XD_DEBUG_MESSAGE ("DBusType '%c' not supported", dtype);
033b73e2
MA
941 return Qnil;
942 }
943}
944
dcbf5805 945/* Return the number of references of the shared CONNECTION. */
243e0530 946static ptrdiff_t
dcbf5805
MA
947xd_get_connection_references (DBusConnection *connection)
948{
949 ptrdiff_t *refcount;
de85e130 950
dcbf5805
MA
951 /* We cannot access the DBusConnection structure, it is not public.
952 But we know, that the reference counter is the first field in
953 that structure. */
954 refcount = (void *) &connection;
955 refcount = (void *) *refcount;
956 return *refcount;
957}
958
959/* Return D-Bus connection address. BUS is either a Lisp symbol,
960 :system or :session, or a string denoting the bus address. */
78c38319 961static DBusConnection *
dcbf5805 962xd_get_connection_address (Lisp_Object bus)
033b73e2
MA
963{
964 DBusConnection *connection;
dcbf5805 965 Lisp_Object val;
033b73e2 966
5cb67954 967 val = CDR_SAFE (Fassoc (bus, xd_registered_buses));
dcbf5805
MA
968 if (NILP (val))
969 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
033b73e2 970 else
3478ec45 971 connection = (DBusConnection *) (intptr_t) XFASTINT (val);
033b73e2 972
dcbf5805 973 if (!dbus_connection_get_is_connected (connection))
3f56d3c6 974 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
033b73e2 975
033b73e2
MA
976 return connection;
977}
978
3fad2ad2 979/* Return the file descriptor for WATCH, -1 if not found. */
3fad2ad2
J
980static int
981xd_find_watch_fd (DBusWatch *watch)
058ed861 982{
eb4c6ace 983#if HAVE_DBUS_WATCH_GET_UNIX_FD
3fad2ad2
J
984 /* TODO: Reverse these on Win32, which prefers the opposite. */
985 int fd = dbus_watch_get_unix_fd (watch);
986 if (fd == -1)
987 fd = dbus_watch_get_socket (watch);
3f56d3c6 988#else
3fad2ad2 989 int fd = dbus_watch_get_fd (watch);
3f56d3c6 990#endif
3fad2ad2
J
991 return fd;
992}
3f56d3c6 993
08609ffd
MA
994/* Prototype. */
995static void
996xd_read_queued_messages (int fd, void *data, int for_read);
058ed861 997
3fad2ad2 998/* Start monitoring WATCH for possible I/O. */
3fad2ad2
J
999static dbus_bool_t
1000xd_add_watch (DBusWatch *watch, void *data)
1001{
1002 unsigned int flags = dbus_watch_get_flags (watch);
1003 int fd = xd_find_watch_fd (watch);
1004
1005 XD_DEBUG_MESSAGE ("fd %d, write %d, enabled %d",
dcbf5805
MA
1006 fd, flags & DBUS_WATCH_WRITABLE,
1007 dbus_watch_get_enabled (watch));
3fad2ad2
J
1008
1009 if (fd == -1)
1010 return FALSE;
1011
1012 if (dbus_watch_get_enabled (watch))
1013 {
1014 if (flags & DBUS_WATCH_WRITABLE)
08609ffd 1015 add_write_fd (fd, xd_read_queued_messages, data);
3fad2ad2 1016 if (flags & DBUS_WATCH_READABLE)
08609ffd 1017 add_read_fd (fd, xd_read_queued_messages, data);
3fad2ad2 1018 }
058ed861
MA
1019 return TRUE;
1020}
1021
3fad2ad2
J
1022/* Stop monitoring WATCH for possible I/O.
1023 DATA is the used bus, either a string or QCdbus_system_bus or
0c372655 1024 QCdbus_session_bus. */
3fad2ad2 1025static void
971de7fb 1026xd_remove_watch (DBusWatch *watch, void *data)
058ed861 1027{
3fad2ad2
J
1028 unsigned int flags = dbus_watch_get_flags (watch);
1029 int fd = xd_find_watch_fd (watch);
3f56d3c6 1030
3fad2ad2
J
1031 XD_DEBUG_MESSAGE ("fd %d", fd);
1032
08609ffd
MA
1033 if (fd == -1)
1034 return;
777013f2 1035
3fad2ad2 1036 /* Unset session environment. */
b4289b64 1037 if (XSYMBOL (QCdbus_session_bus) == data)
3fad2ad2 1038 {
dcbf5805
MA
1039 // XD_DEBUG_MESSAGE ("unsetenv DBUS_SESSION_BUS_ADDRESS");
1040 // unsetenv ("DBUS_SESSION_BUS_ADDRESS");
058ed861
MA
1041 }
1042
3fad2ad2
J
1043 if (flags & DBUS_WATCH_WRITABLE)
1044 delete_write_fd (fd);
1045 if (flags & DBUS_WATCH_READABLE)
1046 delete_read_fd (fd);
1047}
1048
1049/* Toggle monitoring WATCH for possible I/O. */
3fad2ad2
J
1050static void
1051xd_toggle_watch (DBusWatch *watch, void *data)
1052{
1053 if (dbus_watch_get_enabled (watch))
1054 xd_add_watch (watch, data);
1055 else
1056 xd_remove_watch (watch, data);
058ed861
MA
1057}
1058
dcbf5805
MA
1059/* Close connection to D-Bus BUS. */
1060static void
1061xd_close_bus (Lisp_Object bus)
1062{
1063 DBusConnection *connection;
1064 Lisp_Object val;
1065
1066 /* Check whether we are connected. */
5cb67954 1067 val = Fassoc (bus, xd_registered_buses);
dcbf5805
MA
1068 if (NILP (val))
1069 return;
1070
1071 /* Retrieve bus address. */
1072 connection = xd_get_connection_address (bus);
1073
1074 /* Close connection, if there isn't another shared application. */
1075 if (xd_get_connection_references (connection) == 1)
1076 {
1077 XD_DEBUG_MESSAGE ("Close connection to bus %s",
1078 XD_OBJECT_TO_STRING (bus));
1079 dbus_connection_close (connection);
1080 }
1081
1082 /* Decrement reference count. */
1083 dbus_connection_unref (connection);
1084
1085 /* Remove bus from list of registered buses. */
5cb67954 1086 xd_registered_buses = Fdelete (val, xd_registered_buses);
dcbf5805
MA
1087
1088 /* Return. */
1089 return;
1090}
1091
1092DEFUN ("dbus-init-bus", Fdbus_init_bus, Sdbus_init_bus, 1, 2, 0,
1093 doc: /* Establish the connection to D-Bus BUS.
1094
1095BUS can be either the symbol `:system' or the symbol `:session', or it
1096can be a string denoting the address of the corresponding bus. For
1097the system and session buses, this function is called when loading
1098`dbus.el', there is no need to call it again.
1099
1100The function returns a number, which counts the connections this Emacs
1101session has established to the BUS under the same unique name (see
1102`dbus-get-unique-name'). It depends on the libraries Emacs is linked
1103with, and on the environment Emacs is running. For example, if Emacs
1104is linked with the gtk toolkit, and it runs in a GTK-aware environment
1105like Gnome, another connection might already be established.
1106
1107When PRIVATE is non-nil, a new connection is established instead of
1108reusing an existing one. It results in a new unique name at the bus.
1109This can be used, if it is necessary to distinguish from another
1110connection used in the same Emacs process, like the one established by
1111GTK+. It should be used with care for at least the `:system' and
1112`:session' buses, because other Emacs Lisp packages might already use
1113this connection to those buses. */)
1114 (Lisp_Object bus, Lisp_Object private)
058ed861
MA
1115{
1116 DBusConnection *connection;
dcbf5805
MA
1117 DBusError derror;
1118 Lisp_Object val;
243e0530 1119 ptrdiff_t refcount;
058ed861 1120
b4289b64 1121 /* Check parameter. */
dcbf5805
MA
1122 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1123
1124 /* Close bus if it is already open. */
1125 xd_close_bus (bus);
1126
1127 /* Initialize. */
1128 dbus_error_init (&derror);
1129
1130 /* Open the connection. */
1131 if (STRINGP (bus))
1132 if (NILP (private))
1133 connection = dbus_connection_open (SSDATA (bus), &derror);
1134 else
1135 connection = dbus_connection_open_private (SSDATA (bus), &derror);
1136
1137 else
1138 if (NILP (private))
1139 connection = dbus_bus_get (EQ (bus, QCdbus_system_bus)
1140 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
1141 &derror);
1142 else
1143 connection = dbus_bus_get_private (EQ (bus, QCdbus_system_bus)
1144 ? DBUS_BUS_SYSTEM : DBUS_BUS_SESSION,
1145 &derror);
1146
1147 if (dbus_error_is_set (&derror))
1148 XD_ERROR (derror);
1149
1150 if (connection == NULL)
1151 XD_SIGNAL2 (build_string ("No connection to bus"), bus);
1152
1153 /* If it is not the system or session bus, we must register
1154 ourselves. Otherwise, we have called dbus_bus_get, which has
1155 configured us to exit if the connection closes - we undo this
1156 setting. */
1157 if (STRINGP (bus))
1158 dbus_bus_register (connection, &derror);
b4289b64 1159 else
dcbf5805 1160 dbus_connection_set_exit_on_disconnect (connection, FALSE);
371cac43 1161
dcbf5805
MA
1162 if (dbus_error_is_set (&derror))
1163 XD_ERROR (derror);
058ed861 1164
777013f2 1165 /* Add the watch functions. We pass also the bus as data, in order
301b181a 1166 to distinguish between the buses in xd_remove_watch. */
058ed861
MA
1167 if (!dbus_connection_set_watch_functions (connection,
1168 xd_add_watch,
1169 xd_remove_watch,
3fad2ad2 1170 xd_toggle_watch,
dcbf5805
MA
1171 SYMBOLP (bus)
1172 ? (void *) XSYMBOL (bus)
1173 : (void *) XSTRING (bus),
1174 NULL))
058ed861
MA
1175 XD_SIGNAL1 (build_string ("Cannot add watch functions"));
1176
0c372655 1177 /* Add bus to list of registered buses. */
3478ec45 1178 XSETFASTINT (val, (intptr_t) connection);
5cb67954 1179 xd_registered_buses = Fcons (Fcons (bus, val), xd_registered_buses);
0c372655 1180
a79b0f28 1181 /* We do not want to abort. */
78320123 1182 putenv ((char *) "DBUS_FATAL_WARNINGS=0");
a79b0f28 1183
dcbf5805
MA
1184 /* Cleanup. */
1185 dbus_error_free (&derror);
0c372655 1186
dcbf5805
MA
1187 /* Return reference counter. */
1188 refcount = xd_get_connection_references (connection);
243e0530 1189 XD_DEBUG_MESSAGE ("Bus %s, Reference counter %"pD"d",
dcbf5805
MA
1190 XD_OBJECT_TO_STRING (bus), refcount);
1191 return make_number (refcount);
058ed861
MA
1192}
1193
033b73e2
MA
1194DEFUN ("dbus-get-unique-name", Fdbus_get_unique_name, Sdbus_get_unique_name,
1195 1, 1, 0,
5125905e 1196 doc: /* Return the unique name of Emacs registered at D-Bus BUS. */)
5842a27b 1197 (Lisp_Object bus)
033b73e2
MA
1198{
1199 DBusConnection *connection;
48f7d213 1200 const char *name;
033b73e2 1201
dcbf5805
MA
1202 /* Check parameter. */
1203 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1204
1205 /* Retrieve bus address. */
1206 connection = xd_get_connection_address (bus);
033b73e2
MA
1207
1208 /* Request the name. */
48f7d213 1209 name = dbus_bus_get_unique_name (connection);
033b73e2 1210 if (name == NULL)
1dae9197 1211 XD_SIGNAL1 (build_string ("No unique name available"));
033b73e2
MA
1212
1213 /* Return. */
1214 return build_string (name);
1215}
1216
dcbf5805
MA
1217DEFUN ("dbus-message-internal", Fdbus_message_internal, Sdbus_message_internal,
1218 4, MANY, 0,
1219 doc: /* Send a D-Bus message.
1220This is an internal function, it shall not be used outside dbus.el.
1221
1222The following usages are expected:
1223
1224`dbus-call-method', `dbus-call-method-asynchronously':
1225 \(dbus-message-internal
1226 dbus-message-type-method-call BUS SERVICE PATH INTERFACE METHOD HANDLER
1227 &optional :timeout TIMEOUT &rest ARGS)
1228
1229`dbus-send-signal':
1230 \(dbus-message-internal
1231 dbus-message-type-signal BUS SERVICE PATH INTERFACE SIGNAL &rest ARGS)
1232
1233`dbus-method-return-internal':
1234 \(dbus-message-internal
1235 dbus-message-type-method-return BUS SERVICE SERIAL &rest ARGS)
1236
1237`dbus-method-error-internal':
1238 \(dbus-message-internal
1239 dbus-message-type-error BUS SERVICE SERIAL &rest ARGS)
1240
1241usage: (dbus-message-internal &rest REST) */)
f66c7cf8 1242 (ptrdiff_t nargs, Lisp_Object *args)
033b73e2 1243{
dcbf5805
MA
1244 Lisp_Object message_type, bus, service, handler;
1245 Lisp_Object path = Qnil;
1246 Lisp_Object interface = Qnil;
1247 Lisp_Object member = Qnil;
033b73e2 1248 Lisp_Object result;
dcbf5805 1249 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, gcpro6;
033b73e2
MA
1250 DBusConnection *connection;
1251 DBusMessage *dmessage;
033b73e2 1252 DBusMessageIter iter;
243e0530
PE
1253 int dtype;
1254 int mtype;
dcbf5805 1255 dbus_uint32_t serial = 0;
3478ec45 1256 unsigned int ui_serial;
90b3fc84 1257 int timeout = -1;
dcbf5805 1258 ptrdiff_t count;
87cf1a39 1259 char signature[DBUS_MAXIMUM_SIGNATURE_LENGTH];
033b73e2 1260
dcbf5805
MA
1261 /* Initialize parameters. */
1262 message_type = args[0];
1263 bus = args[1];
1264 service = args[2];
1265 handler = Qnil;
1266
1267 CHECK_NATNUM (message_type);
243e0530
PE
1268 if (! (DBUS_MESSAGE_TYPE_INVALID < XFASTINT (message_type)
1269 && XFASTINT (message_type) < DBUS_NUM_MESSAGE_TYPES))
dcbf5805 1270 XD_SIGNAL2 (build_string ("Invalid message type"), message_type);
243e0530 1271 mtype = XFASTINT (message_type);
dcbf5805
MA
1272
1273 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1274 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1275 {
1276 path = args[3];
1277 interface = args[4];
1278 member = args[5];
1279 if (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1280 handler = args[6];
1281 count = (mtype == DBUS_MESSAGE_TYPE_METHOD_CALL) ? 7 : 6;
1282 }
1283 else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1284 {
ff88beb8 1285 serial = xd_extract_unsigned (args[3], TYPE_MAXIMUM (dbus_uint32_t));
dcbf5805
MA
1286 count = 4;
1287 }
1288
033b73e2 1289 /* Check parameters. */
dcbf5805
MA
1290 XD_DBUS_VALIDATE_BUS_ADDRESS (bus);
1291 XD_DBUS_VALIDATE_BUS_NAME (service);
1292 if (nargs < count)
1293 xsignal2 (Qwrong_number_of_arguments,
1294 Qdbus_message_internal,
1295 make_number (nargs));
1296
1297 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1298 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
1299 {
1300 XD_DBUS_VALIDATE_PATH (path);
1301 XD_DBUS_VALIDATE_INTERFACE (interface);
1302 XD_DBUS_VALIDATE_MEMBER (member);
1303 if (!NILP (handler) && (!FUNCTIONP (handler)))
1304 wrong_type_argument (Qinvalid_function, handler);
1305 }
90b3fc84 1306
dcbf5805
MA
1307 /* Protect Lisp variables. */
1308 GCPRO6 (bus, service, path, interface, member, handler);
1309
1310 /* Trace parameters. */
1311 switch (mtype)
033b73e2 1312 {
dcbf5805
MA
1313 case DBUS_MESSAGE_TYPE_METHOD_CALL:
1314 XD_DEBUG_MESSAGE ("%s %s %s %s %s %s %s",
1315 XD_MESSAGE_TYPE_TO_STRING (mtype),
1316 XD_OBJECT_TO_STRING (bus),
1317 XD_OBJECT_TO_STRING (service),
1318 XD_OBJECT_TO_STRING (path),
1319 XD_OBJECT_TO_STRING (interface),
1320 XD_OBJECT_TO_STRING (member),
1321 XD_OBJECT_TO_STRING (handler));
1322 break;
1323 case DBUS_MESSAGE_TYPE_SIGNAL:
1324 XD_DEBUG_MESSAGE ("%s %s %s %s %s %s",
1325 XD_MESSAGE_TYPE_TO_STRING (mtype),
1326 XD_OBJECT_TO_STRING (bus),
1327 XD_OBJECT_TO_STRING (service),
1328 XD_OBJECT_TO_STRING (path),
1329 XD_OBJECT_TO_STRING (interface),
1330 XD_OBJECT_TO_STRING (member));
1331 break;
1332 default: /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
3478ec45 1333 ui_serial = serial;
dcbf5805
MA
1334 XD_DEBUG_MESSAGE ("%s %s %s %u",
1335 XD_MESSAGE_TYPE_TO_STRING (mtype),
1336 XD_OBJECT_TO_STRING (bus),
1337 XD_OBJECT_TO_STRING (service),
3478ec45 1338 ui_serial);
033b73e2
MA
1339 }
1340
dcbf5805
MA
1341 /* Retrieve bus address. */
1342 connection = xd_get_connection_address (bus);
54371585 1343
dcbf5805
MA
1344 /* Create the D-Bus message. */
1345 dmessage = dbus_message_new (mtype);
033b73e2 1346 if (dmessage == NULL)
dcbf5805
MA
1347 {
1348 UNGCPRO;
1349 XD_SIGNAL1 (build_string ("Unable to create a new message"));
1350 }
1351
1352 if (STRINGP (service))
033b73e2 1353 {
dcbf5805
MA
1354 if (mtype != DBUS_MESSAGE_TYPE_SIGNAL)
1355 /* Set destination. */
8c7a4ac5 1356 {
dcbf5805
MA
1357 if (!dbus_message_set_destination (dmessage, SSDATA (service)))
1358 {
1359 UNGCPRO;
1360 XD_SIGNAL2 (build_string ("Unable to set the destination"),
1361 service);
1362 }
8c7a4ac5 1363 }
dcbf5805 1364
8c7a4ac5 1365 else
dcbf5805 1366 /* Set destination for unicast signals. */
8c7a4ac5 1367 {
dcbf5805 1368 Lisp_Object uname;
033b73e2 1369
dcbf5805
MA
1370 /* If it is the same unique name as we are registered at the
1371 bus or an unknown name, we regard it as broadcast message
1372 due to backward compatibility. */
1373 if (dbus_bus_name_has_owner (connection, SSDATA (service), NULL))
1374 uname = call2 (intern ("dbus-get-name-owner"), bus, service);
1375 else
1376 uname = Qnil;
87cf1a39 1377
dcbf5805
MA
1378 if (STRINGP (uname)
1379 && (strcmp (dbus_bus_get_unique_name (connection), SSDATA (uname))
1380 != 0)
1381 && (!dbus_message_set_destination (dmessage, SSDATA (service))))
1382 {
1383 UNGCPRO;
1384 XD_SIGNAL2 (build_string ("Unable to set signal destination"),
1385 service);
1386 }
1387 }
033b73e2
MA
1388 }
1389
dcbf5805
MA
1390 /* Set message parameters. */
1391 if ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1392 || (mtype == DBUS_MESSAGE_TYPE_SIGNAL))
033b73e2 1393 {
dcbf5805
MA
1394 if ((!dbus_message_set_path (dmessage, SSDATA (path)))
1395 || (!dbus_message_set_interface (dmessage, SSDATA (interface)))
1396 || (!dbus_message_set_member (dmessage, SSDATA (member))))
2c3a8b27 1397 {
dcbf5805
MA
1398 UNGCPRO;
1399 XD_SIGNAL1 (build_string ("Unable to set the message parameter"));
2c3a8b27 1400 }
033b73e2 1401 }
13ecc6dc 1402
dcbf5805
MA
1403 else /* DBUS_MESSAGE_TYPE_METHOD_RETURN, DBUS_MESSAGE_TYPE_ERROR */
1404 {
1405 if (!dbus_message_set_reply_serial (dmessage, serial))
1406 {
1407 UNGCPRO;
1408 XD_SIGNAL1 (build_string ("Unable to create a return message"));
1409 }
13ecc6dc 1410
dcbf5805
MA
1411 if ((mtype == DBUS_MESSAGE_TYPE_ERROR)
1412 && (!dbus_message_set_error_name (dmessage, DBUS_ERROR_FAILED)))
1413 {
1414 UNGCPRO;
1415 XD_SIGNAL1 (build_string ("Unable to create a error message"));
1416 }
1417 }
90b3fc84
MA
1418
1419 /* Check for timeout parameter. */
dcbf5805 1420 if ((count+2 <= nargs) && (EQ ((args[count]), QCdbus_timeout)))
033b73e2 1421 {
dcbf5805 1422 CHECK_NATNUM (args[count+1]);
42b2a986 1423 timeout = min (XFASTINT (args[count+1]), INT_MAX);
dcbf5805 1424 count = count+2;
033b73e2
MA
1425 }
1426
54371585
MA
1427 /* Initialize parameter list of message. */
1428 dbus_message_iter_init_append (dmessage, &iter);
1429
033b73e2 1430 /* Append parameters to the message. */
dcbf5805 1431 for (; count < nargs; ++count)
033b73e2 1432 {
dcbf5805
MA
1433 dtype = XD_OBJECT_TO_DBUS_TYPE (args[count]);
1434 if (XD_DBUS_TYPE_P (args[count]))
8c7a4ac5 1435 {
dcbf5805
MA
1436 XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
1437 XD_DEBUG_VALID_LISP_OBJECT_P (args[count+1]);
1438 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s %s", count - 4,
1439 XD_OBJECT_TO_STRING (args[count]),
1440 XD_OBJECT_TO_STRING (args[count+1]));
1441 ++count;
8c7a4ac5
MA
1442 }
1443 else
1444 {
dcbf5805
MA
1445 XD_DEBUG_VALID_LISP_OBJECT_P (args[count]);
1446 XD_DEBUG_MESSAGE ("Parameter%"pD"d %s", count - 4,
1447 XD_OBJECT_TO_STRING (args[count]));
8c7a4ac5 1448 }
033b73e2 1449
abe136ee 1450 /* Check for valid signature. We use DBUS_TYPE_INVALID as
87cf1a39 1451 indication that there is no parent type. */
dcbf5805 1452 xd_signature (signature, dtype, DBUS_TYPE_INVALID, args[count]);
87cf1a39 1453
dcbf5805 1454 xd_append_arg (dtype, args[count], &iter);
033b73e2
MA
1455 }
1456
ca4f31ea
MA
1457 if (!NILP (handler))
1458 {
1459 /* Send the message. The message is just added to the outgoing
1460 message queue. */
1461 if (!dbus_connection_send_with_reply (connection, dmessage,
1462 NULL, timeout))
dcbf5805
MA
1463 {
1464 UNGCPRO;
1465 XD_SIGNAL1 (build_string ("Cannot send message"));
1466 }
033b73e2 1467
f04bb9b2 1468 /* The result is the key in Vdbus_registered_objects_table. */
08686060 1469 serial = dbus_message_get_serial (dmessage);
dcbf5805
MA
1470 result = list3 (QCdbus_registered_serial,
1471 bus, make_fixnum_or_float (serial));
13ecc6dc 1472
ca4f31ea 1473 /* Create a hash table entry. */
f04bb9b2 1474 Fputhash (result, handler, Vdbus_registered_objects_table);
ca4f31ea
MA
1475 }
1476 else
1477 {
1478 /* Send the message. The message is just added to the outgoing
1479 message queue. */
1480 if (!dbus_connection_send (connection, dmessage, NULL))
dcbf5805
MA
1481 {
1482 UNGCPRO;
1483 XD_SIGNAL1 (build_string ("Cannot send message"));
1484 }
13ecc6dc 1485
ca4f31ea
MA
1486 result = Qnil;
1487 }
1488
dcbf5805 1489 XD_DEBUG_MESSAGE ("Message sent: %s", XD_OBJECT_TO_STRING (result));
13ecc6dc
MA
1490
1491 /* Cleanup. */
1492 dbus_message_unref (dmessage);
1493
1494 /* Return the result. */
1495 RETURN_UNGCPRO (result);
1496}
1497
3fad2ad2
J
1498/* Read one queued incoming message of the D-Bus BUS.
1499 BUS is either a Lisp symbol, :system or :session, or a string denoting
1500 the bus address. */
3fad2ad2
J
1501static void
1502xd_read_message_1 (DBusConnection *connection, Lisp_Object bus)
033b73e2 1503{
a31d47c7 1504 Lisp_Object args, key, value;
033b73e2 1505 struct gcpro gcpro1;
15f16c1b 1506 struct input_event event;
033b73e2
MA
1507 DBusMessage *dmessage;
1508 DBusMessageIter iter;
243e0530
PE
1509 int dtype;
1510 int mtype;
30217ff0 1511 dbus_uint32_t serial;
08686060 1512 unsigned int ui_serial;
a8e72f4f 1513 const char *uname, *path, *interface, *member;
39abdd4a 1514
033b73e2
MA
1515 dmessage = dbus_connection_pop_message (connection);
1516
1517 /* Return if there is no queued message. */
1518 if (dmessage == NULL)
3fad2ad2 1519 return;
033b73e2
MA
1520
1521 /* Collect the parameters. */
a31d47c7
MA
1522 args = Qnil;
1523 GCPRO1 (args);
033b73e2 1524
033b73e2 1525 /* Loop over the resulting parameters. Construct a list. */
17bc8f94 1526 if (dbus_message_iter_init (dmessage, &iter))
033b73e2 1527 {
17bc8f94
MA
1528 while ((dtype = dbus_message_iter_get_arg_type (&iter))
1529 != DBUS_TYPE_INVALID)
1530 {
1531 args = Fcons (xd_retrieve_arg (dtype, &iter), args);
1532 dbus_message_iter_next (&iter);
1533 }
1534 /* The arguments are stored in reverse order. Reorder them. */
1535 args = Fnreverse (args);
033b73e2
MA
1536 }
1537
13ecc6dc
MA
1538 /* Read message type, message serial, unique name, object path,
1539 interface and member from the message. */
367ea173 1540 mtype = dbus_message_get_type (dmessage);
08686060 1541 ui_serial = serial =
367ea173
MA
1542 ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1543 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
1544 ? dbus_message_get_reply_serial (dmessage)
1545 : dbus_message_get_serial (dmessage);
1546 uname = dbus_message_get_sender (dmessage);
1547 path = dbus_message_get_path (dmessage);
a8e72f4f 1548 interface = dbus_message_get_interface (dmessage);
367ea173 1549 member = dbus_message_get_member (dmessage);
a8e72f4f 1550
30217ff0 1551 XD_DEBUG_MESSAGE ("Event received: %s %u %s %s %s %s %s",
dcbf5805 1552 XD_MESSAGE_TYPE_TO_STRING (mtype),
08686060 1553 ui_serial, uname, path, interface, member,
dcbf5805 1554 XD_OBJECT_TO_STRING (args));
17bc8f94 1555
dcbf5805
MA
1556 if (mtype == DBUS_MESSAGE_TYPE_INVALID)
1557 goto cleanup;
1558
1559 else if ((mtype == DBUS_MESSAGE_TYPE_METHOD_RETURN)
1560 || (mtype == DBUS_MESSAGE_TYPE_ERROR))
13ecc6dc
MA
1561 {
1562 /* Search for a registered function of the message. */
dcbf5805
MA
1563 key = list3 (QCdbus_registered_serial, bus,
1564 make_fixnum_or_float (serial));
f04bb9b2 1565 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
13ecc6dc
MA
1566
1567 /* There shall be exactly one entry. Construct an event. */
1568 if (NILP (value))
1569 goto cleanup;
1570
1571 /* Remove the entry. */
f04bb9b2 1572 Fremhash (key, Vdbus_registered_objects_table);
13ecc6dc
MA
1573
1574 /* Construct an event. */
1575 EVENT_INIT (event);
1576 event.kind = DBUS_EVENT;
1577 event.frame_or_window = Qnil;
1578 event.arg = Fcons (value, args);
1579 }
a31d47c7 1580
dcbf5805 1581 else /* DBUS_MESSAGE_TYPE_METHOD_CALL, DBUS_MESSAGE_TYPE_SIGNAL. */
a31d47c7 1582 {
f04bb9b2
MA
1583 /* Vdbus_registered_objects_table requires non-nil interface and
1584 member. */
13ecc6dc
MA
1585 if ((interface == NULL) || (member == NULL))
1586 goto cleanup;
1587
1588 /* Search for a registered function of the message. */
dcbf5805
MA
1589 key = list4 ((mtype == DBUS_MESSAGE_TYPE_METHOD_CALL)
1590 ? QCdbus_registered_method
1591 : QCdbus_registered_signal,
1592 bus, build_string (interface), build_string (member));
f04bb9b2 1593 value = Fgethash (key, Vdbus_registered_objects_table, Qnil);
13ecc6dc
MA
1594
1595 /* Loop over the registered functions. Construct an event. */
1596 while (!NILP (value))
a31d47c7 1597 {
13ecc6dc
MA
1598 key = CAR_SAFE (value);
1599 /* key has the structure (UNAME SERVICE PATH HANDLER). */
1600 if (((uname == NULL)
1601 || (NILP (CAR_SAFE (key)))
59d6fe83 1602 || (strcmp (uname, SSDATA (CAR_SAFE (key))) == 0))
13ecc6dc
MA
1603 && ((path == NULL)
1604 || (NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
1605 || (strcmp (path,
59d6fe83 1606 SSDATA (CAR_SAFE (CDR_SAFE (CDR_SAFE (key)))))
13ecc6dc
MA
1607 == 0))
1608 && (!NILP (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))))))
1609 {
1610 EVENT_INIT (event);
1611 event.kind = DBUS_EVENT;
1612 event.frame_or_window = Qnil;
b4289b64
MA
1613 event.arg
1614 = Fcons (CAR_SAFE (CDR_SAFE (CDR_SAFE (CDR_SAFE (key)))), args);
13ecc6dc
MA
1615 break;
1616 }
1617 value = CDR_SAFE (value);
a31d47c7 1618 }
13ecc6dc
MA
1619
1620 if (NILP (value))
1621 goto cleanup;
a31d47c7 1622 }
033b73e2 1623
13ecc6dc
MA
1624 /* Add type, serial, uname, path, interface and member to the event. */
1625 event.arg = Fcons ((member == NULL ? Qnil : build_string (member)),
1626 event.arg);
1627 event.arg = Fcons ((interface == NULL ? Qnil : build_string (interface)),
1628 event.arg);
1629 event.arg = Fcons ((path == NULL ? Qnil : build_string (path)),
1630 event.arg);
1631 event.arg = Fcons ((uname == NULL ? Qnil : build_string (uname)),
1632 event.arg);
08686060 1633 event.arg = Fcons (make_fixnum_or_float (serial), event.arg);
13ecc6dc
MA
1634 event.arg = Fcons (make_number (mtype), event.arg);
1635
1636 /* Add the bus symbol to the event. */
1637 event.arg = Fcons (bus, event.arg);
1638
1639 /* Store it into the input event queue. */
1640 kbd_buffer_store_event (&event);
1641
dcbf5805 1642 XD_DEBUG_MESSAGE ("Event stored: %s", XD_OBJECT_TO_STRING (event.arg));
13ecc6dc 1643
c1d5ce94 1644 /* Cleanup. */
a8e72f4f 1645 cleanup:
033b73e2 1646 dbus_message_unref (dmessage);
c1d5ce94 1647
3fad2ad2
J
1648 UNGCPRO;
1649}
1650
1651/* Read queued incoming messages of the D-Bus BUS.
1652 BUS is either a Lisp symbol, :system or :session, or a string denoting
1653 the bus address. */
3fad2ad2
J
1654static Lisp_Object
1655xd_read_message (Lisp_Object bus)
1656{
dcbf5805
MA
1657 /* Retrieve bus address. */
1658 DBusConnection *connection = xd_get_connection_address (bus);
3fad2ad2
J
1659
1660 /* Non blocking read of the next available message. */
1661 dbus_connection_read_write (connection, 0);
1662
1663 while (dbus_connection_get_dispatch_status (connection)
1664 != DBUS_DISPATCH_COMPLETE)
1665 xd_read_message_1 (connection, bus);
1666 return Qnil;
033b73e2
MA
1667}
1668
08609ffd
MA
1669/* Callback called when something is ready to read or write. */
1670static void
1671xd_read_queued_messages (int fd, void *data, int for_read)
033b73e2 1672{
5cb67954 1673 Lisp_Object busp = xd_registered_buses;
08609ffd 1674 Lisp_Object bus = Qnil;
dcbf5805 1675 Lisp_Object key;
96faeb40 1676
08609ffd
MA
1677 /* Find bus related to fd. */
1678 if (data != NULL)
1679 while (!NILP (busp))
1680 {
dcbf5805
MA
1681 key = CAR_SAFE (CAR_SAFE (busp));
1682 if ((SYMBOLP (key) && XSYMBOL (key) == data)
1683 || (STRINGP (key) && XSTRING (key) == data))
1684 bus = key;
08609ffd
MA
1685 busp = CDR_SAFE (busp);
1686 }
1687
5e617bc2 1688 if (NILP (bus))
08609ffd
MA
1689 return;
1690
1691 /* We ignore all Lisp errors during the call. */
0c372655 1692 xd_in_read_queued_messages = 1;
08609ffd 1693 internal_catch (Qdbus_error, xd_read_message, bus);
0c372655 1694 xd_in_read_queued_messages = 0;
033b73e2
MA
1695}
1696
033b73e2
MA
1697\f
1698void
971de7fb 1699syms_of_dbusbind (void)
033b73e2
MA
1700{
1701
cd3520a4 1702 DEFSYM (Qdbus_init_bus, "dbus-init-bus");
058ed861
MA
1703 defsubr (&Sdbus_init_bus);
1704
cd3520a4 1705 DEFSYM (Qdbus_get_unique_name, "dbus-get-unique-name");
033b73e2
MA
1706 defsubr (&Sdbus_get_unique_name);
1707
dcbf5805
MA
1708 DEFSYM (Qdbus_message_internal, "dbus-message-internal");
1709 defsubr (&Sdbus_message_internal);
17bc8f94 1710
cd3520a4 1711 DEFSYM (Qdbus_error, "dbus-error");
033b73e2
MA
1712 Fput (Qdbus_error, Qerror_conditions,
1713 list2 (Qdbus_error, Qerror));
1714 Fput (Qdbus_error, Qerror_message,
d67b4f80 1715 make_pure_c_string ("D-Bus error"));
033b73e2 1716
cd3520a4
JB
1717 DEFSYM (QCdbus_system_bus, ":system");
1718 DEFSYM (QCdbus_session_bus, ":session");
cd3520a4
JB
1719 DEFSYM (QCdbus_timeout, ":timeout");
1720 DEFSYM (QCdbus_type_byte, ":byte");
1721 DEFSYM (QCdbus_type_boolean, ":boolean");
1722 DEFSYM (QCdbus_type_int16, ":int16");
1723 DEFSYM (QCdbus_type_uint16, ":uint16");
1724 DEFSYM (QCdbus_type_int32, ":int32");
1725 DEFSYM (QCdbus_type_uint32, ":uint32");
1726 DEFSYM (QCdbus_type_int64, ":int64");
1727 DEFSYM (QCdbus_type_uint64, ":uint64");
1728 DEFSYM (QCdbus_type_double, ":double");
1729 DEFSYM (QCdbus_type_string, ":string");
1730 DEFSYM (QCdbus_type_object_path, ":object-path");
1731 DEFSYM (QCdbus_type_signature, ":signature");
da1fec2b 1732#ifdef DBUS_TYPE_UNIX_FD
cd3520a4 1733 DEFSYM (QCdbus_type_unix_fd, ":unix-fd");
da1fec2b 1734#endif
cd3520a4
JB
1735 DEFSYM (QCdbus_type_array, ":array");
1736 DEFSYM (QCdbus_type_variant, ":variant");
1737 DEFSYM (QCdbus_type_struct, ":struct");
1738 DEFSYM (QCdbus_type_dict_entry, ":dict-entry");
dcbf5805
MA
1739 DEFSYM (QCdbus_registered_serial, ":serial");
1740 DEFSYM (QCdbus_registered_method, ":method");
1741 DEFSYM (QCdbus_registered_signal, ":signal");
1742
1743 DEFVAR_LISP ("dbus-compiled-version",
1744 Vdbus_compiled_version,
1745 doc: /* The version of D-Bus Emacs is compiled against. */);
1746#ifdef DBUS_VERSION_STRING
1747 Vdbus_compiled_version = make_pure_c_string (DBUS_VERSION_STRING);
1748#else
1749 Vdbus_compiled_version = Qnil;
1750#endif
54371585 1751
dcbf5805
MA
1752 DEFVAR_LISP ("dbus-runtime-version",
1753 Vdbus_runtime_version,
1754 doc: /* The version of D-Bus Emacs runs with. */);
1755 {
1756#ifdef DBUS_VERSION
1757 int major, minor, micro;
243e0530 1758 char s[sizeof ".." + 3 * INT_STRLEN_BOUND (int)];
dcbf5805 1759 dbus_get_version (&major, &minor, &micro);
a8290ec3
DA
1760 Vdbus_runtime_version
1761 = make_formatted_string (s, "%d.%d.%d", major, minor, micro);
dcbf5805
MA
1762#else
1763 Vdbus_runtime_version = Qnil;
1764#endif
1765 }
1766
1767 DEFVAR_LISP ("dbus-message-type-invalid",
1768 Vdbus_message_type_invalid,
1769 doc: /* This value is never a valid message type. */);
1770 Vdbus_message_type_invalid = make_number (DBUS_MESSAGE_TYPE_INVALID);
1771
1772 DEFVAR_LISP ("dbus-message-type-method-call",
1773 Vdbus_message_type_method_call,
1774 doc: /* Message type of a method call message. */);
1775 Vdbus_message_type_method_call = make_number (DBUS_MESSAGE_TYPE_METHOD_CALL);
1776
1777 DEFVAR_LISP ("dbus-message-type-method-return",
1778 Vdbus_message_type_method_return,
1779 doc: /* Message type of a method return message. */);
1780 Vdbus_message_type_method_return
1781 = make_number (DBUS_MESSAGE_TYPE_METHOD_RETURN);
1782
1783 DEFVAR_LISP ("dbus-message-type-error",
1784 Vdbus_message_type_error,
1785 doc: /* Message type of an error reply message. */);
1786 Vdbus_message_type_error = make_number (DBUS_MESSAGE_TYPE_ERROR);
1787
1788 DEFVAR_LISP ("dbus-message-type-signal",
1789 Vdbus_message_type_signal,
1790 doc: /* Message type of a signal message. */);
1791 Vdbus_message_type_signal = make_number (DBUS_MESSAGE_TYPE_SIGNAL);
0c372655 1792
f04bb9b2 1793 DEFVAR_LISP ("dbus-registered-objects-table",
29208e82 1794 Vdbus_registered_objects_table,
39abdd4a 1795 doc: /* Hash table of registered functions for D-Bus.
0c372655 1796
f04bb9b2
MA
1797There are two different uses of the hash table: for accessing
1798registered interfaces properties, targeted by signals or method calls,
1799and for calling handlers in case of non-blocking method call returns.
13ecc6dc 1800
dcbf5805
MA
1801In the first case, the key in the hash table is the list (TYPE BUS
1802INTERFACE MEMBER). TYPE is one of the Lisp symbols `:method',
1803`:signal' or `:property'. BUS is either a Lisp symbol, `:system' or
0c372655
MA
1804`:session', or a string denoting the bus address. INTERFACE is a
1805string which denotes a D-Bus interface, and MEMBER, also a string, is
1806either a method, a signal or a property INTERFACE is offering. All
1807arguments but BUS must not be nil.
a31d47c7 1808
dcbf5805
MA
1809The value in the hash table is a list of quadruple lists \((UNAME
1810SERVICE PATH OBJECT [RULE]) ...). SERVICE is the service name as
1811registered, UNAME is the corresponding unique name. In case of
1812registered methods and properties, UNAME is nil. PATH is the object
1813path of the sending object. All of them can be nil, which means a
1814wildcard then. OBJECT is either the handler to be called when a D-Bus
1815message, which matches the key criteria, arrives (TYPE `:method' and
1816`:signal'), or a cons cell containing the value of the property (TYPE
1817`:property').
13ecc6dc 1818
dcbf5805
MA
1819For entries of type `:signal', there is also a fifth element RULE,
1820which keeps the match string the signal is registered with.
a3de0cbd 1821
dcbf5805 1822In the second case, the key in the hash table is the list (:serial BUS
0c372655
MA
1823SERIAL). BUS is either a Lisp symbol, `:system' or `:session', or a
1824string denoting the bus address. SERIAL is the serial number of the
1825non-blocking method call, a reply is expected. Both arguments must
1826not be nil. The value in the hash table is HANDLER, the function to
1827be called when the D-Bus reply message arrives. */);
1828 {
1829 Lisp_Object args[2];
1830 args[0] = QCtest;
1831 args[1] = Qequal;
1832 Vdbus_registered_objects_table = Fmake_hash_table (2, args);
1833 }
033b73e2 1834
29208e82 1835 DEFVAR_LISP ("dbus-debug", Vdbus_debug,
39abdd4a 1836 doc: /* If non-nil, debug messages of D-Bus bindings are raised. */);
033b73e2
MA
1837#ifdef DBUS_DEBUG
1838 Vdbus_debug = Qt;
a79b0f28
MA
1839 /* We can also set environment variable DBUS_VERBOSE=1 in order to
1840 see more traces. This requires libdbus-1 to be configured with
1841 --enable-verbose-mode. */
033b73e2
MA
1842#else
1843 Vdbus_debug = Qnil;
1844#endif
1845
5cb67954
MA
1846 /* Initialize internal objects. */
1847 xd_registered_buses = Qnil;
1848 staticpro (&xd_registered_buses);
1849
d67b4f80 1850 Fprovide (intern_c_string ("dbusbind"), Qnil);
033b73e2
MA
1851
1852}
1853
1854#endif /* HAVE_DBUS */