diff options
Diffstat (limited to 'common')
| -rw-r--r-- | common/Makefile.am | 4 | ||||
| -rw-r--r-- | common/glib-ectomy.c | 185 | ||||
| -rw-r--r-- | common/glib-ectomy.h | 92 | 
3 files changed, 280 insertions, 1 deletions
| diff --git a/common/Makefile.am b/common/Makefile.am index 71592813..5a5a4702 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,8 +1,10 @@ -noinst_LIBRARIES = libtextfile.a +noinst_LIBRARIES = libtextfile.a libglib-ectomy.a  libtextfile_a_SOURCES = textfile.h textfile.c +libglib_ectomy_a_SOURCES = glib-ectomy.h glib-ectomy.c +  noinst_PROGRAMS = test_textfile  test_textfile_LDADD = libtextfile.a diff --git a/common/glib-ectomy.c b/common/glib-ectomy.c new file mode 100644 index 00000000..bea7f47c --- /dev/null +++ b/common/glib-ectomy.c @@ -0,0 +1,185 @@ +#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; +} diff --git a/common/glib-ectomy.h b/common/glib-ectomy.h new file mode 100644 index 00000000..c507e3c7 --- /dev/null +++ b/common/glib-ectomy.h @@ -0,0 +1,92 @@ +#ifndef __GLIB_ECTOMY_H +#define __GLIB_ECTOMY_H + +#include <stdlib.h> +#include <sys/poll.h> + +typedef char	gchar; +typedef short	gshort; +typedef long	glong; +typedef int	gint; +typedef gint	gboolean; + +typedef unsigned char	guchar; +typedef unsigned short	gushort; +typedef unsigned long	gulong; +typedef unsigned int	guint; + +typedef float	gfloat; +typedef double	gdouble; + +typedef void *		gpointer; +typedef const void *	gconstpointer; + +typedef size_t	gsize; +typedef ssize_t	gssize; + +#ifndef SSIZE_MAX +#define SSIZE_MAX	INT_MAX +#endif + +typedef struct _GIOChannel { +	int fd; +} GIOChannel; + +typedef struct _GMainContext { +	int dummy; +} GMainContext; + +typedef struct _GMainLoop { +	int bail; +} GMainLoop; + +typedef enum { +	G_IO_ERROR_NONE, +	G_IO_ERROR_AGAIN, +	G_IO_ERROR_INVAL, +	G_IO_ERROR_UNKNOWN +} GIOError; + +typedef enum { +	G_IO_STATUS_ERROR	= -1, +	G_IO_STATUS_NORMAL	= 0, +	G_IO_STATUS_EOF		= 1, +	G_IO_STATUS_AGAIN	= 2 +} GIOStatus; + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef TRUE +#define TRUE (!FALSE) +#endif + +typedef enum { +	G_IO_IN		= POLLIN, +	G_IO_OUT	= POLLOUT, +	G_IO_PRI	= POLLPRI, +	G_IO_ERR	= POLLERR, +	G_IO_HUP	= POLLHUP, +	G_IO_NVAL	= POLLNVAL +} GIOCondition; + +typedef gboolean (*GIOFunc) (GIOChannel *source, GIOCondition condition, gpointer data); + +GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read); +void g_io_channel_close(GIOChannel *channel); + +GIOChannel *g_io_channel_unix_new(int fd); +gint g_io_channel_unix_get_fd(GIOChannel *channel); +guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, GIOFunc func, gpointer user_data); +void g_io_remove_watch(guint id); + +GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running); +void g_main_loop_run(GMainLoop *loop); +void g_main_loop_quit(GMainLoop *loop); + +#define g_main_new(is_running)	g_main_loop_new(NULL, is_running); +#define g_main_run(loop)	g_main_loop_run(loop) +#define g_main_quit(loop)	g_main_loop_quit(loop) + +#endif /* __GLIB_ECTOMY_H */ | 
