+ /* allocation */
+ sig = malloc(sizeof *sig);
+ if (sig == NULL) {
+ errno = ENOMEM;
+ goto error;
+ }
+ sig->name = strdup(name);
+ if (!sig->name) {
+ errno = ENOMEM;
+ goto error2;
+ }
+
+ /* record the signal */
+ sig->onsignal_s = onsignal_s;
+ sig->onsignal_j = onsignal_j;
+ sig->data = data;
+ sig->next = jbus->signals;
+ jbus->signals = sig;
+
+ return 0;
+
+ error2:
+ free(sig);
+ error:
+ return -1;
+}
+
+static int on_reply(struct sd_bus_message *smsg, struct jrespw *jrespw, sd_bus_error *error)
+{
+ struct json_object *obj;
+ const char *reply;
+ int iserror;
+
+ /* check the type */
+ if (!sd_bus_message_has_signature(smsg, "s")
+ || sd_bus_message_read_basic(smsg, 's', &reply) < 0) {
+ sd_bus_error_set_const(error, "bad signature", "");
+ goto end;
+ }
+ iserror = sd_bus_message_is_method_error(smsg, NULL);
+
+ /* dispatch string? */
+ if (jrespw->onresp_s != NULL) {
+ jrespw->onresp_s(iserror, reply, jrespw->data);
+ goto end;
+ }
+
+ /* dispatch json */
+ if (!jparse(jrespw->jbus, reply, &obj))
+ obj = json_object_new_string(reply);
+ jrespw->onresp_j(iserror, obj, jrespw->data);
+ json_object_put(obj);
+
+ end:
+ free(jrespw);
+ return 1;
+}
+
+/*
+ * Creates a message for 'method' with one string parameter being 'query'
+ * and sends it to the destination, object and interface linked to 'jbus'.
+ *
+ * Adds to 'jbus' the response handler defined by the callbacks 'onresp_s'
+ * (for string) and 'onresp_j' (for json) and the closure parameter 'data'.
+ *
+ * Returns 0 in case of success or -1 in case of error.
+ */
+static int call(
+ struct jbus *jbus,
+ const char *method,
+ const char *query,
+ void (*onresp_s) (int, const char *, void *),
+ void (*onresp_j) (int, struct json_object *, void *),
+ void *data)
+{
+ int rc;
+ struct jrespw *resp;
+
+ /* allocates the response structure */
+ resp = malloc(sizeof *resp);
+ if (resp == NULL) {
+ errno = ENOMEM;
+ goto error;
+ }
+
+ /* fulfill the response structure */
+ resp->jbus = jbus;
+ resp->onresp_s = onresp_s;
+ resp->onresp_j = onresp_j;
+ resp->data = data;
+
+ rc = sd_bus_call_method_async(jbus->sdbus, NULL, jbus->name, jbus->path, jbus->name, method, (void*)on_reply, resp, "s", query);
+ if (rc < 0) {
+ errno = -rc;
+ goto error2;
+ }
+
+ return 0;
+
+ error2:
+ free(resp);
+ error:
+ return -1;
+}
+
+/********************* MAIN FUNCTIONS *****************************************/
+
+/*
+ * Creates a 'jbus' bound the 'path' and it derived names and linked
+ * either to the DBUS SYSTEM when 'session' is nul or to the DBUS SESSION
+ * if 'session' is not nul.
+ *
+ * The parameter 'path' is intended to be the path of a DBUS single object.
+ * Single means that it exists only one instance of the object on the
+ * given bus. That path implies 2 derived DBUS names:
+ * 1. the destination name of the program that handles the object
+ * 2. the interface name of the object
+ * These names are derived by removing the heading slash (/) and
+ * by replacing all occurences of slashes by dots.
+ * For example, passing path = /a/b/c means that the object /a/b/c is
+ * handled by the destination a.b.c and replies to the interface a.b.c
+ *
+ * Returns the created jbus or NULL in case of error.
+ */
+struct jbus *create_jbus(struct sd_bus *sdbus, const char *path)