Logo Search packages:      
Sourcecode: ulatencyd version File versions  Download package

dbus.c

/*
    Copyright 2010,2011 ulatencyd developers

    This file is part of ulatencyd.

    ulatencyd 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.

    ulatencyd 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 ulatencyd. If not, see http://www.gnu.org/licenses/.
*/

#include "config.h"
#include "ulatency.h"
#include <stdint.h>
#include <glib.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <dbus/dbus-glib-bindings.h>
#include <dbus/dbus-protocol.h>

//char INTRO[] = {
//#include "myfile.txt"
//}
#define INTROSPECT \
"    <interface name=\"org.freedesktop.DBus.Properties\">\n" \
"       <method name=\"Get\">\n" \
"          <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
"          <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
"          <arg name=\"value\" direction=\"out\" type=\"v\"/>\n" \
"       </method>\n" \
"       <method name=\"Set\">\n" \
"          <arg name=\"interface\" direction=\"in\" type=\"s\"/>\n" \
"          <arg name=\"property\" direction=\"in\" type=\"s\"/>\n" \
"          <arg name=\"value\" direction=\"in\" type=\"v\"/>\n" \
"       </method>\n" \
"    </interface>\n" \
"    <interface name=\"org.freedesktop.DBus.Introspectable\">\n" \
"       <method name=\"Introspect\">\n" \
"          <arg name=\"data\" type=\"s\" direction=\"out\"/>\n" \
"       </method>\n" \
"    </interface>\n"


const char *INTROSPECT_XML_USER = \
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
"<node name=\"" U_DBUS_USER_PATH "\">\n"
"  <interface name=\"" U_DBUS_USER_INTERFACE "\">\n"
"    <method name=\"setActive\">\n"
"      <arg type=\"t\" name=\"pid\" direction=\"in\" />\n"
"    </method>\n"
"    <method name=\"setActiveWithUser\">\n"
"      <arg type=\"t\" name=\"uid\" direction=\"in\" />\n"
"      <arg type=\"t\" name=\"pid\" direction=\"in\" />\n"
"    </method>\n"
"    <method name=\"setActiveControl\">\n"
"      <arg type=\"b\" name=\"enabled\" direction=\"in\" />\n"
"    </method>\n"
//"    <method name=\"wishGroup\">\n"
//"      <arg type=\"i\" name=\"pid\" direction=\"in\" />\n"
//"      <arg type=\"i\" name=\"priority\" direction=\"in\" />\n"
//"    </method>\n"
"    <property name=\"activeListLength\" type=\"q\" access=\"readwrite\"/>\n"
"  </interface>\n"
INTROSPECT
"</node>\n";

