/*
 * dbus-daemon-proxy.c - Source for dbus-daemon-proxy
 * Copyright (C) 2010 Collabora Ltd.
 *   @author: Alban Crequy <alban.crequy@collabora.co.uk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <dbus/dbus.h>
#include <dbus/dbus-glib.h>
#include <dbus/dbus-glib-lowlevel.h>
#include <pwd.h>
#define DBUS_MESSAGE_PATH_COM(msg, path)           strcmp(dbus_message_get_path(msg), path) == 0
#define DBUS_MESSAGE_INTERFACE_COM(msg, interface) strcmp(dbus_message_get_interface(msg),interface) == 0
#define DBUS_MESSAGE_MEMBER_COM(msg, member)       strcmp(dbus_message_get_member(msg), member) == 0
#define DBSU_MESSAGE_DESTINATION_COM(msg, dest)    strcmp(dbus_message_get_destination(msg), dest) == 0

#define PROXY_CONFIG_FILE_PATH  "/opt/compatibility_layer/config/bus/confliction/"
#define SESSBUS_LIST  "dbus-sess-proxy.list"
#define SYSBUS_LIST  "dbus-sys-proxy.list"
#define ACTIVED_LIST_GROUP      "activeList"

struct dbusDaemonProxy
{
  DBusBusType type;
  gchar *host; 
  gchar *bind;
  gchar *port;
  gchar *family;
  gchar *address;
  gchar *namespace;
  gboolean verbose;
  gboolean trace;
  GList *nameList;
  int logfd;
};
typedef struct dbusDaemonProxy dbusDaemonProxy;

struct connPair
{
  DBusConnection *client_side;      //应用程序客户端
  DBusConnection *server_side;      //dbus-daemon
  dbusDaemonProxy *proxy;
  char *wellKnowName;  
};
typedef struct connPair connPair;

static connPair *conn_pair_new (DBusConnection *client)
{
  connPair *pair = malloc(sizeof(connPair));
  if(pair)
  {
    pair->client_side = client;
    pair->server_side = NULL;
    pair->wellKnowName = NULL;
    pair->proxy = NULL;
    return pair;
  }
  return NULL;
}

static void conn_pair_free (connPair *pair)
{

  dbus_connection_close (pair->client_side);
  dbus_connection_unref (pair->client_side);
  dbus_connection_close (pair->server_side);
  dbus_connection_unref (pair->server_side);

  if (pair->wellKnowName)
    free(pair->wellKnowName);
  if (pair)
    free(pair);
}

static void display_list(GList* list)
{
    GList *it = NULL;
    g_print("---------start----------\n");

    /* 遍历链表 */
    for (it = list; it; it = it->next) {
        g_print("%s\n", (char *)it->data);
    }
    g_print("----------end-----------\n");
}

static dbus_bool_t find_item (GList *list, void *data)
{
    GList *it = NULL;
    /* 遍历链表 */
    for (it = list; it; it = it->next) {
      if( strcmp(it->data, (char*)data) == 0)
      {
          return TRUE;
      }
    }
    return FALSE;
}

