aul_comp_status.h
aul_app_group.h
aul_comp_info.h
+ aul_comp_context.h
)
# Install headers, other files
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
};
--- /dev/null
+/*
+ * 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
* @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__"
%{_bindir}/launch_app
%{_bindir}/appid2pid
%{_bindir}/launch_debug
+%{_bindir}/compmgr_tool
%{_datadir}/aul/miregex/*
%{_datadir}/aul/preexec_list.txt
%{_datadir}/appsvc/*
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";
}
--- /dev/null
+/*
+ * 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;
+}
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,
};
#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"
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)
--- /dev/null
+/*
+ * 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;
+}