const char *INTROSPECT_XML_SYSTEM = \
"<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
"<node name=\"" U_DBUS_SYSTEM_PATH "\">\n"
"  <interface name=\"" U_DBUS_SYSTEM_INTERFACE "\">\n"
"    <method name=\"setSchedulerConfig\">\n"
"      <arg type=\"s\" name=\"name\" direction=\"in\" />\n"
"      <arg type=\"b\" name=\"success\" direction=\"out\" />\n"
"    </method>\n"
"    <method name=\"listSchedulerConfigs\">\n"
"      <arg type=\"as\" name=\"names\" direction=\"out\" />\n"
"    </method>\n"
"    <method name=\"getSchedulerConfigDescription\">\n"
"      <arg type=\"s\" name=\"name\" direction=\"in\" />\n"
"      <arg type=\"s\" name=\"description\" direction=\"out\" />\n"
"    </method>\n"
"    <method name=\"listSystemFlags\">\n"
"      <arg type=\"aa{sv}\" direction=\"out\" />\n"
"    </method>\n"
"    <method name=\"addFlag\">\n"
"      <arg type=\"t\" name=\"pid\" direction=\"in\" />\n"
"      <arg type=\"t\" name=\"tid\" direction=\"in\" />\n"
"      <arg type=\"s\" name=\"name\" direction=\"in\" />\n"
"      <arg type=\"s\" name=\"reason\" direction=\"in\" />\n"
"      <arg type=\"t\" name=\"timeout\" direction=\"in\" />\n"
"      <arg type=\"i\" name=\"priority\" direction=\"in\" />\n"
"      <arg type=\"x\" name=\"value\" direction=\"in\" />\n"
"      <arg type=\"x\" name=\"threshold\" direction=\"in\" />\n"
"      <arg type=\"b\" name=\"inherit\" direction=\"in\" />\n"
"    </method>\n"
"    <method name=\"listFlags\">\n"
"      <arg type=\"t\" name=\"pid\" direction=\"in\" />\n"
"      <arg type=\"b\" name=\"recrusive\" direction=\"in\" />\n"
"      <arg type=\"a(ta{sv})\" name=\"flags\" direction=\"out\" />\n"
"    </method>\n"
"    <method name=\"delFlag\">\n"
"      <arg type=\"t\" name=\"pid\" direction=\"in\" />\n"
"      <arg type=\"t\" name=\"id\" direction=\"in\" />\n"
"    </method>\n"
"    <method name=\"clearFlags\">\n"
"      <arg type=\"t\" name=\"pid\" direction=\"in\" />\n"
"    </method>\n"
"    <method name=\"scheduleTask\">\n"
"      <arg type=\"t\" name=\"pid\" direction=\"in\" />\n"
"      <arg type=\"b\" name=\"update\" direction=\"in\" />\n"
"      <arg type=\"b\" name=\"success\" direction=\"out\" />\n"
"    </method>\n"
"    <property name=\"config\" type=\"s\" access=\"read\"/>\n"
"    <property name=\"version\" type=\"s\" access=\"read\"/>\n"
"  </interface>\n"
INTROSPECT
"</node>\n";

// pointer for flags as source
const void *U_DBUS_POINTER = &INTROSPECT_XML_SYSTEM;


#define U_DBUS_ERROR_NO_PID "org.quamquam.ulatency.DBus.Error.PidNotFound"


#define GET_CALLER() \
    if ((caller = dbus_bus_get_unix_user(c, dbus_message_get_sender(m), &error)) == (unsigned long) -1) { \
            g_warning("dbus_message_get_unix_user() failed: %s\n", error.message); \
            ret = dbus_message_new_error(m, DBUS_ERROR_ACCESS_DENIED, "not a local connection"); \
            goto finish; \
    }

