From 5938aedc98430070bc009c88696829462e7bd273 Mon Sep 17 00:00:00 2001 From: Sergey Poznyakoff Date: Mon, 14 Aug 2017 16:10:58 +0300 Subject: Fix grecs_node_unlink function; implement grecs_sockaddr_str. * include/grecs/sockaddr.h (grecs_sockaddr) : New member. (grecs_sockaddr_to_str): New proto. * src/sockaddr.c (grecs_sockaddr_new): Initialize str. (grecs_sockaddr_free): Free str. (grecs_sockaddr_str): New function. * src/tree.c (grecs_node_unlink): Fix. --- include/grecs/sockaddr.h | 4 ++- src/sockaddr.c | 64 +++++++++++++++++++++++++++++++++++++++++++++++- src/tree.c | 7 +++--- 3 files changed, 69 insertions(+), 6 deletions(-) diff --git a/include/grecs/sockaddr.h b/include/grecs/sockaddr.h index c8a3de2..835f698 100644 --- a/include/grecs/sockaddr.h +++ b/include/grecs/sockaddr.h @@ -1,5 +1,5 @@ /* grecs - Gray's Extensible Configuration System -*- c -*- - Copyright (C) 2007-2016 Sergey Poznyakoff + Copyright (C) 2007-2017 Sergey Poznyakoff Grecs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -20,6 +20,7 @@ struct grecs_sockaddr { #if GRECS_SOCKADDR_LIST struct grecs_sockaddr *next; + char *str; #endif int len; struct sockaddr *sa; @@ -45,6 +46,7 @@ void grecs_sockaddr_free(struct grecs_sockaddr *p); int grecs_str_to_sockaddr(struct grecs_sockaddr **sap, const char *arg, struct grecs_sockaddr_hints *gh, grecs_locus_t const *locus); +char const *grecs_sockaddr_to_str(struct grecs_sockaddr *); #endif #define GRECS_INADDR_BYTES 16 diff --git a/src/sockaddr.c b/src/sockaddr.c index 8cd790d..83f2450 100644 --- a/src/sockaddr.c +++ b/src/sockaddr.c @@ -1,5 +1,5 @@ /* grecs - Gray's Extensible Configuration System - Copyright (C) 2007-2016 Sergey Poznyakoff + Copyright (C) 2007-2017 Sergey Poznyakoff Grecs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the @@ -19,6 +19,7 @@ #ifdef HAVE_CONFIG_H # include #endif +#include #include #include #include @@ -36,6 +37,7 @@ grecs_sockaddr_new(size_t s) { struct grecs_sockaddr *sp = grecs_malloc(sizeof(*sp)); sp->next = NULL; + sp->str = NULL; sp->sa = grecs_zalloc(s); sp->len = s; return sp; @@ -47,6 +49,7 @@ grecs_sockaddr_free(struct grecs_sockaddr *p) while (p) { struct grecs_sockaddr *next = p->next; free(p->sa); + free(p->str); free(p); p = next; } @@ -279,3 +282,62 @@ grecs_str_to_sockaddr(struct grecs_sockaddr **sap, return parse_inet(sap, AF_UNSPEC, arg, arg, gh, locus); } + +#define S_UN_NAME(sa, salen) \ + ((salen < offsetof(struct sockaddr_un,sun_path)) ? \ + "" : (sa)->sun_path) + +static int +sockaddr_str(struct sockaddr *sa, socklen_t salen, char **pbuf, size_t *psz) +{ + int rc; + + switch (sa->sa_family) { + case AF_INET: + case AF_INET6: { + char host[NI_MAXHOST]; + char srv[NI_MAXSERV]; + if (getnameinfo(sa, salen, + host, sizeof(host), srv, sizeof(srv), + NI_NUMERICHOST|NI_NUMERICSERV) == 0) + rc = grecs_asprintf(pbuf, psz, "%s://%s:%s", + sa->sa_family == AF_INET ? + "inet" : "inet6", + host, srv); + else + rc = grecs_asprintf(pbuf, psz, + "%s://[getnameinfo failed]", + sa->sa_family == AF_INET ? + "inet" : "inet6"); + break; + } + case AF_UNIX: { + struct sockaddr_un *s_un = (struct sockaddr_un *)sa; + if (S_UN_NAME(s_un, salen)[0] == 0) + rc = grecs_asprintf(pbuf, psz, + "unix://[anonymous socket]"); + else + rc = grecs_asprintf(pbuf, psz, "unix://%s", + s_un->sun_path); + break; + } + + default: + rc = grecs_asprintf(pbuf, psz, "family:%d", sa->sa_family); + } + return rc; +} + +char const * +grecs_sockaddr_str(struct grecs_sockaddr *sa) +{ + if (!sa->str) { + size_t sz = 0; + if (sockaddr_str(sa->sa, sa->len, &sa->str, &sz)) { + //FIXME + abort(); + } + } + return sa->str; +} + diff --git a/src/tree.c b/src/tree.c index 5826abf..307682c 100644 --- a/src/tree.c +++ b/src/tree.c @@ -120,14 +120,13 @@ grecs_node_bind(struct grecs_node *master, struct grecs_node *node, int dn) int grecs_node_unlink(struct grecs_node *node) { + if (node->up && node->up->down == node) + node->up->down = node->prev; if (node->prev) node->prev->next = node->next; - else if (node->up) - node->up->down = node->next; - else - return 1; if (node->next) node->next->prev = node->prev; + node->up = node->prev = node->next = NULL; return 0; } -- cgit v1.2.1