aboutsummaryrefslogtreecommitdiff
path: root/utils.c
diff options
context:
space:
mode:
Diffstat (limited to 'utils.c')
-rw-r--r--utils.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/utils.c b/utils.c
index 27d9e8d..e1580e0 100644
--- a/utils.c
+++ b/utils.c
@@ -34,6 +34,9 @@
#define N_ELEMENTS(a) (sizeof (a) / sizeof ((a)[0]))
+#define BLOCK_START do {
+#define BLOCK_END } while (0)
+
// --- Safe memory management --------------------------------------------------
// When a memory allocation fails and we need the memory, we're usually pretty
@@ -76,6 +79,31 @@ xrealloc (void *o, size_t n)
return p;
}
+// --- Double-linked list helpers ----------------------------------------------
+
+#define LIST_HEADER(type) \
+ type *next; \
+ type *prev;
+
+#define LIST_PREPEND(head, link) \
+ BLOCK_START \
+ (link)->prev = NULL; \
+ (link)->next = (head); \
+ if ((link)->next) \
+ (link)->next->prev = (link); \
+ (head) = (link); \
+ BLOCK_END
+
+#define LIST_UNLINK(head, link) \
+ BLOCK_START \
+ if ((link)->prev) \
+ (link)->prev->next = (link)->next; \
+ else \
+ (head) = (link)->next; \
+ if ((link)->next) \
+ (link)->next->prev = (link)->prev; \
+ BLOCK_END
+
// --- Dynamically allocated strings -------------------------------------------
// Basically a string builder to abstract away manual memory management.
@@ -191,6 +219,49 @@ str_append_printf (struct str *self, const char *fmt, ...)
// --- Utilities ---------------------------------------------------------------
static bool
+set_blocking (int fd, bool blocking)
+{
+ int flags = fcntl (fd, F_GETFL);
+ bool prev = !(flags & O_NONBLOCK);
+ if (blocking)
+ flags &= ~O_NONBLOCK;
+ else
+ flags |= O_NONBLOCK;
+ return prev;
+}
+
+static void
+xclose (int fd)
+{
+ while (close (fd) == -1)
+ if (errno != EINTR)
+ break;
+}
+
+static char *xstrdup_printf (const char *, ...) ATTRIBUTE_PRINTF (1, 2);
+
+static char *
+xstrdup_printf (const char *format, ...)
+{
+ va_list ap;
+ struct str tmp;
+ str_init (&tmp);
+ va_start (ap, format);
+ str_append_vprintf (&tmp, format, ap);
+ va_end (ap);
+ return str_steal (&tmp);
+}
+
+static char *
+format_host_port_pair (const char *host, const char *port)
+{
+ // IPv6 addresses mess with the "colon notation"; let's go with RFC 2732
+ if (strchr (host, ':'))
+ return xstrdup_printf ("[%s]:%s", host, port);
+ return xstrdup_printf ("%s:%s", host, port);
+}
+
+static bool
xstrtoul (unsigned long *out, const char *s, int base)
{
char *end;