#define PUSH_ERROR(ID, MSG) \
      { if(error.name) { \
        ret = dbus_message_new_error(m, error.name, error.message); \
      } else { \
        ret = dbus_message_new_error(m, ID, #MSG); } \
      goto finish; \
      }


static DBusHandlerResult dbus_user_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
    DBusError error;
    DBusMessage *ret = NULL;
    uid_t caller;
    int is2 = 0;
    dbus_error_init(&error);
    if(dbus_message_is_method_call(m, U_DBUS_USER_INTERFACE, "setActive") ||
       (is2 = dbus_message_is_method_call(m, U_DBUS_USER_INTERFACE, "setActiveWithUser"))) {
        uid_t uid;
        pid_t pid;
        uint64_t tmpu;
        uint64_t tmpp;

        GET_CALLER()

        if(is2) {
          if(!dbus_message_get_args(m, &error,
                                    DBUS_TYPE_UINT64, &tmpu,
                                    DBUS_TYPE_UINT64, &tmpp,
                                    DBUS_TYPE_INVALID))
                PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")
          uid = (uid_t)tmpu;
        } else {
          if(!dbus_message_get_args(m, &error,
                                    DBUS_TYPE_UINT64, &tmpp,
                                    DBUS_TYPE_INVALID))
                PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")

          uid = (pid_t)caller;
        }
        pid = (pid_t)tmpp;

        if(caller != 0 && caller != uid) {
          ret = dbus_message_new_error(m, DBUS_ERROR_ACCESS_DENIED, "not allowed to set aktive pids of foreign users");

          goto finish;
        }
        set_active_pid(uid, pid);
        ret = dbus_message_new_method_return(m);

        goto finish;

    } else if (dbus_message_is_method_call(m, U_DBUS_USER_INTERFACE, "setActiveControl")) {
        gboolean enable;
        struct user_active *ua;

        if(!dbus_message_get_args(m, &error,
                                  DBUS_TYPE_BOOLEAN, &enable,
                                  DBUS_TYPE_INVALID))
                PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")

        GET_CALLER()

        ua = get_userlist(caller, TRUE);
        if(enable)
          ua->active_agent = USER_ACTIVE_AGENT_DBUS;
        else
          ua->active_agent = USER_ACTIVE_AGENT_NONE;

        ret = dbus_message_new_method_return(m);

        goto finish;
    } else if (dbus_message_is_method_call(m, DBUS_INTERFACE_PROPERTIES, "Get")) {
        const char *interface, *property;
        struct user_active *ua;

        if (!dbus_message_get_args(m, &error,
                                      DBUS_TYPE_STRING, &interface,
                                      DBUS_TYPE_STRING, &property,
                                      DBUS_TYPE_INVALID)) {
            g_warning("Failed to parse property get call: %s\n", error.message);
            ret = dbus_message_new_error(m, error.name, error.message);
            goto finish;
        }

        if (g_strcmp0(interface, U_DBUS_USER_INTERFACE) == 0) {

            GET_CALLER()

            ua = get_userlist(caller, TRUE);
            ret = dbus_message_new_method_return(m);

            if(g_strcmp0(property, "activeListLength") == 0) {
                dbus_message_append_args (ret,
                                          DBUS_TYPE_UINT32, &ua->max_processes,
                                          DBUS_TYPE_INVALID);
                goto finish;
            }

            dbus_message_unref(ret);
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        } else    {
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        }

    } else if (dbus_message_is_method_call(m, DBUS_INTERFACE_PROPERTIES, "Set")) {
        const char *interface, *property;
        struct user_active *ua;
        DBusMessageIter imsg;
        if (!dbus_message_get_args(m, &error,
                                      DBUS_TYPE_STRING, &interface,
                                      DBUS_TYPE_STRING, &property,
                                      DBUS_TYPE_INVALID) ||
            !dbus_message_iter_init (m, &imsg)) {
              g_warning("Failed to parse property set call: %s\n", error.message);
              ret = dbus_message_new_error(m, error.name, error.message);
              goto finish;
        }
        dbus_message_iter_next(&imsg);
        dbus_message_iter_next(&imsg);

        if (g_strcmp0(interface, U_DBUS_USER_INTERFACE) == 0) {

            GET_CALLER()
            ua = get_userlist(caller, TRUE);
            ret = dbus_message_new_method_return(m);

            if(g_strcmp0(property, "activeList") == 0) {
                if(!dbus_message_iter_get_arg_type(&imsg) == DBUS_TYPE_UINT32)
                    goto error;

                dbus_message_iter_get_basic (&imsg, &ua->max_processes);

                goto finish;
            }

            dbus_message_unref(ret);
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        } else    {
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        }

    } else if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) {
        ret = dbus_message_new_method_return(m);
        dbus_message_append_args(ret,
                                 DBUS_TYPE_STRING, &INTROSPECT_XML_USER,
                                 DBUS_TYPE_INVALID);
        goto finish;
    } else
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

error:
    if(ret)
      dbus_message_unref(ret);
    ret = dbus_message_new_error(m, DBUS_ERROR_INVALID_ARGS , "wrong arguments");


finish:
    if (ret) {
        dbus_connection_send(c, ret, NULL);
        dbus_message_unref(ret);
    }

    dbus_error_free(&error);

    return DBUS_HANDLER_RESULT_HANDLED;
};