//处理activated类型的服务
static dbus_bool_t find_in_config_file(dbusDaemonProxy *proxy, const char *name, char **newName)
{
  char configfile[512] = {0};
  FILE *fp = NULL;
  char *value = NULL;
  char *key = NULL;
  char *keyptr = NULL;

  if(proxy->type == DBUS_BUS_SESSION)
    snprintf(configfile, sizeof(configfile), "%s%s", PROXY_CONFIG_FILE_PATH, SESSBUS_LIST);
  else
    snprintf(configfile, sizeof(configfile), "%s%s", PROXY_CONFIG_FILE_PATH, SYSBUS_LIST);

  fp = fopen(configfile, "rb");
  if(!fp)
  {
    g_printerr ("Cannot open activate list %s\n", configfile);
    return FALSE;
  }
  
  if(proxy->trace)
    g_print ("open activation file list %s succeed\n", configfile);

  while (!feof(fp) && !ferror(fp))
  {
    char line[256] = {0};
    char tmp_info[256] = {0};

    fgets(line, sizeof(line)-1, fp);
    strncpy(tmp_info, line, sizeof(tmp_info)-1);

    if(proxy->trace)
      g_print ("file line %s\n", tmp_info);

    key = strtok_r(tmp_info, "=", &keyptr);

    if ((key)
      && !strcmp(key, name))
    {
      value = &line[0] + strlen(key);
      char *out = strdup(++value);
      if(!out)
      {
        g_printerr ("parsing activate list for %s failed as oom\n", name);
        return FALSE;
      }

      if(proxy->verbose)
        g_print ("service %s is namespaced as %s\n", key, value);
      
      *newName = out;
      fclose(fp);
      return TRUE;
    }
  }

  fclose(fp);
  return FALSE;

  #if 0
  char** keylist = NULL;
  char* tmpgroup = NULL;
  int index = 0;
  int ret = -1;

  int id = kdk_conf_init(PROXY_CONFIG_FILE_PATH);
  if (0 >= id)
  {
    g_printerr ("kysdk-config Init config file %s failed\n", PROXY_CONFIG_FILE_PATH);
    goto exit;
  }

  char** grouplist = kdk_conf_list_group(id);
  if (!grouplist)
  {
    g_printerr ("kysdk-config list groups in file %s failed\n", PROXY_CONFIG_FILE_PATH);
    goto exit;
  }

  while ((tmpgroup = grouplist[index++]))
  {
    if (strcmp(tmpgroup, ACTIVED_LIST_GROUP) == 0)
    {
      keylist = kdk_conf_list_key(id, tmpgroup);
      char* tmpkey;
      int k_index = 0;
      while ((tmpkey = keylist[k_index++]))
      {
        if (strcmp(tmpkey, name) == 0)
        { 
          const char* tmpval = kdk_conf_get_value(id, tmpgroup, tmpkey);
          if (tmpval)
          {
            *newName = strdup(tmpval);
            ret = 0;
          }
        }
      }
      if (keylist)
        kdk_config_freeall(keylist);
    }
  }

exit:
  if (id > 0)
    kdk_conf_destroy(id);
  if (grouplist)
    kdk_config_freeall(grouplist);
  return ret;
  #endif
}

static int proxy_hello_call_for_client(connPair* pair, DBusMessage *msg)
{
  DBusMessage* welcome = NULL;
  /* our unique D-Bus name on the real bus */
  const gchar* dbus_local_name = NULL;
  guint32 serial;
  int r = -1;

  dbus_local_name = dbus_bus_get_unique_name(pair->server_side);
  if(!dbus_local_name)
  {
    g_printerr ("Cannot reply to Hello message as oom of new unique name\n");
    goto exit;
  }

  welcome = dbus_message_new_method_return (msg);
  if(!welcome)
  {
    g_printerr ("Cannot reply to Hello message as oom of new message\n");
    goto exit;
  }

  if (!dbus_message_append_args (welcome,
                                  DBUS_TYPE_STRING, 
                                  &dbus_local_name,
                                  DBUS_TYPE_INVALID))
  {
    g_printerr ("Cannot reply to Hello message as oom of new args\n");
    goto exit;
  }

  r = dbus_connection_send (pair->client_side, welcome, &serial) ? 0 : -1;
  
  if (pair->proxy->verbose)
    g_print ("[CLIENT:]Hello received and unique name %s is assigned, notify client %s\n", dbus_local_name, r ? "FAILED" : "SUCCEED");

exit:
  if(welcome)
    dbus_message_unref(welcome);
  
  return r;
}

