diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-08-14 16:10:58 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2017-08-14 16:14:24 +0300 |
commit | 5938aedc98430070bc009c88696829462e7bd273 (patch) | |
tree | bacd78a135892aede7a89811ac35ce30d95ff7e9 /src/sockaddr.c | |
parent | 4e9e225408eeaa1f161ae366f68715529bea2d2a (diff) | |
download | grecs-5938aedc98430070bc009c88696829462e7bd273.tar.gz grecs-5938aedc98430070bc009c88696829462e7bd273.tar.bz2 |
Fix grecs_node_unlink function; implement grecs_sockaddr_str.
* include/grecs/sockaddr.h (grecs_sockaddr) <str>: 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.
Diffstat (limited to 'src/sockaddr.c')
-rw-r--r-- | src/sockaddr.c | 64 |
1 files changed, 63 insertions, 1 deletions
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 <config.h> #endif +#include <stddef.h> #include <string.h> #include <ctype.h> #include <sys/types.h> @@ -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; +} + |