From 8a9d1780d1e3548bae13eaaae56afdcf99ed297d Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Sat, 20 Jan 2007 06:03:26 +0000 Subject: Add main loop and single list functions --- eglib/gmain.c | 815 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 815 insertions(+) create mode 100644 eglib/gmain.c (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c new file mode 100644 index 00000000..a3bf3760 --- /dev/null +++ b/eglib/gmain.c @@ -0,0 +1,815 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct timeout { + guint id; + guint interval; + struct timeval expiration; + gpointer data; + GSourceFunc function; +}; + +struct _GIOChannel { + int fd; + gboolean closed; + gboolean close_on_unref; +}; + +struct _GMainContext { + guint next_id; + glong next_timeout; + + GSList *timeouts; + GSList *proc_timeouts; + gboolean timeout_lock; + + GSList *watches; + GSList *proc_watches; + gboolean watch_lock; +}; + +struct _GMainLoop { + gboolean is_running; + GMainContext *context; +}; + +GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read) +{ + int fd = channel->fd; + gssize result; + + if (channel->closed) + return G_IO_STATUS_ERROR; + + /* 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 || channel->closed) + return; + + close(channel->fd); + + channel->closed = TRUE; +} + +void g_io_channel_unref(GIOChannel *channel) +{ + if (!channel) + return; + + if (channel->close_on_unref && channel->fd >= 0) + g_io_channel_close(channel); + + free(channel); +} + +GIOChannel *g_io_channel_unix_new(int fd) +{ + GIOChannel *channel; + + channel = malloc(sizeof(GIOChannel)); + if (!channel) + return NULL; + + memset(channel, 0, sizeof(GIOChannel)); + + channel->fd = fd; + + return channel; +} + +void g_io_channel_set_close_on_unref(GIOChannel *channel, gboolean do_close) +{ + channel->close_on_unref = do_close; +} + +gint g_io_channel_unix_get_fd(GIOChannel *channel) +{ + if (channel->closed) + return -1; + + return channel->fd; +} + +struct watch { + guint id; + GIOChannel *channel; + gint priority; + GIOCondition condition; + short *revents; + GIOFunc func; + gpointer user_data; + GDestroyNotify destroy; +}; + +static GMainContext *default_context = NULL; + +static void watch_free(struct watch *watch) +{ + if (watch->destroy) + watch->destroy(watch->user_data); + free(watch); +} + +static GMainContext *g_main_context_default() +{ + if (default_context) + return default_context; + + default_context = malloc(sizeof(GMainContext)); + if (!default_context) + return NULL; + + memset(default_context, 0, sizeof(GMainContext)); + + default_context->next_timeout = -1; + default_context->next_id = 1; + + return default_context; +} + +void g_io_remove_watch(guint id) +{ + GMainContext *context = g_main_context_default(); + GSList *l; + struct watch *w; + + if (!context) + return; + + for (l = context->watches; l != NULL; l = l->next) { + w = l->data; + + if (w->id != id) + continue; + + context->watches = g_slist_remove(context->watches, w); + watch_free(w); + + return; + } + + for (l = context->proc_watches; l != NULL; l = l->next) { + w = l->data; + + if (w->id != id) + continue; + + context->proc_watches = g_slist_remove(context->proc_watches, w); + watch_free(w); + + return; + } +} + +int watch_prio_cmp(struct watch *w1, struct watch *w2) +{ + return w1->priority - w2->priority; +} + +#define watch_list_add(l, w) g_slist_insert_sorted((l), (w), (GCompareFunc) watch_prio_cmp) + +guint g_io_add_watch_full(GIOChannel *channel, gint priority, + GIOCondition condition, GIOFunc func, + gpointer user_data, GDestroyNotify notify) +{ + struct watch *watch; + GMainContext *context = g_main_context_default(); + + if (!context) + return 0; + + watch = malloc(sizeof(struct watch)); + if (!watch) + return 0; + + watch->id = context->next_id++; + watch->channel = channel; + watch->priority = priority; + watch->condition = condition; + watch->func = func; + watch->user_data = user_data; + watch->destroy = notify; + + if (context->watch_lock) + context->proc_watches = watch_list_add(context->proc_watches, watch); + else + context->watches = watch_list_add(context->watches, watch); + + return watch->id; +} + +guint g_io_add_watch(GIOChannel *channel, GIOCondition condition, + GIOFunc func, gpointer user_data) +{ + return g_io_add_watch_full(channel, 0, condition, + func, user_data, NULL); +} + +GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) +{ + GMainLoop *ml; + + if (!context) + context = g_main_context_default(); + + if (!context) + return NULL; + + ml = malloc(sizeof(GMainLoop)); + if (!ml) + return NULL; + + memset(ml, 0, sizeof(GMainLoop)); + + ml->context = context; + ml->is_running = is_running; + + return ml; +} + +static void timeout_handlers_prepare(GMainContext *context) +{ + GSList *l; + struct timeval tv; + glong msec, timeout = LONG_MAX; + + gettimeofday(&tv, NULL); + + for (l = context->timeouts; l != NULL; l = l->next) { + struct timeout *t = l->data; + + /* calculate the remainning time */ + msec = (t->expiration.tv_sec - tv.tv_sec) * 1000 + + (t->expiration.tv_usec - tv.tv_usec) / 1000; + if (msec < 0) + msec = 0; + + timeout = MIN_TIMEOUT(timeout, msec); + } + + /* set to min value found or NO timeout */ + context->next_timeout = (timeout != LONG_MAX ? timeout : -1); +} + +static int ptr_cmp(const void *t1, const void *t2) +{ + return t1 - t2; +} + +static void timeout_handlers_check(GMainContext *context) +{ + struct timeval tv; + + gettimeofday(&tv, NULL); + + context->timeout_lock = TRUE; + + while (context->timeouts) { + struct timeout *t = context->timeouts->data; + glong secs, msecs; + gboolean ret; + + if (timercmp(&tv, &t->expiration, <)) { + context->timeouts = g_slist_remove(context->timeouts, t); + context->proc_timeouts = g_slist_append(context->proc_timeouts, t); + continue; + } + + ret = t->function(t->data); + + /* Check if the handler was removed/freed by the callback + * function */ + if (!g_slist_find_custom(context->timeouts, t, ptr_cmp)) + continue; + + context->timeouts = g_slist_remove(context->timeouts, t); + + if (!ret) { + free(t); + continue; + } + + /* update the next expiration time */ + secs = t->interval / 1000; + msecs = t->interval - secs * 1000; + + t->expiration.tv_sec = tv.tv_sec + secs; + t->expiration.tv_usec = tv.tv_usec + msecs * 1000; + if (t->expiration.tv_usec >= 1000000) { + t->expiration.tv_usec -= 1000000; + t->expiration.tv_sec++; + } + + context->proc_timeouts = g_slist_append(context->proc_timeouts, t); + } + + context->timeouts = context->proc_timeouts; + context->proc_timeouts = NULL; + context->timeout_lock = FALSE; +} + +void g_main_loop_run(GMainLoop *loop) +{ + int open_max = sysconf(_SC_OPEN_MAX); + struct pollfd *ufds; + GMainContext *context = loop->context; + + ufds = malloc(open_max * sizeof(struct pollfd)); + if (!ufds) + return; + + loop->is_running = TRUE; + + while (loop->is_running) { + int nfds; + GSList *l; + struct watch *w; + + for (nfds = 0, l = context->watches; l != NULL; l = l->next, nfds++) { + w = l->data; + ufds[nfds].fd = w->channel->fd; + ufds[nfds].events = w->condition; + ufds[nfds].revents = 0; + w->revents = &ufds[nfds].revents; + } + + /* calculate the next timeout */ + timeout_handlers_prepare(context); + + if (poll(ufds, nfds, context->next_timeout) < 0) + continue; + + context->watch_lock = TRUE; + + while (context->watches) { + gboolean ret; + + w = context->watches->data; + + if (!*w->revents) { + context->watches = g_slist_remove(context->watches, w); + context->proc_watches = watch_list_add(context->proc_watches, w); + continue; + } + + ret = w->func(w->channel, *w->revents, w->user_data); + + /* Check if the watch was removed/freed by the callback + * function */ + if (!g_slist_find_custom(context->watches, w, ptr_cmp)) + continue; + + context->watches = g_slist_remove(context->watches, w); + + if (!ret) { + watch_free(w); + continue; + } + + context->proc_watches = watch_list_add(context->proc_watches, w); + } + + context->watches = context->proc_watches; + context->proc_watches = NULL; + context->watch_lock = FALSE; + + /* check expired timers */ + timeout_handlers_check(loop->context); + } + + free(ufds); +} + +void g_main_loop_quit(GMainLoop *loop) +{ + loop->is_running = FALSE; +} + +void g_main_loop_unref(GMainLoop *loop) +{ + if (!loop->context) + return; + + g_slist_foreach(loop->context->watches, (GFunc)watch_free, NULL); + g_slist_free(loop->context->watches); + + g_slist_foreach(loop->context->timeouts, (GFunc)free, NULL); + g_slist_free(loop->context->timeouts); + + free(loop->context); + loop->context = NULL; +} + +guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) +{ + GMainContext *context = g_main_context_default(); + struct timeval tv; + guint secs; + guint msecs; + struct timeout *t; + + if (!context || !function) + return 0; + + t = malloc(sizeof(*t)); + + if (!t) + return 0; + + memset(t, 0, sizeof(*t)); + t->interval = interval; + t->function = function; + t->data = data; + + gettimeofday(&tv, NULL); + + secs = interval /1000; + msecs = interval - secs * 1000; + + t->expiration.tv_sec = tv.tv_sec + secs; + t->expiration.tv_usec = tv.tv_usec + msecs * 1000; + + if (t->expiration.tv_usec >= 1000000) { + t->expiration.tv_usec -= 1000000; + t->expiration.tv_sec++; + } + + /* attach the timeout the default context */ + t->id = context->next_id++; + + if (context->timeout_lock) + context->proc_timeouts = g_slist_prepend(context->proc_timeouts, t); + else + context->timeouts = g_slist_prepend(context->timeouts, t); + + return t->id; +} + +gint g_timeout_remove(const guint id) +{ + GMainContext *context = g_main_context_default(); + GSList *l; + struct timeout *t; + + if (!context) + return -1; + + l = context->timeouts; + + while (l) { + t = l->data; + l = l->next; + + if (t->id != id) + continue; + + context->timeouts = g_slist_remove(context->timeouts, t); + free(t); + + return 0; + } + + l = context->proc_timeouts; + + while (l) { + t = l->data; + l = l->next; + + if (t->id != id) + continue; + + context->proc_timeouts = g_slist_remove(context->proc_timeouts, t); + free(t); + + return 0; + } + + return -1; +} + +/* UTF-8 Validation: approximate copy/paste from glib2. */ + +#define UNICODE_VALID(c) \ + ((c) < 0x110000 && \ + (((c) & 0xFFFFF800) != 0xD800) && \ + ((c) < 0xFDD0 || (c) > 0xFDEF) && \ + ((c) & 0xFFFE) != 0xFFFE) + +#define CONTINUATION_CHAR(c, val) \ + do { \ + if (((c) & 0xc0) != 0x80) /* 10xxxxxx */ \ + goto failed; \ + (val) <<= 6; \ + (val) |= (c) & 0x3f; \ + } while (0) + +#define INCREMENT_AND_CHECK_MAX(p, i, max_len) \ + do { \ + (i)++; \ + if ((p)[(i)] == '\0' || ((max_len) >= 0 && (i) >= (max_len))) \ + goto failed; \ + } while (0) + + +gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end) +{ + unsigned long val, min, i; + const unsigned char *p, *last; + + min = val = 0; + + for (p = (unsigned char *) str, i = 0; p[i]; i++) { + if (max_len >= 0 && i >= max_len) + break; + + if (p[i] < 128) + continue; + + last = &p[i]; + + if ((p[i] & 0xe0) == 0xc0) { /* 110xxxxx */ + if ((p[i] & 0x1e) == 0) + goto failed; + INCREMENT_AND_CHECK_MAX(p, i, max_len); + if ((p[i] & 0xc0) != 0x80) + goto failed; /* 10xxxxxx */ + } else { + if ((p[i] & 0xf0) == 0xe0) { + /* 1110xxxx */ + min = (1 << 11); + val = p[i] & 0x0f; + goto two_remaining; + } else if ((p[i] & 0xf8) == 0xf0) { + /* 11110xxx */ + min = (1 << 16); + val = p[i] & 0x07; + } else + goto failed; + + INCREMENT_AND_CHECK_MAX(p, i, max_len); + CONTINUATION_CHAR(p[i], val); +two_remaining: + INCREMENT_AND_CHECK_MAX(p, i, max_len); + CONTINUATION_CHAR(p[i], val); + + INCREMENT_AND_CHECK_MAX(p, i, max_len); + CONTINUATION_CHAR(p[i], val); + + if (val < min || !UNICODE_VALID(val)) + goto failed; + } + } + + if (end) + *end = (const gchar *) &p[i]; + + return TRUE; + +failed: + if (end) + *end = (const gchar *) last; + + return FALSE; +} + +/* GSList functions */ + +GSList *g_slist_append(GSList *list, void *data) +{ + GSList *entry, *tail; + + entry = malloc(sizeof(GSList)); + /* FIXME: this currently just silently fails */ + if (!entry) + return list; + + entry->data = data; + entry->next = NULL; + + if (!list) + return entry; + + /* Find the end of the list */ + for (tail = list; tail->next; tail = tail->next); + + tail->next = entry; + + return list; +} + +GSList *g_slist_prepend(GSList *list, void *data) +{ + GSList *entry; + + entry = malloc(sizeof(GSList)); + /* FIXME: this currently just silently fails */ + if (!entry) + return list; + + entry->data = data; + entry->next = list; + + return entry; +} + +GSList *g_slist_insert_sorted(GSList *list, void *data, GCompareFunc cmp_func) +{ + GSList *tmp, *prev, *entry; + int cmp; + + entry = malloc(sizeof(GSList)); + if (!entry) + return list; + + entry->data = data; + entry->next = NULL; + + if (!list) + return entry; + + prev = NULL; + tmp = list; + + cmp = cmp_func(data, tmp->data); + + while (tmp->next && cmp > 0) { + prev = tmp; + tmp = tmp->next; + + cmp = cmp_func(data, tmp->data); + } + + if (!tmp->next && cmp > 0) { + tmp->next = entry; + return list; + } + + if (prev) { + prev->next = entry; + entry->next = tmp; + return list; + } else { + entry->next = list; + return entry; + } +} + +GSList *g_slist_remove(GSList *list, void *data) +{ + GSList *l, *next, *prev = NULL, *match = NULL; + + if (!list) + return NULL; + + for (l = list; l != NULL; l = l->next) { + if (l->data == data) { + match = l; + break; + } + prev = l; + } + + if (!match) + return list; + + next = match->next; + + free(match); + + /* If the head was removed, return the next element */ + if (!prev) + return next; + + prev->next = next; + + return list; +} + +GSList *g_slist_find_custom(GSList *list, const void *data, + GCompareFunc cmp_func) +{ + GSList *l; + + for (l = list; l != NULL; l = l->next) { + if (!cmp_func(l->data, data)) + return l; + } + + return NULL; +} + +static GSList *g_slist_sort_merge(GSList *l1, GSList *l2, + GCompareFunc cmp_func) +{ + GSList list, *l; + int cmp; + + l = &list; + + while (l1 && l2) { + cmp = cmp_func(l1->data, l2->data); + + if (cmp <= 0) { + l = l->next = l1; + l1 = l1->next; + } else { + l = l->next = l2; + l2 = l2->next; + } + } + + l->next = l1 ? l1 : l2; + + return list.next; +} + +GSList *g_slist_sort(GSList *list, GCompareFunc cmp_func) +{ + GSList *l1, *l2; + + if (!list || !list->next) + return list; + + l1 = list; + l2 = list->next; + + while ((l2 = l2->next) != NULL) { + if ((l2 = l2->next) == NULL) + break; + l1 = l1->next; + } + + l2 = l1->next; + l1->next = NULL; + + return g_slist_sort_merge(g_slist_sort(list, cmp_func), + g_slist_sort(l2, cmp_func), cmp_func); +} + +int g_slist_length(GSList *list) +{ + int len; + + for (len = 0; list != NULL; list = list->next) + len++; + + return len; +} + +void g_slist_foreach(GSList *list, GFunc func, void *user_data) +{ + while (list) { + GSList *next = list->next; + func(list->data, user_data); + list = next; + } +} + +void g_slist_free(GSList *list) +{ + GSList *l, *next; + + for (l = list; l != NULL; l = next) { + next = l->next; + free(l); + } +} -- cgit From 3fd70cad862febf8f1a60bd47576cb758d085958 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Jan 2007 11:50:05 +0000 Subject: Implement memory allocation functions for eglib --- eglib/gmain.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index a3bf3760..bc1af91a 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -813,3 +813,78 @@ void g_slist_free(GSList *list) free(l); } } + +/* Memory allocation functions */ + +gpointer g_malloc(gulong n_bytes) +{ + gpointer mem; + + if (!n_bytes) + return NULL; + + mem = malloc((size_t) n_bytes); + if (!mem) { + fprintf(stderr, "g_malloc: failed to allocate %lu bytes", + n_bytes); + abort(); + } + + return mem; +} + +gpointer g_malloc0(gulong n_bytes) +{ + gpointer mem; + + if (!n_bytes) + return NULL; + + mem = g_malloc(n_bytes); + + memset(mem, 0, (size_t) n_bytes); + + return mem; +} + +gpointer g_try_malloc(gulong n_bytes) +{ + if (!n_bytes) + return NULL; + + return malloc((size_t) n_bytes); +} + +gpointer g_try_malloc0(gulong n_bytes) +{ + gpointer mem; + + mem = g_try_malloc(n_bytes); + if (mem) + memset(mem, 0, (size_t) n_bytes); + + return mem; +} + +void g_free(gpointer mem) +{ + if (mem) + free(mem); +} + +gchar *g_strdup(const gchar *str) +{ + gchar *s; + + if (!str) + return NULL; + + s = strdup(str); + if (!s) { + fprintf(stderr, "strdup: failed to allocate new string"); + abort(); + } + + return s; +} + -- cgit From 88a2fca09c8a94a11b2a8073fb65f3f3e752d090 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Jan 2007 12:37:21 +0000 Subject: Implement stubs of missing eglib functions --- eglib/gmain.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 188 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index bc1af91a..8566265c 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -80,6 +81,13 @@ retry: return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF; } +GIOError g_io_channel_write(GIOChannel *channel, const gchar *buf, gsize count, + gsize *bytes_written) +{ + /* Not implemented */ + return G_IO_STATUS_ERROR; +} + void g_io_channel_close(GIOChannel *channel) { if (!channel || channel->closed) @@ -166,6 +174,12 @@ static GMainContext *g_main_context_default() return default_context; } +gboolean g_source_remove(guint tag) +{ + /* Not implemented yet */ + return FALSE; +} + void g_io_remove_watch(guint id) { GMainContext *context = g_main_context_default(); @@ -526,6 +540,44 @@ gint g_timeout_remove(const guint id) return -1; } +guint g_idle_add(GSourceFunc func, gpointer user_data) +{ + /* Not implemented */ + return 0; +} + +/* GError */ +void g_error_free(GError *err) +{ + g_free(err->message); + g_free(err); +} + +/* Spawning related functions */ + +gboolean g_spawn_async(const gchar *working_directory, + gchar **argv, gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GPid *child_pid, + GError **error) +{ + /* Not implemented */ + return FALSE; +} + +void g_spawn_close_pid(GPid pid) +{ + return; +} + +guint g_child_watch_add(GPid pid, GChildWatchFunc func, gpointer user_data) +{ + /* Not implemented */ + return 0; +} + /* UTF-8 Validation: approximate copy/paste from glib2. */ #define UNICODE_VALID(c) \ @@ -724,6 +776,18 @@ GSList *g_slist_remove(GSList *list, void *data) return list; } +GSList *g_slist_find(GSList *list, gconstpointer data) +{ + GSList *l; + + for (l = list; l != NULL; l = l->next) { + if (l->data == data) + return l; + } + + return NULL; +} + GSList *g_slist_find_custom(GSList *list, const void *data, GCompareFunc cmp_func) { @@ -888,3 +952,127 @@ gchar *g_strdup(const gchar *str) return s; } +gchar *g_strdup_printf(const gchar *format, ...) +{ + gchar str[1024]; + va_list ap; + + memset(str, 0, sizeof(str)); + + va_start(ap, format); + + vsnprintf(str, sizeof(str) - 1, format, ap); + + va_end(ap); + + return g_strdup(str); +} + +void g_strfreev(gchar **str_array) +{ + int i; + + if (!str_array) + return; + + for (i = 0; str_array[i] != NULL; i++) + g_free(str_array[i]); + + g_free(str_array); +} + +/* g_shell_* */ + +gboolean g_shell_parse_argv(const gchar *command_line, + gint *argcp, + gchar ***argvp, + GError **error) +{ + /* Not implemented */ + return FALSE; +} + +/* GKeyFile */ + +typedef gpointer GHashTable; + +typedef struct _GKeyFileGroup GKeyFileGroup; + +struct _GKeyFile { + GSList *groups; + + GKeyFileGroup *start_group; + GKeyFileGroup *current_group; + + /* Holds up to one line of not-yet-parsed data */ + gchar *parse_buffer; + + /* Used for sizing the output buffer during serialization */ + gsize approximate_size; + + gchar list_separator; + + GKeyFileFlags flags; +}; + +typedef struct _GKeyFileKeyValuePair GKeyFileKeyValuePair; + +struct _GKeyFileGroup { + /* NULL for above first group (which will be comments) */ + const gchar *name; + + /* Special comment that is stuck to the top of a group */ + GKeyFileKeyValuePair *comment; + + GSList *key_value_pairs; + + /* Used in parallel with key_value_pairs for + * increased lookup performance + */ + GHashTable *lookup_map; +}; + +struct _GKeyFileKeyValuePair { + gchar *key; /* NULL for comments */ + gchar *value; +}; + +GKeyFile *g_key_file_new(void) +{ + /* Not implemented */ + return NULL; +} + +void g_key_file_free(GKeyFile *key_file) +{ + /* Not implemented fully */ + g_free(key_file); +} + +gboolean g_key_file_load_from_file(GKeyFile *key_file, + const gchar *file, + GKeyFileFlags flags, + GError **error) +{ + /* Not implemented */ + return FALSE; +} + +gchar *g_key_file_get_string(GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error) +{ + /* Not implemented */ + return NULL; +} + +gboolean g_key_file_get_boolean(GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error) +{ + /* Not implemented */ + return FALSE; +} + -- cgit From f2fdd9fee9109cb0fa7f37a26acd0b1eaf2f40f2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Jan 2007 14:43:59 +0000 Subject: Get rid of g_timeout_remove and g_io_remove_watch in favor for g_source_remove --- eglib/gmain.c | 114 ++++++++++++++++++++++++++++++---------------------------- 1 file changed, 59 insertions(+), 55 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 8566265c..ea3adebd 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -174,21 +174,11 @@ static GMainContext *g_main_context_default() return default_context; } -gboolean g_source_remove(guint tag) +static gboolean g_io_remove_watch(GMainContext *context, guint id) { - /* Not implemented yet */ - return FALSE; -} - -void g_io_remove_watch(guint id) -{ - GMainContext *context = g_main_context_default(); GSList *l; struct watch *w; - if (!context) - return; - for (l = context->watches; l != NULL; l = l->next) { w = l->data; @@ -198,7 +188,7 @@ void g_io_remove_watch(guint id) context->watches = g_slist_remove(context->watches, w); watch_free(w); - return; + return TRUE; } for (l = context->proc_watches; l != NULL; l = l->next) { @@ -210,8 +200,64 @@ void g_io_remove_watch(guint id) context->proc_watches = g_slist_remove(context->proc_watches, w); watch_free(w); - return; + return TRUE; + } + + return FALSE; +} + +static gboolean g_timeout_remove(GMainContext *context, const guint id) +{ + GSList *l; + struct timeout *t; + + l = context->timeouts; + + while (l) { + t = l->data; + l = l->next; + + if (t->id != id) + continue; + + context->timeouts = g_slist_remove(context->timeouts, t); + free(t); + + return TRUE; } + + l = context->proc_timeouts; + + while (l) { + t = l->data; + l = l->next; + + if (t->id != id) + continue; + + context->proc_timeouts = g_slist_remove(context->proc_timeouts, t); + free(t); + + return TRUE; + } + + return FALSE; +} + +gboolean g_source_remove(guint tag) +{ + GMainContext *context = g_main_context_default(); + + if (!context) + return FALSE; + + if (g_io_remove_watch(context, tag)) + return TRUE; + + if (g_timeout_remove(context, tag)) + return TRUE; + + return FALSE; } int watch_prio_cmp(struct watch *w1, struct watch *w2) @@ -498,48 +544,6 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) return t->id; } -gint g_timeout_remove(const guint id) -{ - GMainContext *context = g_main_context_default(); - GSList *l; - struct timeout *t; - - if (!context) - return -1; - - l = context->timeouts; - - while (l) { - t = l->data; - l = l->next; - - if (t->id != id) - continue; - - context->timeouts = g_slist_remove(context->timeouts, t); - free(t); - - return 0; - } - - l = context->proc_timeouts; - - while (l) { - t = l->data; - l = l->next; - - if (t->id != id) - continue; - - context->proc_timeouts = g_slist_remove(context->proc_timeouts, t); - free(t); - - return 0; - } - - return -1; -} - guint g_idle_add(GSourceFunc func, gpointer user_data) { /* Not implemented */ -- cgit From 89edbea0fde48f3e91b634589299f5c0f13e1543 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Jan 2007 14:53:59 +0000 Subject: Get rid of g_idle_add --- eglib/gmain.c | 6 ------ 1 file changed, 6 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index ea3adebd..a5e46a3a 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -544,12 +544,6 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) return t->id; } -guint g_idle_add(GSourceFunc func, gpointer user_data) -{ - /* Not implemented */ - return 0; -} - /* GError */ void g_error_free(GError *err) { -- cgit From eeb436f3b83e749dd9d7ae1c123765188155aa9c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Jan 2007 20:10:16 +0000 Subject: Use glib memory allocation for gmain.c --- eglib/gmain.c | 78 +++++++++++++++-------------------------------------------- 1 file changed, 19 insertions(+), 59 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index a5e46a3a..f14b1f09 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -106,18 +106,14 @@ void g_io_channel_unref(GIOChannel *channel) if (channel->close_on_unref && channel->fd >= 0) g_io_channel_close(channel); - free(channel); + g_free(channel); } GIOChannel *g_io_channel_unix_new(int fd) { GIOChannel *channel; - channel = malloc(sizeof(GIOChannel)); - if (!channel) - return NULL; - - memset(channel, 0, sizeof(GIOChannel)); + channel = g_new0(GIOChannel, 1); channel->fd = fd; @@ -154,7 +150,7 @@ static void watch_free(struct watch *watch) { if (watch->destroy) watch->destroy(watch->user_data); - free(watch); + g_free(watch); } static GMainContext *g_main_context_default() @@ -162,11 +158,7 @@ static GMainContext *g_main_context_default() if (default_context) return default_context; - default_context = malloc(sizeof(GMainContext)); - if (!default_context) - return NULL; - - memset(default_context, 0, sizeof(GMainContext)); + default_context = g_new0(GMainContext, 1); default_context->next_timeout = -1; default_context->next_id = 1; @@ -221,7 +213,7 @@ static gboolean g_timeout_remove(GMainContext *context, const guint id) continue; context->timeouts = g_slist_remove(context->timeouts, t); - free(t); + g_free(t); return TRUE; } @@ -236,7 +228,7 @@ static gboolean g_timeout_remove(GMainContext *context, const guint id) continue; context->proc_timeouts = g_slist_remove(context->proc_timeouts, t); - free(t); + g_free(t); return TRUE; } @@ -248,9 +240,6 @@ gboolean g_source_remove(guint tag) { GMainContext *context = g_main_context_default(); - if (!context) - return FALSE; - if (g_io_remove_watch(context, tag)) return TRUE; @@ -274,12 +263,7 @@ guint g_io_add_watch_full(GIOChannel *channel, gint priority, struct watch *watch; GMainContext *context = g_main_context_default(); - if (!context) - return 0; - - watch = malloc(sizeof(struct watch)); - if (!watch) - return 0; + watch = g_new(struct watch, 1); watch->id = context->next_id++; watch->channel = channel; @@ -311,14 +295,7 @@ GMainLoop *g_main_loop_new(GMainContext *context, gboolean is_running) if (!context) context = g_main_context_default(); - if (!context) - return NULL; - - ml = malloc(sizeof(GMainLoop)); - if (!ml) - return NULL; - - memset(ml, 0, sizeof(GMainLoop)); + ml = g_new0(GMainLoop, 1); ml->context = context; ml->is_running = is_running; @@ -384,7 +361,7 @@ static void timeout_handlers_check(GMainContext *context) context->timeouts = g_slist_remove(context->timeouts, t); if (!ret) { - free(t); + g_free(t); continue; } @@ -413,9 +390,7 @@ void g_main_loop_run(GMainLoop *loop) struct pollfd *ufds; GMainContext *context = loop->context; - ufds = malloc(open_max * sizeof(struct pollfd)); - if (!ufds) - return; + ufds = g_new(struct pollfd, open_max); loop->is_running = TRUE; @@ -476,7 +451,7 @@ void g_main_loop_run(GMainLoop *loop) timeout_handlers_check(loop->context); } - free(ufds); + g_free(ufds); } void g_main_loop_quit(GMainLoop *loop) @@ -492,10 +467,10 @@ void g_main_loop_unref(GMainLoop *loop) g_slist_foreach(loop->context->watches, (GFunc)watch_free, NULL); g_slist_free(loop->context->watches); - g_slist_foreach(loop->context->timeouts, (GFunc)free, NULL); + g_slist_foreach(loop->context->timeouts, (GFunc)g_free, NULL); g_slist_free(loop->context->timeouts); - free(loop->context); + g_free(loop->context); loop->context = NULL; } @@ -507,15 +482,8 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) guint msecs; struct timeout *t; - if (!context || !function) - return 0; - - t = malloc(sizeof(*t)); + t = g_new0(struct timeout, 1); - if (!t) - return 0; - - memset(t, 0, sizeof(*t)); t->interval = interval; t->function = function; t->data = data; @@ -667,10 +635,7 @@ GSList *g_slist_append(GSList *list, void *data) { GSList *entry, *tail; - entry = malloc(sizeof(GSList)); - /* FIXME: this currently just silently fails */ - if (!entry) - return list; + entry = g_new(GSList, 1); entry->data = data; entry->next = NULL; @@ -690,10 +655,7 @@ GSList *g_slist_prepend(GSList *list, void *data) { GSList *entry; - entry = malloc(sizeof(GSList)); - /* FIXME: this currently just silently fails */ - if (!entry) - return list; + entry = g_new(GSList, 1); entry->data = data; entry->next = list; @@ -706,9 +668,7 @@ GSList *g_slist_insert_sorted(GSList *list, void *data, GCompareFunc cmp_func) GSList *tmp, *prev, *entry; int cmp; - entry = malloc(sizeof(GSList)); - if (!entry) - return list; + entry = g_new(GSList, 1); entry->data = data; entry->next = NULL; @@ -763,7 +723,7 @@ GSList *g_slist_remove(GSList *list, void *data) next = match->next; - free(match); + g_free(match); /* If the head was removed, return the next element */ if (!prev) @@ -872,7 +832,7 @@ void g_slist_free(GSList *list) for (l = list; l != NULL; l = next) { next = l->next; - free(l); + g_free(l); } } -- cgit From 852a332dbcd42a929bd98de248fdce3cc6edc077 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Jan 2007 21:14:30 +0000 Subject: Add eglib g_io_channel_write implementation --- eglib/gmain.c | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index f14b1f09..08d73eb8 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -84,8 +84,39 @@ retry: GIOError g_io_channel_write(GIOChannel *channel, const gchar *buf, gsize count, gsize *bytes_written) { - /* Not implemented */ - return G_IO_STATUS_ERROR; + int fd = channel->fd; + gssize result; + + if (channel->closed) + return G_IO_STATUS_ERROR; + + /* At least according to the Debian manpage for read */ + if (count > SSIZE_MAX) + count = SSIZE_MAX; + +retry: + result = write(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_written = result; + + return (result > 0) ? G_IO_STATUS_NORMAL : G_IO_STATUS_EOF; } void g_io_channel_close(GIOChannel *channel) -- cgit From 79169bd1c7f9b311a20fe25324c974633c7d7876 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sat, 20 Jan 2007 21:32:28 +0000 Subject: eglib fixes --- eglib/gmain.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 08d73eb8..182f5efa 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -22,6 +22,7 @@ struct timeout { struct _GIOChannel { int fd; + int ref_count; gboolean closed; gboolean close_on_unref; }; @@ -98,7 +99,7 @@ retry: result = write(fd, buf, count); if (result < 0) { - *bytes_read = 0; + *bytes_written = 0; switch (errno) { #ifdef EINTR @@ -131,6 +132,9 @@ void g_io_channel_close(GIOChannel *channel) void g_io_channel_unref(GIOChannel *channel) { + if (--channel->ref_count > 0) + return; + if (!channel) return; @@ -140,6 +144,12 @@ void g_io_channel_unref(GIOChannel *channel) g_free(channel); } +GIOChannel *g_io_channel_ref(GIOChannel *channel) +{ + channel->ref_count++; + return channel; +} + GIOChannel *g_io_channel_unix_new(int fd) { GIOChannel *channel; @@ -147,6 +157,7 @@ GIOChannel *g_io_channel_unix_new(int fd) channel = g_new0(GIOChannel, 1); channel->fd = fd; + channel->ref_count = 1; return channel; } @@ -181,6 +192,7 @@ static void watch_free(struct watch *watch) { if (watch->destroy) watch->destroy(watch->user_data); + g_io_channel_unref(watch->channel); g_free(watch); } @@ -297,7 +309,7 @@ guint g_io_add_watch_full(GIOChannel *channel, gint priority, watch = g_new(struct watch, 1); watch->id = context->next_id++; - watch->channel = channel; + watch->channel = g_io_channel_ref(channel); watch->priority = priority; watch->condition = condition; watch->func = func; -- cgit From c5d749832f000907deeb836b547e396c7638998b Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 01:36:04 +0000 Subject: Implement GChildWatch --- eglib/gmain.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 191 insertions(+), 47 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 182f5efa..dfe56fcd 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -9,6 +9,9 @@ #include #include #include +#include +#include +#include #include @@ -27,6 +30,13 @@ struct _GIOChannel { gboolean close_on_unref; }; +struct child_watch { + guint id; + GPid pid; + GChildWatchFunc function; + gpointer user_data; +}; + struct _GMainContext { guint next_id; glong next_timeout; @@ -35,9 +45,13 @@ struct _GMainContext { GSList *proc_timeouts; gboolean timeout_lock; - GSList *watches; - GSList *proc_watches; - gboolean watch_lock; + GSList *io_watches; + GSList *proc_io_watches; + gboolean io_lock; + + GSList *child_watches; + GSList *proc_child_watches; + gboolean child_lock; }; struct _GMainLoop { @@ -175,7 +189,7 @@ gint g_io_channel_unix_get_fd(GIOChannel *channel) return channel->fd; } -struct watch { +struct io_watch { guint id; GIOChannel *channel; gint priority; @@ -188,7 +202,7 @@ struct watch { static GMainContext *default_context = NULL; -static void watch_free(struct watch *watch) +static void watch_free(struct io_watch *watch) { if (watch->destroy) watch->destroy(watch->user_data); @@ -212,27 +226,27 @@ static GMainContext *g_main_context_default() static gboolean g_io_remove_watch(GMainContext *context, guint id) { GSList *l; - struct watch *w; + struct io_watch *w; - for (l = context->watches; l != NULL; l = l->next) { + for (l = context->io_watches; l != NULL; l = l->next) { w = l->data; if (w->id != id) continue; - context->watches = g_slist_remove(context->watches, w); + context->io_watches = g_slist_remove(context->io_watches, w); watch_free(w); return TRUE; } - for (l = context->proc_watches; l != NULL; l = l->next) { + for (l = context->proc_io_watches; l != NULL; l = l->next) { w = l->data; if (w->id != id) continue; - context->proc_watches = g_slist_remove(context->proc_watches, w); + context->proc_io_watches = g_slist_remove(context->proc_io_watches, w); watch_free(w); return TRUE; @@ -279,20 +293,7 @@ static gboolean g_timeout_remove(GMainContext *context, const guint id) return FALSE; } -gboolean g_source_remove(guint tag) -{ - GMainContext *context = g_main_context_default(); - - if (g_io_remove_watch(context, tag)) - return TRUE; - - if (g_timeout_remove(context, tag)) - return TRUE; - - return FALSE; -} - -int watch_prio_cmp(struct watch *w1, struct watch *w2) +int watch_prio_cmp(struct io_watch *w1, struct io_watch *w2) { return w1->priority - w2->priority; } @@ -303,10 +304,10 @@ guint g_io_add_watch_full(GIOChannel *channel, gint priority, GIOCondition condition, GIOFunc func, gpointer user_data, GDestroyNotify notify) { - struct watch *watch; + struct io_watch *watch; GMainContext *context = g_main_context_default(); - watch = g_new(struct watch, 1); + watch = g_new(struct io_watch, 1); watch->id = context->next_id++; watch->channel = g_io_channel_ref(channel); @@ -316,10 +317,10 @@ guint g_io_add_watch_full(GIOChannel *channel, gint priority, watch->user_data = user_data; watch->destroy = notify; - if (context->watch_lock) - context->proc_watches = watch_list_add(context->proc_watches, watch); + if (context->io_lock) + context->proc_io_watches = watch_list_add(context->proc_io_watches, watch); else - context->watches = watch_list_add(context->watches, watch); + context->io_watches = watch_list_add(context->io_watches, watch); return watch->id; } @@ -440,9 +441,9 @@ void g_main_loop_run(GMainLoop *loop) while (loop->is_running) { int nfds; GSList *l; - struct watch *w; + struct io_watch *w; - for (nfds = 0, l = context->watches; l != NULL; l = l->next, nfds++) { + for (nfds = 0, l = context->io_watches; l != NULL; l = l->next, nfds++) { w = l->data; ufds[nfds].fd = w->channel->fd; ufds[nfds].events = w->condition; @@ -456,16 +457,16 @@ void g_main_loop_run(GMainLoop *loop) if (poll(ufds, nfds, context->next_timeout) < 0) continue; - context->watch_lock = TRUE; + context->io_lock = TRUE; - while (context->watches) { + while (context->io_watches) { gboolean ret; - w = context->watches->data; + w = context->io_watches->data; if (!*w->revents) { - context->watches = g_slist_remove(context->watches, w); - context->proc_watches = watch_list_add(context->proc_watches, w); + context->io_watches = g_slist_remove(context->io_watches, w); + context->proc_io_watches = watch_list_add(context->proc_io_watches, w); continue; } @@ -473,22 +474,22 @@ void g_main_loop_run(GMainLoop *loop) /* Check if the watch was removed/freed by the callback * function */ - if (!g_slist_find_custom(context->watches, w, ptr_cmp)) + if (!g_slist_find_custom(context->io_watches, w, ptr_cmp)) continue; - context->watches = g_slist_remove(context->watches, w); + context->io_watches = g_slist_remove(context->io_watches, w); if (!ret) { watch_free(w); continue; } - context->proc_watches = watch_list_add(context->proc_watches, w); + context->proc_io_watches = watch_list_add(context->proc_io_watches, w); } - context->watches = context->proc_watches; - context->proc_watches = NULL; - context->watch_lock = FALSE; + context->io_watches = context->proc_io_watches; + context->proc_io_watches = NULL; + context->io_lock = FALSE; /* check expired timers */ timeout_handlers_check(loop->context); @@ -507,8 +508,8 @@ void g_main_loop_unref(GMainLoop *loop) if (!loop->context) return; - g_slist_foreach(loop->context->watches, (GFunc)watch_free, NULL); - g_slist_free(loop->context->watches); + g_slist_foreach(loop->context->io_watches, (GFunc)watch_free, NULL); + g_slist_free(loop->context->io_watches); g_slist_foreach(loop->context->timeouts, (GFunc)g_free, NULL); g_slist_free(loop->context->timeouts); @@ -564,6 +565,112 @@ void g_error_free(GError *err) /* Spawning related functions */ +static int child_watch_pipe[2] = { -1, -1 }; + +static void sigchld_handler(int signal) +{ + int ret; + ret = write(child_watch_pipe[1], "B", 1); +} + +static gboolean child_watch_remove(GMainContext *context, guint id) +{ + GSList *l; + struct child_watch *w; + + for (l = context->child_watches; l != NULL; l = l->next) { + w = l->data; + + if (w->id != id) + continue; + + context->child_watches = + g_slist_remove(context->child_watches, w); + g_free(w); + + return TRUE; + } + + for (l = context->proc_child_watches; l != NULL; l = l->next) { + w = l->data; + + if (w->id != id) + continue; + + context->proc_child_watches = + g_slist_remove(context->proc_child_watches, w); + g_free(w); + + return TRUE; + } + + + return FALSE; +} + +gboolean child_watch(GIOChannel *io, GIOCondition cond, gpointer user_data) +{ + int ret; + char b[20]; + GMainContext *context = g_main_context_default(); + + ret = read(child_watch_pipe[0], b, 20); + + context->child_lock = TRUE; + + while (context->child_watches) { + gint status; + struct child_watch *w = context->child_watches->data; + + if (waitpid(w->pid, &status, WNOHANG) <= 0) { + context->child_watches = + g_slist_remove(context->child_watches, w); + context->proc_child_watches = + watch_list_add(context->proc_child_watches, w); + continue; + } + + w->function(w->pid, status, w->user_data); + + /* Check if the callback already removed us */ + if (!g_slist_find(context->child_watches, w)) + continue; + + context->child_watches = g_slist_remove(context->child_watches, w); + g_free(w); + } + + context->child_watches = context->proc_child_watches; + context->proc_child_watches = NULL; + context->child_lock = FALSE; + + return TRUE; +} + +static void init_child_pipe(void) +{ + struct sigaction action; + GIOChannel *io; + + if (pipe(child_watch_pipe) < 0) { + fprintf(stderr, "Unable to initialize child watch pipe: %s (%d)\n", + strerror(errno), errno); + abort(); + } + + fcntl(child_watch_pipe[1], F_SETFL, + O_NONBLOCK | fcntl(child_watch_pipe[1], F_GETFL)); + + action.sa_handler = sigchld_handler; + sigemptyset(&action.sa_mask); + action.sa_flags = SA_NOCLDSTOP; + sigaction(SIGCHLD, &action, NULL); + + io = g_io_channel_unix_new(child_watch_pipe[0]); + g_io_add_watch(io, G_IO_IN, child_watch, NULL); + g_io_channel_unref(io); +} + gboolean g_spawn_async(const gchar *working_directory, gchar **argv, gchar **envp, GSpawnFlags flags, @@ -572,7 +679,9 @@ gboolean g_spawn_async(const gchar *working_directory, GPid *child_pid, GError **error) { - /* Not implemented */ + if (child_watch_pipe[0] < 0) + init_child_pipe(); + return FALSE; } @@ -583,8 +692,43 @@ void g_spawn_close_pid(GPid pid) guint g_child_watch_add(GPid pid, GChildWatchFunc func, gpointer user_data) { - /* Not implemented */ - return 0; + struct child_watch *w; + GMainContext *context = g_main_context_default(); + + if (child_watch_pipe[0] < 0) + init_child_pipe(); + + w = g_new(struct child_watch, 1); + + w->id = context->next_id++; + w->pid = pid; + w->function = func; + w->user_data = user_data; + + if (context->child_lock) + context->proc_child_watches = + watch_list_add(context->proc_child_watches, w); + else + context->child_watches = + watch_list_add(context->child_watches, w); + + return w->id; +} + +gboolean g_source_remove(guint tag) +{ + GMainContext *context = g_main_context_default(); + + if (g_io_remove_watch(context, tag)) + return TRUE; + + if (g_timeout_remove(context, tag)) + return TRUE; + + if (child_watch_remove(context, tag)) + return TRUE; + + return FALSE; } /* UTF-8 Validation: approximate copy/paste from glib2. */ -- cgit From 404ef616fb79ab1f95e6f91c8ea62e49b33b5e2a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 01:40:49 +0000 Subject: make child_watch() static --- eglib/gmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index dfe56fcd..8da81b21 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -608,7 +608,7 @@ static gboolean child_watch_remove(GMainContext *context, guint id) return FALSE; } -gboolean child_watch(GIOChannel *io, GIOCondition cond, gpointer user_data) +static gboolean child_watch(GIOChannel *io, GIOCondition cond, gpointer user_data) { int ret; char b[20]; -- cgit From 3240a5476f0c18bc0a30b0e0c5d995b55320ae7e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 02:27:49 +0000 Subject: First step of g_spawn_async implementation --- eglib/gmain.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 8da81b21..fc493878 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -671,6 +671,17 @@ static void init_child_pipe(void) g_io_channel_unref(io); } +static void exec_child(const gchar *working_directory, + gchar **argv, gchar **envp, + GSpawnFlags flags) +{ + if (chdir(working_directory) < 0) + _exit(EXIT_FAILURE); + + if (execv(argv[0], argv) < 0) + _exit(EXIT_FAILURE); +} + gboolean g_spawn_async(const gchar *working_directory, gchar **argv, gchar **envp, GSpawnFlags flags, @@ -679,9 +690,25 @@ gboolean g_spawn_async(const gchar *working_directory, GPid *child_pid, GError **error) { + GPid pid; + if (child_watch_pipe[0] < 0) init_child_pipe(); + switch (pid = fork()) { + case -1: + return FALSE; + case 0: + if (child_setup) + child_setup(user_data); + exec_child(working_directory, argv, envp, flags); + break; + default: + if (child_pid) + *child_pid = pid; + return TRUE; + } + return FALSE; } -- cgit From 7006ed3265196dfeb24ab2790dda6b817462cf48 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 14:19:49 +0000 Subject: More g_spawn_async functionality --- eglib/gmain.c | 38 +++++++++++++++++++++++++++++++------- 1 file changed, 31 insertions(+), 7 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index fc493878..c3c2ec9b 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -673,13 +673,32 @@ static void init_child_pipe(void) static void exec_child(const gchar *working_directory, gchar **argv, gchar **envp, - GSpawnFlags flags) + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data) { - if (chdir(working_directory) < 0) - _exit(EXIT_FAILURE); + int null; - if (execv(argv[0], argv) < 0) + if (working_directory && chdir(working_directory) < 0) _exit(EXIT_FAILURE); + + null = open("/dev/null", O_RDWR); + dup2(null, STDIN_FILENO); + dup2(null, STDOUT_FILENO); + dup2(null, STDERR_FILENO); + if (null > 2) + close(null); + + if (child_setup) + child_setup(user_data); + + if (envp) + execve(argv[0], argv, envp); + else + execv(argv[0], argv); + + /* exec failed if we get here */ + _exit(EXIT_FAILURE); } gboolean g_spawn_async(const gchar *working_directory, @@ -692,16 +711,21 @@ gboolean g_spawn_async(const gchar *working_directory, { GPid pid; + if (access(argv[0], X_OK) < 0) + return FALSE; + if (child_watch_pipe[0] < 0) init_child_pipe(); + /* Flush output streams so child doesn't get them */ + fflush(NULL); + switch (pid = fork()) { case -1: return FALSE; case 0: - if (child_setup) - child_setup(user_data); - exec_child(working_directory, argv, envp, flags); + exec_child(working_directory, argv, envp, flags, + child_setup, user_data); break; default: if (child_pid) -- cgit From d125028230c2ea56b2015c8ae457449d75c583bc Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 14:36:37 +0000 Subject: Further fixes to g_spawn_async --- eglib/gmain.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index c3c2ec9b..8132d635 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -682,10 +682,22 @@ static void exec_child(const gchar *working_directory, if (working_directory && chdir(working_directory) < 0) _exit(EXIT_FAILURE); + if (!(flags & G_SPAWN_LEAVE_DESCRIPTORS_OPEN)) { + int open_max, fd, ret; + + ret = 0; + open_max = sysconf(_SC_OPEN_MAX); + for (fd = 0; fd < open_max && ret == 0; fd++) + ret = fcntl(fd, F_SETFD, FD_CLOEXEC); + } + null = open("/dev/null", O_RDWR); - dup2(null, STDIN_FILENO); - dup2(null, STDOUT_FILENO); - dup2(null, STDERR_FILENO); + if (!(flags & G_SPAWN_CHILD_INHERITS_STDIN)) + dup2(null, STDIN_FILENO); + if (flags & G_SPAWN_STDOUT_TO_DEV_NULL) + dup2(null, STDOUT_FILENO); + if (flags & G_SPAWN_STDERR_TO_DEV_NULL) + dup2(null, STDERR_FILENO); if (null > 2) close(null); -- cgit From 8f490d50d839a9a0f5efe212faa88c7940c553b5 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 16:22:36 +0000 Subject: Get rid of g_shell_parse_argv and g_strdup_printf since they are not needed anymore --- eglib/gmain.c | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 8132d635..714aba13 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1160,22 +1160,6 @@ gchar *g_strdup(const gchar *str) return s; } -gchar *g_strdup_printf(const gchar *format, ...) -{ - gchar str[1024]; - va_list ap; - - memset(str, 0, sizeof(str)); - - va_start(ap, format); - - vsnprintf(str, sizeof(str) - 1, format, ap); - - va_end(ap); - - return g_strdup(str); -} - void g_strfreev(gchar **str_array) { int i; @@ -1189,17 +1173,6 @@ void g_strfreev(gchar **str_array) g_free(str_array); } -/* g_shell_* */ - -gboolean g_shell_parse_argv(const gchar *command_line, - gint *argcp, - gchar ***argvp, - GError **error) -{ - /* Not implemented */ - return FALSE; -} - /* GKeyFile */ typedef gpointer GHashTable; -- cgit From 91fcf748ea86a85685af4bee5fb269285e3e91ca Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 16:27:41 +0000 Subject: Get rid of g_strfreev too --- eglib/gmain.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 714aba13..102e8bc9 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1160,19 +1160,6 @@ gchar *g_strdup(const gchar *str) return s; } -void g_strfreev(gchar **str_array) -{ - int i; - - if (!str_array) - return; - - for (i = 0; str_array[i] != NULL; i++) - g_free(str_array[i]); - - g_free(str_array); -} - /* GKeyFile */ typedef gpointer GHashTable; -- cgit From 22920bd5c9ee7e8f42ab695a0667cdc6deee5cf9 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 19:10:58 +0000 Subject: Cleanup GKeyFile stuff so real implementation can start --- eglib/gmain.c | 63 ++++++++++++++++++++++------------------------------------- 1 file changed, 23 insertions(+), 40 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 102e8bc9..381aece1 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -557,6 +557,20 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) } /* GError */ + +GError* g_error_new_literal(GQuark domain, gint code, const gchar *message) +{ + GError *err; + + err = g_new(GError, 1); + + err->domain = domain; + err->code = code; + err->message = g_strdup(message); + + return err; +} + void g_error_free(GError *err) { g_free(err->message); @@ -1162,42 +1176,8 @@ gchar *g_strdup(const gchar *str) /* GKeyFile */ -typedef gpointer GHashTable; - -typedef struct _GKeyFileGroup GKeyFileGroup; - struct _GKeyFile { - GSList *groups; - - GKeyFileGroup *start_group; - GKeyFileGroup *current_group; - - /* Holds up to one line of not-yet-parsed data */ - gchar *parse_buffer; - - /* Used for sizing the output buffer during serialization */ - gsize approximate_size; - - gchar list_separator; - - GKeyFileFlags flags; -}; - -typedef struct _GKeyFileKeyValuePair GKeyFileKeyValuePair; - -struct _GKeyFileGroup { - /* NULL for above first group (which will be comments) */ - const gchar *name; - - /* Special comment that is stuck to the top of a group */ - GKeyFileKeyValuePair *comment; - - GSList *key_value_pairs; - - /* Used in parallel with key_value_pairs for - * increased lookup performance - */ - GHashTable *lookup_map; + gchar *filename; }; struct _GKeyFileKeyValuePair { @@ -1207,13 +1187,12 @@ struct _GKeyFileKeyValuePair { GKeyFile *g_key_file_new(void) { - /* Not implemented */ - return NULL; + return g_new0(GKeyFile, 1); } void g_key_file_free(GKeyFile *key_file) { - /* Not implemented fully */ + g_free(key_file->filename); g_free(key_file); } @@ -1222,8 +1201,8 @@ gboolean g_key_file_load_from_file(GKeyFile *key_file, GKeyFileFlags flags, GError **error) { - /* Not implemented */ - return FALSE; + key_file->filename = g_strdup(file); + return TRUE; } gchar *g_key_file_get_string(GKeyFile *key_file, @@ -1232,6 +1211,8 @@ gchar *g_key_file_get_string(GKeyFile *key_file, GError **error) { /* Not implemented */ + if (error) + *error = g_error_new_literal(0, 0, "Not implemented"); return NULL; } @@ -1241,6 +1222,8 @@ gboolean g_key_file_get_boolean(GKeyFile *key_file, GError **error) { /* Not implemented */ + if (error) + *error = g_error_new_literal(0, 0, "Not implemented"); return FALSE; } -- cgit From 49f7899a1bde827dff68a755977be4f0cb52f20e Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 20:13:06 +0000 Subject: First go at somewhat functional g_key_file_* impementation --- eglib/gmain.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 120 insertions(+), 13 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 381aece1..108df5f5 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -12,6 +12,9 @@ #include #include #include +#include +#include +#include #include @@ -571,6 +574,24 @@ GError* g_error_new_literal(GQuark domain, gint code, const gchar *message) return err; } +void g_set_error(GError **err, GQuark domain, gint code, + const gchar *format, ...) +{ + gchar msg[1024]; + va_list ap; + + if (!err) + return; + + va_start(ap, format); + + vsnprintf(msg, sizeof(msg) - 1, format, ap); + + va_end(ap); + + *err = g_error_new_literal(domain, code, msg); +} + void g_error_free(GError *err) { g_free(err->message); @@ -1180,11 +1201,6 @@ struct _GKeyFile { gchar *filename; }; -struct _GKeyFileKeyValuePair { - gchar *key; /* NULL for comments */ - gchar *value; -}; - GKeyFile *g_key_file_new(void) { return g_new0(GKeyFile, 1); @@ -1210,10 +1226,90 @@ gchar *g_key_file_get_string(GKeyFile *key_file, const gchar *key, GError **error) { - /* Not implemented */ - if (error) - *error = g_error_new_literal(0, 0, "Not implemented"); - return NULL; + struct stat st; + char *map, *nl, *off, *group = NULL, *value = NULL, tmp[1024]; + off_t size; + size_t key_len, to_copy, value_len; + int fd, err = 0; + + fd = open(key_file->filename, O_RDONLY); + if (fd < 0) { + g_set_error(error, 0, 0, "%s: %s", key_file->filename, + strerror(errno)); + return NULL; + } + + if (flock(fd, LOCK_SH) < 0) { + err = errno; + goto close; + } + + if (fstat(fd, &st) < 0) { + err = errno; + goto unlock; + } + + size = st.st_size; + + map = mmap(NULL, size, PROT_READ, MAP_SHARED, fd, 0); + if (!map || map == MAP_FAILED) { + err = errno; + goto unlock; + } + + group = strstr(map, group_name); + if (!group) + goto unmap; + + nl = strchr(group, '\n'); + if (!nl) + goto unmap; + + off = strstr(nl + 1, key); + if (!off) + goto unmap; + + key_len = strlen(key); + + if (off[key_len] != '=') + goto unmap; + + off += key_len + 1; + + nl = strchr(off, '\n'); + if (!nl) + goto unmap; + + value_len = nl - off; + + to_copy = value_len > (sizeof(tmp) - 1) ? sizeof(tmp) - 1 : value_len; + + memset(tmp, 0, sizeof(tmp)); + + strncpy(tmp, off, to_copy); + + value = g_strdup(tmp); + +unmap: + munmap(map, size); + +unlock: + flock(fd, LOCK_UN); + +close: + close(fd); + + if (err) + g_set_error(error, 0, 0, "%s: %s", key_file->filename, + strerror(err)); + else if (!group) + g_set_error(error, 0, 0, "%s: group %s not found", + key_file->filename, group_name); + else if (!value) + g_set_error(error, 0, 0, "%s: key %s not found", + key_file->filename, key); + + return value; } gboolean g_key_file_get_boolean(GKeyFile *key_file, @@ -1221,9 +1317,20 @@ gboolean g_key_file_get_boolean(GKeyFile *key_file, const gchar *key, GError **error) { - /* Not implemented */ - if (error) - *error = g_error_new_literal(0, 0, "Not implemented"); - return FALSE; + gboolean ret; + gchar *str; + + str = g_key_file_get_string(key_file, group_name, key, error); + if (!str) + return FALSE; + + if (strcmp(str, str) == 0) + ret = TRUE; + else + ret = FALSE; + + g_free(str); + + return ret; } -- cgit From 17518a93c3aa48b769ea0fb8a9573b64b2420039 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 20:33:04 +0000 Subject: Fix get_boolean "true" mapping --- eglib/gmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 108df5f5..a2c095f3 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1324,7 +1324,7 @@ gboolean g_key_file_get_boolean(GKeyFile *key_file, if (!str) return FALSE; - if (strcmp(str, str) == 0) + if (strcmp(str, "true") == 0 || strcmp(str, "1") == 0) ret = TRUE; else ret = FALSE; -- cgit From ccf289e82013b0eedd2fc35433e104aa53e042be Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 21:47:57 +0000 Subject: Excplicitly close only fd's > 2 --- eglib/gmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index a2c095f3..5be81a3c 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -722,7 +722,7 @@ static void exec_child(const gchar *working_directory, ret = 0; open_max = sysconf(_SC_OPEN_MAX); - for (fd = 0; fd < open_max && ret == 0; fd++) + for (fd = 3; fd < open_max && ret == 0; fd++) ret = fcntl(fd, F_SETFD, FD_CLOEXEC); } -- cgit From 55c2c934de2702933652af1d655e0e377a829e6c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 22:47:52 +0000 Subject: Cleanup for g_text_file_get_string --- eglib/gmain.c | 77 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 26 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 5be81a3c..9936143d 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -15,6 +15,7 @@ #include #include #include +#include #include @@ -1221,15 +1222,29 @@ gboolean g_key_file_load_from_file(GKeyFile *key_file, return TRUE; } +static char *next_line(const char *ptr) +{ + char *nl; + + nl = strchr(ptr, '\n'); + if (!nl) + return NULL; + + if (nl[1] == '\0') + return NULL; + + return nl + 1; +} + gchar *g_key_file_get_string(GKeyFile *key_file, const gchar *group_name, const gchar *key, GError **error) { struct stat st; - char *map, *nl, *off, *group = NULL, *value = NULL, tmp[1024]; + char *map, *line, *group = NULL, *value = NULL; off_t size; - size_t key_len, to_copy, value_len; + size_t key_len, group_len; int fd, err = 0; fd = open(key_file->filename, O_RDONLY); @@ -1257,40 +1272,50 @@ gchar *g_key_file_get_string(GKeyFile *key_file, goto unlock; } - group = strstr(map, group_name); - if (!group) - goto unmap; - - nl = strchr(group, '\n'); - if (!nl) - goto unmap; + group_len = strlen(group_name); + key_len = strlen(key); - off = strstr(nl + 1, key); - if (!off) - goto unmap; + for (line = map; line != NULL; line = next_line(line)) { + int i; + size_t to_copy, value_len; + char tmp[1024], *nl; - key_len = strlen(key); + if (*line == '#') + continue; - if (off[key_len] != '=') - goto unmap; + if (!group) { + if (line[0] != '[' || strcmp(line + 1, group_name)) + continue; + if (line[group_len + 1] == ']') + group = line + 1; + continue; + } - off += key_len + 1; + if (strncmp(line, key, key_len)) + continue; - nl = strchr(off, '\n'); - if (!nl) - goto unmap; + for (i = 0; line[i] != '\n'; i++) { + if (line[i] == '=') + break; + if (!isspace(line[i])) + break; + } - value_len = nl - off; + if (line[i] != '=') + continue; - to_copy = value_len > (sizeof(tmp) - 1) ? sizeof(tmp) - 1 : value_len; + nl = strchr(line, '\n'); + if (!nl) + continue; - memset(tmp, 0, sizeof(tmp)); + value_len = nl - (line + i + 1); + to_copy = value_len > (sizeof(tmp) - 1) ? sizeof(tmp) - 1 : value_len; + memset(tmp, 0, sizeof(tmp)); + strncpy(tmp, line + i + 1, to_copy); - strncpy(tmp, off, to_copy); + value = g_strdup(tmp); + } - value = g_strdup(tmp); - -unmap: munmap(map, size); unlock: -- cgit From 61b451225e9e945f3d921750336b4c35cfe59b49 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 22:53:33 +0000 Subject: Small fix for g_key_file_get_string --- eglib/gmain.c | 1 + 1 file changed, 1 insertion(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 9936143d..6f2f2688 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1314,6 +1314,7 @@ gchar *g_key_file_get_string(GKeyFile *key_file, strncpy(tmp, line + i + 1, to_copy); value = g_strdup(tmp); + break; } munmap(map, size); -- cgit From 17455416144df12415dce55a355f61815435dc68 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 23:04:12 +0000 Subject: Fix eglib g_key_file_get_string group detection --- eglib/gmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 6f2f2688..794057b2 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1284,7 +1284,7 @@ gchar *g_key_file_get_string(GKeyFile *key_file, continue; if (!group) { - if (line[0] != '[' || strcmp(line + 1, group_name)) + if (line[0] != '[' || strncmp(line + 1, group_name, group_len)) continue; if (line[group_len + 1] == ']') group = line + 1; -- cgit From e67f1e9e5f1fd1f1c5ded32cd7f3bf2242d20f0d Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 23:11:43 +0000 Subject: Fix g_key_file_parse_string (again) --- eglib/gmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 794057b2..0a42f1b9 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1294,7 +1294,7 @@ gchar *g_key_file_get_string(GKeyFile *key_file, if (strncmp(line, key, key_len)) continue; - for (i = 0; line[i] != '\n'; i++) { + for (i = key_len; line[i] != '\n'; i++) { if (line[i] == '=') break; if (!isspace(line[i])) -- cgit From 137a41351e834e4ca98edbfdb40c4726dc3d2f04 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Sun, 21 Jan 2007 23:48:20 +0000 Subject: Fix g_spawn_async error reporting --- eglib/gmain.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 0a42f1b9..8375cd9a 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -759,8 +759,10 @@ gboolean g_spawn_async(const gchar *working_directory, { GPid pid; - if (access(argv[0], X_OK) < 0) + if (access(argv[0], X_OK) < 0) { + g_set_error(error, 0, 0, "%s is not executable", argv[0]); return FALSE; + } if (child_watch_pipe[0] < 0) init_child_pipe(); @@ -770,6 +772,7 @@ gboolean g_spawn_async(const gchar *working_directory, switch (pid = fork()) { case -1: + g_set_error(error, 0, 0, "fork failed: %s", strerror(errno)); return FALSE; case 0: exec_child(working_directory, argv, envp, flags, @@ -781,6 +784,7 @@ gboolean g_spawn_async(const gchar *working_directory, return TRUE; } + /* Never reached */ return FALSE; } -- cgit From cc9f2aa0bcd7ea83aaea39d701d5c676c9fd57fd Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 24 Jan 2007 19:32:26 +0000 Subject: Make eglib g_io_channel_unref behave as its glib counterpart with respect to a NULL parameter --- eglib/gmain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 8375cd9a..037bdd26 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -150,10 +150,10 @@ void g_io_channel_close(GIOChannel *channel) void g_io_channel_unref(GIOChannel *channel) { - if (--channel->ref_count > 0) + if (!channel) return; - if (!channel) + if (--channel->ref_count > 0) return; if (channel->close_on_unref && channel->fd >= 0) -- cgit From abe6ebba50e723df0b6ac5c7fece98338830826f Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 3 May 2007 12:14:05 +0000 Subject: Minor coding style cleanup --- eglib/gmain.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 037bdd26..6bb13022 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -63,7 +63,8 @@ struct _GMainLoop { GMainContext *context; }; -GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read) +GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, + gsize *bytes_read) { int fd = channel->fd; gssize result; -- cgit From 61548a46c286f2d3112cde38882ef4b0c6f0bed7 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 3 May 2007 15:41:42 +0000 Subject: Implement eglib versions of needed GString functions --- eglib/gmain.c | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 6bb13022..d2f002f8 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1179,6 +1179,18 @@ gpointer g_try_malloc0(gulong n_bytes) return mem; } +gpointer g_realloc(gpointer mem, gulong n_bytes) +{ + mem = realloc(mem, n_bytes); + if (!mem) { + fprintf(stderr, "g_realloc: failed to allocate %lu bytes", + n_bytes); + abort(); + } + + return mem; +} + void g_free(gpointer mem) { if (mem) @@ -1365,3 +1377,100 @@ gboolean g_key_file_get_boolean(GKeyFile *key_file, return ret; } +/* GString */ + +#define MY_MAXSIZE ((gsize)-1) + +static gsize nearest_power(gsize base, gsize num) +{ + gsize n = base; + + if (num > MY_MAXSIZE / 2) + return MY_MAXSIZE; + + while (n < num) + n <<= 1; + + return n; +} + +static void g_string_maybe_expand(GString *string, gsize len) +{ + if (string->len + len < string->allocated_len) + return; + + string->allocated_len = nearest_power(1, string->len + len + 1); + string->str = g_realloc(string->str, string->allocated_len); +} + +static GString *g_string_sized_new(gsize dfl_size) +{ + GString *string; + + string = g_new0(GString, 1); + + g_string_maybe_expand(string, dfl_size); + string->str[0] = '\0'; + + return string; +} + +static GString *g_string_append_len(GString *string, const gchar *val, gssize len) +{ + g_string_maybe_expand(string, len); + + if (len == 1) + string->str[string->len] = *val; + else + memcpy(string->str + string->len, val, len); + + string->len += len; + string->str[string->len] = '\0'; + + return string; +} + +GString *g_string_new(const gchar *init) +{ + GString *string; + gint len; + + if (init == NULL || *init == '\0') + return g_string_sized_new(2); + + len = strlen(init); + string = g_string_sized_new(len + 2); + + g_string_append_len(string, init, len); + + return string; +} + +void g_string_append_printf(GString *string, const gchar *format, ...) +{ + gchar buffer[1024]; + gint length; + va_list args; + + va_start(args, format); + length = vsnprintf(buffer, sizeof(buffer) - 1, format, args); + va_end(args); + + g_string_append_len(string, buffer, length); +} + +gchar *g_string_free(GString *string, gboolean free_segment) +{ + gchar *segment; + + if (free_segment) { + g_free(string->str); + segment = NULL; + } + else + segment = string->str; + + g_free(string); + + return segment; +} -- cgit From e11b4cced0f967a66ea81e3b6b92448e55d49624 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Fri, 18 May 2007 17:59:12 +0000 Subject: Add g_slist_nth, g_slist_nth_data, g_slist_last and g_slist_position functions to eglib. --- eglib/gmain.c | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index d2f002f8..89794c05 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1127,6 +1127,43 @@ void g_slist_free(GSList *list) } } +GSList *g_slist_nth(GSList *list, guint n) +{ + while (n-- > 0 && list) + list = list->next; + + return list; +} + +gpointer g_slist_nth_data(GSList *list, guint n) +{ + while (n-- > 0 && list) + list = list->next; + + return list ? list->data : NULL; +} + +gint g_slist_position(GSList *list, GSList *link) +{ + gint i; + + for (i = 0; list; list = list->next, i++) { + if (list == link) + return i; + } + + return -1; +} + +GSList* g_slist_last(GSList *list) +{ + if (list) + while (list->next) + list = list->next; + + return list; +} + /* Memory allocation functions */ gpointer g_malloc(gulong n_bytes) -- cgit From e80c7f2ae7d3946a5398cfa35dfe92027249024b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Fri, 25 May 2007 14:53:21 +0000 Subject: Add missing list functions --- eglib/gmain.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 89794c05..027fd60c 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1164,6 +1164,40 @@ GSList* g_slist_last(GSList *list) return list; } +static inline GSList* _g_slist_remove_link(GSList *list, GSList *link) +{ + GSList *tmp; + GSList *prev; + + prev = NULL; + tmp = list; + + while (tmp) { + if (tmp == link) { + if (prev) + prev->next = tmp->next; + if (list == tmp) + list = list->next; + + tmp->next = NULL; + break; + } + + prev = tmp; + tmp = tmp->next; + } + + return list; +} + +GSList* g_slist_delete_link(GSList *list, GSList *link) +{ + list = _g_slist_remove_link(list, link); + g_free(link); + + return list; +} + /* Memory allocation functions */ gpointer g_malloc(gulong n_bytes) -- cgit From 3863eba35ca65bb4ea17d3763ae27afafdf0f4c2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 16 Aug 2007 15:36:11 +0000 Subject: Implement some missing functions --- eglib/gmain.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 027fd60c..ed708fc2 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -561,6 +561,11 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) return t->id; } +guint g_idle_add(GSourceFunc function, gpointer data) +{ + return g_timeout_add(1, function, data); +} + /* GError */ GError* g_error_new_literal(GQuark domain, gint code, const gchar *message) -- cgit From 5c33278a29873c438d2ee963674462c7a501995b Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 22 Aug 2007 14:23:09 +0000 Subject: Add dummy functions for g_strdelimit() and g_strdup_printf() --- eglib/gmain.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index ed708fc2..f658b02a 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1289,6 +1289,19 @@ gchar *g_strdup(const gchar *str) return s; } +gchar* g_strdup_printf(const gchar *format, ...) +{ + /* FIXME: Implement this */ + return g_strdup(format); +} + +gchar* g_strdelimit(gchar *string, const gchar *delimiters, + gchar new_delimiter) +{ + /* FIXME: Implement this */ + return string; +} + /* GKeyFile */ struct _GKeyFile { -- cgit From 75b016927c9deb7c1a1b05628aa2fe56d9c8f255 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 23 Aug 2007 08:01:06 +0000 Subject: Fix missing eglib functions --- eglib/gmain.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index f658b02a..9a4f0097 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1289,16 +1289,30 @@ gchar *g_strdup(const gchar *str) return s; } -gchar* g_strdup_printf(const gchar *format, ...) +gchar *g_strdup_printf(const gchar *format, ...) { - /* FIXME: Implement this */ - return g_strdup(format); + va_list args; + gchar buffer[1024]; + gint length; + + va_start(args, format); + length = vsnprintf(buffer, sizeof(buffer) - 1, format, args); + va_end(args); + + return strdup(buffer); } -gchar* g_strdelimit(gchar *string, const gchar *delimiters, - gchar new_delimiter) +gchar *g_strdelimit(gchar *string, const gchar *delimiters, gchar new_delim) { - /* FIXME: Implement this */ + register gchar *c; + + if (!string) + return NULL; + + for (c = string; *c; c++) + if (strchr(delimiters, *c)) + *c = new_delim; + return string; } -- cgit From 7c3cfae4b835a040e5e4af68a95f260046d7b710 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Thu, 23 Aug 2007 08:40:34 +0000 Subject: g_strdup_printf should not return NULL on OOM --- eglib/gmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 9a4f0097..b341d516 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1299,7 +1299,7 @@ gchar *g_strdup_printf(const gchar *format, ...) length = vsnprintf(buffer, sizeof(buffer) - 1, format, args); va_end(args); - return strdup(buffer); + return g_strdup(buffer); } gchar *g_strdelimit(gchar *string, const gchar *delimiters, gchar new_delim) -- cgit From a797f53418e4f58b570c4a355dd46b33f2f68906 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 1 Feb 2008 11:32:10 +0000 Subject: Add GModule support to eglib --- eglib/gmain.c | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index b341d516..ce35b816 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -16,6 +16,7 @@ #include #include #include +#include #include @@ -1577,3 +1578,71 @@ gchar *g_string_free(GString *string, gboolean free_segment) return segment; } + +/* GModule */ + +struct _GModule { + void *handle; +}; + +static const char *dl_error_string = NULL; + +GModule *g_module_open(const gchar *file_name, GModuleFlags flags) +{ + GModule *module; + + module = g_try_new0(GModule, 1); + if (module == NULL) { + dl_error_string = strerror(ENOMEM); + return NULL; + } + + module->handle = dlopen(file_name, flags); + + if (module->handle == NULL) { + dl_error_string = dlerror(); + g_free(module); + return NULL; + } + + return module; +} + +gboolean g_module_symbol(GModule *module, const gchar *symbol_name, + gpointer *symbol) +{ + void *sym; + + dlerror(); + sym = dlsym(module->handle, symbol_name); + dl_error_string = dlerror(); + + if (dl_error_string != NULL) + return FALSE; + + *symbol = sym; + + return TRUE; +} + +gboolean g_module_close(GModule *module) +{ + if (dlclose(module->handle) != 0) { + dl_error_string = dlerror(); + return FALSE; + } + + g_free(module); + + return TRUE; +} + +const gchar *g_module_error(void) +{ + const char *str; + + str = dl_error_string; + dl_error_string = NULL; + + return str; +} -- cgit From 9225eadeb28150fcb0b05ec0b31349ce812dd3d0 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 1 Feb 2008 14:21:14 +0000 Subject: Move GModule code to gmodule.c and gmodule.h --- eglib/gmain.c | 68 ----------------------------------------------------------- 1 file changed, 68 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index ce35b816..8b631eb5 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1578,71 +1578,3 @@ gchar *g_string_free(GString *string, gboolean free_segment) return segment; } - -/* GModule */ - -struct _GModule { - void *handle; -}; - -static const char *dl_error_string = NULL; - -GModule *g_module_open(const gchar *file_name, GModuleFlags flags) -{ - GModule *module; - - module = g_try_new0(GModule, 1); - if (module == NULL) { - dl_error_string = strerror(ENOMEM); - return NULL; - } - - module->handle = dlopen(file_name, flags); - - if (module->handle == NULL) { - dl_error_string = dlerror(); - g_free(module); - return NULL; - } - - return module; -} - -gboolean g_module_symbol(GModule *module, const gchar *symbol_name, - gpointer *symbol) -{ - void *sym; - - dlerror(); - sym = dlsym(module->handle, symbol_name); - dl_error_string = dlerror(); - - if (dl_error_string != NULL) - return FALSE; - - *symbol = sym; - - return TRUE; -} - -gboolean g_module_close(GModule *module) -{ - if (dlclose(module->handle) != 0) { - dl_error_string = dlerror(); - return FALSE; - } - - g_free(module); - - return TRUE; -} - -const gchar *g_module_error(void) -{ - const char *str; - - str = dl_error_string; - dl_error_string = NULL; - - return str; -} -- cgit From 8c5c4cfaf172603650aac99fb87adbc56be8f00c Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 5 Mar 2008 21:22:00 +0000 Subject: Implement empty stubs for a minimal set of GMarkup functions --- eglib/gmain.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 8b631eb5..9eb1308f 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1578,3 +1578,29 @@ gchar *g_string_free(GString *string, gboolean free_segment) return segment; } + +/* GMarkup */ + +struct _GMarkupParseContext { +}; + +GMarkupParseContext *g_markup_parse_context_new(const GMarkupParser *parser, + GMarkupParseFlags flags, + gpointer user_data, + GDestroyNotify user_data_dnotify) +{ + return g_new0(GMarkupParseContext, 1); +} + +gboolean g_markup_parse_context_parse(GMarkupParseContext *context, + const gchar *text, gssize text_len, + GError **error) +{ + g_set_error(error, 0, 0, "Not implemented"); + return FALSE; +} + +void g_markup_parse_context_free(GMarkupParseContext *context) +{ + g_free(context); +} -- cgit From 8b610428cc0c768c8df15625c15e19b36b7373a2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 5 Mar 2008 21:32:30 +0000 Subject: Make sure that sizeof(struct _GMarkupParseContext) > 0 --- eglib/gmain.c | 1 + 1 file changed, 1 insertion(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 9eb1308f..9fa8ff86 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1582,6 +1582,7 @@ gchar *g_string_free(GString *string, gboolean free_segment) /* GMarkup */ struct _GMarkupParseContext { + char dummy; }; GMarkupParseContext *g_markup_parse_context_new(const GMarkupParser *parser, -- cgit From e7e3d513c99d23f06edf387d0e8ed97150d574e2 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 11 Mar 2008 18:53:33 +0000 Subject: Add implemention of g_str_equal, g_strsplit and g_strconcat to eglib. --- eglib/gmain.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 9fa8ff86..b6f40f32 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1317,6 +1317,93 @@ gchar *g_strdelimit(gchar *string, const gchar *delimiters, gchar new_delim) return string; } +gchar *g_strconcat(const gchar *string1, ...) +{ + gsize l; + va_list args; + gchar *s, *concat; + + if (!string1) + return NULL; + + l = 1 + strlen(string1); + va_start(args, string1); + s = va_arg(args, gchar *); + while (s) { + l += strlen(s); + s = va_arg(args, gchar *); + } + va_end (args); + + concat = g_new(gchar, l); + concat[0] = '\0'; + + va_start(args, string1); + s = va_arg(args, gchar*); + while (s) { + strcat(concat, s); + s = va_arg(args, gchar *); + } + va_end (args); + + return concat; +} + +gchar **g_strsplit(const gchar *string, const gchar *delimiter, gint max_tokens) +{ + GSList *string_list = NULL, *slist; + gchar **str_array, *s; + guint n = 0; + const gchar *remainder; + + if (string == NULL || delimiter == NULL || delimiter[0] == '\0') + return NULL; + + if (max_tokens < 1) + max_tokens = SSIZE_MAX; + + remainder = string; + s = strstr(remainder, delimiter); + if (s) { + gsize delimiter_len = strlen(delimiter); + + while (--max_tokens && s) { + gsize len; + gchar *tmp; + + len = s - remainder; + tmp = g_new(char, len); + memcpy(tmp, remainder, len); + string_list = g_slist_prepend(string_list, tmp); + n++; + remainder = s + delimiter_len; + s = strstr(remainder, delimiter); + } + } + if (*string) { + n++; + string_list = g_slist_prepend(string_list, g_strdup(remainder)); + } + + str_array = g_new(gchar *, n + 1); + + str_array[n--] = NULL; + for (slist = string_list; slist; slist = slist->next) + str_array[n--] = slist->data; + + g_slist_free(string_list); + + return str_array; +} + +gboolean g_str_equal(gconstpointer v1, gconstpointer v2) +{ + const gchar *string1 = v1; + const gchar *string2 = v2; + + return strcmp(string1, string2) == 0; +} + /* GKeyFile */ struct _GKeyFile { -- cgit From 388aa36ed4cd66347e79c600b46378b3f3846363 Mon Sep 17 00:00:00 2001 From: Vinicius Gomes Date: Tue, 11 Mar 2008 22:11:22 +0000 Subject: eglib: Fixing a warning in the g_strsplit, caused by the overflow of setting a int variable to SSIZE_MAX. --- eglib/gmain.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index b6f40f32..878760d8 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -235,7 +235,7 @@ static gboolean g_io_remove_watch(GMainContext *context, guint id) struct io_watch *w; for (l = context->io_watches; l != NULL; l = l->next) { - w = l->data; + w = l->data; if (w->id != id) continue; @@ -247,7 +247,7 @@ static gboolean g_io_remove_watch(GMainContext *context, guint id) } for (l = context->proc_io_watches; l != NULL; l = l->next) { - w = l->data; + w = l->data; if (w->id != id) continue; @@ -691,7 +691,7 @@ static gboolean child_watch(GIOChannel *io, GIOCondition cond, gpointer user_dat } static void init_child_pipe(void) -{ +{ struct sigaction action; GIOChannel *io; @@ -781,7 +781,7 @@ gboolean g_spawn_async(const gchar *working_directory, case -1: g_set_error(error, 0, 0, "fork failed: %s", strerror(errno)); return FALSE; - case 0: + case 0: exec_child(working_directory, argv, envp, flags, child_setup, user_data); break; @@ -790,7 +790,7 @@ gboolean g_spawn_async(const gchar *working_directory, *child_pid = pid; return TRUE; } - + /* Never reached */ return FALSE; } @@ -863,7 +863,7 @@ gboolean g_source_remove(guint tag) if ((p)[(i)] == '\0' || ((max_len) >= 0 && (i) >= (max_len))) \ goto failed; \ } while (0) - + gboolean g_utf8_validate(const gchar *str, gssize max_len, const gchar **end) { @@ -911,7 +911,7 @@ two_remaining: if (val < min || !UNICODE_VALID(val)) goto failed; - } + } } if (end) @@ -1085,19 +1085,19 @@ GSList *g_slist_sort(GSList *list, GCompareFunc cmp_func) { GSList *l1, *l2; - if (!list || !list->next) + if (!list || !list->next) return list; - l1 = list; + l1 = list; l2 = list->next; while ((l2 = l2->next) != NULL) { - if ((l2 = l2->next) == NULL) + if ((l2 = l2->next) == NULL) break; l1 = l1->next; } - l2 = l1->next; + l2 = l1->next; l1->next = NULL; return g_slist_sort_merge(g_slist_sort(list, cmp_func), @@ -1360,7 +1360,7 @@ gchar **g_strsplit(const gchar *string, const gchar *delimiter, gint max_tokens) return NULL; if (max_tokens < 1) - max_tokens = SSIZE_MAX; + max_tokens = INT_MAX; remainder = string; s = strstr(remainder, delimiter); @@ -1452,7 +1452,7 @@ gchar *g_key_file_get_string(GKeyFile *key_file, struct stat st; char *map, *line, *group = NULL, *value = NULL; off_t size; - size_t key_len, group_len; + size_t key_len, group_len; int fd, err = 0; fd = open(key_file->filename, O_RDONLY); @@ -1599,7 +1599,7 @@ static GString *g_string_sized_new(gsize dfl_size) GString *string; string = g_new0(GString, 1); - + g_string_maybe_expand(string, dfl_size); string->str[0] = '\0'; -- cgit From 0ef72a5769f1c283786aa105d67127d6b113168c Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Tue, 11 Mar 2008 22:54:59 +0000 Subject: Add g_dir* and g_str_has_prefix functions to eglib. --- eglib/gmain.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 85 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 878760d8..7bc96961 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -17,6 +17,7 @@ #include #include #include +#include #include @@ -64,6 +65,11 @@ struct _GMainLoop { GMainContext *context; }; +struct _GDir +{ + DIR *dirp; +}; + GIOError g_io_channel_read(GIOChannel *channel, gchar *buf, gsize count, gsize *bytes_read) { @@ -1404,6 +1410,23 @@ gboolean g_str_equal(gconstpointer v1, gconstpointer v2) return strcmp(string1, string2) == 0; } +gboolean g_str_has_prefix(const gchar *str, const gchar *prefix) +{ + int str_len; + int prefix_len; + + if (str == NULL || prefix == NULL) + return FALSE; + + str_len = strlen (str); + prefix_len = strlen (prefix); + + if (str_len < prefix_len) + return FALSE; + + return strncmp(str, prefix, prefix_len) == 0; +} + /* GKeyFile */ struct _GKeyFile { @@ -1692,3 +1715,65 @@ void g_markup_parse_context_free(GMarkupParseContext *context) { g_free(context); } + +gchar * g_build_filename (const gchar *first_element, ...) +{ + gchar *str; + va_list args; + + va_start (args, first_element); + str = g_build_pathname_va(first_element, &args, NULL); + va_end (args); + + return str; +} + +GDir *g_dir_open(const gchar *path, guint flags, GError **error) +{ + GDir *dir; + + if (path == NULL) + return NULL; + + dir = g_new (GDir, 1); + + dir->dirp = opendir (path); + + if (dir->dirp) + return dir; + + /* error case */ + g_set_error(error, 0, 0, "Error opening directory '%s': %s", path, + strerror(errno)); + + g_free (dir); + + return NULL; +} + +const gchar *g_dir_read_name(GDir *dir) +{ + struct dirent *entry; + + if (dir == NULL) + return NULL; + + entry = readdir (dir->dirp); + while (entry && (0 == strcmp(entry->d_name, ".") || + 0 == strcmp(entry->d_name, ".."))) + entry = readdir(dir->dirp); + + if (entry) + return entry->d_name; + else + return NULL; +} + +void g_dir_close(GDir *dir) +{ + if (dir == NULL) + return; + + closedir (dir->dirp); + g_free (dir); +} -- cgit From e6bce39040a253c0bf62e26ab275e3cf307ed288 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 11 Mar 2008 23:45:09 +0000 Subject: Fix memory leaks and coding style in eglib --- eglib/gmain.c | 55 ++++++++++++++++++++++++++++++------------------------- 1 file changed, 30 insertions(+), 25 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 7bc96961..9474c8d6 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -857,10 +857,10 @@ gboolean g_source_remove(guint tag) #define CONTINUATION_CHAR(c, val) \ do { \ - if (((c) & 0xc0) != 0x80) /* 10xxxxxx */ \ - goto failed; \ - (val) <<= 6; \ - (val) |= (c) & 0x3f; \ + if (((c) & 0xc0) != 0x80) /* 10xxxxxx */ \ + goto failed; \ + (val) <<= 6; \ + (val) |= (c) & 0x3f; \ } while (0) #define INCREMENT_AND_CHECK_MAX(p, i, max_len) \ @@ -1680,8 +1680,7 @@ gchar *g_string_free(GString *string, gboolean free_segment) if (free_segment) { g_free(string->str); segment = NULL; - } - else + } else segment = string->str; g_free(string); @@ -1716,18 +1715,26 @@ void g_markup_parse_context_free(GMarkupParseContext *context) g_free(context); } -gchar * g_build_filename (const gchar *first_element, ...) +gchar *g_build_pathname_va(const gchar *first_element, va_list args, + gpointer *data) +{ + return NULL; +} + +gchar *g_build_filename(const gchar *first_element, ...) { gchar *str; va_list args; - va_start (args, first_element); - str = g_build_pathname_va(first_element, &args, NULL); - va_end (args); + va_start(args, first_element); + str = g_build_pathname_va(first_element, args, NULL); + va_end(args); return str; } +/* GDir */ + GDir *g_dir_open(const gchar *path, guint flags, GError **error) { GDir *dir; @@ -1735,18 +1742,18 @@ GDir *g_dir_open(const gchar *path, guint flags, GError **error) if (path == NULL) return NULL; - dir = g_new (GDir, 1); + dir = g_new(GDir, 1); - dir->dirp = opendir (path); + dir->dirp = opendir(path); if (dir->dirp) return dir; /* error case */ - g_set_error(error, 0, 0, "Error opening directory '%s': %s", path, - strerror(errno)); + g_set_error(error, 0, 0, "Error opening directory '%s': %s", + path, strerror(errno)); - g_free (dir); + g_free(dir); return NULL; } @@ -1756,17 +1763,15 @@ const gchar *g_dir_read_name(GDir *dir) struct dirent *entry; if (dir == NULL) - return NULL; + return NULL; - entry = readdir (dir->dirp); - while (entry && (0 == strcmp(entry->d_name, ".") || - 0 == strcmp(entry->d_name, ".."))) + entry = readdir(dir->dirp); + + while (entry && (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0)) entry = readdir(dir->dirp); - if (entry) - return entry->d_name; - else - return NULL; + return entry ? entry->d_name : NULL; } void g_dir_close(GDir *dir) @@ -1774,6 +1779,6 @@ void g_dir_close(GDir *dir) if (dir == NULL) return; - closedir (dir->dirp); - g_free (dir); + closedir(dir->dirp); + g_free(dir); } -- cgit From 856f263c19d082772797a729f8d0a4faa336114c Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 11 Mar 2008 23:50:18 +0000 Subject: Import functions correctly --- eglib/gmain.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 9474c8d6..8341c664 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1715,8 +1715,8 @@ void g_markup_parse_context_free(GMarkupParseContext *context) g_free(context); } -gchar *g_build_pathname_va(const gchar *first_element, va_list args, - gpointer *data) +static gchar *g_build_pathname_va(const gchar *first_element, + va_list args, gpointer *data) { return NULL; } -- cgit From b313aacb3dd7ab17e773206d1c6e074deba913b4 Mon Sep 17 00:00:00 2001 From: Vinicius Gomes Date: Wed, 26 Mar 2008 18:47:26 +0000 Subject: eglib: adding filename related functions for loading dynamic libraries. --- eglib/gmain.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 8341c664..b51da600 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1355,6 +1355,37 @@ gchar *g_strconcat(const gchar *string1, ...) return concat; } +gsize g_strlcat(gchar *dest, const gchar *src, gsize dest_size) +{ + gchar *d = dest; + const gchar *s = src; + gsize bytes_left = dest_size; + gsize dlength; /* Logically, MIN(strlen(d), dest_size) */ + + if (!d || !s) + return 0; + + /* Find the end of dst and adjust bytes left but don't go past end */ + while (*d != 0 && bytes_left-- != 0) + d++; + dlength = d - dest; + bytes_left = dest_size - dlength; + + if (bytes_left == 0) + return dlength + strlen(s); + + while (*s != 0) { + if (bytes_left != 1) { + *d++ = *s; + bytes_left--; + } + s++; + } + *d = 0; + + return dlength + (s - src); /* count does not include NULL */ +} + gchar **g_strsplit(const gchar *string, const gchar *delimiter, gint max_tokens) { GSList *string_list = NULL, *slist; @@ -1427,6 +1458,23 @@ gboolean g_str_has_prefix(const gchar *str, const gchar *prefix) return strncmp(str, prefix, prefix_len) == 0; } +gboolean g_str_has_suffix(const gchar *str, const gchar *suffix) +{ + int str_len; + int suffix_len; + + if (!str || !suffix) + return FALSE; + + str_len = strlen(str); + suffix_len = strlen(suffix); + + if (str_len < suffix_len) + return FALSE; + + return strcmp(str + str_len - suffix_len, suffix) == 0; +} + /* GKeyFile */ struct _GKeyFile { @@ -1718,7 +1766,20 @@ void g_markup_parse_context_free(GMarkupParseContext *context) static gchar *g_build_pathname_va(const gchar *first_element, va_list args, gpointer *data) { - return NULL; + gchar result[PATH_MAX], *element; + + strncpy(result, first_element, PATH_MAX); + element = va_arg(args, gchar *); + + while (element) { + g_strlcat(result, "/", PATH_MAX); + g_strlcat(result, element, PATH_MAX); + element = va_arg(args, gchar *); + } + + va_end(args); + + return g_strdup(result); } gchar *g_build_filename(const gchar *first_element, ...) -- cgit From b47a2a08851a5bacc0e2498846db25d8837ba069 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 23 Apr 2008 14:17:50 +0000 Subject: Introduce g_io_channel_set_flags to eglib. --- eglib/gmain.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index b51da600..8071c62b 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -201,6 +201,52 @@ gint g_io_channel_unix_get_fd(GIOChannel *channel) return channel->fd; } +static int set_flags(int fd, long flags) +{ + long arg; + + arg = fcntl(fd, F_GETFL); + if (arg < 0) + return -errno; + + /* Return if already set */ + if ((arg & flags) == flags) + return 0; + + arg |= flags; + if (fcntl(fd, F_SETFL, arg) < 0) + return -errno; + + return 0; +} + +GIOStatus g_io_channel_set_flags(GIOChannel *channel, GIOFlags flags, + GError **error) +{ + int err, fd; + long fd_flags = 0; + + if (!channel || channel->closed) + return G_IO_STATUS_ERROR; + + fd = g_io_channel_unix_get_fd(channel); + + if (flags & G_IO_FLAG_APPEND) + fd_flags |= O_APPEND; + if (flags & G_IO_FLAG_NONBLOCK) + fd_flags |= O_NONBLOCK; + + err = set_flags(fd, fd_flags); + if (err < 0) { + if (error) + g_set_error(error, 0, 0, "Unable to set flags: %s", + strerror(-err)); + return G_IO_STATUS_ERROR; + } + + return G_IO_STATUS_NORMAL; +} + struct io_watch { guint id; GIOChannel *channel; -- cgit From 4538ab2cc8f6a59a5a4bb987fe89ae361dcf0f60 Mon Sep 17 00:00:00 2001 From: Cidorvan Leite Date: Wed, 7 May 2008 14:57:35 +0000 Subject: Added g_ascii_strup function to eglib --- eglib/gmain.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 8071c62b..27b2dd9a 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1479,6 +1479,24 @@ gchar **g_strsplit(const gchar *string, const gchar *delimiter, gint max_tokens) return str_array; } +gchar *g_ascii_strup(const gchar *str, gssize len) +{ + int i; + gchar *s; + + s = g_strdup(str); + if (!s) + return NULL; + + if (len < 0) + len = strlen(s); + + for (i = 0; i < len; i++) + s[i] = toupper(s[i]); + + return s; +} + gboolean g_str_equal(gconstpointer v1, gconstpointer v2) { const gchar *string1 = v1; -- cgit From 021c7fa891b23d8623beebf3f9ee79a36a1ff174 Mon Sep 17 00:00:00 2001 From: Luiz Augusto von Dentz Date: Wed, 14 May 2008 21:35:33 +0000 Subject: Introduce g_key_file_get_integer to eglib. --- eglib/gmain.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 27b2dd9a..a3fa95a9 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1703,6 +1703,25 @@ gboolean g_key_file_get_boolean(GKeyFile *key_file, return ret; } +gint g_key_file_get_integer(GKeyFile *key_file, + const gchar *group_name, + const gchar *key, + GError **error) +{ + int ret; + gchar *str; + + str = g_key_file_get_string(key_file, group_name, key, error); + if (!str) + return 0; + + ret = atoi(str); + + g_free(str); + + return ret; +} + /* GString */ #define MY_MAXSIZE ((gsize)-1) -- cgit From 09de5efbaa85d79e04f1c2375f5870c9aeba65f5 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 16 May 2008 10:28:33 +0000 Subject: Implement g_strfreev and add stub for g_key_file_get_string_list --- eglib/gmain.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index a3fa95a9..27f168d5 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1539,6 +1539,19 @@ gboolean g_str_has_suffix(const gchar *str, const gchar *suffix) return strcmp(str + str_len - suffix_len, suffix) == 0; } +void g_strfreev(gchar **str_array) +{ + int i; + + if (str_array == NULL) + return; + + for(i = 0; str_array[i] != NULL; i++) + g_free(str_array[i]); + + g_free(str_array); +} + /* GKeyFile */ struct _GKeyFile { @@ -1718,10 +1731,17 @@ gint g_key_file_get_integer(GKeyFile *key_file, ret = atoi(str); g_free(str); - + return ret; } +gchar **g_key_file_get_string_list(GKeyFile *key_file, const gchar *group_name, + const gchar *key, gsize *length, + GError **error) +{ + return g_new0(gchar *, 1); +} + /* GString */ #define MY_MAXSIZE ((gsize)-1) -- cgit From 7a7e09d564017f7f514f843996f9a0fb5fad5fd2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 16 May 2008 12:35:02 +0000 Subject: Implement g_key_file_get_string_list --- eglib/gmain.c | 26 +++++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 27f168d5..3259a43e 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -1739,7 +1739,31 @@ gchar **g_key_file_get_string_list(GKeyFile *key_file, const gchar *group_name, const gchar *key, gsize *length, GError **error) { - return g_new0(gchar *, 1); + gchar *str, *item, **list; + int items = 0; + + str = g_key_file_get_string(key_file, group_name, key, error); + if (!str) + return NULL; + + items = 0; + list = g_new0(char *, 1); + + item = strtok(str, ","); + while (item) { + items++; + + list = g_renew(char *, list, items + 1); + + list[items - 1] = g_strdup(item); + list[items] = NULL; + + item = strtok(NULL, ","); + } + + g_free(str); + + return list; } /* GString */ -- cgit From b80c668f0829ae704b62cc89dfb538c2df9ec677 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Tue, 10 Jun 2008 00:23:21 +0000 Subject: Add g_timeout_add_seconds to eglib --- eglib/gmain.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 3259a43e..be11056e 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -614,6 +614,11 @@ guint g_timeout_add(guint interval, GSourceFunc function, gpointer data) return t->id; } +guint g_timeout_add_seconds(guint interval, GSourceFunc function, gpointer data) +{ + return g_timeout_add(interval, function, data); +} + guint g_idle_add(GSourceFunc function, gpointer data) { return g_timeout_add(1, function, data); -- cgit From 45c36dbd276501aa76d9798a8fafe6c202db7276 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Wed, 11 Jun 2008 13:20:50 +0000 Subject: Avoid direct inclusion of malloc.h --- eglib/gmain.c | 1 - 1 file changed, 1 deletion(-) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index be11056e..1ca3d67a 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -4,7 +4,6 @@ #include #include #include -#include #include #include #include -- cgit From 8afa644ef281be85d7f5f5d3406d6be3a4ea71c1 Mon Sep 17 00:00:00 2001 From: Marcel Holtmann Date: Thu, 10 Jul 2008 01:47:55 +0000 Subject: Make sure to include --- eglib/gmain.c | 1 + 1 file changed, 1 insertion(+) (limited to 'eglib/gmain.c') diff --git a/eglib/gmain.c b/eglib/gmain.c index 1ca3d67a..3475fdbf 100644 --- a/eglib/gmain.c +++ b/eglib/gmain.c @@ -17,6 +17,7 @@ #include #include #include +#include #include -- cgit