libixp

git clone git://oldgit.suckless.org/libixp/
Log | Files | Refs | LICENSE

commit 5165675d6a893d7edc061226a47a30b87a384dcb
parent f4df93ddf312c9c4204b0d035c9d6da84287cdd1
Author: Kris Maglione <jg@suckless.org>
Date:   Wed, 28 Mar 2007 14:25:07 -0400

Refactored socket.c.

Diffstat:
libixp/socket.c | 272++++++++++++++++++++++++++++++++++++++++---------------------------------------
1 file changed, 139 insertions(+), 133 deletions(-)

diff --git a/libixp/socket.c b/libixp/socket.c @@ -15,119 +15,97 @@ #include <unistd.h> #include "ixp.h" +/* Note: These functions modify the strings that they are passed. + * The lookup function duplicates the original string, so it is + * not modified. + */ + typedef struct sockaddr sockaddr; +typedef struct sockaddr_un sockaddr_un; +typedef struct sockaddr_in sockaddr_in; static int -dial_unix(char *address) { - struct sockaddr_un sa; - socklen_t salen; - int fd; - - memset(&sa, 0, sizeof(sa)); +get_port(char *addr) { + char *s, *end; + int port; - sa.sun_family = AF_UNIX; - strncpy(sa.sun_path, address, sizeof(sa.sun_path)); - salen = SUN_LEN(&sa); - - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(fd < 0) { - errstr = strerror(errno); + s = strrchr(addr, '!'); + if(s == nil) { + errstr = "no port provided"; return -1; } - if(connect(fd, (sockaddr*) &sa, salen)) { - errstr = strerror(errno); - close(fd); + + *s++ = '\0'; + port = strtol(s, &end, 10); + if(*s == '\0' && *end != '\0') { + errstr = "invalid port number"; return -1; } - return fd; + return port; } static int -dial_tcp(char *host) { - struct sockaddr_in sa; - struct hostent *hp; - char *port; - uint prt; +sock_unix(char *address, sockaddr_un *sa, socklen_t *salen) { int fd; - memset(&sa, 0, sizeof(sa)); - - port = strrchr(host, '!'); - if(port == nil) { - errstr = "no port provided"; - return -1; - } - *port++ = '\0'; + memset(sa, 0, sizeof(sa)); - if(sscanf(port, "%u", &prt) != 1) - return -1; + sa->sun_family = AF_UNIX; + strncpy(sa->sun_path, address, sizeof(sa->sun_path)); + *salen = SUN_LEN(sa); - fd = socket(AF_INET, SOCK_STREAM, 0); + fd = socket(AF_UNIX, SOCK_STREAM, 0); if(fd < 0) { errstr = strerror(errno); return -1; } - - hp = gethostbyname(host); - sa.sin_family = AF_INET; - sa.sin_port = htons(prt); - memcpy(&sa.sin_addr, hp->h_addr, hp->h_length); - - if(connect(fd, (sockaddr*)&sa, sizeof(struct sockaddr_in))) { - errstr = strerror(errno); - close(fd); - return -1; - } return fd; } static int -announce_tcp(char *host) { - struct sockaddr_in sa; +sock_tcp(char *host, sockaddr_in *sa) { struct hostent *he; - char *port; - uint prt; - int fd; + int port, fd; - memset(&sa, 0, sizeof(sa)); - - port = strrchr(host, '!'); - if(port == nil) { - errstr = "no port provided"; + /* Truncates host at '!' */ + port = get_port(host); + if(port < 0) return -1; - } - - *port++ = '\0'; - if(sscanf(port, "%u", &prt) != 1) { - errstr = "invalid port number"; - return -1; - } signal(SIGPIPE, SIG_IGN); - if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { - errstr = "cannot open socket"; - return -1; - } + fd = socket(AF_INET, SOCK_STREAM, 0); + if(fd < 0) + goto fail; - sa.sin_family = AF_INET; - sa.sin_port = htons(prt); + memset(sa, 0, sizeof(sa)); + sa->sin_family = AF_INET; + sa->sin_port = htons(port); - if(!strcmp(host, "*")) - sa.sin_addr.s_addr = htonl(INADDR_ANY); + if(strcmp(host, "*") == 0) + sa->sin_addr.s_addr = htonl(INADDR_ANY); else if((he = gethostbyname(host))) - memcpy(&sa.sin_addr, he->h_addr, he->h_length); - else { - errstr = "cannot translate hostname to an address"; - return -1; - } + memcpy(&sa->sin_addr, he->h_addr, he->h_length); + else + goto fail; - if(bind(fd, (sockaddr*)&sa, sizeof(struct sockaddr_in)) < 0) { - errstr = strerror(errno); - close(fd); - return -1; - } + return fd; + +fail: + errstr = strerror(errno); + return -1; +} - if(listen(fd, IXP_MAX_CACHE) < 0) { +static int +dial_unix(char *address) { + sockaddr_un sa; + socklen_t salen; + int fd; + + fd = sock_unix(address, &sa, &salen); + if(fd == -1) + return fd; + + if(connect(fd, (sockaddr*) &sa, salen)) { errstr = strerror(errno); close(fd); return -1; @@ -138,77 +116,95 @@ announce_tcp(char *host) { static int announce_unix(char *file) { const int yes = 1; - struct sockaddr_un sa; + sockaddr_un sa; socklen_t salen; int fd; - memset(&sa, 0, sizeof(sa)); - signal(SIGPIPE, SIG_IGN); - fd = socket(AF_UNIX, SOCK_STREAM, 0); - if(fd < 0) { - errstr = "cannot open socket"; - return -1; - } + fd = sock_unix(file, &sa, &salen); + if(fd == -1) + return fd; - if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0) { - errstr = strerror(errno); - close(fd); - return -1; - } - - sa.sun_family = AF_UNIX; - strncpy(sa.sun_path, file, sizeof(sa.sun_path)); - salen = SUN_LEN(&sa); + if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (void*)&yes, sizeof(yes)) < 0) + goto fail; unlink(file); - - if(bind(fd, (sockaddr*)&sa, salen) < 0) { - errstr = strerror(errno); - close(fd); - return -1; - } + if(bind(fd, (sockaddr*)&sa, salen) < 0) + goto fail; chmod(file, S_IRWXU); - if(listen(fd, IXP_MAX_CACHE) < 0) { + if(listen(fd, IXP_MAX_CACHE) < 0) + goto fail; + + return fd; + +fail: + errstr = strerror(errno); + close(fd); + return -1; +} + +static int +dial_tcp(char *host) { + sockaddr_in sa; + int fd; + + fd = sock_tcp(host, &sa); + if(fd == -1) + return fd; + + if(connect(fd, (sockaddr*)&sa, sizeof(sa))) { errstr = strerror(errno); close(fd); return -1; } + return fd; } -int -ixp_dial(char *address) { - char *addr, *type; - int ret; - - ret = -1; - type = ixp_estrdup(address); +static int +announce_tcp(char *host) { + sockaddr_in sa; + int fd; - addr = strchr(type, '!'); - if(addr == nil) - errstr = "no address type defined"; - else { - *addr++ = '\0'; - if(strcmp(type, "unix") == 0) - ret = dial_unix(addr); - else if(strcmp(type, "tcp") == 0) - ret = dial_tcp(addr); - else - errstr = "unkown address type"; - } + fd = sock_tcp(host, &sa); + if(fd == -1) + return fd; - free(type); - return ret; + if(bind(fd, (sockaddr*)&sa, sizeof(sa)) < 0) + goto fail; + + if(listen(fd, IXP_MAX_CACHE) < 0) + goto fail; + + return fd; + +fail: + errstr = strerror(errno); + close(fd); + return -1; } -int -ixp_announce(char *address) { +typedef struct addrtab addrtab; +struct addrtab { + char *type; + int (*fn)(char*); +} dtab[] = { + {"tcp", dial_tcp}, + {"unix", dial_unix}, + {0, 0} +}, atab[] = { + {"tcp", announce_tcp}, + {"unix", announce_unix}, + {0, 0} +}; + +static int +lookup(char *address, addrtab *tab) { char *addr, *type; int ret; - + ret = -1; type = ixp_estrdup(address); @@ -217,14 +213,24 @@ ixp_announce(char *address) { errstr = "no address type defined"; else { *addr++ = '\0'; - if(strcmp(type, "unix") == 0) - ret = announce_unix(addr); - else if(strcmp(type, "tcp") == 0) - ret = announce_tcp(addr); + for(; tab->type; tab++) + if(strcmp(tab->type, type)) break; + if(tab->type == nil) + errstr = "unsupported address type"; else - errstr = "unkown address type"; + ret = tab->fn(addr); } free(type); return ret; } + +int +ixp_dial(char *address) { + return lookup(address, dtab); +} + +int +ixp_announce(char *address) { + return lookup(address, atab); +}