static int proxy_request_name_call_for_client(connPair* pair, DBusMessage *msg)
{  
  const char* name = NULL;
  char wellName[512] = {0};
  dbus_uint32_t flags;
  guint32 serial;
  DBusError error;
  DBusMessage *reply = NULL;
  int r = -1;
  int retFromDaemon = DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER;

  dbus_error_init(&error);

  if (!dbus_message_get_args (msg, &error, 
                              DBUS_TYPE_STRING, &name, 
                              DBUS_TYPE_UINT32, &flags,
                              DBUS_TYPE_INVALID) )
  {
    g_print("[CLIENT:]Failed to get RequestName args\n");
    dbus_set_error (&error, DBUS_ERROR_INVALID_ARGS, "[CLIENT:]Failed to get RequestName args");
    goto exit;
  }

  if(!name)
  {
    g_print("[CLIENT:]Failed to get RequestName name arg, null\n");
    dbus_set_error (&error, DBUS_ERROR_INVALID_ARGS, "[CLIENT:]Failed to get RequestName name args, null");
    goto exit;
  }

  if(dbus_bus_name_has_owner(pair->server_side, name, &error))// wellknown name is taken, we should add namespace for it
  {
    snprintf(wellName, sizeof(wellName), "%s.%s", name, pair->proxy->namespace);
  }
  else
  {
    snprintf(wellName, sizeof(wellName), "%s", name);
  }

  if (pair->wellKnowName == NULL)//TODO 一个 client 会不会有多个 wellKnowName ？
  {
    pair->wellKnowName = strdup (wellName);
    if(!pair->wellKnowName)
    {
      dbus_set_error (&error, DBUS_ERROR_NO_MEMORY, "[CLIENT:]Failed to dup Requested Name %s", wellName);
      goto exit;
    }
    pair->proxy->nameList = g_list_append(pair->proxy->nameList, pair->wellKnowName);  //TODO list释放问题
  }

  retFromDaemon = dbus_bus_request_name(pair->server_side, wellName, flags, &error);
  if(-1 == retFromDaemon)//normally : [DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER, DBUS_REQUEST_NAME_REPLY_IN_QUEUE, DBUS_REQUEST_NAME_REPLY_EXISTS, DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER]
  {
    g_print("[CLIENT:]Failed to RequestName name %s, error: %s\n", wellName, error.message);
  }
  else
  {
    r = 0;
  }

exit:
  if(!r)
  {
    reply = dbus_message_new_method_return (msg);
    if (!reply
      || !dbus_message_append_args (reply, DBUS_TYPE_UINT32, &retFromDaemon, DBUS_TYPE_INVALID))
    {
      dbus_set_error (&error, DBUS_ERROR_NO_MEMORY, "[CLIENT:]Failed to proxy RequestName %s", wellName);
      r = -1;
    }

    if (pair->proxy->verbose)
      g_print("[CLIENT:]Client RequestName name %s SUCCEED\n", wellName);
  }

  if(r)
  {
    const char *client_id = dbus_message_get_sender(msg);
    g_print ("[CLIENT:] client %s request wellknown name [%s] failed\n", client_id ? client_id : "NULL", pair->wellKnowName ? pair->wellKnowName : "NULL");
    if (dbus_error_is_set (&error))//this case refer to dispatch.c dispatch()
    {
      reply = dbus_message_new_error (msg, error.name, error.message);
      dbus_error_free (&error);
    }
  }

  if(reply)
  {
    dbus_connection_send (pair->client_side, reply, &serial);
    dbus_message_unref(reply);
  }

  return r;
}


static int proxy_other_calls_for_client(connPair* pair, DBusMessage *msg)
{
  DBusMessage* reply = NULL;
  DBusError error;
  guint32 serial;
  char namespacedDestName[512] = {0};
  char* namespacedActivatableName = NULL;
  dbus_bool_t bRet = FALSE;

  dbus_error_init(&error);

  snprintf(namespacedDestName, sizeof(namespacedDestName), "%s.%s", dbus_message_get_destination(msg), pair->proxy->namespace);

  // 此处必须使用find_item，使用 g_list_find 会找不到，g_list_find的使用pair->wellKnowName去找，但是此时还不知道有没有
  bRet = find_item(pair->proxy->nameList, (void*)namespacedDestName);

  if (bRet)// The destination wellknown name is namespaced, redirect destination
  {
    if (!dbus_message_set_destination(msg, namespacedDestName))
    {
      g_printerr ("Cannot redirect requested-destination to %s for client call\n", namespacedDestName);
      goto error_reply;
    }

    if (pair->proxy->verbose) 
      g_print ("[CLIENT]normal dbus-call for namespaced service %s\n", namespacedDestName);
  }
  else if (TRUE == find_in_config_file(pair->proxy, dbus_message_get_destination(msg), &namespacedActivatableName)
    && !strncmp(namespacedActivatableName, namespacedDestName,strlen(namespacedDestName)))//This destination service maynot from RequestName, but from .service file activation
  {
    bRet = dbus_message_set_destination(msg, namespacedDestName);
      
    if(!bRet)
    {
      g_printerr ("Cannot redirect active-destination to %s for client call\n", namespacedDestName);
      goto error_reply;
    }

    if (pair->proxy->verbose) 
      g_print ("[CLIENT]normal dbus-call for namespaced activatable service %s\n", namespacedDestName);
  }  
  else
  {
    //normal call
    if (pair->proxy->verbose) 
      g_print ("[CLIENT]normal dbus-call for service %s\n", dbus_message_get_destination(msg));
  }

  if(namespacedActivatableName)
    free(namespacedActivatableName);

  return 0;

error_reply:
//msg from client will be blocked and error reply will be responsed by proxy
  dbus_set_error (&error, DBUS_ERROR_SERVICE_UNKNOWN, "[CLIENT:]Failed to proxy method-call for %s", namespacedDestName);
  reply = dbus_message_new_error (msg, error.name, error.message);
  dbus_error_free (&error);

  if(reply)
  {
    dbus_connection_send (pair->client_side, reply, &serial);
    dbus_message_unref(reply);
  }

  if(namespacedActivatableName)
    free(namespacedActivatableName);

  return -1;
}


