2005-06-22 18:20:32 +00:00
|
|
|
/*
|
|
|
|
* mooapp/mooappinput.c
|
|
|
|
*
|
2007-04-07 03:21:52 -05:00
|
|
|
* Copyright (C) 2004-2007 by Yevgen Muntyan <muntyan@math.tamu.edu>
|
2005-06-22 18:20:32 +00:00
|
|
|
*
|
2007-06-24 12:56:20 -05:00
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
2007-09-23 11:47:28 -05:00
|
|
|
* License version 2.1 as published by the Free Software Foundation.
|
2005-06-22 18:20:32 +00:00
|
|
|
*
|
|
|
|
* See COPYING file that comes with this distribution.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#ifdef __WIN32__
|
2007-07-10 10:32:29 -05:00
|
|
|
#define MOO_APP_INPUT_WIN32
|
|
|
|
#else
|
|
|
|
#define MOO_APP_INPUT_SOCKET
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if defined(MOO_APP_INPUT_WIN32)
|
|
|
|
# include <windows.h>
|
|
|
|
# include <io.h>
|
|
|
|
#else
|
|
|
|
# include <sys/socket.h>
|
|
|
|
# include <sys/un.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifndef __WIN32__
|
2005-06-22 18:20:32 +00:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <stdlib.h>
|
2007-07-10 10:32:29 -05:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#endif
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
#include <fcntl.h>
|
2005-10-13 14:08:18 +00:00
|
|
|
#include <errno.h>
|
2005-06-22 18:20:32 +00:00
|
|
|
#include <stdio.h>
|
2005-11-02 02:32:07 +00:00
|
|
|
#include <string.h>
|
2008-02-20 06:52:05 -06:00
|
|
|
#include "mooappinput.h"
|
|
|
|
#include "mooapp-ipc.h"
|
|
|
|
#include "mooutils-misc.h"
|
|
|
|
#include "mooutils-thread.h"
|
|
|
|
#include "mooutils-debug.h"
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-08-20 22:15:58 -05:00
|
|
|
MOO_DEBUG_INIT(input, TRUE)
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
#define MAX_BUFFER_SIZE 4096
|
2008-02-20 06:52:05 -06:00
|
|
|
#define IPC_MAGIC_CHAR 'I'
|
|
|
|
#define MOO_APP_INPUT_NAME_DEFAULT "main"
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
#ifdef MOO_APP_INPUT_SOCKET
|
|
|
|
#define INPUT_PREFIX "in-"
|
|
|
|
#else
|
|
|
|
#define INPUT_PREFIX "input-"
|
|
|
|
#endif
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
typedef struct MooAppInput MooAppInput;
|
2007-07-10 10:32:29 -05:00
|
|
|
typedef struct InputChannel InputChannel;
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
struct MooAppInput
|
2006-06-03 02:26:18 -05:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
GSList *pipes;
|
|
|
|
char *appname;
|
2007-07-13 03:42:31 -05:00
|
|
|
char *main_path;
|
2008-02-20 06:52:05 -06:00
|
|
|
MooAppInputCallback callback;
|
|
|
|
gpointer callback_data;
|
2006-06-03 02:26:18 -05:00
|
|
|
};
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
static MooAppInput *inp_instance;
|
|
|
|
|
2007-07-13 03:42:31 -05:00
|
|
|
static InputChannel *input_channel_new (const char *appname,
|
|
|
|
const char *name,
|
|
|
|
gboolean may_fail);
|
|
|
|
static void input_channel_free (InputChannel *ch);
|
|
|
|
static char *input_channel_get_path (InputChannel *ch);
|
2008-02-20 06:52:05 -06:00
|
|
|
static const char *input_channel_get_name (InputChannel *ch);
|
2006-06-03 02:26:18 -05:00
|
|
|
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
static void
|
|
|
|
exec_callback (char cmd,
|
|
|
|
const char *data,
|
|
|
|
guint len)
|
|
|
|
{
|
|
|
|
g_return_if_fail (inp_instance && inp_instance->callback);
|
|
|
|
if (cmd == IPC_MAGIC_CHAR)
|
|
|
|
_moo_ipc_dispatch (data, len);
|
|
|
|
else
|
|
|
|
inp_instance->callback (cmd, data, len, inp_instance->callback_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static MooAppInput *
|
2008-04-01 11:02:42 -05:00
|
|
|
moo_app_input_new (const char *name,
|
2008-02-20 06:52:05 -06:00
|
|
|
gboolean bind_default,
|
|
|
|
MooAppInputCallback callback,
|
|
|
|
gpointer callback_data)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
MooAppInput *ch;
|
2007-07-10 10:32:29 -05:00
|
|
|
InputChannel *ich;
|
2008-04-01 11:02:42 -05:00
|
|
|
const char *appname = g_get_prgname ();
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-04-01 11:02:42 -05:00
|
|
|
g_return_val_if_fail (appname != NULL, FALSE);
|
2008-02-20 06:52:05 -06:00
|
|
|
g_return_val_if_fail (callback != NULL, NULL);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-02-03 02:10:35 -06:00
|
|
|
ch = moo_new0 (MooAppInput);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
ch->callback = callback;
|
|
|
|
ch->callback_data = callback_data;
|
2007-07-10 10:32:29 -05:00
|
|
|
ch->pipes = NULL;
|
|
|
|
ch->appname = g_strdup (appname);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if ((ich = input_channel_new (appname, _moo_get_pid_string (), FALSE)))
|
2007-07-13 03:42:31 -05:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
ch->pipes = g_slist_prepend (ch->pipes, ich);
|
2007-07-13 03:42:31 -05:00
|
|
|
ch->main_path = input_channel_get_path (ich);
|
|
|
|
}
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (name && (ich = input_channel_new (appname, name, FALSE)))
|
|
|
|
ch->pipes = g_slist_prepend (ch->pipes, ich);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (bind_default && (ich = input_channel_new (appname, MOO_APP_INPUT_NAME_DEFAULT, TRUE)))
|
|
|
|
ch->pipes = g_slist_prepend (ch->pipes, ich);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
return ch;
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
|
2005-10-13 14:08:18 +00:00
|
|
|
void
|
2008-04-01 11:02:42 -05:00
|
|
|
_moo_app_input_start (const char *name,
|
2008-02-20 06:52:05 -06:00
|
|
|
gboolean bind_default,
|
|
|
|
MooAppInputCallback callback,
|
|
|
|
gpointer callback_data)
|
|
|
|
{
|
|
|
|
g_return_if_fail (inp_instance == NULL);
|
2008-04-01 11:02:42 -05:00
|
|
|
inp_instance = moo_app_input_new (name, bind_default,
|
2008-02-20 06:52:05 -06:00
|
|
|
callback, callback_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
moo_app_input_free (MooAppInput *ch)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
|
|
|
g_return_if_fail (ch != NULL);
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
g_slist_foreach (ch->pipes, (GFunc) input_channel_free, NULL);
|
2007-08-06 13:17:25 -05:00
|
|
|
g_slist_free (ch->pipes);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-13 03:42:31 -05:00
|
|
|
g_free (ch->main_path);
|
2007-07-10 10:32:29 -05:00
|
|
|
g_free (ch->appname);
|
2008-02-03 02:10:35 -06:00
|
|
|
moo_free (MooAppInput, ch);
|
2006-06-03 02:26:18 -05:00
|
|
|
}
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
void
|
|
|
|
_moo_app_input_shutdown (void)
|
|
|
|
{
|
|
|
|
if (inp_instance)
|
|
|
|
{
|
|
|
|
MooAppInput *tmp = inp_instance;
|
|
|
|
inp_instance = NULL;
|
|
|
|
moo_app_input_free (tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2006-06-03 02:26:18 -05:00
|
|
|
|
2007-07-13 03:42:31 -05:00
|
|
|
const char *
|
2008-02-20 06:52:05 -06:00
|
|
|
_moo_app_input_get_path (void)
|
2007-07-13 03:42:31 -05:00
|
|
|
{
|
2008-02-20 06:52:05 -06:00
|
|
|
return inp_instance ? inp_instance->main_path : NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
_moo_app_input_running (void)
|
|
|
|
{
|
|
|
|
return inp_instance != NULL;
|
2007-07-13 03:42:31 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2005-10-13 14:08:18 +00:00
|
|
|
static void
|
2007-07-10 10:32:29 -05:00
|
|
|
commit (GString **buffer)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-05-14 20:08:25 -05:00
|
|
|
char buf[MAX_BUFFER_SIZE];
|
|
|
|
GString *freeme = NULL;
|
|
|
|
char *ptr;
|
|
|
|
gsize len;
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (!(*buffer)->len)
|
2007-05-14 20:08:25 -05:00
|
|
|
{
|
2007-08-20 22:15:58 -05:00
|
|
|
moo_dmsg ("%s: got empty command", G_STRLOC);
|
2007-05-14 20:08:25 -05:00
|
|
|
return;
|
|
|
|
}
|
2005-10-13 14:08:18 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if ((*buffer)->len + 1 > MAX_BUFFER_SIZE)
|
2005-10-13 14:08:18 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
freeme = *buffer;
|
|
|
|
*buffer = g_string_new_len (NULL, MAX_BUFFER_SIZE);
|
2007-05-14 20:08:25 -05:00
|
|
|
ptr = freeme->str;
|
|
|
|
len = freeme->len;
|
2005-10-13 14:08:18 +00:00
|
|
|
}
|
2005-06-22 18:20:32 +00:00
|
|
|
else
|
2005-10-13 14:08:18 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
memcpy (buf, (*buffer)->str, (*buffer)->len + 1);
|
2007-05-14 20:08:25 -05:00
|
|
|
ptr = buf;
|
2007-07-10 10:32:29 -05:00
|
|
|
len = (*buffer)->len;
|
|
|
|
g_string_truncate (*buffer, 0);
|
2005-10-13 14:08:18 +00:00
|
|
|
}
|
|
|
|
|
2007-08-18 02:23:59 -05:00
|
|
|
if (0)
|
2007-05-14 20:08:25 -05:00
|
|
|
g_print ("%s: commit %c\n%s\n-----\n", G_STRLOC, ptr[0], ptr + 1);
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
exec_callback (ptr[0], ptr + 1, len - 1);
|
2007-05-14 20:08:25 -05:00
|
|
|
|
|
|
|
if (freeme)
|
|
|
|
g_string_free (freeme, TRUE);
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
#ifndef MOO_APP_INPUT_WIN32
|
|
|
|
|
2008-04-01 11:02:42 -05:00
|
|
|
static const char *
|
|
|
|
get_display_name (void)
|
|
|
|
{
|
|
|
|
static char *name;
|
|
|
|
|
|
|
|
#ifdef GDK_WINDOWING_X11
|
|
|
|
static gboolean been_here;
|
|
|
|
if (!been_here)
|
|
|
|
{
|
|
|
|
GdkDisplay *display;
|
|
|
|
const char *display_name;
|
|
|
|
|
|
|
|
been_here = TRUE;
|
|
|
|
|
|
|
|
if ((display = gdk_display_get_default ()))
|
|
|
|
{
|
|
|
|
display_name = gdk_display_get_name (display);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
display_name = gdk_get_display_arg_name ();
|
|
|
|
if (!display_name || !display_name[0])
|
|
|
|
display_name = g_getenv ("DISPLAY");
|
|
|
|
}
|
|
|
|
|
|
|
|
if (display_name && display_name[0])
|
|
|
|
{
|
|
|
|
char *colon, *dot;
|
|
|
|
|
|
|
|
if ((colon = strchr (display_name, ':')) &&
|
|
|
|
(dot = strrchr (display_name, '.')) &&
|
|
|
|
dot > colon)
|
|
|
|
name = g_strndup (display_name, dot - display_name);
|
|
|
|
else
|
|
|
|
name = g_strdup (display_name);
|
|
|
|
|
|
|
|
if (name[0] == ':')
|
|
|
|
{
|
|
|
|
if (name[1])
|
|
|
|
{
|
|
|
|
char *tmp = g_strdup (name + 1);
|
|
|
|
g_free (name);
|
|
|
|
name = tmp;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
g_free (name);
|
|
|
|
name = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (name)
|
|
|
|
g_strcanon (name,
|
|
|
|
G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS,
|
|
|
|
'-');
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static const char *
|
|
|
|
get_user_name (void)
|
|
|
|
{
|
|
|
|
static char *user_name;
|
|
|
|
|
|
|
|
if (!user_name)
|
|
|
|
user_name = g_strcanon (g_strdup (g_get_user_name ()),
|
|
|
|
G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS,
|
|
|
|
'-');
|
|
|
|
|
|
|
|
return user_name;
|
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static char *
|
|
|
|
get_pipe_dir (const char *appname)
|
|
|
|
{
|
2008-04-01 11:02:42 -05:00
|
|
|
const char *display_name;
|
|
|
|
const char *user_name;
|
2007-07-10 10:32:29 -05:00
|
|
|
char *name;
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
g_return_val_if_fail (appname != NULL, NULL);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-04-01 11:02:42 -05:00
|
|
|
display_name = get_display_name ();
|
|
|
|
user_name = get_user_name ();
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-04-01 11:02:42 -05:00
|
|
|
if (display_name)
|
|
|
|
name = g_strdup_printf ("%s/%s-%s-%s", g_get_tmp_dir (), appname, user_name, display_name);
|
|
|
|
else
|
|
|
|
name = g_strdup_printf ("%s/%s-%s", g_get_tmp_dir (), appname, user_name);
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
return name;
|
|
|
|
}
|
|
|
|
|
|
|
|
static char *
|
|
|
|
get_pipe_path (const char *pipe_dir,
|
|
|
|
const char *name)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
return g_strdup_printf ("%s/" INPUT_PREFIX "%s",
|
|
|
|
pipe_dir, name);
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static gboolean
|
|
|
|
input_channel_start_io (int fd,
|
|
|
|
GIOFunc io_func,
|
|
|
|
gpointer data,
|
|
|
|
GIOChannel **io_channel,
|
|
|
|
guint *io_watch)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
GSource *source;
|
|
|
|
|
|
|
|
*io_channel = g_io_channel_unix_new (fd);
|
|
|
|
g_io_channel_set_encoding (*io_channel, NULL, NULL);
|
|
|
|
|
|
|
|
*io_watch = _moo_io_add_watch (*io_channel,
|
|
|
|
G_IO_IN | G_IO_PRI | G_IO_HUP | G_IO_ERR,
|
|
|
|
io_func, data);
|
|
|
|
|
|
|
|
source = g_main_context_find_source_by_id (NULL, *io_watch);
|
|
|
|
g_source_set_can_recurse (source, TRUE);
|
|
|
|
|
|
|
|
return TRUE;
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static gboolean do_send (const char *filename,
|
2008-02-20 06:52:05 -06:00
|
|
|
const char *iheader,
|
2007-07-10 10:32:29 -05:00
|
|
|
const char *data,
|
|
|
|
gssize data_len);
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
try_send (const char *pipe_dir_name,
|
|
|
|
const char *name,
|
2008-02-20 06:52:05 -06:00
|
|
|
const char *iheader,
|
2007-07-10 10:32:29 -05:00
|
|
|
const char *data,
|
|
|
|
gssize data_len)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
char *filename = NULL;
|
|
|
|
gboolean result = FALSE;
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
g_return_val_if_fail (name && name[0], FALSE);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-31 08:02:07 -05:00
|
|
|
filename = get_pipe_path (pipe_dir_name, name);
|
2007-08-20 22:15:58 -05:00
|
|
|
moo_dmsg ("try_send: sending data to `%s'", filename);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (!g_file_test (filename, G_FILE_TEST_EXISTS))
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-08-20 22:15:58 -05:00
|
|
|
moo_dmsg ("try_send: file %s doesn't exist", filename);
|
2007-07-10 10:32:29 -05:00
|
|
|
goto out;
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
result = do_send (filename, iheader, data, data_len);
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
out:
|
|
|
|
g_free (filename);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
gboolean
|
2008-04-01 11:02:42 -05:00
|
|
|
_moo_app_input_send_msg (const char *name,
|
2007-07-10 10:32:29 -05:00
|
|
|
const char *data,
|
|
|
|
gssize len)
|
|
|
|
{
|
|
|
|
const char *entry;
|
|
|
|
GDir *pipe_dir = NULL;
|
|
|
|
char *pipe_dir_name;
|
|
|
|
gboolean success = FALSE;
|
2008-04-01 11:02:42 -05:00
|
|
|
const char *appname = g_get_prgname ();
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
g_return_val_if_fail (appname != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (data != NULL, FALSE);
|
|
|
|
|
2007-08-20 22:15:58 -05:00
|
|
|
moo_dmsg ("_moo_app_input_send_msg: sending data to %s", name ? name : "NONE");
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
pipe_dir_name = get_pipe_dir (appname);
|
|
|
|
g_return_val_if_fail (pipe_dir_name != NULL, FALSE);
|
|
|
|
|
|
|
|
if (name)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2008-02-20 06:52:05 -06:00
|
|
|
success = try_send (pipe_dir_name, name, NULL, data, len);
|
2007-07-10 10:32:29 -05:00
|
|
|
goto out;
|
|
|
|
}
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
success = try_send (pipe_dir_name, MOO_APP_INPUT_NAME_DEFAULT, NULL, data, len);
|
2007-07-31 08:02:07 -05:00
|
|
|
if (success)
|
|
|
|
goto out;
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
pipe_dir = g_dir_open (pipe_dir_name, 0, NULL);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (!pipe_dir)
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
while ((entry = g_dir_read_name (pipe_dir)))
|
|
|
|
{
|
|
|
|
if (!strncmp (entry, INPUT_PREFIX, strlen (INPUT_PREFIX)))
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
name = entry + strlen (INPUT_PREFIX);
|
2006-03-16 04:39:35 -06:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
if (try_send (pipe_dir_name, name, NULL, data, len))
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
success = TRUE;
|
|
|
|
goto out;
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
}
|
2007-07-10 10:32:29 -05:00
|
|
|
}
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
out:
|
|
|
|
if (pipe_dir)
|
|
|
|
g_dir_close (pipe_dir);
|
|
|
|
g_free (pipe_dir_name);
|
|
|
|
return success;
|
|
|
|
}
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
void
|
|
|
|
_moo_app_input_broadcast (const char *header,
|
|
|
|
const char *data,
|
|
|
|
gssize len)
|
|
|
|
{
|
|
|
|
const char *entry;
|
|
|
|
GDir *pipe_dir = NULL;
|
|
|
|
char *pipe_dir_name;
|
|
|
|
|
|
|
|
g_return_if_fail (data != NULL);
|
|
|
|
|
|
|
|
moo_dmsg ("_moo_app_input_broadcast");
|
|
|
|
|
|
|
|
if (!inp_instance)
|
|
|
|
return;
|
|
|
|
|
|
|
|
pipe_dir_name = get_pipe_dir (inp_instance->appname);
|
|
|
|
g_return_if_fail (pipe_dir_name != NULL);
|
|
|
|
|
|
|
|
pipe_dir = g_dir_open (pipe_dir_name, 0, NULL);
|
|
|
|
|
|
|
|
while (pipe_dir && (entry = g_dir_read_name (pipe_dir)))
|
|
|
|
{
|
|
|
|
if (!strncmp (entry, INPUT_PREFIX, strlen (INPUT_PREFIX)))
|
|
|
|
{
|
|
|
|
GSList *l;
|
|
|
|
gboolean my_name = FALSE;
|
|
|
|
const char *name = entry + strlen (INPUT_PREFIX);
|
|
|
|
|
|
|
|
for (l = inp_instance->pipes; !my_name && l != NULL; l = l->next)
|
|
|
|
{
|
|
|
|
InputChannel *ch = l->data;
|
|
|
|
const char *ch_name = input_channel_get_name (ch);
|
|
|
|
if (ch_name && strcmp (ch_name, name) == 0)
|
|
|
|
my_name = TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!my_name)
|
|
|
|
try_send (pipe_dir_name, name, header, data, len);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (pipe_dir)
|
|
|
|
g_dir_close (pipe_dir);
|
|
|
|
g_free (pipe_dir_name);
|
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static gboolean
|
|
|
|
do_write (int fd,
|
|
|
|
const char *data,
|
|
|
|
gsize data_len)
|
|
|
|
{
|
|
|
|
while (data_len > 0)
|
|
|
|
{
|
|
|
|
ssize_t n;
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
n = write (fd, data, data_len);
|
|
|
|
|
|
|
|
if (n < 0)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
if (errno != EAGAIN && errno != EINTR)
|
2005-06-22 18:20:32 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
g_warning ("%s in write: %s", G_STRLOC, g_strerror (errno));
|
|
|
|
return FALSE;
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
}
|
2007-07-10 10:32:29 -05:00
|
|
|
else
|
|
|
|
{
|
|
|
|
data += n;
|
|
|
|
data_len -= n;
|
|
|
|
}
|
2005-06-22 18:20:32 +00:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
return TRUE;
|
2006-12-19 02:12:37 -06:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
#endif
|
2006-12-19 02:12:37 -06:00
|
|
|
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
#ifdef MOO_APP_INPUT_SOCKET
|
|
|
|
|
|
|
|
#ifndef UNIX_PATH_MAX
|
|
|
|
#define UNIX_PATH_MAX 108
|
|
|
|
#endif
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
typedef struct {
|
|
|
|
int fd;
|
|
|
|
GIOChannel *io;
|
|
|
|
guint io_watch;
|
|
|
|
GString *buffer; /* messages are zero-terminated */
|
|
|
|
InputChannel *ch;
|
|
|
|
} Connection;
|
|
|
|
|
|
|
|
struct InputChannel
|
|
|
|
{
|
|
|
|
char *name;
|
|
|
|
char *path;
|
|
|
|
char *pipe_dir;
|
|
|
|
gboolean owns_file;
|
|
|
|
int fd;
|
|
|
|
GIOChannel *io;
|
|
|
|
guint io_watch;
|
|
|
|
GSList *connections;
|
|
|
|
};
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-13 03:42:31 -05:00
|
|
|
static char *
|
|
|
|
input_channel_get_path (InputChannel *ch)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (ch != NULL, NULL);
|
|
|
|
return g_strdup (ch->path);
|
|
|
|
}
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
static const char *
|
|
|
|
input_channel_get_name (InputChannel *ch)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (ch != NULL, NULL);
|
|
|
|
return ch->name;
|
|
|
|
}
|
|
|
|
|
2006-12-19 02:12:37 -06:00
|
|
|
static void
|
2007-07-10 10:32:29 -05:00
|
|
|
connection_free (Connection *conn)
|
2006-12-19 02:12:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
if (conn->io_watch)
|
|
|
|
g_source_remove (conn->io_watch);
|
|
|
|
|
|
|
|
if (conn->io)
|
2006-12-19 02:12:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
g_io_channel_shutdown (conn->io, FALSE, NULL);
|
|
|
|
g_io_channel_unref (conn->io);
|
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (conn->fd != -1)
|
|
|
|
close (conn->fd);
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
g_string_free (conn->buffer, TRUE);
|
2008-02-03 02:10:35 -06:00
|
|
|
moo_free (Connection, conn);
|
2006-12-19 02:12:37 -06:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static void
|
|
|
|
input_channel_shutdown (InputChannel *ch)
|
2006-12-19 02:12:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
g_slist_foreach (ch->connections, (GFunc) connection_free, NULL);
|
|
|
|
g_slist_free (ch->connections);
|
|
|
|
ch->connections = NULL;
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (ch->io_watch)
|
|
|
|
{
|
|
|
|
g_source_remove (ch->io_watch);
|
|
|
|
ch->io_watch = 0;
|
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (ch->io)
|
|
|
|
{
|
|
|
|
g_io_channel_shutdown (ch->io, FALSE, NULL);
|
|
|
|
g_io_channel_unref (ch->io);
|
|
|
|
ch->io = NULL;
|
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (ch->fd != -1)
|
2006-12-19 02:12:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
close (ch->fd);
|
|
|
|
ch->fd = -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ch->path)
|
|
|
|
{
|
|
|
|
if (ch->owns_file)
|
|
|
|
unlink (ch->path);
|
|
|
|
g_free (ch->path);
|
|
|
|
ch->path = NULL;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
read_input (G_GNUC_UNUSED GIOChannel *source,
|
|
|
|
G_GNUC_UNUSED GIOCondition condition,
|
|
|
|
Connection *conn)
|
|
|
|
{
|
|
|
|
char c;
|
2007-07-31 08:02:07 -05:00
|
|
|
int n;
|
2007-07-15 03:04:05 -05:00
|
|
|
gboolean do_commit = FALSE;
|
2007-07-31 08:02:07 -05:00
|
|
|
|
2007-07-15 03:04:05 -05:00
|
|
|
errno = 0;
|
|
|
|
|
2007-07-31 08:02:07 -05:00
|
|
|
while ((n = read (conn->fd, &c, 1)) > 0)
|
2007-07-10 10:32:29 -05:00
|
|
|
{
|
|
|
|
if (c == 0)
|
2007-07-31 08:02:07 -05:00
|
|
|
{
|
2007-07-15 03:04:05 -05:00
|
|
|
do_commit = TRUE;
|
2007-07-31 08:02:07 -05:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_string_append_c (conn->buffer, c);
|
2007-07-10 10:32:29 -05:00
|
|
|
}
|
|
|
|
|
2007-07-31 08:02:07 -05:00
|
|
|
if (n <= 0)
|
2007-07-10 10:32:29 -05:00
|
|
|
{
|
2007-07-15 03:04:05 -05:00
|
|
|
if (n < 0)
|
2007-08-20 22:15:58 -05:00
|
|
|
moo_dmsg ("%s: %s", G_STRLOC, g_strerror (errno));
|
2007-07-15 03:04:05 -05:00
|
|
|
else
|
2007-08-20 22:15:58 -05:00
|
|
|
moo_dmsg ("%s: EOF", G_STRLOC);
|
2007-07-31 08:02:07 -05:00
|
|
|
goto remove;
|
2006-12-19 02:12:37 -06:00
|
|
|
}
|
2007-09-08 18:08:10 -05:00
|
|
|
else
|
|
|
|
{
|
|
|
|
moo_dmsg ("%s: got bytes: '%s'", G_STRLOC, conn->buffer->str);
|
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-15 03:04:05 -05:00
|
|
|
if (do_commit)
|
|
|
|
commit (&conn->buffer);
|
|
|
|
|
2007-09-08 18:08:10 -05:00
|
|
|
if (condition & (G_IO_ERR | G_IO_HUP))
|
|
|
|
{
|
|
|
|
moo_dmsg ("%s: %s", G_STRLOC,
|
|
|
|
(condition & G_IO_ERR) ? "G_IO_ERR" : "G_IO_HUP");
|
|
|
|
goto remove;
|
|
|
|
}
|
|
|
|
|
2006-12-19 02:12:37 -06:00
|
|
|
return TRUE;
|
2007-07-31 08:02:07 -05:00
|
|
|
|
|
|
|
remove:
|
|
|
|
conn->ch->connections = g_slist_remove (conn->ch->connections, conn);
|
|
|
|
connection_free (conn);
|
|
|
|
return FALSE;
|
2006-12-19 02:12:37 -06:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static gboolean
|
|
|
|
accept_connection (G_GNUC_UNUSED GIOChannel *source,
|
|
|
|
GIOCondition condition,
|
|
|
|
InputChannel *ch)
|
2006-12-19 02:12:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
Connection *conn;
|
|
|
|
socklen_t dummy;
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (condition & G_IO_ERR)
|
|
|
|
{
|
|
|
|
input_channel_shutdown (ch);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2008-02-03 02:10:35 -06:00
|
|
|
conn = moo_new0 (Connection);
|
2007-07-10 10:32:29 -05:00
|
|
|
conn->ch = ch;
|
|
|
|
conn->buffer = g_string_new_len (NULL, MAX_BUFFER_SIZE);
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
conn->fd = accept (ch->fd, NULL, &dummy);
|
|
|
|
|
|
|
|
if (conn->fd == -1)
|
|
|
|
{
|
|
|
|
g_warning ("%s in accept: %s", G_STRLOC, g_strerror (errno));
|
2008-02-03 02:10:35 -06:00
|
|
|
moo_free (Connection, conn);
|
2006-12-19 02:12:37 -06:00
|
|
|
return TRUE;
|
2007-07-10 10:32:29 -05:00
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (!input_channel_start_io (conn->fd, (GIOFunc) read_input, conn,
|
|
|
|
&conn->io, &conn->io_watch))
|
|
|
|
{
|
|
|
|
close (conn->fd);
|
2008-02-03 02:10:35 -06:00
|
|
|
moo_free (Connection, conn);
|
2007-07-10 10:32:29 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
ch->connections = g_slist_prepend (ch->connections, conn);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-07-31 08:02:07 -05:00
|
|
|
static gboolean
|
|
|
|
try_connect (const char *filename,
|
|
|
|
int *fdp)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
|
|
|
|
g_return_val_if_fail (filename != NULL, FALSE);
|
|
|
|
|
2007-10-26 04:46:57 -05:00
|
|
|
if (strlen (filename) + 1 > sizeof addr.sun_path)
|
2007-07-31 08:02:07 -05:00
|
|
|
{
|
|
|
|
g_critical ("%s: oops", G_STRLOC);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
addr.sun_family = AF_UNIX;
|
2007-10-26 04:46:57 -05:00
|
|
|
strcpy (addr.sun_path, filename);
|
2007-07-31 08:02:07 -05:00
|
|
|
fd = socket (PF_UNIX, SOCK_STREAM, 0);
|
|
|
|
|
|
|
|
if (fd == -1)
|
|
|
|
{
|
|
|
|
g_warning ("%s in socket for %s: %s", G_STRLOC, filename, g_strerror (errno));
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
errno = 0;
|
|
|
|
|
|
|
|
if (connect (fd, (struct sockaddr *) &addr, sizeof addr) == -1)
|
|
|
|
{
|
|
|
|
unlink (filename);
|
|
|
|
close (fd);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (fdp)
|
|
|
|
*fdp = fd;
|
|
|
|
else
|
|
|
|
close (fd);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static gboolean
|
|
|
|
input_channel_start (InputChannel *ch,
|
|
|
|
gboolean may_fail)
|
|
|
|
{
|
|
|
|
struct sockaddr_un addr;
|
|
|
|
|
|
|
|
mkdir (ch->pipe_dir, S_IRWXU);
|
|
|
|
|
2007-07-31 08:02:07 -05:00
|
|
|
if (try_connect (ch->path, NULL))
|
|
|
|
{
|
|
|
|
if (!may_fail)
|
|
|
|
g_warning ("%s: '%s' is already in use",
|
|
|
|
G_STRLOC, ch->path);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2007-10-26 04:46:57 -05:00
|
|
|
if (strlen (ch->path) + 1 > sizeof addr.sun_path)
|
2007-07-10 10:32:29 -05:00
|
|
|
{
|
|
|
|
g_critical ("%s: oops", G_STRLOC);
|
2006-12-19 02:12:37 -06:00
|
|
|
return FALSE;
|
2007-07-10 10:32:29 -05:00
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
addr.sun_family = AF_UNIX;
|
2007-10-26 04:46:57 -05:00
|
|
|
strcpy (addr.sun_path, ch->path);
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
errno = 0;
|
|
|
|
|
|
|
|
if ((ch->fd = socket (PF_UNIX, SOCK_STREAM, 0)) == -1)
|
2006-12-19 02:12:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
g_warning ("%s in socket for %s: %s", G_STRLOC, ch->path, g_strerror (errno));
|
|
|
|
return FALSE;
|
2006-12-19 02:12:37 -06:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (bind (ch->fd, (struct sockaddr*) &addr, sizeof addr) == -1)
|
2007-07-31 08:02:07 -05:00
|
|
|
{
|
|
|
|
g_warning ("%s in bind for %s: %s", G_STRLOC, ch->path, g_strerror (errno));
|
|
|
|
close (ch->fd);
|
|
|
|
ch->fd = -1;
|
|
|
|
return FALSE;
|
|
|
|
}
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
if (listen (ch->fd, 5) == -1)
|
2006-12-19 02:12:37 -06:00
|
|
|
{
|
2007-07-31 08:02:07 -05:00
|
|
|
g_warning ("%s in listen for %s: %s", G_STRLOC, ch->path, g_strerror (errno));
|
2007-07-10 10:32:29 -05:00
|
|
|
close (ch->fd);
|
|
|
|
ch->fd = -1;
|
|
|
|
return FALSE;
|
2006-12-19 02:12:37 -06:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
ch->owns_file = TRUE;
|
|
|
|
|
|
|
|
if (!input_channel_start_io (ch->fd, (GIOFunc) accept_connection, ch,
|
|
|
|
&ch->io, &ch->io_watch))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static InputChannel *
|
|
|
|
input_channel_new (const char *appname,
|
|
|
|
const char *name,
|
|
|
|
gboolean may_fail)
|
|
|
|
{
|
|
|
|
InputChannel *ch;
|
|
|
|
|
|
|
|
g_return_val_if_fail (appname != NULL, NULL);
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
|
|
|
2008-02-03 02:10:35 -06:00
|
|
|
ch = moo_new0 (InputChannel);
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
ch->name = g_strdup (name);
|
|
|
|
ch->pipe_dir = get_pipe_dir (appname);
|
|
|
|
ch->path = get_pipe_path (ch->pipe_dir, name);
|
|
|
|
ch->fd = -1;
|
|
|
|
ch->io = NULL;
|
|
|
|
ch->io_watch = 0;
|
|
|
|
|
|
|
|
if (!input_channel_start (ch, may_fail))
|
2006-12-19 02:12:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
input_channel_free (ch);
|
|
|
|
return NULL;
|
2006-12-19 02:12:37 -06:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
return ch;
|
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static void
|
|
|
|
input_channel_free (InputChannel *ch)
|
|
|
|
{
|
|
|
|
input_channel_shutdown (ch);
|
|
|
|
g_free (ch->name);
|
|
|
|
g_free (ch->path);
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (ch->pipe_dir)
|
|
|
|
{
|
|
|
|
remove (ch->pipe_dir);
|
|
|
|
g_free (ch->pipe_dir);
|
|
|
|
}
|
|
|
|
|
2008-02-03 02:10:35 -06:00
|
|
|
moo_free (InputChannel, ch);
|
2007-07-10 10:32:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
do_send (const char *filename,
|
2008-02-20 06:52:05 -06:00
|
|
|
const char *iheader,
|
2007-07-10 10:32:29 -05:00
|
|
|
const char *data,
|
|
|
|
gssize data_len)
|
|
|
|
{
|
|
|
|
int fd;
|
|
|
|
gboolean result = TRUE;
|
|
|
|
|
|
|
|
g_return_val_if_fail (filename != NULL, FALSE);
|
|
|
|
g_return_val_if_fail (data != NULL || data_len == 0, FALSE);
|
|
|
|
|
2007-07-31 08:02:07 -05:00
|
|
|
if (!try_connect (filename, &fd))
|
2007-07-10 10:32:29 -05:00
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
if (data_len < 0)
|
2008-02-20 06:52:05 -06:00
|
|
|
data_len = strlen (data);
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
if (iheader)
|
2007-07-10 10:32:29 -05:00
|
|
|
{
|
2008-02-20 06:52:05 -06:00
|
|
|
char c = IPC_MAGIC_CHAR;
|
|
|
|
result = do_write (fd, &c, 1) &&
|
|
|
|
do_write (fd, iheader, strlen (iheader));
|
2007-07-10 10:32:29 -05:00
|
|
|
}
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
if (result && data_len)
|
|
|
|
result = do_write (fd, data, data_len);
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
if (result)
|
2006-08-22 23:19:08 -05:00
|
|
|
{
|
2008-02-20 06:52:05 -06:00
|
|
|
char c = 0;
|
|
|
|
result = do_write (fd, &c, 1);
|
2006-08-22 23:19:08 -05:00
|
|
|
}
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
close (fd);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
#endif /* MOO_APP_INPUT_SOCKET */
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
|
|
|
|
/****************************************************************************/
|
|
|
|
/* WIN32
|
|
|
|
*/
|
|
|
|
#ifdef MOO_APP_INPUT_WIN32
|
|
|
|
|
|
|
|
typedef struct {
|
|
|
|
char *pipe_name;
|
|
|
|
guint event_id;
|
|
|
|
} ListenerInfo;
|
|
|
|
|
|
|
|
struct InputChannel
|
|
|
|
{
|
|
|
|
char *appname;
|
|
|
|
char *name;
|
|
|
|
char *pipe_name;
|
|
|
|
GString *buffer;
|
|
|
|
guint event_id;
|
|
|
|
};
|
|
|
|
|
2007-07-13 03:42:31 -05:00
|
|
|
static char *
|
|
|
|
input_channel_get_path (InputChannel *ch)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (ch != NULL, NULL);
|
|
|
|
return g_strdup (ch->pipe_name);
|
|
|
|
}
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
static const char *
|
|
|
|
input_channel_get_name (InputChannel *ch)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (ch != NULL, NULL);
|
|
|
|
return ch->name;
|
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static ListenerInfo *
|
|
|
|
listener_info_new (const char *pipe_name,
|
|
|
|
guint event_id)
|
|
|
|
{
|
|
|
|
ListenerInfo *info = g_new (ListenerInfo, 1);
|
|
|
|
info->pipe_name = g_strdup (pipe_name);
|
|
|
|
info->event_id = event_id;
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
listener_info_free (ListenerInfo *info)
|
|
|
|
{
|
|
|
|
if (info)
|
2006-11-16 04:25:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
g_free (info->pipe_name);
|
|
|
|
g_free (info);
|
2006-11-16 04:25:37 -06:00
|
|
|
}
|
2007-07-10 10:32:29 -05:00
|
|
|
}
|
2006-08-22 23:19:08 -05:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
static gpointer
|
|
|
|
listener_main (ListenerInfo *info)
|
|
|
|
{
|
|
|
|
HANDLE input;
|
|
|
|
|
|
|
|
_moo_message_async ("%s: hi there", G_STRLOC);
|
|
|
|
|
2008-01-15 00:47:36 -06:00
|
|
|
/* XXX unicode */
|
|
|
|
input = CreateNamedPipeA (info->pipe_name,
|
|
|
|
PIPE_ACCESS_DUPLEX,
|
|
|
|
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
|
|
|
|
PIPE_UNLIMITED_INSTANCES,
|
|
|
|
0, 0, 200, NULL);
|
2007-07-10 10:32:29 -05:00
|
|
|
|
|
|
|
if (input == INVALID_HANDLE_VALUE)
|
2006-08-18 02:24:18 -05:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
_moo_message_async ("%s: could not create input pipe", G_STRLOC);
|
|
|
|
listener_info_free (info);
|
|
|
|
return NULL;
|
2006-08-18 02:24:18 -05:00
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
_moo_message_async ("%s: opened pipe %s", G_STRLOC, info->pipe_name);
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
while (TRUE)
|
2006-11-16 04:25:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
DWORD bytes_read;
|
|
|
|
char c;
|
|
|
|
|
|
|
|
DisconnectNamedPipe (input);
|
|
|
|
_moo_message_async ("%s: opening connection", G_STRLOC);
|
|
|
|
|
|
|
|
if (!ConnectNamedPipe (input, NULL))
|
|
|
|
{
|
|
|
|
DWORD err = GetLastError();
|
|
|
|
|
|
|
|
if (err != ERROR_PIPE_CONNECTED)
|
|
|
|
{
|
|
|
|
char *msg = g_win32_error_message (err);
|
|
|
|
_moo_message_async ("%s: error in ConnectNamedPipe()", G_STRLOC);
|
|
|
|
_moo_message_async ("%s: %s", G_STRLOC, msg);
|
|
|
|
CloseHandle (input);
|
|
|
|
g_free (msg);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_moo_message_async ("%s: client connected", G_STRLOC);
|
|
|
|
|
|
|
|
while (ReadFile (input, &c, 1, &bytes_read, NULL))
|
|
|
|
{
|
|
|
|
if (bytes_read == 1)
|
|
|
|
{
|
|
|
|
_moo_event_queue_push (info->event_id, GINT_TO_POINTER ((int) c), NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
_moo_message_async ("%s: client disconnected", G_STRLOC);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_moo_message_async ("%s: goodbye", G_STRLOC);
|
|
|
|
|
|
|
|
CloseHandle (input);
|
|
|
|
listener_info_free (info);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static char *
|
|
|
|
get_pipe_name (const char *appname,
|
|
|
|
const char *name)
|
|
|
|
{
|
|
|
|
if (!name)
|
|
|
|
name = _moo_get_pid_string ();
|
|
|
|
return g_strdup_printf ("\\\\.\\pipe\\%s_in_%s",
|
|
|
|
appname, name);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
event_callback (GList *events,
|
|
|
|
InputChannel *ch)
|
|
|
|
{
|
|
|
|
while (events)
|
|
|
|
{
|
|
|
|
char c = GPOINTER_TO_INT (events->data);
|
|
|
|
|
|
|
|
if (c != 0)
|
|
|
|
g_string_append_c (ch->buffer, c);
|
|
|
|
else
|
|
|
|
{
|
|
|
|
gdk_threads_enter ();
|
|
|
|
commit (&ch->buffer);
|
|
|
|
gdk_threads_leave ();
|
|
|
|
}
|
|
|
|
|
|
|
|
events = events->next;
|
2006-11-16 04:25:37 -06:00
|
|
|
}
|
2007-07-10 10:32:29 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
input_channel_start (InputChannel *ch)
|
|
|
|
{
|
|
|
|
ListenerInfo *info;
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
g_free (ch->pipe_name);
|
|
|
|
ch->pipe_name = get_pipe_name (ch->appname, ch->name);
|
|
|
|
ch->event_id = _moo_event_queue_connect ((MooEventQueueCallback) event_callback,
|
|
|
|
ch, NULL);
|
|
|
|
|
|
|
|
info = listener_info_new (ch->pipe_name, ch->event_id);
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (!g_thread_create ((GThreadFunc) listener_main, info, FALSE, NULL))
|
2006-11-16 04:25:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
g_critical ("could not start listener thread");
|
|
|
|
listener_info_free (info);
|
|
|
|
g_free (ch->pipe_name);
|
|
|
|
ch->pipe_name = NULL;
|
|
|
|
_moo_event_queue_disconnect (ch->event_id);
|
|
|
|
ch->event_id = 0;
|
|
|
|
return FALSE;
|
2006-11-16 04:25:37 -06:00
|
|
|
}
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static InputChannel *
|
|
|
|
input_channel_new (const char *appname,
|
|
|
|
const char *name,
|
|
|
|
G_GNUC_UNUSED gboolean may_fail)
|
|
|
|
{
|
|
|
|
InputChannel *ch;
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2008-02-03 02:10:35 -06:00
|
|
|
ch = moo_new0 (InputChannel);
|
2007-07-10 10:32:29 -05:00
|
|
|
ch->appname = g_strdup (appname);
|
|
|
|
ch->name = g_strdup (name);
|
|
|
|
ch->buffer = g_string_new_len (NULL, MAX_BUFFER_SIZE);
|
|
|
|
|
|
|
|
if (!input_channel_start (ch))
|
2006-11-16 04:25:37 -06:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
input_channel_free (ch);
|
|
|
|
return NULL;
|
2006-11-16 04:25:37 -06:00
|
|
|
}
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
return ch;
|
|
|
|
}
|
2006-08-18 02:24:18 -05:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
static void
|
|
|
|
input_channel_free (InputChannel *ch)
|
|
|
|
{
|
|
|
|
if (ch->event_id)
|
|
|
|
_moo_event_queue_disconnect (ch->event_id);
|
|
|
|
if (ch->buffer)
|
|
|
|
g_string_free (ch->buffer, TRUE);
|
|
|
|
g_free (ch->pipe_name);
|
|
|
|
g_free (ch->appname);
|
|
|
|
g_free (ch->name);
|
2008-02-03 02:10:35 -06:00
|
|
|
moo_free (InputChannel, ch);
|
2006-08-18 02:24:18 -05:00
|
|
|
}
|
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
static gboolean
|
|
|
|
write_data (HANDLE file,
|
|
|
|
const char *data,
|
|
|
|
gsize len,
|
|
|
|
const char *pipe_name)
|
|
|
|
{
|
|
|
|
DWORD bytes_written;
|
|
|
|
|
|
|
|
if (!WriteFile (file, data, len, &bytes_written, NULL))
|
|
|
|
{
|
|
|
|
char *err_msg = g_win32_error_message (GetLastError ());
|
|
|
|
g_warning ("could not write data to '%s': %s", pipe_name, err_msg);
|
|
|
|
g_free (err_msg);
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (bytes_written < (DWORD) len)
|
|
|
|
{
|
|
|
|
g_warning ("written less data than requested to '%s'", pipe_name);
|
|
|
|
return FALSE;
|
|
|
|
}
|
2008-02-20 18:44:51 -06:00
|
|
|
|
|
|
|
return TRUE;
|
2008-02-20 06:52:05 -06:00
|
|
|
}
|
|
|
|
|
2005-11-02 02:32:07 +00:00
|
|
|
gboolean
|
2008-05-15 17:27:52 -05:00
|
|
|
_moo_app_input_send_msg (const char *name,
|
2006-12-18 11:08:01 -06:00
|
|
|
const char *data,
|
2007-07-10 10:32:29 -05:00
|
|
|
gssize len)
|
2005-11-02 02:32:07 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
char *err_msg = NULL;
|
|
|
|
char *pipe_name;
|
|
|
|
HANDLE pipe_handle;
|
|
|
|
gboolean result = FALSE;
|
2008-05-15 17:27:52 -05:00
|
|
|
const char *appname = g_get_prgname ();
|
2005-11-02 02:32:07 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
g_return_val_if_fail (appname != NULL, FALSE);
|
2005-11-02 02:32:07 +00:00
|
|
|
g_return_val_if_fail (data != NULL, FALSE);
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (len < 0)
|
|
|
|
len = strlen (data);
|
2006-11-16 04:25:37 -06:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (!len)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
if (!name)
|
|
|
|
name = "main";
|
|
|
|
|
|
|
|
pipe_name = get_pipe_name (appname, name);
|
2008-01-15 00:47:36 -06:00
|
|
|
/* XXX unicode */
|
|
|
|
pipe_handle = CreateFileA (pipe_name, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
|
2005-11-02 02:32:07 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
if (!pipe_handle)
|
2005-11-02 02:32:07 +00:00
|
|
|
{
|
2007-07-10 10:32:29 -05:00
|
|
|
err_msg = g_win32_error_message (GetLastError ());
|
|
|
|
g_warning ("could not open pipe '%s': %s", pipe_name, err_msg);
|
2006-08-18 02:24:18 -05:00
|
|
|
goto out;
|
|
|
|
}
|
2005-11-02 02:32:07 +00:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
result = write_data (pipe_handle, data, len, pipe_name);
|
2005-11-02 02:32:07 +00:00
|
|
|
|
2008-02-20 06:52:05 -06:00
|
|
|
if (result)
|
2006-08-18 02:24:18 -05:00
|
|
|
{
|
2008-02-20 06:52:05 -06:00
|
|
|
char c = 0;
|
|
|
|
result = write_data (pipe_handle, &c, 1, pipe_name);
|
2005-11-02 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
out:
|
2007-07-10 10:32:29 -05:00
|
|
|
if (pipe_handle != INVALID_HANDLE_VALUE)
|
|
|
|
CloseHandle (pipe_handle);
|
|
|
|
|
|
|
|
g_free (pipe_name);
|
|
|
|
g_free (err_msg);
|
|
|
|
return result;
|
2005-11-02 02:32:07 +00:00
|
|
|
}
|
|
|
|
|
2008-02-20 18:44:51 -06:00
|
|
|
void
|
|
|
|
_moo_app_input_broadcast (const char *header,
|
|
|
|
const char *data,
|
|
|
|
gssize len)
|
|
|
|
{
|
|
|
|
#warning "Implement me"
|
|
|
|
|
|
|
|
g_return_if_fail (header != NULL);
|
|
|
|
g_return_if_fail (data != NULL);
|
|
|
|
|
|
|
|
if (len < 0)
|
|
|
|
len = strlen (data);
|
|
|
|
|
|
|
|
g_return_if_fail (len != 0);
|
|
|
|
}
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
#endif /* MOO_APP_INPUT_WIN32 */
|