Passing selection and surrounding text have limit of 4096 bytes if using string type argument
in wayland protocol, the wayland-client library will crash if over this limit. using fd type
argument does not have this constraint.
Change-Id: I07b4d7fc8f7024b2b8096ad2b37ab741b3613f7a
AC_SUBST(UINT32)
AC_SUBST(UINT64)
+AC_CHECK_MEMBERS([struct msghdr.msg_control],,, [#include <sys/socket.h>])
+
# Checks for library functions.
AC_FUNC_MALLOC
AC_CHECK_FUNCS([gettimeofday memmove memset nl_langinfo setlocale daemon])
*/
#include "scim_private.h"
+#include <unistd.h>
#include <Ecore.h>
#include <Ecore_Evas.h>
if (!imcontext || !imcontext->ctx) return;
if (imcontext->input_panel_data)
- free(imcontext->input_panel_data);
+ free (imcontext->input_panel_data);
- imcontext->input_panel_data = calloc(1, length);
- memcpy(imcontext->input_panel_data, input_panel_data, length);
+ imcontext->input_panel_data = calloc (1, length);
+ memcpy (imcontext->input_panel_data, input_panel_data, length);
imcontext->input_panel_data_length = length;
}
static void
text_input_get_selection_text (void *data,
- struct wl_text_input *text_input EINA_UNUSED,
- uint32_t serial)
+ struct wl_text_input *text_input EINA_UNUSED,
+ int32_t fd)
{
char *selection = NULL;
- LOGD ("%d", serial);
+ LOGD ("%d", fd);
WaylandIMContext *imcontext = (WaylandIMContext *)data;
if (!imcontext || !imcontext->ctx) {
LOGD ("");
+ close (fd);
return;
}
ecore_imf_context_selection_get (imcontext->ctx, &selection);
if (imcontext->text_input) {
LOGD ("selection :%s", selection ? selection : "");
- wl_text_input_set_selection_text (imcontext->text_input, serial, selection ? selection : "");
+ if (selection) {
+ char *_selection = selection;
+ size_t len = strlen (selection);
+ while (len) {
+ ssize_t ret = write (fd, _selection, len);
+ if (ret <= 0) {
+ if (errno == EINTR)
+ continue;
+ LOGW ("write pipe failed, errno: %d", errno);
+ break;
+ }
+ _selection += ret;
+ len -= ret;
+ }
+ }
}
-
if (selection)
free (selection);
+ close (fd);
}
static void
text_input_get_surrounding_text (void *data,
- struct wl_text_input *text_input EINA_UNUSED,
- uint32_t serial,
- uint32_t maxlen_before,
- uint32_t maxlen_after)
+ struct wl_text_input *text_input EINA_UNUSED,
+ uint32_t maxlen_before,
+ uint32_t maxlen_after,
+ int32_t fd)
{
int cursor_pos;
char *surrounding = NULL;
- LOGD ("serial: %d maxlen_before: %d maxlen_after: %d", serial, maxlen_before, maxlen_after);
+ LOGD("fd: %d maxlen_before: %d maxlen_after: %d", fd, maxlen_before, maxlen_after);
WaylandIMContext *imcontext = (WaylandIMContext *)data;
if (!imcontext || !imcontext->ctx) {
- LOGD ("");
+ LOGD("");
+ close(fd);
return;
}
/* cursor_pos is a byte index */
if (ecore_imf_context_surrounding_get (imcontext->ctx, &surrounding, &cursor_pos)) {
- LOGD ("surrounding :%s, cursor: %d", surrounding? surrounding : "", cursor_pos);
+ LOGD ("surrounding :%s, cursor: %d", surrounding ? surrounding : "", cursor_pos);
if (imcontext->text_input) {
Eina_Unicode *wide_surrounding = eina_unicode_utf8_to_unicode (surrounding, NULL);
size_t wlen = eina_unicode_strlen (wide_surrounding);
char *req_surrounding = eina_unicode_unicode_to_utf8_range (wide_surrounding + maxlen_before, maxlen_after - maxlen_before, NULL);
- wl_text_input_set_surrounding_text (imcontext->text_input,
- serial, req_surrounding ? req_surrounding : "", cursor_pos);
+ if (req_surrounding) {
+ char *_surrounding = req_surrounding;
+ size_t len = strlen(req_surrounding);
+ while (len) {
+ ssize_t ret = write(fd, _surrounding, len);
+ if (ret <= 0) {
+ if (errno == EINTR)
+ continue;
+ LOGW ("write pipe failed, errno: %d", errno);
+ break;
+ }
+ _surrounding += ret;
+ len -= ret;
+ }
+ }
if (req_surrounding)
free (req_surrounding);
if (surrounding)
free (surrounding);
}
+ close(fd);
}
//
unlock();
}
- void socket_helper_get_surrounding_text(int client, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after) {
+ void socket_helper_get_surrounding_text(int client, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after, const int fd) {
SCIM_DEBUG_MAIN(4) << __FUNCTION__ << " (" << client << ")\n";
LOGD ("client id:%d\n", client);
unlock();
}
- void socket_helper_get_selection(int client, uint32 context_id) {
+ void socket_helper_get_selection(int client, uint32 context_id, const int fd) {
SCIM_DEBUG_MAIN(4) << __FUNCTION__ << " (" << client << ")\n";
LOGD ("client id:%d\n", client);
if (m_recv_trans.get_data(uuid) &&
m_recv_trans.get_data(maxlen_before) &&
m_recv_trans.get_data(maxlen_after)) {
- m_info_manager->socket_helper_get_surrounding_text(client_id, uuid, maxlen_before, maxlen_after);
+ int fd;
+ client.read_fd (&fd);
+ if (fd == -1) {
+ LOGW ("wrong format of transaction\n");
+ } else {
+ m_info_manager->socket_helper_get_surrounding_text(client_id, uuid, maxlen_before, maxlen_after, fd);
+ close (fd);
+ }
} else {
LOGW ("wrong format of transaction\n");
}
String uuid;
if (m_recv_trans.get_data(uuid)) {
- m_info_manager->socket_helper_get_selection(client_id, uuid);
+ int fd;
+ client.read_fd (&fd);
+ if (fd == -1) {
+ LOGW ("wrong format of transaction\n");
+ } else {
+ m_info_manager->socket_helper_get_selection(client_id, uuid, fd);
+ close (fd);
+ }
} else {
LOGW ("wrong format of transaction\n");
}
/////////////////////////////////////////////////////////////////////////////
// Implementation of Wayland Input Method functions.
/////////////////////////////////////////////////////////////////////////////
-static void
-_wsc_im_ctx_surrounding_text(void *data, struct wl_input_method_context *im_ctx, uint32_t serial, const char *text, uint32_t cursor_position)
-{
- LOGD ("");
- WSCContextISF *wsc_ctx = (WSCContextISF*)data;
- if (!wsc_ctx) return;
-
- if (wsc_ctx->surrounding_text)
- free (wsc_ctx->surrounding_text);
-
- wsc_ctx->surrounding_text = strdup (text ? text : "");
- wsc_ctx->surrounding_cursor = cursor_position;
- g_info_manager->socket_update_surrounding_text (wsc_ctx->surrounding_text, wsc_ctx->surrounding_cursor);
-
- LOGD ("text : '%s', cursor : %d\n", text, cursor_position);
-}
static void
_wsc_im_ctx_reset(void *data, struct wl_input_method_context *im_ctx)
}
static void
-_wsc_im_ctx_selection_text(void *data, struct wl_input_method_context *im_ctx, uint32_t serial, const char *text)
-{
- WSCContextISF *wsc_ctx = (WSCContextISF*)data;
-
- LOGD ("im_context = %p selection text = %s\n", im_ctx, text);
- if (!wsc_ctx) return;
-
- g_info_manager->socket_update_selection (text);
-}
-
-static void
_wsc_im_ctx_cursor_position(void *data, struct wl_input_method_context *im_ctx, uint32_t cursor_pos)
{
WSCContextISF *wsc_ctx = (WSCContextISF*)data;
}
static const struct wl_input_method_context_listener wsc_im_context_listener = {
- _wsc_im_ctx_surrounding_text,
_wsc_im_ctx_reset,
_wsc_im_ctx_content_type,
_wsc_im_ctx_invoke_action,
_wsc_im_ctx_return_key_disabled,
_wsc_im_ctx_input_panel_data,
_wsc_im_ctx_bidi_direction,
- _wsc_im_ctx_selection_text,
- _wsc_im_ctx_cursor_position,
+ _wsc_im_ctx_cursor_position
};
static void
}
void
- socket_helper_get_surrounding_text (int id, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after) {
- LOGD ("client id:%d", id);
+ socket_helper_get_surrounding_text (int id, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after, const int fd) {
+ LOGD ("client id:%d, fd:%d", id, fd);
WSCContextISF* ic = find_ic (context_id);
- wl_input_method_context_get_surrounding_text(ic->im_ctx, ic->serial, maxlen_before, maxlen_after);
+ wl_input_method_context_get_surrounding_text(ic->im_ctx, maxlen_before, maxlen_after, fd);
}
void
}
void
- socket_helper_get_selection (int id, uint32 context_id) {
- LOGD ("client id:%d", id);
+ socket_helper_get_selection (int id, uint32 context_id, const int fd) {
+ LOGD ("client id:%d, fd:%d", id, fd);
WSCContextISF* ic = find_ic (context_id);
- wl_input_method_context_get_selection_text (ic->im_ctx, ic->serial);
+ wl_input_method_context_get_selection_text (ic->im_ctx, fd);
}
};
}
}
//SCIM_TRANS_CMD_GET_SURROUNDING_TEXT
- void socket_helper_get_surrounding_text (int client, String uuid, uint32 maxlen_before, uint32 maxlen_after) {
+ void socket_helper_get_surrounding_text (int client, String uuid, uint32 maxlen_before, uint32 maxlen_after, const int fd) {
SCIM_DEBUG_MAIN (4) << __FUNCTION__ << " (" << client << ")\n";
LOGD ("");
int focused_client;
ClientInfo client_info = socket_get_client_info (focused_client);
if (client_info.type == FRONTEND_CLIENT) {
- m_panel_agent_manager.socket_helper_get_surrounding_text (focused_client, focused_context, maxlen_before, maxlen_after);
+ m_panel_agent_manager.socket_helper_get_surrounding_text (focused_client, focused_context, maxlen_before, maxlen_after, fd);
}
}
//SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT
}
}
//SCIM_TRANS_CMD_GET_SELECTION
- void socket_helper_get_selection (int client, String uuid) {
+ void socket_helper_get_selection (int client, String uuid, const int fd) {
SCIM_DEBUG_MAIN (4) << __FUNCTION__ << " (" << client << ")\n";
LOGD ("");
int focused_client;
ClientInfo client_info = socket_get_client_info (focused_client);
if (client_info.type == FRONTEND_CLIENT) {
- m_panel_agent_manager.socket_helper_get_selection (focused_client, focused_context);
+ m_panel_agent_manager.socket_helper_get_selection (focused_client, focused_context, fd);
}
}
//SCIM_TRANS_CMD_SET_SELECTION
}
//SCIM_TRANS_CMD_GET_SURROUNDING_TEXT
-void InfoManager::socket_helper_get_surrounding_text (int client, String uuid, uint32 maxlen_before, uint32 maxlen_after)
+void InfoManager::socket_helper_get_surrounding_text (int client, String uuid, uint32 maxlen_before, uint32 maxlen_after, const int fd)
{
- m_impl->socket_helper_get_surrounding_text (client, uuid, maxlen_before, maxlen_after);
+ m_impl->socket_helper_get_surrounding_text (client, uuid, maxlen_before, maxlen_after, fd);
}
//SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT
}
//SCIM_TRANS_CMD_GET_SELECTION
-void InfoManager::socket_helper_get_selection (int client, String uuid)
+void InfoManager::socket_helper_get_selection (int client, String uuid, const int fd)
{
- m_impl->socket_helper_get_selection (client, uuid);
+ m_impl->socket_helper_get_selection (client, uuid, fd);
}
//SCIM_TRANS_CMD_SET_SELECTION
void socket_helper_commit_string (int client, uint32 target_ic, String target_uuid, WideString wstr);
//SCIM_TRANS_CMD_GET_SURROUNDING_TEXT
- void socket_helper_get_surrounding_text (int client, String uuid, uint32 maxlen_before, uint32 maxlen_after);
+ void socket_helper_get_surrounding_text (int client, String uuid, uint32 maxlen_before, uint32 maxlen_after, const int fd);
//SCIM_TRANS_CMD_DELETE_SURROUNDING_TEXT
void socket_helper_delete_surrounding_text (int client, uint32 offset, uint32 len);
//SCIM_TRANS_CMD_GET_SELECTION
- void socket_helper_get_selection (int client, String uuid);
+ void socket_helper_get_selection (int client, String uuid, const int fd);
//SCIM_TRANS_CMD_SET_SELECTION
void socket_helper_set_selection (int client, uint32 start, uint32 end);
//SCIM_TRANS_CMD_GET_SURROUNDING_TEXT
//socket_helper_get_surrounding_text
-void PanelAgentBase::socket_helper_get_surrounding_text (int client, uint32 context, uint32 maxlen_before, uint32 maxlen_after)
+void PanelAgentBase::socket_helper_get_surrounding_text (int client, uint32 context, uint32 maxlen_before, uint32 maxlen_after, const int fd)
{
LOGW ("not implemented for %s", m_name.c_str ());
}
LOGD ("not implemented ");
}
//SCIM_TRANS_CMD_GET_SELECTION
-void PanelAgentBase::socket_helper_get_selection (int client, uint32 context)
+void PanelAgentBase::socket_helper_get_selection (int client, uint32 context, const int fd)
{
LOGW ("not implemented for %s", m_name.c_str ());
}
*
* @return none.
*/
- virtual void socket_helper_get_surrounding_text (int client, uint32 context, uint32 maxlen_before, uint32 maxlen_after);
+ virtual void socket_helper_get_surrounding_text (int client, uint32 context, uint32 maxlen_before, uint32 maxlen_after, const int fd);
/**
* @brief socket_helper_delete_surrounding_text.
*
* @return none.
*/
- virtual void socket_helper_get_selection (int client, uint32 context);
+ virtual void socket_helper_get_selection (int client, uint32 context, const int fd);
/**
* @brief socket_helper_set_selection.
_p->socket_helper_key_event (id, context_id, cmd, key);
}
-void PanelAgentManager::socket_helper_get_surrounding_text (int id, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after)
+void PanelAgentManager::socket_helper_get_surrounding_text (int id, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after, const int fd)
{
PanelAgentPointer _p = m_impl->get_panel_agent_by_id (id);
if (!_p.null ())
- _p->socket_helper_get_surrounding_text (id, context_id, maxlen_before, maxlen_after);
+ _p->socket_helper_get_surrounding_text (id, context_id, maxlen_before, maxlen_after, fd);
}
void PanelAgentManager::socket_helper_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len)
_p->socket_helper_delete_surrounding_text (id, context_id, offset, len);
}
-void PanelAgentManager::socket_helper_get_selection (int id, uint32 context_id)
+void PanelAgentManager::socket_helper_get_selection (int id, uint32 context_id, const int fd)
{
PanelAgentPointer _p = m_impl->get_panel_agent_by_id (id);
if (!_p.null ())
- _p->socket_helper_get_selection (id, context_id);
+ _p->socket_helper_get_selection (id, context_id, fd);
}
void PanelAgentManager::socket_helper_set_selection (int id, uint32 context_id, uint32 start, uint32 end)
void helper_process_imengine_event (int client, uint32 context, const String& ic_uuid, const Transaction& nest_transaction);
void process_helper_event (int client, uint32 context, String target_uuid, String active_uuid, Transaction& nest_trans);
void socket_helper_key_event (int client, uint32 context, int cmd , KeyEvent& key);
- void socket_helper_get_surrounding_text (int client, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after);
+ void socket_helper_get_surrounding_text (int client, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after, const int fd);
void socket_helper_delete_surrounding_text (int client, uint32 context_id, uint32 offset, uint32 len);
- void socket_helper_get_selection (int client, uint32 context_id);
+ void socket_helper_get_selection (int client, uint32 context_id, const int fd);
void socket_helper_set_selection (int client, uint32 context_id, uint32 start, uint32 end);
void update_ise_input_context (int focused_client, uint32 focused_context, uint32 type, uint32 value);
void send_private_command (int focused_client, uint32 focused_context, String command);
#include <string.h>
#include <unistd.h>
+#include <fcntl.h>
#include "scim_private.h"
#include "scim.h"
HelperAgent::get_surrounding_text (int maxlen_before, int maxlen_after, String &text, int &cursor)
{
LOGD ("");
- if (m_impl->surrounding_text) {
- free (m_impl->surrounding_text);
- m_impl->surrounding_text = NULL;
- }
if (!m_impl->socket_active.is_connected ())
return;
m_impl->send.put_data (maxlen_after);
m_impl->send.write_to_socket (m_impl->socket_active, m_impl->magic_active);
+#ifdef WAYLAND
+ int filedes[2];
+ if (pipe2(filedes,O_CLOEXEC|O_NONBLOCK) ==-1 ) {
+ LOGD ("create pipe failed");
+ return;
+ }
+ LOGD("%d,%d",filedes[0],filedes[1]);
+
+ m_impl->socket_active.write_fd (filedes[1]);
+ close (filedes[1]);
+
+ for (int i = 0; i < 3; i++) {
+ int fds[3];
+ fds[0] = m_impl->socket_active.get_id();
+ fds[1] = filedes[0];
+ fds[2] = 0;
+ if (!scim_wait_for_data (fds)) {
+ LOGE ("");
+ break;
+ }
+
+ if (fds[1]) {
+ char buff[512];
+ int len = read (fds[1], buff, sizeof(buff));
+ if (len <= 0)
+ break;
+ else {
+ buff[len] = '\0';
+ text.append (buff);
+ }
+ }
+ if (fds[0])
+ filter_event ();
+ }
+ close (filedes[0]);
+ cursor = m_impl->cursor_pos;
+#else
+ if (m_impl->surrounding_text) {
+ free (m_impl->surrounding_text);
+ m_impl->surrounding_text = NULL;
+ }
+
for (int i = 0; i < 3; i++) {
if (filter_event () && m_impl->surrounding_text) {
text = m_impl->surrounding_text;
free (m_impl->surrounding_text);
m_impl->surrounding_text = NULL;
}
+#endif
}
/**
HelperAgent::get_selection_text (String &text)
{
LOGD ("");
- if (m_impl->selection_text) {
- free (m_impl->selection_text);
- m_impl->selection_text = NULL;
- }
if (!m_impl->socket_active.is_connected ())
return;
m_impl->send.put_command (SCIM_TRANS_CMD_GET_SELECTION);
m_impl->send.put_data ("");
m_impl->send.write_to_socket (m_impl->socket_active, m_impl->magic_active);
+#ifdef WAYLAND
+ int filedes[2];
+ if (pipe2 (filedes,O_CLOEXEC|O_NONBLOCK) == -1 ) {
+ LOGD ("create pipe failed");
+ return;
+ }
+ LOGD("%d,%d", filedes[0], filedes[1]);
+
+ m_impl->socket_active.write_fd (filedes[1]);
+ close (filedes[1]);
+
+ for (int i = 0; i < 3; i++) {
+ int fds[3];
+ fds[0] = m_impl->socket_active.get_id();
+ fds[1] = filedes[0];
+ fds[2] = 0;
+ if (!scim_wait_for_data (fds)) {
+ LOGE ("");
+ break;
+ }
+
+ if (fds[1]) {
+ char buff[512];
+ int len = read (fds[1], buff, sizeof(buff));
+ if (len <= 0)
+ break;
+ else {
+ buff[len] = '\0';
+ text.append (buff);
+ }
+ }
+ if (fds[0])
+ filter_event ();
+ }
+ close (filedes[0]);
+#else
+ if (m_impl->selection_text) {
+ free (m_impl->selection_text);
+ m_impl->selection_text = NULL;
+ }
for (int i = 0; i < 3; i++) {
if (filter_event () && m_impl->selection_text) {
break;
}
}
-
if (m_impl->selection_text) {
free (m_impl->selection_text);
m_impl->selection_text = NULL;
}
+#endif
}
/**
return m_id >= 0;
}
+ void write_fd (int fd) {
+ struct msghdr msg;
+ char buff[]={0};
+ struct iovec iov[1];
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ union{
+ struct cmsghdr cm;
+ char control[CMSG_SPACE (sizeof (int))];
+ }control_un;
+ struct cmsghdr *cmptr;
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof(control_un.control);
+ cmptr = CMSG_FIRSTHDR (&msg);
+ cmptr->cmsg_len = CMSG_LEN (sizeof(int));
+ cmptr->cmsg_level = SOL_SOCKET;
+ cmptr->cmsg_type = SCM_RIGHTS;
+ memcpy (CMSG_DATA (cmptr), &fd, sizeof(int));
+#else
+ msg.msg_accrights = (caddr_t)&fd;
+ msg.msg_accrightslen = sizeof (int);
+#endif
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ iov[0].iov_base = buff;
+ iov[0].iov_len = sizeof (buff);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ sendmsg (m_id, &msg, 0);
+ }
+
+ void read_fd (int *fd) {
+ struct msghdr msg;
+ char buff[]={0};
+ struct iovec iov[1];
+#ifndef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ int newfd;
+#endif
+
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ union{
+ struct cmsghdr cm;
+ char control[CMSG_SPACE (sizeof (int))];
+ }control_un;
+ struct cmsghdr *cmptr;
+ msg.msg_control = control_un.control;
+ msg.msg_controllen = sizeof (control_un.control);
+#else
+ msg.msg_accrights = (caddr_t) &newfd;
+ msg.msg_accrightslen = sizeof (int);
+#endif
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ iov[0].iov_base = buff;
+ iov[0].iov_len = sizeof (buff);
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ while (true) {
+ if (recvmsg (m_id, &msg, 0) <= 0) {
+ if (errno == EAGAIN)
+ continue;
+ *fd = -1;
+ LOGE ("%d", errno);
+ return;
+ }
+ break;
+ }
+#ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
+ cmptr = CMSG_FIRSTHDR (&msg);
+ if ((cmptr != NULL) && (cmptr->cmsg_len == CMSG_LEN (sizeof (int)))) {
+ if (cmptr->cmsg_level != SOL_SOCKET || cmptr->cmsg_type != SCM_RIGHTS) {
+ *fd = -1;
+ LOGE ("unknow message");
+ return;
+ }
+ memcpy (fd, CMSG_DATA (cmptr), sizeof(int));
+ }
+ else
+ {
+ *fd = -1;
+ LOGE ("unknow message format");
+ }
+#else
+ if (msg.msg_accrightslen == sizeof (int))
+ *fd = newfd;
+ else
+ *fd = -1;
+#endif
+ }
+
int read (void *buf, size_t size) {
if (!buf || !size) { m_err = EINVAL; return -1; }
if (m_id < 0) { m_err = EBADF; return -1; }
return m_impl->set_nonblock_mode ();
}
+void
+Socket::write_fd (int fd) const
+{
+ m_impl->write_fd (fd);
+}
+
+void
+Socket::read_fd (int *fd) const
+{
+ m_impl->read_fd (fd);
+}
+
bool
Socket::create (SocketFamily family)
{
return String ("");
}
+bool
+scim_wait_for_data (int *fds)
+{
+ fd_set _fd_set;
+ int max_fd;
+ int *_fds;
+ if (fds == NULL)
+ return false;
+ max_fd = *fds;
+ FD_ZERO (&_fd_set);
+ for (_fds = fds; *_fds; _fds++) {
+ FD_SET (*_fds, &_fd_set);
+ if (*_fds > max_fd)
+ max_fd = *_fds;
+ }
+ while (true) {
+ int ret = select (max_fd + 1, &_fd_set, NULL, NULL, NULL);
+ if (ret < 0) {
+ if (errno == EINTR)
+ continue;
+ LOGW ("%d", errno);
+ return false;
+ }
+ else if (ret == 0)
+ continue;
+ else
+ break;
+ }
+
+ for (_fds = fds; *_fds; _fds++) {
+ if (!FD_ISSET(*_fds, &_fd_set))
+ *_fds = 0;
+ }
+ return true;
+}
+
+
} // namespace scim
/*
*/
int set_nonblock_mode ();
+ void write_fd (int fd) const;
+ void read_fd (int *fd) const;
+
+
protected:
/**
const String &client_types,
const Socket &socket,
int timeout = -1);
+
+EXAPI bool scim_wait_for_data (int *fds);
/** @} */
} // namespace scim