static DBusHandlerResult filter_cb (DBusConnection* conn,
                                    DBusMessage* msg,
                                    void* user_data)
{
  gchar* marshalled = NULL;
  gint len;
  guint32 serial;
  connPair* pair = user_data;  

  if (pair->proxy->trace)
  {
    g_print ("[CLIENT:]pair.server = %p,pair.client = %p\n", pair->server_side, pair->client_side);
    g_print ("[CLIENT:]New message from client: type='%d' path='%s' iface='%s',"
             "member='%s',dest='%s'\n",
             dbus_message_get_type (msg),
             dbus_message_get_path (msg),
             dbus_message_get_interface (msg),
             dbus_message_get_member (msg),
             dbus_message_get_destination(msg));
  }
  
  if (dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL &&
      // DBUS_MESSAGE_PATH_COM(msg, DBUS_PATH_DBUS) &&
      // DBUS_MESSAGE_INTERFACE_COM(msg, DBUS_INTERFACE_DBUS) &&
      DBSU_MESSAGE_DESTINATION_COM(msg, DBUS_SERVICE_DBUS))
  {
    if (DBUS_MESSAGE_MEMBER_COM(msg, "Hello"))
    {
      proxy_hello_call_for_client(pair, msg);
      goto skip_send_to_server;
    }
    else if (DBUS_MESSAGE_MEMBER_COM (msg, "RequestName"))
    {
      //当前策略： 如果容器内 client 请求的服务名未被占用，则直接注册在 host 总线， 否则为 服务名添加 namespace 后，再注册在 host 总线，避免冲突
      //这样做主要为了和 dbus-daemon 解耦，尽量不改动 dbus-daemon !!!!，因此不再需要 dbus_message_set_namespace dbus_message_get_namespace 的调用了
      //未来可能会有问题的场景： 容器或host APP 作为client，访问容器内带namespace的服务——因此此时没有 dbus-daemon 做的映射了；这种场景目前的认知看应该不会出现，
      //因为一旦服务带了namespace ，意味着宿主机上一定有同名的服务存在，那策略就是优先使用宿主机的服务
      //如果后续有此种场景，那么我们在 proxy 与 daemon 间增加一个 dbus-daemon-agent ， 来管理服务映射
      proxy_request_name_call_for_client(pair, msg);
      goto skip_send_to_server;
    }
    //other calls to org.freedesktop.DBus will be sent, won't be skipped
  }

  else if (dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_SIGNAL &&
      DBUS_MESSAGE_INTERFACE_COM(msg, DBUS_INTERFACE_LOCAL) && 
      DBUS_MESSAGE_MEMBER_COM(msg, "Disconnected"))
  {
    /* connection was disconnected */
    GList* it = NULL;

    it = g_list_find(pair->proxy->nameList, pair->wellKnowName);
    if(it)
    {
      pair->proxy->nameList = g_list_remove(pair->proxy->nameList, pair->wellKnowName);
    }
    g_print ("[CLIENT:][%s]connection was disconnected\n", pair->wellKnowName ? pair->wellKnowName : "NULL");
    conn_pair_free(pair);
    goto skip_send_to_server;
  }

  else if (dbus_message_get_type (msg) == DBUS_MESSAGE_TYPE_METHOD_CALL)
  {
    if(proxy_other_calls_for_client(pair, msg))
      goto skip_send_to_server;
  }

  //send to server, which is dbus-daemon
  if (dbus_message_marshal (msg, &marshalled, &len))
    dbus_connection_send (pair->server_side, msg, &serial);

skip_send_to_server:
  if (marshalled != NULL)
    g_free (marshalled);

  return DBUS_HANDLER_RESULT_HANDLED;
}

