Add new functions for retrieving running component context 05/203105/9
authorHwankyu Jhun <h.jhun@samsung.com>
Wed, 10 Apr 2019 02:16:29 +0000 (11:16 +0900)
committerHwankyu Jhun <h.jhun@samsung.com>
Mon, 22 Apr 2019 02:38:43 +0000 (11:38 +0900)
Adds:
 - aul_comp_context_foreach()
 - aul_comp_context_foreach_usr()
 - aul_comp_context_get_app_id()
 - aul_comp_context_get_instance_id()
 - aul_comp_context_get_comp_id()
 - aul_comp_context_get_type()
 - aul_comp_context_get_pid()
 - aul_comp_context_get_status()
 - aul_comp_context_is_sub_comp()

Requires:
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/aul-1/+/203105/
 - https://review.tizen.org/gerrit/#/c/platform/core/appfw/amd/+/204068/

Change-Id: Ic1757e8ccea42339677ccffe444ca56efc362300
Signed-off-by: Hwankyu Jhun <h.jhun@samsung.com>
CMakeLists.txt
include/aul_cmd.h
include/aul_comp_context.h [new file with mode: 0644]
include/aul_key.h
packaging/aul.spec
src/aul_cmd.c
src/aul_comp_context.c [new file with mode: 0644]
src/aul_comp_info.c
src/aul_comp_status.c
tool/CMakeLists.txt
tool/compmgr_tool.c [new file with mode: 0644]

index 07a1cfe..08ae927 100755 (executable)
@@ -70,6 +70,7 @@ SET(HEADERS_LIB_AUL
        aul_comp_status.h
        aul_app_group.h
        aul_comp_info.h
+       aul_comp_context.h
        )
 
 # Install headers, other files
index 12d93af..dbe6727 100755 (executable)
@@ -150,6 +150,7 @@ enum app_cmd {
        APP_GROUP_GET_LEADER_IDS = 117,
        APP_GROUP_GET_GROUP_INFO = 118,
        APP_GROUP_GET_IDLE_INFO = 119,
+       COMP_CONTEXT_FOREACH = 120,
 
        APP_CMD_MAX
 };
diff --git a/include/aul_comp_context.h b/include/aul_comp_context.h
new file mode 100644 (file)
index 0000000..15212ab
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <unistd.h>
+#include <stdbool.h>
+
+#include "aul.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief The component context handle.
+ * @since_tizen 5.5
+ */
+typedef struct aul_comp_context_s *aul_comp_context_h;
+
+/**
+ * @brief Called to get the component context for each component.
+ * @since_tizen 5.5
+ *
+ * @param[in]   handle          The component context handle
+ * @param[in]   user_data       The user data passed from the foreach function
+ * @return      @c true to continue with the next iteration of the loop, \n
+ *              otherwise @ false to break out of the loop
+ * @see aul_comp_context_foreach()
+ */
+typedef void (*aul_comp_context_cb)(aul_comp_context_h handle, void *user_data);
+
+/**
+ * @brief Retrieves all running components context.
+ * @since_tizen 5.5
+ *
+ * @param[in]   callback        The callback function to invoke
+ * @param[in]   user_data       The user data to be passed to the callback function
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ * @see aul_comp_context_cb()
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_comp_context_foreach(aul_comp_context_cb callback, void *user_data);
+
+/**
+ * @brief Gets the application ID of the component.
+ * @since_tizen 5.5
+ * @remarks You MUST NOT release @a app_id using free().
+ *
+ * @param[in]   handle          The component context handle
+ * @param[out]  app_id          The application ID of the component
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_comp_context_get_app_id(aul_comp_context_h handle, const char **app_id);
+
+/**
+ * @brief Gets the instance ID of the component.
+ * @since_tizen 5.5
+ * @remarks You MUST NOT release @a app_id using free().
+ *
+ * @param[in]   handle          The component context handle
+ * @param[out]  instance_id     The instance ID of the component
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_comp_context_get_instance_id(aul_comp_context_h handle,
+               const char **instance_id);
+
+/**
+ * @brief Gets the ID of the component.
+ * @since_tizen 5.5
+ * @remarks You MUST NOT release @a comp_id using free().
+ *
+ * @param[in]   handle          The component context handle
+ * @param[out]  comp_id         The ID of the component
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_comp_context_get_comp_id(aul_comp_context_h handle,
+               const char **comp_id);
+
+/**
+ * @brief Gets the type of the component.
+ * @since_tizen 5.5
+ * @remarks You MUST NOT release @a type using free().
+ *
+ * @param[in]   handle          The component context handle
+ * @param[out]  type            The type of the component
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_comp_context_get_type(aul_comp_context_h handle, const char **type);
+
+/**
+ * @brief Gets the process ID of the component.
+ * @since_tizen 5.5
+ *
+ * @param[in]   handle          The component context handle
+ * @param[out]  pid             The process ID of the component
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_comp_context_get_pid(aul_comp_context_h handle, pid_t *pid);
+
+/**
+ * @brief Gets the status of the component.
+ * @since_tizen 5.5
+ *
+ * @param[in]   handle          The component context handle
+ * @param[out]  status          The status of the component
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_comp_context_get_status(aul_comp_context_h handle, int *status);
+
+/**
+ * @brief Checks whether the component is sub component of the app group or not.
+ * @since_tizen 5.5
+ *
+ * @param[in]   handle          The component context handle
+ * @param[out]  is_sub_comp     @c true if the component is sub component, \n
+ *                              otherwise @c false
+ * @return      @c 0 on success,
+ *              otherwise a negative error value
+ *
+ * @remarks This function is only for App Framework internally.
+ */
+int aul_comp_context_is_sub_comp(aul_comp_context_h handle, bool *is_sub_comp);
+
+#ifdef __cplusplus
+}
+#endif
index 5988461..9530749 100644 (file)
  * @since_tizen 5.5
  */
 #define AUL_K_FG_FLAG                   "__AUL_FG_FLAG__"