static void push_flag(DBusMessage *ret, u_proc *proc, int recrusive) {
    GList *cur, *lst;
    u_flag *fl;
    char *name = NULL;
    uint32_t tu32;
    DBusMessageIter imsg, array, strukt, dict, entry, value;

    dbus_message_iter_init_append(ret, &imsg);

    if(proc) {
        lst = u_proc_list_flags(proc, recrusive);
        cur = lst;
        dbus_message_iter_open_container(&imsg, DBUS_TYPE_ARRAY,
            "(ta{sv})"
            , &array);
    } else {
        cur = g_list_first(system_flags);
        dbus_message_iter_open_container(&imsg, DBUS_TYPE_ARRAY,
            "a{sv}"
            , &array);
    }


    #define PUSH_VARIANT(NAME, VAR, TYPE) {\
        name = #NAME ; \
        dbus_message_iter_open_container(&entry, DBUS_TYPE_DICT_ENTRY, NULL, &dict); \
        dbus_message_iter_append_basic(&dict, DBUS_TYPE_STRING, &name); \
        dbus_message_iter_open_container(&dict, DBUS_TYPE_VARIANT, TYPE##_AS_STRING, &value); \
        dbus_message_iter_append_basic(&value, TYPE, VAR); \
        dbus_message_iter_close_container(&dict, &value); \
        dbus_message_iter_close_container(&entry, &dict); }


    while(cur) {
        fl = cur->data;
        uint64_t flp = (uint64_t)fl;
        uint64_t tid = (uint64_t)fl->tid;

        if(proc) {
            dbus_message_iter_open_container(&array, DBUS_TYPE_STRUCT,
                                             NULL, &strukt);

            dbus_message_iter_append_basic(&strukt, DBUS_TYPE_UINT64, &flp);
            dbus_message_iter_open_container(&strukt, DBUS_TYPE_ARRAY,
                                             "{sv}", &entry);
        } else {
            dbus_message_iter_open_container(&array, DBUS_TYPE_ARRAY,
                                              "{sv}", &entry);
        }

        PUSH_VARIANT(name, &fl->name, DBUS_TYPE_STRING);
        PUSH_VARIANT(tid, &tid, DBUS_TYPE_UINT64);
        if(fl->reason)
            PUSH_VARIANT(reason, &fl->reason, DBUS_TYPE_STRING);
        tu32 = (uint32_t)fl->timeout;
        PUSH_VARIANT(timeout, &tu32, DBUS_TYPE_UINT32);
        PUSH_VARIANT(priority, &fl->priority, DBUS_TYPE_INT32);
        PUSH_VARIANT(value, &fl->value, DBUS_TYPE_INT64);
        PUSH_VARIANT(threshold, &fl->threshold, DBUS_TYPE_INT64);
        tu32 = (uint32_t)fl->inherit;
        PUSH_VARIANT(inherit, &tu32, DBUS_TYPE_BOOLEAN);

        if(proc) {
           dbus_message_iter_close_container(&strukt, &entry);
           dbus_message_iter_close_container(&array, &strukt);
           DEC_REF(fl);
        } else {
           dbus_message_iter_close_container(&array, &entry);
        }

        cur = g_list_next(cur);
    }
    #undef PUSH_VARIANT
    dbus_message_iter_close_container(&imsg, &array);
    if(proc)
      g_list_free(lst);
    return;
}

static void set_config_callback(struct callback_data *data) {
    DBusMessage *ret = dbus_message_new_method_return(data->message);
    u_scheduler *sched = scheduler_get();
    g_message("DBUS: setSchedulerConfig(\"%s\") executed", (char *)data->user_data);
    dbus_bool_t rv = (dbus_bool_t)sched->set_config((char *)data->user_data);
    dbus_message_append_args (ret,
                              DBUS_TYPE_BOOLEAN, &rv,
                              DBUS_TYPE_INVALID);
    dbus_connection_send(data->connection, ret, NULL);
    dbus_message_unref(ret);
}