static DBusHandlerResult master_filter_cb (DBusConnection* conn,
                                           DBusMessage* msg,
                                           void* user_data)
{
  gchar* marshalled = NULL;
  gint len;
  guint32 serial;
  connPair* pair = user_data;

  if (!pair->client_side)
    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;

  if (pair->proxy->trace)
  {
    g_print ("[SERVICE:]pair.server = %p,pair.client = %p\n", pair->server_side, pair->client_side);
    g_print ("[SERVICE:]New message from server: type='%d' path='%s' iface='%s'"
        " member='%s', dest='%s'\n",
        dbus_message_get_type (msg),
        dbus_message_get_path (msg),
        dbus_message_get_interface (msg),
        dbus_message_get_member (msg),
        dbus_message_get_destination(msg));
  }

  if (!dbus_message_marshal (msg, &marshalled, &len))
    goto out;

  dbus_connection_send (pair->client_side, msg, &serial);
out:
  if (marshalled != NULL)
    g_free (marshalled);
  
  return DBUS_HANDLER_RESULT_HANDLED;
}

static dbus_bool_t allow_all_connections (DBusConnection* conn,
                                          unsigned long uid,
                                          void* data)
{
  return TRUE;
}

static void new_connection_cb (DBusServer* server,
                               DBusConnection* conn,
                               void* data)
{
  GError* gError = NULL;
  DBusGConnection* master_conn = NULL;
  dbusDaemonProxy* proxy = data;
  connPair* pair = NULL;

  if (proxy->trace) 
    g_print ("New connection\n");

  pair = conn_pair_new(conn);
  if (pair == NULL)
  {    
    goto exception;
  }
    
  master_conn = dbus_g_bus_get_private (proxy->type, NULL, &gError);
  if (!master_conn)
  {
    g_printerr ("Failed to open connection to %s bus: %s\n",
                proxy->type == DBUS_BUS_SESSION? "session" : "system",
                gError->message);
    g_clear_error(&gError);
    goto exception;
  }

  dbus_connection_add_filter (dbus_g_connection_get_connection (master_conn),
                              master_filter_cb, (void*)pair, NULL);//TODO 添加 free_data_func 
  pair->server_side = dbus_g_connection_get_connection (master_conn);
  pair->proxy = proxy;

  dbus_connection_ref (pair->client_side);
  dbus_connection_setup_with_g_main (pair->client_side, NULL);
  dbus_connection_add_filter (pair->client_side, filter_cb, (void*)pair, NULL);//确定一个用户ID是否允许连接 TODO 添加 free_data_func 
  dbus_connection_set_unix_user_function (pair->client_side, allow_all_connections, 
                                          NULL, NULL);
  dbus_connection_set_allow_anonymous (pair->client_side, TRUE);//允许匿名连接（TODO）

  return;

exception:
  if(pair)
    free(pair);//TODO  replaced with conn_pair_free
}

void start_bus (dbusDaemonProxy* proxy)
{
  /* the address that we are listening for D-Bus connections on */
  gchar* dbus_srv_addr;

  /* the server that's listening on dbus_srv_addr */
  DBusServer* dbus_srv;
  DBusError error;

  dbus_error_init (&error);


  dbus_srv_addr = g_strdup_printf
    ("tcp:host=%s,bind=%s,port=%s,family=%s",
     proxy->host?:"localhost", proxy->bind?:"*", proxy->port?:"8080", proxy->family?:"ipv4");
  g_print ("Listen on address: %s\n", dbus_srv_addr);

  dbus_srv = dbus_server_listen (dbus_srv_addr, &error);
  if (dbus_srv == NULL)
  {
    g_printerr ("Cannot listen on '%s'\n", dbus_srv_addr);
    if(proxy->logfd >= 0)
      close (proxy->logfd);
    exit (1);
  }
  dbus_server_set_new_connection_function (dbus_srv,
                                           new_connection_cb,
                                           proxy, NULL);
  dbus_server_setup_with_g_main (dbus_srv, NULL);
  g_free (dbus_srv_addr);
}

static void usage (char* name, int ecode)
{
  g_printerr ("Usage: %s [--system | --session | --address ADDRESS]\n", name);
  g_printerr ("        [--host <host>]\n");
  g_printerr ("        [--bind <bind>]\n");
  g_printerr ("        [--port <port>]\n");
  g_printerr ("        [--namespace <namespace>]\n");
  g_printerr ("        [--family <family>]\n");
  g_printerr ("\n");
  g_printerr ("port\n");
  exit (ecode);
}

