2005-06-22 18:20:32 +00:00
|
|
|
/*
|
2015-12-25 21:58:17 -08:00
|
|
|
* mooapp/mooappinput-unix.c
|
2005-06-22 18:20:32 +00:00
|
|
|
*
|
2015-12-25 21:58:17 -08:00
|
|
|
* Copyright (C) 2004-2015 by Yevgen Muntyan <emuntyan@users.sourceforge.net>
|
2005-06-22 18:20:32 +00:00
|
|
|
*
|
2008-09-05 17:20:50 -05:00
|
|
|
* This file is part of medit. medit 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.
|
2005-06-22 18:20:32 +00:00
|
|
|
*
|
2008-09-05 17:20:50 -05:00
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with medit. If not, see <http://www.gnu.org/licenses/>.
|
2005-06-22 18:20:32 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
2015-12-25 21:30:53 -08:00
|
|
|
#define MOO_DO_NOT_MANGLE_GLIB_FUNCTIONS
|
|
|
|
#include <mooglib/moo-glib.h>
|
|
|
|
MGW_ERROR_IF_NOT_SHARED_LIBC
|
2015-12-25 21:58:17 -08:00
|
|
|
|
|
|
|
#include "mooutils/mooappinput-priv.h"
|
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
# include <sys/socket.h>
|
|
|
|
# include <sys/un.h>
|
|
|
|
|
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>
|
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 "mooapp-ipc.h"
|
|
|
|
#include "mooutils-misc.h"
|
|
|
|
#include "mooutils-thread.h"
|
|
|
|
#include "mooutils-debug.h"
|
2005-06-22 18:20:32 +00:00
|
|
|
|
2007-07-10 10:32:29 -05:00
|
|
|
#define INPUT_PREFIX "in-"
|
2005-06-22 18:20:32 +00:00
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
|
|
|
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
|
|
|
|
2010-09-21 22:25:26 -07:00
|
|
|
pipe_dir_name = get_pipe_dir (MOO_PACKAGE_NAME);
|
2007-07-10 10:32:29 -05:00
|
|
|
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");
|
|
|
|
|
2015-12-25 21:58:17 -08:00
|
|
|
if (!_moo_app_input_instance)
|
2008-02-20 06:52:05 -06:00
|
|
|
return;
|
|
|
|
|
2015-12-25 21:58:17 -08:00
|
|
|
pipe_dir_name = get_pipe_dir (_moo_app_input_instance->appname);
|
2008-02-20 06:52:05 -06:00
|
|
|
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);
|
|
|
|
|
2015-12-25 21:58:17 -08:00
|
|
|
for (l = _moo_app_input_instance->pipes; !my_name && l != NULL; l = l->next)
|
2008-02-20 06:52:05 -06:00
|
|
|
{
|
|
|
|
InputChannel *ch = l->data;
|
2015-12-25 21:58:17 -08:00
|
|
|
const char *ch_name = _moo_app_input_channel_get_name (ch);
|
2008-02-20 06:52:05 -06:00
|
|
|
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
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
g_warning ("in write: %s", g_strerror (errno));
|
2007-07-10 10:32:29 -05:00
|
|
|
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
|
|
|
#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
|
|
|
|
2015-12-25 21:58:17 -08:00
|
|
|
char *
|
|
|
|
_moo_app_input_channel_get_path (InputChannel *ch)
|
2007-07-13 03:42:31 -05:00
|
|
|
{
|
|
|
|
g_return_val_if_fail (ch != NULL, NULL);
|
|
|
|
return g_strdup (ch->path);
|
|
|
|
}
|
|
|
|
|
2015-12-25 21:58:17 -08:00
|
|
|
const char *
|
|
|
|
_moo_app_input_channel_get_name (InputChannel *ch)
|
2008-02-20 06:52:05 -06:00
|
|
|
{
|
|
|
|
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);
|
2011-01-13 00:36:22 -08:00
|
|
|
g_slice_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)
|
2011-01-14 02:37:04 -08:00
|
|
|
moo_dmsg ("%s", g_strerror (errno));
|
2007-07-15 03:04:05 -05:00
|
|
|
else
|
2011-01-14 02:37:04 -08:00
|
|
|
moo_dmsg ("EOF");
|
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
|
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
moo_dmsg ("got bytes: '%s'", conn->buffer->str);
|
2007-09-08 18:08:10 -05:00
|
|
|
}
|
2006-12-19 02:12:37 -06:00
|
|
|
|
2007-07-15 03:04:05 -05:00
|
|
|
if (do_commit)
|
2015-12-25 21:58:17 -08:00
|
|
|
_moo_app_input_channel_commit (&conn->buffer);
|
2007-07-15 03:04:05 -05:00
|
|
|
|
2010-12-17 00:26:14 -08:00
|
|
|
if (!do_commit && (condition & (G_IO_ERR | G_IO_HUP)))
|
2007-09-08 18:08:10 -05:00
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
moo_dmsg ("%s", (condition & G_IO_ERR) ? "G_IO_ERR" : "G_IO_HUP");
|
2007-09-08 18:08:10 -05:00
|
|
|
goto remove;
|
|
|
|
}
|
|
|
|
|
2006-12-19 02:12:37 -06:00
|
|
|
return TRUE;
|
2007-07-31 08:02:07 -05:00
|
|
|
|
|
|
|
remove:
|
2008-12-13 15:09:06 -06:00
|
|
|
if (conn->ch)
|
|
|
|
conn->ch->connections = g_slist_remove (conn->ch->connections, conn);
|
2007-07-31 08:02:07 -05:00
|
|
|
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
|
|
|
|
2011-01-13 00:36:22 -08:00
|
|
|
conn = g_slice_new0 (Connection);
|
2007-07-10 10:32:29 -05:00
|
|
|
conn->ch = ch;
|
2015-12-25 21:58:17 -08:00
|
|
|
conn->buffer = g_string_new_len (NULL, MOO_APP_INPUT_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)
|
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
g_warning ("in accept: %s", g_strerror (errno));
|
2011-01-13 00:36:22 -08:00
|
|
|
g_slice_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);
|
2011-01-13 00:36:22 -08:00
|
|
|
g_slice_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
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
g_critical ("oops");
|
2007-07-31 08:02:07 -05:00
|
|
|
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)
|
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
g_warning ("in socket for %s: %s", filename, g_strerror (errno));
|
2007-07-31 08:02:07 -05:00
|
|
|
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)
|
2011-01-14 02:37:04 -08:00
|
|
|
g_warning ("'%s' is already in use", ch->path);
|
2007-07-31 08:02:07 -05:00
|
|
|
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
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
g_critical ("oops");
|
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
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
g_warning ("in socket for %s: %s", ch->path, g_strerror (errno));
|
2007-07-10 10:32:29 -05:00
|
|
|
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
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
g_warning ("in bind for %s: %s", ch->path, g_strerror (errno));
|
2007-07-31 08:02:07 -05:00
|
|
|
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
|
|
|
{
|
2011-01-14 02:37:04 -08:00
|
|
|
g_warning ("in listen for %s: %s", 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;
|
|
|
|
}
|
|
|
|
|
2015-12-25 21:58:17 -08:00
|
|
|
InputChannel *
|
|
|
|
_moo_app_input_channel_new (const char *appname,
|
|
|
|
const char *name,
|
|
|
|
gboolean may_fail)
|
2007-07-10 10:32:29 -05:00
|
|
|
{
|
|
|
|
InputChannel *ch;
|
|
|
|
|
|
|
|
g_return_val_if_fail (appname != NULL, NULL);
|
|
|
|
g_return_val_if_fail (name != NULL, NULL);
|
|
|
|
|
2011-01-13 00:36:22 -08:00
|
|
|
ch = g_slice_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
|
|
|
{
|
2015-12-25 21:58:17 -08:00
|
|
|
_moo_app_input_channel_free (ch);
|
2007-07-10 10:32:29 -05:00
|
|
|
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
|
|
|
|
2015-12-25 21:58:17 -08:00
|
|
|
void
|
|
|
|
_moo_app_input_channel_free (InputChannel *ch)
|
2007-07-10 10:32:29 -05:00
|
|
|
{
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-01-13 00:36:22 -08:00
|
|
|
g_slice_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
|
|
|
{
|
2015-12-25 21:58:17 -08:00
|
|
|
char c = MOO_APP_INPUT_IPC_MAGIC_CHAR;
|
2008-02-20 06:52:05 -06:00
|
|
|
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;
|
|
|
|
}
|