/* Authors: Pavel Březina Copyright (C) 2014 Red Hat This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include "lib/sifp/sss_sifp.h" #include "lib/sifp/sss_sifp_dbus.h" #include "lib/sifp/sss_sifp_private.h" static sss_sifp_error sss_sifp_ifp_call(sss_sifp_ctx *ctx, const char *object_path, const char *interface, const char *method, int first_arg_type, va_list ap, DBusMessage **_reply) { DBusMessage *msg = NULL; sss_sifp_error ret; dbus_bool_t bret; if (object_path == NULL || interface == NULL || method == NULL) { return SSS_SIFP_INVALID_ARGUMENT; } msg = sss_sifp_create_message(object_path, interface, method); if (msg == NULL) { ret = SSS_SIFP_OUT_OF_MEMORY; goto done; } if (first_arg_type != DBUS_TYPE_INVALID) { bret = dbus_message_append_args_valist(msg, first_arg_type, ap); if (!bret) { ret = SSS_SIFP_IO_ERROR; goto done; } } ret = sss_sifp_send_message(ctx, msg, _reply); done: if (msg != NULL) { dbus_message_unref(msg); } return ret; } DBusMessage * sss_sifp_create_message(const char *object_path, const char *interface, const char *method) { return dbus_message_new_method_call(SSS_SIFP_ADDRESS, object_path, interface, method); } sss_sifp_error sss_sifp_send_message(sss_sifp_ctx *ctx, DBusMessage *msg, DBusMessage **_reply) { return sss_sifp_send_message_ex(ctx, msg, 5000, _reply); } sss_sifp_error sss_sifp_send_message_ex(sss_sifp_ctx *ctx, DBusMessage *msg, int timeout, DBusMessage **_reply) { DBusMessage *reply = NULL; DBusError dbus_error; sss_sifp_error ret; if (ctx == NULL || msg == NULL) { return SSS_SIFP_INVALID_ARGUMENT; } dbus_error_init(&dbus_error); reply = dbus_connection_send_with_reply_and_block(ctx->conn, msg, timeout, &dbus_error); if (dbus_error_is_set(&dbus_error)) { sss_sifp_set_io_error(ctx, &dbus_error); ret = SSS_SIFP_IO_ERROR; goto done; } if (_reply == NULL) { dbus_message_unref(reply); } else { *_reply = reply; } ret = SSS_SIFP_OK; done: dbus_error_free(&dbus_error); return ret; } static sss_sifp_error sss_sifp_invoke_list_va(sss_sifp_ctx *ctx, const char *object_path, const char *interface, const char *method, char ***_object_paths, int first_arg_type, va_list ap) { DBusMessage *reply = NULL; char *dbus_method = NULL; sss_sifp_error ret; if (ctx == NULL || method == NULL || _object_paths == NULL) { return SSS_SIFP_INVALID_ARGUMENT; } dbus_method = sss_sifp_strcat(ctx, "List", method); if (dbus_method == NULL) { ret = SSS_SIFP_OUT_OF_MEMORY; goto done; } ret = sss_sifp_ifp_call(ctx, object_path, interface, dbus_method, first_arg_type, ap, &reply); if (ret != SSS_SIFP_OK) { goto done; } ret = sss_sifp_parse_object_path_list(ctx, reply, _object_paths); done: sss_sifp_free_string(ctx, &dbus_method); if (reply != NULL) { dbus_message_unref(reply); } return ret; } sss_sifp_error sss_sifp_invoke_list_ex(sss_sifp_ctx *ctx, const char *object_path, const char *interface, const char *method, char ***_object_paths, int first_arg_type, ...) { va_list ap; sss_sifp_error ret; va_start(ap, first_arg_type); ret = sss_sifp_invoke_list_va(ctx, object_path, interface, method, _object_paths, first_arg_type, ap); va_end(ap); return ret; } sss_sifp_error sss_sifp_invoke_list(sss_sifp_ctx *ctx, const char *method, char ***_object_paths, int first_arg_type, ...) { va_list ap; sss_sifp_error ret; va_start(ap, first_arg_type); ret = sss_sifp_invoke_list_ex(ctx, SSS_SIFP_PATH, SSS_SIFP_IFACE, method, _object_paths, first_arg_type, ap); va_end(ap); return ret; } static sss_sifp_error sss_sifp_invoke_find_va(sss_sifp_ctx *ctx, const char *object_path, const char *interface, const char *method, char **_object_path, int first_arg_type, va_list ap) { DBusMessage *reply = NULL; char *dbus_method = NULL; sss_sifp_error ret; if (ctx == NULL || method == NULL || _object_path == NULL) { return SSS_SIFP_INVALID_ARGUMENT; } dbus_method = sss_sifp_strcat(ctx, "Find", method); if (dbus_method == NULL) { ret = SSS_SIFP_OUT_OF_MEMORY; goto done; } ret = sss_sifp_ifp_call(ctx, object_path, interface, dbus_method, first_arg_type, ap, &reply); if (ret != SSS_SIFP_OK) { goto done; } ret = sss_sifp_parse_object_path(ctx, reply, _object_path); done: sss_sifp_free_string(ctx, &dbus_method); if (reply != NULL) { dbus_message_unref(reply); } return ret; } sss_sifp_error sss_sifp_invoke_find_ex(sss_sifp_ctx *ctx, const char *object_path, const char *interface, const char *method, char **_object_path, int first_arg_type, ...) { va_list ap; sss_sifp_error ret; va_start(ap, first_arg_type); ret = sss_sifp_invoke_find_va(ctx, object_path, interface, method, _object_path, first_arg_type, ap); va_end(ap); return ret; } sss_sifp_error sss_sifp_invoke_find(sss_sifp_ctx *ctx, const char *method, char **_object_path, int first_arg_type, ...) { va_list ap; sss_sifp_error ret; va_start(ap, first_arg_type); ret = sss_sifp_invoke_find_va(ctx, SSS_SIFP_PATH, SSS_SIFP_IFACE, method, _object_path, first_arg_type, ap); va_end(ap); return ret; }