Fix some compile problems with Sun C compiler.
[platform/upstream/ibus.git] / bus / main.c
1 /* vim:set et sts=4: */
2 /* ibus - The Input Bus
3  * Copyright (C) 2008-2009 Huang Peng <shawn.p.huang@gmail.com>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.     See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18  * Boston, MA 02111-1307, USA.
19  */
20 #include <config.h>
21 #include <unistd.h>
22 #include <sys/types.h>
23 #include <sys/stat.h>
24 #include <fcntl.h>
25 #include <pwd.h>
26 #include <stdlib.h>
27 #include <locale.h>
28 #include "server.h"
29 #include "ibusimpl.h"
30
31 gchar **g_argv = NULL;
32
33 static gboolean daemonize = FALSE;
34 static gboolean single = FALSE;
35 static gboolean xim = FALSE;
36 static gboolean replace = FALSE;
37 static gchar *panel = "default";
38 static gchar *config = "default";
39 static gchar *desktop = "gnome";
40 static gchar *address = "";
41 gboolean g_rescan = FALSE;
42 static gboolean verbose = FALSE;
43
44 static const GOptionEntry entries[] =
45 {
46     { "daemonize", 'd', 0, G_OPTION_ARG_NONE, &daemonize, "run ibus as background process.", NULL },
47     { "single", 's', 0, G_OPTION_ARG_NONE, &single, "do not execute panel and config module.", NULL },
48     { "xim", 'x', 0, G_OPTION_ARG_NONE, &xim, "execute ibus XIM server.", NULL },
49     { "desktop", 'n', 0, G_OPTION_ARG_STRING, &desktop, "specify the name of desktop session. [default=gnome]", "name" },
50     { "panel", 'p', 0, G_OPTION_ARG_STRING, &panel, "specify the cmdline of panel program.", "cmdline" },
51     { "config", 'c', 0, G_OPTION_ARG_STRING, &config, "specify the cmdline of config program.", "cmdline" },
52     { "address", 'a', 0, G_OPTION_ARG_STRING, &address, "specify the address of ibus daemon.", "address" },
53     { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace, "if there is an old ibus-daemon is running, it will be replaced.", NULL },
54     { "re-scan", 't', 0, G_OPTION_ARG_NONE, &g_rescan, "force to re-scan components, and re-create registry cache.", NULL },
55     { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "verbose.", NULL },
56     { NULL },
57 };
58
59 static gboolean
60 execute_cmdline (const gchar *cmdline)
61 {
62     g_assert (cmdline);
63
64     gint argc;
65     gchar **argv;
66     gboolean retval;
67     GError *error;
68
69     error = NULL;
70     if (!g_shell_parse_argv (cmdline, &argc, &argv, &error)) {
71         g_warning ("Can not parse cmdline `%s` exec: %s", cmdline, error->message);
72         g_error_free (error);
73         return FALSE;
74     }
75
76     error = NULL;
77     retval = g_spawn_async (NULL, argv, NULL,
78                             G_SPAWN_STDOUT_TO_DEV_NULL | G_SPAWN_STDERR_TO_DEV_NULL,
79                             NULL, NULL,
80                             NULL, &error);
81     g_strfreev (argv);
82
83     if (!retval) {
84         g_warning ("Can not execute cmdline `%s`: %s", cmdline, error->message);
85         g_error_free (error);
86         return FALSE;
87     }
88
89     return TRUE;
90 }
91
92 #ifndef HAVE_DAEMON
93 void closeall(int fd)
94 {
95     int fdlimit = sysconf(_SC_OPEN_MAX);
96
97     while (fd < fdlimit)
98       close(fd++);
99 }
100
101 int daemon(int nochdir, int noclose)
102 {
103     switch (fork())
104     {
105         case 0:  break;
106         case -1: return -1;
107         default: _exit(0);
108     }
109
110     if (setsid() < 0)
111       return -1;
112
113     switch (fork())
114     {
115         case 0:  break;
116         case -1: return -1;
117         default: _exit(0);
118     }
119
120     if (!nochdir)
121       chdir("/");
122
123     if (!noclose)
124     {
125         closeall(0);
126         open("/dev/null",O_RDWR);
127         dup(0); dup(0);
128     }
129
130     return 0;
131 }
132 #endif
133
134 gint
135 main (gint argc, gchar **argv)
136 {
137     GOptionContext *context;
138     BusServer *server;
139     IBusBus *bus;
140
141     GError *error = NULL;
142
143     setlocale (LC_ALL, "");
144
145     context = g_option_context_new ("- ibus daemon");
146
147     g_option_context_add_main_entries (context, entries, "ibus-daemon");
148
149     g_argv = g_strdupv (argv);
150     if (!g_option_context_parse (context, &argc, &argv, &error)) {
151         g_printerr ("Option parsing failed: %s\n", error->message);
152         exit (-1);
153     }
154
155     /* check uid */
156     {
157         const gchar *username = ibus_get_user_name ();
158         uid_t uid = getuid ();
159         struct passwd *pwd = getpwuid (uid);
160
161         if (pwd == NULL || strcmp (pwd->pw_name, username) != 0) {
162             g_printerr ("Please run ibus-daemon with login user! Do not run ibus-daemon with sudo or su.\n");
163             exit (-1);
164         }
165     }
166
167     /* daemonize process */
168     if (daemonize) {
169         if (daemon (1, 0) != 0) {
170             g_printerr ("Can not daemonize ibus.\n");
171             exit (-1);
172         }
173     }
174
175     /* create a new process group */
176     setpgrp ();
177
178     g_type_init ();
179
180     /* check if ibus-daemon is running in this session */
181     bus = ibus_bus_new ();
182
183     if (ibus_bus_is_connected (bus)) {
184         if (!replace) {
185             g_printerr ("current session already has an ibus-daemon.\n");
186             exit (-1);
187         }
188         ibus_bus_exit (bus, FALSE);
189         while (ibus_bus_is_connected (bus)) {
190             g_main_context_iteration (NULL, TRUE);
191         }
192     }
193     g_object_unref (bus);
194     bus = NULL;
195
196     /* create ibus server */
197     server = bus_server_get_default ();
198     bus_server_listen (server);
199
200     if (!single) {
201         /* execute config component */
202         if (g_strcmp0 (config, "default") == 0) {
203             IBusComponent *component;
204             component = bus_registry_lookup_component_by_name (BUS_DEFAULT_REGISTRY, IBUS_SERVICE_CONFIG);
205             if (component == NULL || !ibus_component_start (component)) {
206                 g_printerr ("Can not execute default config program\n");
207                 exit (-1);
208             }
209         } else if (g_strcmp0 (config, "disable") != 0 && g_strcmp0 (config, "") != 0) {
210             if (!execute_cmdline (config))
211                 exit (-1);
212         }
213
214         /* execut panel component */
215         if (g_strcmp0 (panel, "default") == 0) {
216             IBusComponent *component;
217             component = bus_registry_lookup_component_by_name (BUS_DEFAULT_REGISTRY, IBUS_SERVICE_PANEL);
218             if (component == NULL || !ibus_component_start (component)) {
219                 g_printerr ("Can not execute default panel program\n");
220                 exit (-1);
221             }
222         } else if (g_strcmp0 (panel, "disable") != 0 && g_strcmp0 (panel, "") != 0) {
223             if (!execute_cmdline (panel))
224                 exit (-1);
225         }
226     }
227
228     /* execute ibus xim server */
229     if (xim) {
230         if (!execute_cmdline (LIBEXECDIR"/ibus-x11 --kill-daemon"))
231             exit (-1);
232     }
233
234     bus_server_run (server);
235
236     return 0;
237 }