static DBusHandlerResult dbus_system_handler(DBusConnection *c, DBusMessage *m, void *userdata) {
    DBusError error;
    DBusMessage *ret = NULL;
    DBusMessageIter imsg;
    uid_t caller;
    uint64_t tu64;
    int is2 = 0;

    dbus_error_init(&error);
    if(dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "listSystemFlags")) {

        ret = dbus_message_new_method_return(m);
        push_flag(ret, NULL, FALSE);
        goto finish;

    } else if(dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "listFlags")) {
        u_proc *proc;
        pid_t pid;
        uint32_t recrusive;

        if (!dbus_message_get_args(m, &error,
                                      DBUS_TYPE_UINT64, &tu64,
                                      DBUS_TYPE_BOOLEAN,&recrusive,
                                      DBUS_TYPE_INVALID) ||
            !dbus_message_iter_init (m, &imsg))
              PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")

        pid = (pid_t)tu64;
        proc = proc_by_pid_with_retry(pid);

        if(!proc)
          PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")

        ret = dbus_message_new_method_return(m);
        push_flag(ret, proc, recrusive);
        goto finish;


    } else if(dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "addFlag")) {
        u_proc *proc;

        uint64_t tpid, ttid, timeout;
        int64_t priority, value, threshold;
        uint32_t inherit;
        u_flag *flag;
        char *name, *reason;

        if (!dbus_message_get_args(m, &error,
                                      DBUS_TYPE_UINT64, &tpid,
                                      DBUS_TYPE_UINT64, &ttid,
                                      DBUS_TYPE_STRING, &name,
                                      DBUS_TYPE_STRING, &reason,
                                      DBUS_TYPE_UINT64, &timeout,
                                      DBUS_TYPE_INT32,  &priority,
                                      DBUS_TYPE_INT64,  &value,
                                      DBUS_TYPE_INT64,  &threshold,
                                      DBUS_TYPE_BOOLEAN,&inherit,
                                      DBUS_TYPE_INVALID) ||
            !dbus_message_iter_init (m, &imsg))
              PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")

        pid_t pid = (pid_t)tpid;
        pid_t tid = (pid_t)ttid;

        proc = proc_by_pid_with_retry(pid);

        GET_CALLER()

        if(!proc)
            PUSH_ERROR(U_DBUS_ERROR_NO_PID, "wrong arguments")

        if(caller != 0 && caller != proc->proc.euid)
            PUSH_ERROR(DBUS_ERROR_ACCESS_DENIED, "access denied")

        flag = u_flag_new((void *)U_DBUS_POINTER, name);
        flag->reason = reason;
        flag->tid = tid;
        flag->timeout = timeout;
        flag->priority = priority;
        flag->value = value;
        flag->threshold = threshold;
        flag->inherit = inherit;

        u_flag_add(proc, flag);

        ret = dbus_message_new_method_return(m);
        goto finish;

    } else if(dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "clearFlags") || 
              (is2 = dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "delFlag"))) {
        u_proc *proc;

        uint64_t tpid;
        uint64_t id;


        if (is2) {
              if (!dbus_message_get_args(m, &error,
                                         DBUS_TYPE_UINT64, &tpid,
                                         DBUS_TYPE_UINT64, &id,
                                         DBUS_TYPE_INVALID) ||
                  !dbus_message_iter_init (m, &imsg))
                      PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")

        } else if(!dbus_message_get_args(m, &error,
                                         DBUS_TYPE_UINT64, &tpid,
                                         DBUS_TYPE_INVALID) ||
                  !dbus_message_iter_init (m, &imsg))
                      PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")

        pid_t pid = (pid_t)tpid;

        proc = proc_by_pid_with_retry(pid);

        GET_CALLER()

        if(!proc)
            PUSH_ERROR(U_DBUS_ERROR_NO_PID, "wrong arguments")

        if(caller != 0 && caller != proc->proc.euid)
            PUSH_ERROR(DBUS_ERROR_ACCESS_DENIED, "access denied")

        if(is2) {
            u_flag_clear_flag(proc, (void *)id);
        } else {
            u_flag_clear_source(proc, U_DBUS_POINTER);
        }

        ret = dbus_message_new_method_return(m);
        goto finish;

    } else if(dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "scheduleTask")) {
        u_proc *proc;
        uint32_t update;
        uint64_t tpid;

        if (!dbus_message_get_args(m, &error,
                                      DBUS_TYPE_UINT64, &tpid,
                                      DBUS_TYPE_BOOLEAN, &update,
                                      DBUS_TYPE_INVALID) ||
            !dbus_message_iter_init (m, &imsg))
              PUSH_ERROR(DBUS_ERROR_INVALID_ARGS, "wrong arguments")

        pid_t pid = (pid_t)tpid;

        proc = proc_by_pid_with_retry(pid);

        GET_CALLER()

        if(!proc)
            PUSH_ERROR(U_DBUS_ERROR_NO_PID, "wrong arguments")

        if(caller != 0 && caller != proc->proc.euid)
            PUSH_ERROR(DBUS_ERROR_ACCESS_DENIED, "access denied")

        ret = dbus_message_new_method_return(m);

        int suc = process_run_one(proc, update, FALSE);

        dbus_message_append_args (ret,
                                  DBUS_TYPE_BOOLEAN, &suc,
                                  DBUS_TYPE_INVALID);


        ret = dbus_message_new_method_return(m);
        goto finish;

    } else if(dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "setSchedulerConfig")) {
        u_scheduler *sched = scheduler_get();
        char *tmps = NULL;

        if (!sched || !sched->set_config) {
            ret = dbus_message_new_error(m, DBUS_ERROR_FAILED, "scheduler does not support setting config");
            goto finish;
        }
        if(!dbus_message_get_args(m, &error,
                                  DBUS_TYPE_STRING, &tmps,
                                  DBUS_TYPE_INVALID)) {
            ret = dbus_message_new_error(m, DBUS_ERROR_INVALID_ARGS , "wrong arguments");
            goto finish;
        }
        if (!tmps) {
            ret = dbus_message_new_error(m, DBUS_ERROR_INVALID_ARGS , "wrong arguments");
            goto finish;
        }

        GET_CALLER()
        if(caller == 0) {
            //set_config_dbus(tmps);
            ret = dbus_message_new_method_return(m);
            g_message("DBUS: setSchedulerConfig(\"%s\") executed", tmps);
            dbus_bool_t rv = (dbus_bool_t)sched->set_config(tmps);
            dbus_message_append_args (ret,
                                      DBUS_TYPE_BOOLEAN, &rv,
                                      DBUS_TYPE_INVALID);
            goto finish;
        } else {
            if(!check_polkit("org.quamquam.ulatencyd.setConfig",
                             c,
                             m,
                             "org.quamquam.ulatencyd.setConfig",
                             set_config_callback,
                             tmps,
                             TRUE,
                             NULL, tmps))
               PUSH_ERROR(DBUS_ERROR_ACCESS_DENIED, "access denied")

            return DBUS_HANDLER_RESULT_HANDLED;
        }

        if(tmps) {

            goto finish;
        } 

    } else if(dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "listSchedulerConfigs")) {
        u_scheduler *sched = scheduler_get();
        DBusMessageIter imsg, array;
        GPtrArray *configs;
        char *tmp;
        int i;

        if (!sched || !sched->list_configs) {
            ret = dbus_message_new_error(m, DBUS_ERROR_FAILED, "scheduler does not support setting config");
            goto finish;
        }
        configs = sched->list_configs();

        ret = dbus_message_new_method_return(m);

        dbus_message_iter_init_append(ret, &imsg);

        dbus_message_iter_open_container(&imsg, DBUS_TYPE_ARRAY, "s" , &array);

        if(configs) {
          for(i = 0; i < configs->len; i++) {
              tmp = g_ptr_array_index(configs, i);
              dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &tmp);
          }
          g_ptr_array_unref(configs);
        }
        dbus_message_iter_close_container(&imsg, &array);

        goto finish;

    } else if(dbus_message_is_method_call(m, U_DBUS_SYSTEM_INTERFACE, "getSchedulerConfigDescription")) {
        u_scheduler *sched = scheduler_get();
        char *name, *desc;

        if (!sched || !sched->get_config_description) {
            ret = dbus_message_new_error(m, DBUS_ERROR_FAILED, "scheduler does not support config descriptions");
            goto finish;
        }

        if(!dbus_message_get_args(m, &error,
                                  DBUS_TYPE_STRING, &name,
                                  DBUS_TYPE_INVALID)) {
            ret = dbus_message_new_error(m, DBUS_ERROR_INVALID_ARGS , "wrong arguments");
            goto finish;
        }

        ret = dbus_message_new_method_return(m);

        desc = sched->get_config_description(name);
        if(desc) {
            dbus_message_append_args(ret,
                                     DBUS_TYPE_STRING, &desc,
                                     DBUS_TYPE_INVALID);
            g_free(desc);
        }

        goto finish;

    } else if (dbus_message_is_method_call(m, DBUS_INTERFACE_PROPERTIES, "Get")) {
        const char *interface, *property;
        u_scheduler *sched = scheduler_get();

        if (!dbus_message_get_args(m, &error,
                                      DBUS_TYPE_STRING, &interface,
                                      DBUS_TYPE_STRING, &property,
                                      DBUS_TYPE_INVALID)) {
            g_warning("Failed to parse property get call: %s\n", error.message);
            ret = dbus_message_new_error(m, error.name, error.message);
            goto finish;
        }

        if (g_strcmp0(interface, U_DBUS_SYSTEM_INTERFACE) == 0) {

            ret = dbus_message_new_method_return(m);

            if(g_strcmp0(property, "config") == 0) {
                if(sched->get_config) {
                    char *tmp = sched->get_config();
                    if(tmp) {
                        dbus_message_append_args (ret,
                                                  DBUS_TYPE_STRING, &tmp,
                                                  DBUS_TYPE_INVALID);
                    }
                    g_free(tmp);
                }
                goto finish;
            } else if(g_strcmp0(property, "version") == 0) {
                const char *tmp = QUOTEME(VERSION);
                dbus_message_append_args (ret,
                                          DBUS_TYPE_STRING, &tmp,
                                          DBUS_TYPE_INVALID);
                goto finish;
            }


            dbus_message_unref(ret);
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        } else    {
            return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
        }

    } else if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) {
        ret = dbus_message_new_method_return(m);
        dbus_message_append_args(ret,
                                 DBUS_TYPE_STRING, &INTROSPECT_XML_SYSTEM,
                                 DBUS_TYPE_INVALID);
    } else
        return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;


