/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */ /* vim:set et sts=4: */ /* ibus - The Input Bus * Copyright (C) 2008-2010 Peng Huang * Copyright (C) 2015-2018 Takao Fujiwara * Copyright (C) 2008-2018 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 * USA */ #include "ibusshare.h" #include #include #include #include #include #include #include #include #include #include static gchar *_display = NULL; const gchar * ibus_get_local_machine_id (void) { static gchar *machine_id = NULL; if (machine_id == NULL) { GError *error = NULL; if (!g_file_get_contents ("/var/lib/dbus/machine-id", &machine_id, NULL, &error) && !g_file_get_contents ("/etc/machine-id", &machine_id, NULL, NULL)) { g_warning ("Unable to load /var/lib/dbus/machine-id: %s", error->message); machine_id = "machine-id"; } else { g_strstrip (machine_id); } if (error != NULL) { g_error_free (error); } } return machine_id; } void ibus_set_display (const gchar *display) { if (_display != NULL) g_free (_display); _display = g_strdup (display); } const gchar * ibus_get_user_name (void) { return g_get_user_name (); } glong ibus_get_daemon_uid (void) { return getuid (); } const gchar * ibus_get_session_id (void) { return g_getenv("IBUS_SESSION_ID"); } const gchar * ibus_get_socket_path (void) { static gchar *path = NULL; if (path == NULL) { gchar *hostname = "unix"; gchar *display; gchar *displaynumber = "0"; /* gchar *screennumber = "0"; */ gchar *p; path = g_strdup (g_getenv ("IBUS_ADDRESS_FILE")); if (path != NULL) { return path; } if (_display == NULL) { display = g_strdup (g_getenv ("DISPLAY")); } else { display = g_strdup (_display); } if (display) { p = display; hostname = display; for (; *p != ':' && *p != '\0'; p++); if (*p == ':') { *p = '\0'; p++; displaynumber = p; } for (; *p != '.' && *p != '\0'; p++); if (*p == '.') { *p = '\0'; p++; /* Do not use screennumber screennumber = p; */ } } if (hostname[0] == '\0') hostname = "unix"; p = g_strdup_printf ("%s-%s-%s", ibus_get_local_machine_id (), hostname, displaynumber); path = g_build_filename (g_get_user_config_dir (), "ibus", "bus", p, NULL); g_free (p); g_free (display); } return path; } gint ibus_get_timeout (void) { /* 16000 ms is the default timeout on the ibus-daemon side * (15 sec) plus 1. */ static const gint default_timeout = 16000; static gint64 timeout = -2; if (timeout == -2) { const gchar *timeout_str = g_getenv ("IBUS_TIMEOUT"); if (timeout_str == NULL) { timeout = default_timeout; } else { timeout = g_ascii_strtoll(timeout_str, NULL, 10); if (timeout < -1 || timeout == 0 || timeout > G_MAXINT) { timeout = default_timeout; } } } return timeout; } const gchar * ibus_get_address (void) { static gchar *address = NULL; pid_t pid = -1; static gchar buffer[1024]; FILE *pf; /* free address */ if (address != NULL) { g_free (address); address = NULL; } /* get address from env variable */ address = g_strdup (g_getenv ("IBUS_ADDRESS")); if (address) { return address; } /* read address from ~/.config/ibus/bus/soketfile */ pf = fopen (ibus_get_socket_path (), "r"); if (pf == NULL) { return NULL; } while (!feof (pf)) { gchar *p = buffer; if (fgets (buffer, sizeof (buffer), pf) == NULL) break; /* skip comment line */ if (p[0] == '#') continue; /* parse IBUS_ADDRESS */ if (strncmp (p, "IBUS_ADDRESS=", sizeof ("IBUS_ADDRESS=") - 1) == 0) { address = p + sizeof ("IBUS_ADDRESS=") - 1; for (p = (gchar *)address; *p != '\n' && *p != '\0'; p++); if (*p == '\n') *p = '\0'; address = g_strdup (address); continue; } /* parse IBUS_DAEMON_PID */ if (strncmp (p, "IBUS_DAEMON_PID=", sizeof ("IBUS_DAEMON_PID=") - 1) == 0) { pid = atoi(p + sizeof ("IBUS_DAEMON_PID=") - 1); continue; } } fclose (pf); if (pid == -1 || kill (pid, 0) != 0) { return NULL; } return address; } void ibus_write_address (const gchar *address) { FILE *pf; gchar *path; g_return_if_fail (address != NULL); path = g_path_get_dirname (ibus_get_socket_path ()); g_mkdir_with_parents (path, 0700); g_free (path); g_unlink (ibus_get_socket_path ()); pf = fopen (ibus_get_socket_path (), "w"); g_return_if_fail (pf != NULL); fprintf (pf, "# This file is created by ibus-daemon, please do not modify it\n" "IBUS_ADDRESS=%s\n" "IBUS_DAEMON_PID=%ld\n", address, (glong) getpid ()); fclose (pf); } void ibus_free_strv (gchar **strv) { gchar **p; if (strv == NULL) return; for (p = strv; *p != NULL; p++) { g_free (*p); } g_free (strv); } void ibus_init (void) { #if !GLIB_CHECK_VERSION(2,35,0) g_type_init (); #endif IBUS_ERROR; IBUS_TYPE_TEXT; IBUS_TYPE_ATTRIBUTE; IBUS_TYPE_ATTR_LIST; IBUS_TYPE_LOOKUP_TABLE; IBUS_TYPE_COMPONENT; IBUS_TYPE_ENGINE_DESC; IBUS_TYPE_OBSERVED_PATH; IBUS_TYPE_REGISTRY; IBUS_TYPE_X_EVENT; } static GMainLoop *main_loop = NULL; void ibus_main (void) { main_loop = g_main_loop_new (NULL, FALSE); g_main_loop_run (main_loop); g_main_loop_unref (main_loop); main_loop = NULL; } void ibus_quit (void) { if (main_loop) { g_main_loop_quit (main_loop); } } static gboolean ibus_log_handler_is_verbose = FALSE; static guint ibus_log_handler_id = 0; static void ibus_log_handler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data) { // In the quiet mode (i.e. not verbose), we'll ignore DEBUG and // WARNING messages. if (!ibus_log_handler_is_verbose && ((log_level & G_LOG_LEVEL_DEBUG) || (log_level & G_LOG_LEVEL_WARNING))) { return; } // Add timing info like "17:34:57.680038" (hour, min, sec, microsecond). struct timeval time_val; gettimeofday (&time_val, NULL); struct tm local_time; localtime_r (&time_val.tv_sec, &local_time); char* new_message = g_strdup_printf ("%02d:%02d:%02d.%6d: %s", local_time.tm_hour, local_time.tm_min, local_time.tm_sec, (int)time_val.tv_usec, message); g_log_default_handler (log_domain, log_level, new_message, user_data); g_free (new_message); } void ibus_set_log_handler (gboolean verbose) { if (ibus_log_handler_id != 0) { g_log_remove_handler (G_LOG_DOMAIN, ibus_log_handler_id); } ibus_log_handler_is_verbose = verbose; ibus_log_handler_id = g_log_set_handler (G_LOG_DOMAIN, G_LOG_LEVEL_MASK, ibus_log_handler, NULL); } void ibus_unset_log_handler (void) { if (ibus_log_handler_id != 0) { g_log_remove_handler (G_LOG_DOMAIN, ibus_log_handler_id); ibus_log_handler_id = 0; } }