+
+/**
+ * @brief Definition for AUL: The type of the component.
+ * @since_tizen 5.5
+ */
+#define AUL_K_COMPONENT_TYPE            "__AUL_COMPONENT_TYPE__"
+
+/**
+ * @breif Definition for AUL: The flag if it's 'true', the component is sub component of the group.
+ * @since_tizen 5.5
+ */
+#define AUL_K_IS_SUB_COMP                "__AUL_IS_SUB_COMP__"
index 2f1bc58..5192f1b 100755 (executable)
@@ -118,6 +118,7 @@ chsmack -a 'User::Home' %{TZ_SYS_DB}/.component.db-journal
 %{_bindir}/launch_app
 %{_bindir}/appid2pid
 %{_bindir}/launch_debug
+%{_bindir}/compmgr_tool
 %{_datadir}/aul/miregex/*
 %{_datadir}/aul/preexec_list.txt
 %{_datadir}/appsvc/*
index bb54372..7e39fa7 100755 (executable)
@@ -264,6 +264,8 @@ API const char *aul_cmd_convert_to_string(int cmd)
                return "APP_GROUP_GET_GROUP_INFO";
        case APP_GROUP_GET_IDLE_INFO:
                return "APP_GROUP_GET_IDLE_INFO";
+       case COMP_CONTEXT_FOREACH:
+               return "COMP_CONTEXT_FOREACH";
        default:
                return "CUSTOM_COMMAND";
        }
diff --git a/src/aul_comp_context.c b/src/aul_comp_context.c
new file mode 100644 (file)
index 0000000..6128929
--- /dev/null
@@ -0,0 +1,228 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+
+#include <bundle.h>
+#include <bundle_internal.h>
+
+#include "aul_comp_context.h"
+#include "aul_error.h"
+#include "aul_util.h"
+#include "aul_sock.h"
+#include "aul_api.h"
+#include "aul.h"
+
+struct aul_comp_context_s {
+       const char *comp_id;
+       const char *instance_id;
+       const char *app_id;
+       const char *type;
+       pid_t pid;
+       int status;
+       bool is_sub_comp;
+};
+
+struct cb_data_s {
+       aul_comp_context_cb callback;
+       void *user_data;
+};
+
+static void __running_context_cb(app_pkt_t *pkt, void *user_data)
+{
+       struct cb_data_s *cb_data = (struct cb_data_s *)user_data;
+       struct aul_comp_context_s context;
+       bundle *b = NULL;
+       const char *val;
+
+       if (!pkt || !cb_data) {
+               _E("Invalid parameter");
+               return;
+       }
+
+       if (pkt->cmd == APP_GET_INFO_ERROR) {
+               _E("Failed to get running component context");
+               return;
+       }
+
+       if (pkt->opt & AUL_SOCK_BUNDLE)
+               b = bundle_decode(pkt->data, pkt->len);
+
+       if (!b)
+               return;
+
+       val = bundle_get_val(b, AUL_K_PID);
+       if (!val) {
+               bundle_free(b);
+               return;
+       }
+       context.pid = atoi(val);
+
+       val = bundle_get_val(b, AUL_K_STATUS);
+       if (!val) {
+               bundle_free(b);
+               return;
+       }
+       context.status = atoi(val);
+
+       val = bundle_get_val(b, AUL_K_IS_SUB_COMP);
+       if (!val) {
+               bundle_free(b);
+               return;
+       }
+       context.is_sub_comp = atoi(val);
+
+       context.comp_id = bundle_get_val(b, AUL_K_COMPONENT_ID);
+       context.instance_id = bundle_get_val(b, AUL_K_INSTANCE_ID);
+       context.app_id = bundle_get_val(b, AUL_K_APPID);
+       context.type = bundle_get_val(b, AUL_K_COMPONENT_TYPE);
+
+       cb_data->callback(&context, cb_data->user_data);
+       bundle_free(b);
+}
+
+API int aul_comp_context_foreach(aul_comp_context_cb callback,
+               void *user_data)
+{
+       struct cb_data_s cb_data = {
+               callback,
+               user_data
+       };
+       char buf[32];
+       bundle *b;
+       int ret;
+       int fd;
+
+       if (!callback) {
+               _E("Invalid parameter");
+               return AUL_R_EINVAL;
+       }
+
+       b = bundle_create();
+       if (!b) {
+               _E("Out of memory");
+               return AUL_R_ERROR;
+       }
+
+       snprintf(buf, sizeof(buf), "%d", getuid());
+       bundle_add(b, AUL_K_TARGET_UID, buf);
+
+       fd = aul_sock_send_bundle(AUL_UTIL_PID, getuid(), COMP_CONTEXT_FOREACH,
+                       b, AUL_SOCK_ASYNC);
+       bundle_free(b);
+       if (fd < 0)
+               return aul_error_convert(fd);
+
+       ret = aul_sock_recv_pkt_with_cb(fd, __running_context_cb, &cb_data);
+       if (ret < 0)
+               return aul_error_convert(ret);
+
+       return AUL_R_OK;
+}
+
+API int aul_comp_context_get_comp_id(aul_comp_context_h context,
+               const char **comp_id)
+{
+       if (!context || !comp_id) {
+               _E("Invalid parameter");
+               return AUL_R_EINVAL;
+       }
+
+       *comp_id = context->comp_id;
+
+       return AUL_R_OK;
+}
+
+API int aul_comp_context_get_instance_id(aul_comp_context_h context,
+               const char **instance_id)
+{
+       if (!context || !instance_id) {
+               _E("Invalid parameter");
+               return AUL_R_EINVAL;
+       }
+
+       *instance_id = context->instance_id;
+
+       return AUL_R_OK;
+}
+
+API int aul_comp_context_get_app_id(aul_comp_context_h context,
+               const char **app_id)
+{
+       if (!context || !app_id) {
+               _E("Invalid parameter");
+               return AUL_R_EINVAL;
+       }
+
+       *app_id = context->app_id;
+
+       return AUL_R_OK;
+}
+
+API  int aul_comp_context_get_type(aul_comp_context_h context,
+               const char **type)
+{
+       if (!context || !type) {
+               _E("Invalid parameter");
+               return AUL_R_EINVAL;
+       }
+
+       *type = context->type;
+
+       return AUL_R_OK;
+}
+
+API int aul_comp_context_get_pid(aul_comp_context_h context,
+               pid_t *pid)
+{
+       if (!context || !pid) {
+               _E("Invalid parameter");
+               return AUL_R_EINVAL;
+       }
+
+       *pid = context->pid;
+
+       return AUL_R_OK;
+}
+
+API int aul_comp_context_get_status(aul_comp_context_h context,
+               int *status)
+{
+       if (!context || !status) {
+               _E("Invalid parameter");
+               return AUL_R_EINVAL;
+       }
+
+       *status = context->status;
+
+       return AUL_R_OK;
+}
+
+API int aul_comp_context_is_sub_comp(aul_comp_context_h context,
+               bool *is_sub_comp)
+{
+       if (!context || !is_sub_comp) {
+               _E("Invalid parameter");
+               return AUL_R_EINVAL;
+       }
+
+       *is_sub_comp = context->is_sub_comp;
+
+       return AUL_R_OK;
+}
index 4c052e0..9e90f08 100644 (file)
@@ -47,8 +47,8 @@ enum aul_comp_info_e {
        AUL_COMP_INFO_MAIN_COMP,
        AUL_COMP_INFO_ICON_DISPLAY,
        AUL_COMP_INFO_TASKMANAGE,
-       AUL_COMP_INFO_ICON,
        AUL_COMP_INFO_LABEL,
+       AUL_COMP_INFO_ICON,
        AUL_COMP_INFO_MAX,
 };
 
index f0dbaf2..8e72aa4 100644 (file)
 #define _GNU_SOURCE
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdbool.h>
 
 #include <bundle.h>
 #include <bundle_internal.h>
 
+#include "aul_comp_status.h"
 #include "aul_util.h"
 #include "aul_sock.h"
 #include "aul_api.h"
index e2ddefb..fd4c5d7 100644 (file)
@@ -40,3 +40,8 @@ add_executable(app_com_tool
                app_com_tool.c)
 target_link_libraries(app_com_tool aul ${pkgs_LDFLAGS} "-pie")
 INSTALL(TARGETS app_com_tool DESTINATION bin)
+
+add_executable(compmgr_tool
+               compmgr_tool.c)
+target_link_libraries(compmgr_tool aul ${pkgs_LDFLAGS} "-pie")
+INSTALL(TARGETS compmgr_tool DESTINATION bin)
diff --git a/tool/compmgr_tool.c b/tool/compmgr_tool.c
new file mode 100644 (file)
index 0000000..7c2c183
--- /dev/null
@@ -0,0 +1,370 @@
+/*
+ * Copyright (c) 2019 Samsung Electronics Co., Ltd All Rights Reserved
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdbool.h>
+#include <sys/types.h>
+#include <linux/limits.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <bundle_internal.h>
+#include <pkgmgr-info.h>
+
+#include "aul.h"
+#include "aul_comp_info.h"
+#include "aul_comp_context.h"
+
+enum command_e {
+       CMD_LIST,
+       CMD_RUNNING_LIST,
+       CMD_MAX,
+};
+
+enum option_e {
+       OPT_USER,
+       OPT_MAX,
+};
+
+struct command {
+       const char *name;
+       int (*init)(void *data);
+       int (*run)(void *data);
+       void (*finish)(void *data);
+};
+
+static GMainLoop *loop;
+static gchar *help;
+static gpointer cmd_opt[CMD_MAX];
+static GOptionEntry cmd_entries[] = {
+       {
+               .long_name = "list",
+               .short_name = 'l',
+               .flags = 0,
+               .arg = G_OPTION_ARG_NONE,
+               .arg_data = &cmd_opt[CMD_LIST],
+               .description = "Show installed component list",
+               .arg_description = NULL
+       },
+       {
+               .long_name = "running-list",
+               .short_name = 'r',
+               .flags = 0,
+               .arg = G_OPTION_ARG_NONE,
+               .arg_data = &cmd_opt[CMD_RUNNING_LIST],
+               .description = "Show the running components information",
+               .arg_description = NULL
+       },
+       {
+               NULL
+       }
+};
+static gpointer opt[OPT_MAX];
+static GOptionEntry opt_entries[] = {
+       {
+               .long_name = "user",
+               .short_name = 'u',
+               .flags = 0,
+               .arg = G_OPTION_ARG_INT,
+               .arg_data = &opt[OPT_USER],
+               .description = "Specify the user ID",
+               .arg_description = "USER ID"
+       },
+       {
+               NULL
+       }
+};
+
+static GOptionGroup *__get_opt_group(void)
+{
+       GOptionGroup *group;
+
+       group = g_option_group_new("option", "Additional Options:",
+                       "Additional options", NULL, NULL);
+       if (!group)
+               return NULL;
+
+       g_option_group_add_entries(group, opt_entries);
+
+       return group;
+}
+
+static void __cmd_common_finish(void *data)
+{
+       g_main_loop_quit(loop);
+}
+
+static bool __comp_info_cb(aul_comp_info_h handle, void *user_data)
+{
+       int *member_count = (int *)user_data;
+       const char *comp_id = NULL;
+       const char *type = NULL;
+       const char *launch_mode = NULL;
+       bool main_comp = false;
+       bool icon_display = false;
+       bool taskmanage = false;
+       const char *icon = NULL;
+       const char *label = NULL;
+       const char *boolean_string[] = {
+               "false",
+               "true",
+       };
+
+       aul_comp_info_get_comp_id(handle, &comp_id);
+       aul_comp_info_get_type(handle, &type);
+       aul_comp_info_get_launch_mode(handle, &launch_mode);
+       aul_comp_info_is_main_comp(handle, &main_comp);
+       aul_comp_info_is_icon_display(handle, &icon_display);
+       aul_comp_info_is_taskmanage(handle, &taskmanage);
+       aul_comp_info_get_icon(handle, &icon);
+       aul_comp_info_get_label(handle, &label);
+
+       (*member_count)++;
+       printf("----------------------------------\n");
+       printf("--- Member       : %d\n", *member_count);
+       printf("  - ID           : %s\n", comp_id);
+       printf("  - Type         : %s\n", type);
+       printf("  - Launch Mode  : %s\n", launch_mode);
+       printf("  - Main Comp    : %s\n", boolean_string[main_comp]);
+       printf("  - TaskManage   : %s\n", boolean_string[taskmanage]);
+       printf("  - Icon Display : %s\n", boolean_string[icon_display]);
+       printf("  - Icon         : %s\n", icon ? icon : "");
+       printf("  - Label        : %s\n", label ? label : "");
+       printf("\n");
+
+       return true;
+}
+
+static int __installed_list_cb(const pkgmgrinfo_appinfo_h handle, void *data)
+{
+       uid_t uid = GPOINTER_TO_UINT(data);
+       char *comp_type = NULL;
+       char *appid = NULL;
+       int member_count = 0;
+       int ret;
+
+       pkgmgrinfo_appinfo_get_component_type(handle, &comp_type);
+       if (comp_type && strcmp(comp_type, "componentbasedapp") != 0)
+               return 0;
+
+       pkgmgrinfo_appinfo_get_appid(handle, &appid);
+       if (!appid)
+               return -1;
+
+       printf("----------------------------------\n");
+       printf("< Application : %s >\n", appid);
+       ret = aul_comp_info_foreach_usr(appid, uid, __comp_info_cb,
+                       (void *)&member_count);
+       if (ret < 0) {
+               fprintf(stderr, "Failed to retrieve component info. %s:%u\n",
+                               appid, uid);
+               return -1;
+       }
+       printf("Member count  : %d\n", member_count);
+       printf("\n");
+
+       return 0;
+}
+
+static int __cmd_list_run(void *data)
+{
+       uid_t uid;
+       int ret;
+
+       if (opt[OPT_USER])
+               uid = GPOINTER_TO_UINT(opt[OPT_USER]);
+       else
+               uid = getuid();
+
+       ret = pkgmgrinfo_appinfo_get_usr_installed_list(__installed_list_cb,
+                       uid, GUINT_TO_POINTER(uid));
+       if (ret == PMINFO_R_OK) {
+               printf("==================================\n");
+               printf("\n");
+       }
+
+       return ret;
+}
+
+static const char *__get_status_string(int status)
+{
+       switch (status) {
+       case STATUS_LAUNCHING:
+               return "STATUS_LAUNCHING";
+       case STATUS_CREATED:
+               return "STATUS_CREATED";
+       case STATUS_FOCUS:
+               return "STATUS_FOCUS";
+       case STATUS_VISIBLE:
+               return "STATUS_VISIBLE";
+       case STATUS_BG:
+               return "STATUS_BG";
+       case STATUS_DYING:
+               return "STATUS_DYING";
+       default:
+               return "Unknown Status";
+       }
+}
+
+static void __comp_context_cb(aul_comp_context_h handle, void *user_data)
+{
+       int *member_count = (int *)user_data;
+       const char *app_id = NULL;
+       const char *instance_id = NULL;
+       const char *comp_id = NULL;
+       const char *type = NULL;
+       pid_t pid = -1;
+       int status = -1;
+       bool is_sub_comp = false;
+
+       aul_comp_context_get_app_id(handle, &app_id);
+       aul_comp_context_get_instance_id(handle, &instance_id);
+       aul_comp_context_get_comp_id(handle, &comp_id);
+       aul_comp_context_get_type(handle, &type);
+       aul_comp_context_get_pid(handle, &pid);
+       aul_comp_context_get_status(handle, &status);
+       aul_comp_context_is_sub_comp(handle, &is_sub_comp);
+
+       (*member_count)++;
+       printf("----------------------------------\n");
+       printf("< Member : %d >\n", *member_count);
+       printf("--- ID             : %s\n", comp_id);
+       printf("  - Instance ID    : %s\n", instance_id);
+       printf("  - Application ID : %s\n", app_id);
+       printf("  - Type           : %s\n", type);
+       printf("  - Process ID     : %d\n", pid);
+       printf("  - Status         : %s\n", __get_status_string(status));
+       printf("  - Sub Component  : %s\n", is_sub_comp ? "true" : "false");
+}
+
+static int __cmd_running_list_run(void *data)
+{
+       int member_count = 0;
+       int ret;
+
+       ret = aul_comp_context_foreach(__comp_context_cb,
+                       (void *)&member_count);
+       if (ret == AUL_R_OK) {
+               printf("==================================\n");
+               printf("\n");
+               printf("Component count : %d\n", member_count);
+       }
+
+       return ret;
+}
+
+static struct command cmd_table[] = {
+       [CMD_LIST] = {
+               .name = "list",
+               .init = NULL,
+               .run = __cmd_list_run,
+               .finish = __cmd_common_finish
+       },
+       [CMD_RUNNING_LIST] = {
+               .name = "running-list",
+               .init = NULL,
+               .run = __cmd_running_list_run,
+               .finish = __cmd_common_finish
+       },
+};
+
+static struct command *__find_cmd(void)
+{
+       int i;
+
+       for (i = 0; i < G_N_ELEMENTS(cmd_table); ++i) {
+               if (cmd_opt[i])
+                       return &cmd_table[i];
+       }
+
+       return NULL;
+}
+
+static gboolean __run_cmd(gpointer data)
+{
+       struct command *cmd;
+       int result;
+
+       cmd = __find_cmd();
+       if (cmd == NULL) {
+               printf("%s", help);
+               g_main_loop_quit(loop);
+               return G_SOURCE_REMOVE;
+       }
+
+       if (cmd->init) {
+               result = cmd->init(data);
+               if (result != 0) {
+                       g_main_loop_quit(loop);
+                       return G_SOURCE_REMOVE;
+               }
+       }
+
+       if (cmd->run) {
+               result = cmd->run(data);
+               if (result != 0) {
+                       g_main_loop_quit(loop);
+                       return G_SOURCE_REMOVE;
+               }
+       }
+
+       if (cmd->finish)
+               cmd->finish(data);
+
+       return G_SOURCE_REMOVE;
+}
+
+int main(int argc, char *argv[])
+{
+       GOptionContext *context;
+       GOptionGroup *opt_group;
+       GError *error = NULL;
+
+       context = g_option_context_new(NULL);
+       g_option_context_add_main_entries(context, cmd_entries, NULL);
+
+       opt_group = __get_opt_group();
+       if (!opt_group) {
+               printf("Failed to get opt group\n");
+               g_option_context_free(context);
+               return -1;
+       }
+       g_option_context_add_group(context, opt_group);
+
+       if (!g_option_context_parse(context, &argc, &argv, &error)) {
+               printf("%s: %s\n", argv[0], error->message);
+               g_option_context_free(context);
+               g_clear_error(&error);
+               return -1;
+       }
+
+       help = g_option_context_get_help(context, TRUE, NULL);
+       g_option_context_free(context);
+
+       g_idle_add(__run_cmd, NULL);
+       loop = g_main_loop_new(NULL, FALSE);
+       if (!loop) {
+               printf("Failed to create glib main loop\n");
+               exit(EXIT_FAILURE);
+       }
+       g_main_loop_run(loop);
+       g_main_loop_unref(loop);
+       free(help);
+
+       return 0;
+}