1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4 * Copyright (C) 2008-2010 Peng Huang <shawn.p.huang@gmail.com>
5 * Copyright (C) 2008-2010 Red Hat, Inc.
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the
19 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20 * Boston, MA 02111-1307, USA.
24 #include <sys/types.h>
37 gchar **g_argv = NULL;
39 static gboolean daemonize = FALSE;
40 static gboolean single = FALSE;
41 static gboolean xim = FALSE;
42 static gboolean replace = FALSE;
43 static gboolean restart = FALSE;
44 static gchar *panel = "default";
45 static gchar *config = "default";
46 static gchar *desktop = "gnome";
47 gchar *g_address = "unix:tmpdir=/tmp";
48 gchar *g_cache = "auto";
49 gboolean g_mempro = FALSE;
50 gboolean g_verbose = FALSE;
51 gint g_dbus_timeout = 5000;
52 #ifdef G_THREADS_ENABLED
53 gint g_monitor_timeout = 0;
57 show_version_and_quit (void)
59 g_print ("%s - Version %s\n", g_get_application_name (), VERSION);
63 static const GOptionEntry entries[] =
65 { "version", 'V', G_OPTION_FLAG_NO_ARG, G_OPTION_ARG_CALLBACK, show_version_and_quit, "Show the application's version.", NULL },
66 { "daemonize", 'd', 0, G_OPTION_ARG_NONE, &daemonize, "run ibus as background process.", NULL },
67 { "single", 's', 0, G_OPTION_ARG_NONE, &single, "do not execute panel and config module.", NULL },
68 { "xim", 'x', 0, G_OPTION_ARG_NONE, &xim, "execute ibus XIM server.", NULL },
69 { "desktop", 'n', 0, G_OPTION_ARG_STRING, &desktop, "specify the name of desktop session. [default=gnome]", "name" },
70 { "panel", 'p', 0, G_OPTION_ARG_STRING, &panel, "specify the cmdline of panel program. pass 'disable' not to start a panel program.", "cmdline" },
71 { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "specify the cmdline of config program. pass 'disable' not to start a config program.", "cmdline" },
72 { "address", 'a', 0, G_OPTION_ARG_STRING, &g_address, "specify the address of ibus daemon.", "address" },
73 { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "if there is an old ibus-daemon is running, it will be replaced.", NULL },
74 { "cache", 't', 0, G_OPTION_ARG_STRING, &g_cache, "specify the cache mode. [auto/refresh/none]", NULL },
75 { "timeout", 'o', 0, G_OPTION_ARG_INT, &g_dbus_timeout, "dbus reply timeout in milliseconds.", "timeout [default is 2000]" },
76 #ifdef G_THREADS_ENABLED
77 { "monitor-timeout", 'j', 0, G_OPTION_ARG_INT, &g_monitor_timeout, "timeout of poll changes of engines in seconds. 0 to disable it. ", "timeout [default is 0]" },
79 { "mem-profile", 'm', 0, G_OPTION_ARG_NONE, &g_mempro, "enable memory profile, send SIGUSR2 to print out the memory profile.", NULL },
80 { "restart", 'R', 0, G_OPTION_ARG_NONE, &restart, "restart panel and config processes when they die.", NULL },
81 { "verbose", 'v', 0, G_OPTION_ARG_NONE, &g_verbose, "verbose.", NULL },
87 * @cmdline: An absolute path of the executable and its parameters, e.g. "/usr/lib/ibus/ibus-x11 --kill-daemon".
88 * @returns: TRUE if both parsing cmdline and executing the command succeed.
90 * Execute cmdline. Child process's stdin, stdout, and stderr are attached to /dev/null.
91 * You don't have to handle SIGCHLD from the child process since glib will do.
94 execute_cmdline (const gchar *cmdline)
100 GError *error = NULL;
101 if (!g_shell_parse_argv (cmdline, &argc, &argv, &error)) {
102 g_warning ("Can not parse cmdline `%s` exec: %s", cmdline, error->message);
103 g_error_free (error);
108 gboolean retval = g_spawn_async (NULL, argv, NULL,
109 G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
115 g_warning ("Can not execute cmdline `%s`: %s", cmdline, error->message);
116 g_error_free (error);
127 gint fdlimit = sysconf(_SC_OPEN_MAX);
129 while (fd < fdlimit) {
135 daemon (gint nochdir, gint noclose)
159 open("/dev/null",O_RDWR);
168 * @sig: the signal number, which is usually SIGUSR2.
170 * A signal handler for SIGUSR2 signal. Dump a summary of memory usage to stderr.
173 _sig_usr2_handler (int sig)
179 main (gint argc, gchar **argv)
181 setlocale (LC_ALL, "");
183 GOptionContext *context = g_option_context_new ("- ibus daemon");
184 g_option_context_add_main_entries (context, entries, "ibus-daemon");
186 g_argv = g_strdupv (argv);
187 GError *error = NULL;
188 if (!g_option_context_parse (context, &argc, &argv, &error)) {
189 g_printerr ("Option parsing failed: %s\n", error->message);
190 g_error_free (error);
195 g_mem_set_vtable (glib_mem_profiler_table);
196 signal (SIGUSR2, _sig_usr2_handler);
201 const gchar *username = ibus_get_user_name ();
202 uid_t uid = getuid ();
203 struct passwd *pwd = getpwuid (uid);
205 if (pwd == NULL || g_strcmp0 (pwd->pw_name, username) != 0) {
206 g_printerr ("Please run ibus-daemon with login user! Do not run ibus-daemon with sudo or su.\n");
211 /* daemonize process */
213 if (daemon (1, 0) != 0) {
214 g_printerr ("Can not daemonize ibus.\n");
219 /* create a new process group. this is important to kill all of its children by SIGTERM at a time in bus_ibus_impl_destroy. */
224 #ifdef G_THREADS_ENABLED
225 g_thread_init (NULL);
227 ibus_set_log_handler (g_verbose);
229 /* check if ibus-daemon is running in this session */
230 if (ibus_get_address () != NULL) {
231 IBusBus *bus = ibus_bus_new ();
233 if (ibus_bus_is_connected (bus)) {
235 g_printerr ("current session already has an ibus-daemon.\n");
238 ibus_bus_exit (bus, FALSE);
239 while (ibus_bus_is_connected (bus)) {
240 g_main_context_iteration (NULL, TRUE);
243 g_object_unref (bus);
248 /* execute config component */
249 if (g_strcmp0 (config, "default") == 0) {
250 BusComponent *component;
251 component = bus_registry_lookup_component_by_name (BUS_DEFAULT_REGISTRY, IBUS_SERVICE_CONFIG);
253 bus_component_set_restart (component, restart);
255 if (component == NULL || !bus_component_start (component, g_verbose)) {
256 g_printerr ("Can not execute default config program\n");
259 } else if (g_strcmp0 (config, "disable") != 0 && g_strcmp0 (config, "") != 0) {
260 if (!execute_cmdline (config))
264 /* execute panel component */
265 if (g_strcmp0 (panel, "default") == 0) {
266 BusComponent *component;
267 component = bus_registry_lookup_component_by_name (BUS_DEFAULT_REGISTRY, IBUS_SERVICE_PANEL);
269 bus_component_set_restart (component, restart);
271 if (component == NULL || !bus_component_start (component, g_verbose)) {
272 g_printerr ("Can not execute default panel program\n");
275 } else if (g_strcmp0 (panel, "disable") != 0 && g_strcmp0 (panel, "") != 0) {
276 if (!execute_cmdline (panel))
281 /* execute ibus xim server */
283 if (!execute_cmdline (LIBEXECDIR "/ibus-x11 --kill-daemon"))