Blame src/ibusshare.c

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