finish:
    if (ret) {
        dbus_connection_send(c, ret, NULL);
        dbus_message_unref(ret);
    }

    dbus_error_free(&error);
    return DBUS_HANDLER_RESULT_HANDLED;
}


void consolekit_init();
void systemd_init();

gboolean u_dbus_setup() {
    static const DBusObjectPathVTable utable = {
        .message_function = dbus_user_handler,
    };
    static const DBusObjectPathVTable stable = {
        .message_function = dbus_system_handler,
    };

    if(!U_dbus_connection) {
      g_warning("dbus connection missing. can't create dbus interface");
      return FALSE;
    }

    DBusError error;
    DBusConnection *c = dbus_g_connection_get_connection(U_dbus_connection);
    
    dbus_error_init(&error);

#ifdef DEVELOP_MODE
    if (dbus_bus_request_name(c, U_DBUS_SERVICE_NAME, DBUS_NAME_FLAG_REPLACE_EXISTING, &error) < 0) {
        g_warning("Failed to register name on bus: %s\n", error.message);
        goto fail;
    }
#else
    if (dbus_bus_request_name(c, U_DBUS_SERVICE_NAME, DBUS_NAME_FLAG_DO_NOT_QUEUE, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
        g_error("daemon already running, can't request: %s", U_DBUS_SERVICE_NAME);
    }
#endif

    dbus_connection_register_object_path(c, U_DBUS_USER_PATH, &utable, NULL);
    dbus_connection_register_object_path(c, U_DBUS_SYSTEM_PATH, &stable, NULL);

    //systemd_init();
    consolekit_init();

    return TRUE;

fail:
    dbus_error_free(&error);
    return FALSE;
}


Generated by  Doxygen 1.6.0   Back to index