blob: bea7f47c82f6cfd8cc6e7b2f8994dfa374409d86 [file] [log] [blame]
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <limits.h>
#include "glib-ectomy.h"
GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read)
{
int fd = channel->fd;
gssize result;
/* At least according to the Debian manpage for read */
if (count > SSIZE_MAX)
count = SSIZE_MAX;
retry:
result = read (fd, buf, count);
if (result < 0) {
*bytes_read = 0;
switch (errno) {
#ifdef EINTR
case EINTR:
goto retry;
#endif
#ifdef EAGAIN
case EAGAIN:
return G_IO_STATUS_AGAIN;
#endif
default:
return G_IO_STATUS_ERROR;
}
}
*bytes_read = result;
return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF;
}
void g_io_channel_close(GIOChannel *channel)
{
if (!channel)
return;
close(channel->fd);
memset(channel, 0, sizeof(channel));
free(channel);
}
GIOChannel *g_io_channel_unix_new(int fd)
{
GIOChannel *channel;
channel = malloc(sizeof(GIOChannel));
if (!channel)
return NULL;
channel->fd = fd;
return channel;
}
gint g_io_channel_unix_get_fd(GIOChannel *channel)
{
return channel->fd;
}
struct watch {
guint id;
GIOChannel *channel;
GIOCondition condition;
GIOFunc func;
gpointer user_data;
struct watch *next;
};
static struct watch watch_head = { .id = 0, .next = 0 };
void g_io_remove_watch(guint id)
{
struct watch *w, *p;
for (p = &watch_head, w = watch_head.next; w; w = w->next)
if (w->id == id) {
p->next = w->next;
free (w);
return;
}
}
guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, GIOFunc func, gpointer user_data)
{
struct watch *watch = malloc(sizeof(struct watch));
watch->id = ++watch_head.id;
watch->channel = channel;
watch->condition = condition;
watch->func = func;
watch->user_data = user_data;
watch->next = watch_head.next;
watch_head.next = watch;
return watch->id;
}
GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running)
{
GMainLoop *ml;
ml = malloc(sizeof(GMainLoop));
if (!ml)
return NULL;
ml->bail = 0;
return ml;
}
void g_main_loop_run(GMainLoop *loop)
{
int open_max = sysconf(_SC_OPEN_MAX);
struct pollfd *ufds;
ufds = malloc(open_max * sizeof(struct pollfd));
if (!ufds)
return;
while (!loop->bail) {
int nfds, rc, i;
struct watch *p, *w;
nfds = 0;
for (w = watch_head.next; w != NULL; w = w->next) {
ufds[nfds].fd = w->channel->fd;
ufds[nfds].events = w->condition;
ufds[nfds].revents = 0;
nfds++;
}
rc = poll(ufds, nfds, -1);
if (rc < 0)
continue;
p = &watch_head;
w = watch_head.next;
i = 0;
while (w) {
if (ufds[i].revents) {
gboolean keep = w->func(w->channel, ufds[i].revents, w->user_data);
if (!keep) {
p->next = w->next;
memset(w, 0, sizeof(*w));
w = p->next;
i++;
continue;
}
}
p = w;
w = w->next;
i++;
}
}
free(ufds);
}
void g_main_loop_quit(GMainLoop *loop)
{
loop->bail = 1;
}