int verify_file(char* const filename) {
  size_t len = strlen(filename);
  if(len  < 6) {
    g_printerr ("logfd file error...'%s'\n", filename);
    return -1;
  }
  else if (strncmp(filename, "/home/", 6) == 0) {
    return 0;
  }

  return -1;
}

int main (int argc, char* argv[])
{
  char* address = NULL;
  gchar* host = NULL;
  gchar* bind = NULL;
  gchar* port = NULL;
  gchar* family = NULL;
  int i;
  int logfd = 0;
  GError* error = NULL;
  GMainLoop* mainloop = NULL;

  dbusDaemonProxy proxy = {
    .type = DBUS_BUS_SESSION,
    .bind = NULL,
    .family = NULL,
    .host = NULL,
    .port = NULL,
    .address = NULL,
    .verbose = FALSE,
    .trace = FALSE,
    .namespace = "docker",
    .nameList = NULL,
    .logfd = -1
  };

  for (i = 1; i < argc; i++)
  {
    char* arg = argv[i];

    if (!strcmp (arg, "--system"))
      proxy.type = DBUS_BUS_SYSTEM;
    else if (!strcmp (arg, "--session"))
      proxy.type = DBUS_BUS_SESSION;
    else if (!strcmp (arg, "--address"))
    {
      if (i+1 < argc)
      {
        proxy.address = argv[i+1];
        i++;
      }
      else
        usage (argv[0], 1);
    }
    else if (!strcmp (arg, "--host"))
    {
      if (i+1 < argc)
      {
        proxy.host = argv[i+1];
        i++;
      }
      else
        usage (argv[0], 1);
    }
    else if (!strcmp (arg, "--bind"))
    {
      if (i+1 < argc)
      {
        proxy.bind = argv[i+1];
        i++;
      }
      else
        usage (argv[0], 1);
    }
    else if (!strcmp (arg, "--port"))
    {
      if (i+1 < argc)
      {
        proxy.port = argv[i+1];
        i++;
      }
      else
        usage (argv[0], 1);
    }
    else if (!strcmp (arg, "--family"))
    {
      if (i+1 < argc)
      {
        proxy.family = argv[i+1];
        i++;
      }
      else
        usage (argv[0], 1);
    }
    else if (!strcmp (arg, "--namespace"))
    {
      if (i+1 < argc)
      {
        proxy.namespace = argv[i+1];
        i++;
      }
      else
        usage (argv[0], 1);
    }
    else if (!strcmp (arg, "--verbose"))
    {
      if(DBUS_BUS_SYSTEM == proxy.type)
      {        
        logfd = open("/var/log/kare-dbus-proxy-sys.log", O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
      }
      else
      {
        struct passwd *pwd = getpwuid(getuid());
        if (pwd == NULL) {
            return 0;
        }
        char*home = pwd->pw_dir;
        if(home)
        {
          char logfile[512] = {0};
          snprintf(logfile, sizeof(logfile), "%s/kare-dbus-proxy-sess.log", home);
          char resolved_path[1024];
          char *result = realpath(logfile, resolved_path);
          if (result !=  NULL) {
            if (!verify_file(resolved_path)) {
              logfd = open(logfile, O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
            }
            else {
              logfd = open("/tmp/kare-dbus-proxy-sess.log", O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
              g_printerr ("RealPath does not start with /home/: '%s'\n", resolved_path);
            }
          }
          else {
            logfd = open("/tmp/kare-dbus-proxy-sess.log", O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
            g_printerr ("Cannot Use RealPath Function.\n");
          }
        }
        else
          logfd = open("/tmp/kare-dbus-proxy-sess.log", O_CREAT | O_RDWR | O_APPEND, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
      }

      if(-1 == logfd)
        g_print ("open /tmp/kare-dbus-proxy-XXX.log failed\n");
      else
      {
				dup2(logfd, 2);
				dup2(logfd, 1);        
      }
      proxy.logfd = logfd;
      proxy.verbose = TRUE;
    }
    else if (!strcmp (arg, "--trace"))
      proxy.trace = TRUE;

    else
      usage (argv[0], 1);
  }

  start_bus (&proxy);
  mainloop = g_main_loop_new (NULL, FALSE);
  g_main_loop_run (mainloop);
  g_list_free (proxy.nameList);
  close(logfd);
  return 0;
}

