9215369b9c4064562dc15da7ba049c06c13c3db5
[platform/upstream/ibus.git] / src / ibusshare.c
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.
6  *
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.
11  *
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.
16  *
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.
21  */
22
23 #include "ibusshare.h"
24 #include <glib.h>
25 #include <glib/gstdio.h>
26 #include <glib-object.h>
27 #include <sys/time.h>
28 #include <sys/types.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <ibus.h>
34
35 static gchar *_display = NULL;
36
37 const gchar *
38 ibus_get_local_machine_id (void)
39 {
40     static gchar *machine_id = NULL;
41
42     if (machine_id == NULL) {
43         GError *error = NULL;
44         if (!g_file_get_contents ("/var/lib/dbus/machine-id",
45                                   &machine_id,
46                                   NULL,
47                                   &error)) {
48             g_warning ("Unable to load /var/lib/dbus/machine-id: %s", error->message);
49             g_error_free (error);
50             machine_id = "machine-id";
51         }
52         else {
53             g_strstrip (machine_id);
54         }
55     }
56
57     return machine_id;
58 }
59
60 void
61 ibus_set_display (const gchar *display)
62 {
63     if (_display != NULL)
64         g_free (_display);
65     _display = g_strdup (display);
66 }
67
68 const gchar *
69 ibus_get_user_name (void)
70 {
71     return g_get_user_name ();
72 #if 0
73     static gchar *username = NULL;
74     if (username == NULL) {
75         username = g_strdup (getlogin());
76         if (username == NULL)
77             username = g_strdup (g_getenv("SUDO_USER"));
78         if (username == NULL) {
79             const gchar *uid = g_getenv ("USERHELPER_UID");
80             if (uid != NULL) {
81                 gchar *end;
82                 uid_t id = (uid_t)strtol(uid, &end, 10);
83                 if (uid != end) {
84                     struct passwd *pw = getpwuid (id);
85                     if (pw != NULL) {
86                         username = g_strdup (pw->pw_name);
87                     }
88                 }
89             }
90         }
91         if (username == NULL)
92             username = g_strdup (g_getenv("USERNAME"));
93         if (username == NULL)
94             username = g_strdup (g_getenv("LOGNAME"));
95         if (username == NULL)
96             username = g_strdup (g_getenv("USER"));
97         if (username == NULL)
98             username = g_strdup (g_getenv("LNAME"));
99
100     }
101     return username;
102 #endif
103 }
104
105 glong
106 ibus_get_daemon_uid (void)
107 {
108     return getuid ();
109 #if 0
110     struct passwd *pwd;
111     uid_t uid;
112     const gchar *username;
113
114     uid = getuid ();
115
116     if (uid != 0)
117         return uid;
118
119     username = ibus_get_user_name ();
120     if (username == NULL)
121         return 0;
122
123     pwd = getpwnam (username);
124     if (pwd == NULL)
125         return 0;
126
127     return pwd->pw_uid;
128 #endif
129 }
130
131 const gchar *
132 ibus_get_session_id (void)
133 {
134     return g_getenv("IBUS_SESSION_ID");
135 }
136
137 const gchar *
138 ibus_get_socket_path (void)
139 {
140     static gchar *path = NULL;
141
142     if (path == NULL) {
143         gchar *hostname = "unix";
144         gchar *display;
145         gchar *displaynumber = "0";
146         /* gchar *screennumber = "0"; */
147         gchar *p;
148
149         path = g_strdup (g_getenv ("IBUS_ADDRESS_FILE"));
150         if (path != NULL) {
151             return path;
152         }
153
154         if (_display == NULL) {
155             display = g_strdup (g_getenv ("DISPLAY"));
156         }
157         else {
158             display = g_strdup (_display);
159         }
160
161         if (display == NULL) {
162             g_warning ("DISPLAY is empty! We use default DISPLAY (:0.0)");
163         }
164         else {
165             p = display;
166             hostname = display;
167             for (; *p != ':' && *p != '\0'; p++);
168
169             if (*p == ':') {
170                 *p = '\0';
171                 p++;
172                 displaynumber = p;
173             }
174
175             for (; *p != '.' && *p != '\0'; p++);
176
177             if (*p == '.') {
178                 *p = '\0';
179                 p++;
180                 /* Do not use screennumber
181                  screennumber = p; */
182             }
183         }
184
185         if (hostname[0] == '\0')
186             hostname = "unix";
187
188         p = g_strdup_printf ("%s-%s-%s",
189                              ibus_get_local_machine_id (),
190                              hostname,
191                              displaynumber);
192         path = g_build_filename (g_get_user_config_dir (),
193                                  "ibus",
194                                  "bus",
195                                  p,
196                                  NULL);
197         g_free (p);
198         g_free (display);
199     }
200     return path;
201 }
202
203 gint
204 ibus_get_timeout (void)
205 {
206     /* 6000 ms is the default timeout on the ibus-daemon side (5 sec) plus 1. */
207     static const gint default_timeout = 6000;
208
209     static gint64 timeout = -2;
210     if (timeout == -2) {
211         const gchar *timeout_str = g_getenv ("IBUS_TIMEOUT");
212         if (timeout_str == NULL) {
213             timeout = default_timeout;
214         } else {
215             timeout = g_ascii_strtoll(timeout_str, NULL, 10);
216             if (timeout < -1 || timeout == 0 || timeout > G_MAXINT) {
217                 timeout = default_timeout;
218             }
219         }
220     }
221     return timeout;
222 }
223
224 const gchar *
225 ibus_get_address (void)
226 {
227     static gchar *address = NULL;
228     pid_t pid = -1;
229     static gchar buffer[1024];
230     FILE *pf;
231
232     /* free address */
233     if (address != NULL) {
234         g_free (address);
235         address = NULL;
236     }
237
238     /* get address from env variable */
239     address = g_strdup (g_getenv ("IBUS_ADDRESS"));
240     if (address) {
241         return address;
242     }
243
244     /* read address from ~/.config/ibus/bus/soketfile */
245     pf = fopen (ibus_get_socket_path (), "r");
246     if (pf == NULL) {
247         return NULL;
248     }
249
250     while (!feof (pf)) {
251         gchar *p = buffer;
252         if (fgets (buffer, sizeof (buffer), pf) == NULL)
253             break;
254
255         /* skip comment line */
256         if (p[0] == '#')
257             continue;
258         /* parse IBUS_ADDRESS */
259         if (strncmp (p, "IBUS_ADDRESS=", sizeof ("IBUS_ADDRESS=") - 1) == 0) {
260             address = p + sizeof ("IBUS_ADDRESS=") - 1;
261             for (p = (gchar *)address; *p != '\n' && *p != '\0'; p++);
262             if (*p == '\n')
263                 *p = '\0';
264             address = g_strdup (address);
265             continue;
266         }
267
268         /* parse IBUS_DAEMON_PID */
269         if (strncmp (p, "IBUS_DAEMON_PID=", sizeof ("IBUS_DAEMON_PID=") - 1) == 0) {
270             pid = atoi(p + sizeof ("IBUS_DAEMON_PID=") - 1);
271             continue;
272         }
273
274     }
275     fclose (pf);
276
277     if (pid == -1 || kill (pid, 0) != 0) {
278         return NULL;
279     }
280
281     return address;
282 }
283
284 void
285 ibus_write_address (const gchar *address)
286 {
287     FILE *pf;
288     gchar *path;
289     g_return_if_fail (address != NULL);
290
291     path = g_path_get_dirname (ibus_get_socket_path ());
292     g_mkdir_with_parents (path, 0700);
293     g_free (path);
294
295     g_unlink (ibus_get_socket_path ());
296     pf = fopen (ibus_get_socket_path (), "w");
297     g_return_if_fail (pf != NULL);
298
299     fprintf (pf,
300         "# This file is created by ibus-daemon, please do not modify it\n"
301         "IBUS_ADDRESS=%s\n"
302         "IBUS_DAEMON_PID=%ld\n",
303         address, (glong) getpid ());
304     fclose (pf);
305 }
306
307 void
308 ibus_free_strv (gchar **strv)
309 {
310     gchar **p;
311
312     if (strv == NULL)
313         return;
314
315     for (p = strv; *p != NULL; p++) {
316         g_free (*p);
317     }
318
319     g_free (strv);
320 }
321
322 void
323 ibus_init (void)
324 {
325     g_type_init ();
326     IBUS_ERROR;
327     IBUS_TYPE_TEXT;
328     IBUS_TYPE_ATTRIBUTE;
329     IBUS_TYPE_ATTR_LIST;
330     IBUS_TYPE_LOOKUP_TABLE;
331     IBUS_TYPE_COMPONENT;
332     IBUS_TYPE_ENGINE_DESC;
333 }
334
335 static GMainLoop *main_loop = NULL;
336
337 void
338 ibus_main (void)
339 {
340     main_loop = g_main_loop_new (NULL, FALSE);
341
342     g_main_loop_run (main_loop);
343
344     g_main_loop_unref (main_loop);
345     main_loop = NULL;
346 }
347
348 void
349 ibus_quit (void)
350 {
351     if (main_loop) {
352         g_main_loop_quit (main_loop);
353     }
354 }
355
356 static gboolean ibus_log_handler_is_verbose = FALSE;
357 static guint ibus_log_handler_id = 0;
358
359 static void
360 ibus_log_handler (const gchar    *log_domain,
361                   GLogLevelFlags  log_level,
362                   const gchar    *message,
363                   gpointer        user_data)
364 {
365     // In the quiet mode (i.e. not verbose), we'll ignore DEBUG and
366     // WARNING messages.
367     if (!ibus_log_handler_is_verbose &&
368         ((log_level & G_LOG_LEVEL_DEBUG) ||
369          (log_level & G_LOG_LEVEL_WARNING))) {
370         return;
371     }
372     // Add timing info like "17:34:57.680038" (hour, min, sec, microsecond).
373     struct timeval time_val;
374     gettimeofday (&time_val, NULL);
375     struct tm local_time;
376     localtime_r (&time_val.tv_sec, &local_time);
377     char* new_message =
378         g_strdup_printf ("%02d:%02d:%02d.%6d: %s",
379                          local_time.tm_hour,
380                          local_time.tm_min,
381                          local_time.tm_sec,
382                          (int)time_val.tv_usec,
383                          message);
384     g_log_default_handler (log_domain, log_level, new_message, user_data);
385     g_free (new_message);
386 }
387
388 void
389 ibus_set_log_handler (gboolean verbose)
390 {
391     if (ibus_log_handler_id != 0) {
392         g_log_remove_handler (G_LOG_DOMAIN, ibus_log_handler_id);
393     }
394
395     ibus_log_handler_is_verbose = verbose;
396     ibus_log_handler_id = g_log_set_handler (G_LOG_DOMAIN,
397                                              G_LOG_LEVEL_MASK,
398                                              ibus_log_handler,
399                                              NULL);
400 }
401
402 void
403 ibus_unset_log_handler (void)
404 {
405     if (ibus_log_handler_id != 0) {
406         g_log_remove_handler (G_LOG_DOMAIN, ibus_log_handler_id);
407         ibus_log_handler_id = 0;
408     }
409 }