From 2689852e45d4a9818f9b0951811f23d273350c61 Mon Sep 17 00:00:00 2001 From: Alex Cornejo Date: Thu, 19 Mar 2009 20:59:40 -0400 Subject: [PATCH] Changed socket interface to support fallbacks. Now we support a list of fallback targets when opening the socket, and socket binding/connect is done inside socket.* instead of luaa.c or awesome-client.c Signed-off-by: Alex Cornejo Signed-off-by: Julien Danjou --- awesome-client.c | 10 +------ common/socket.c | 71 ++++++++++++++++++++++++++++++++++++------------ common/socket.h | 8 +++++- luaa.c | 26 +++--------------- 4 files changed, 65 insertions(+), 50 deletions(-) diff --git a/awesome-client.c b/awesome-client.c index b2282a0b5..be697be63 100644 --- a/awesome-client.c +++ b/awesome-client.c @@ -56,17 +56,9 @@ sockets_init(void) if((csfd = socket_getclient()) < 0) return false; - if(!(addr = socket_getaddr(getenv("HOME"), display))) + if(!(addr = socket_open(csfd, display, SOCKET_MODE_CONNECT))) return false; - if(connect(csfd, addr, sizeof(struct sockaddr_un)) == -1) - { - if(!(addr = socket_getaddr("/tmp", display))) - return false; - if(connect(csfd, addr, sizeof(struct sockaddr_un)) == -1) - return false; - } - return true; } diff --git a/common/socket.c b/common/socket.c index 3fb9b68e0..88f8efa53 100644 --- a/common/socket.c +++ b/common/socket.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -32,41 +33,75 @@ #define CONTROL_UNIX_SOCKET_PATH ".awesome_ctl." -/** Get a sockaddr_un struct with information feeded for opening a - * communication to the awesome socket for given display - * \param directory Where socket is created. +/** Open a communication socket with awesome for a given display. + * \param csfd The socket file descriptor. * \param display the display number - * \return sockaddr_un struct ready to be used or NULL if a problem occured + * \param mode The open mode, either Bind or Connect. + * \return sockaddr_un Struct ready to be used or NULL if a problem ocurred. */ struct sockaddr_un * -socket_getaddr(const char *directory, const char *display) +socket_open(int csfd, const char *display, const socket_mode_t mode) { char *host = NULL; int screenp = 0, displayp = 0; + bool is_socket_opened = false; ssize_t path_len, len; struct sockaddr_un *addr; + const char *fallback[] = { ":HOME", ":TMPDIR", "/tmp", NULL }, *directory; addr = p_new(struct sockaddr_un, 1); + addr->sun_family = AF_UNIX; xcb_parse_display(NULL, &host, &displayp, &screenp); - len = a_strlen(host); - /* + 2 for / and . and \0 */ - path_len = snprintf(addr->sun_path, sizeof(addr->sun_path), - "%s/" CONTROL_UNIX_SOCKET_PATH "%s%s%d", - directory, len ? host : "", len ? "." : "", - displayp); + for(int i = 0; fallback[i] && !is_socket_opened; i++) + { + if(fallback[i][0] == ':') + { + if(!(directory = getenv(fallback[i] + 1))) + continue; + } + else + directory = fallback[i]; + + /* + 2 for / and . and \0 */ + path_len = snprintf(addr->sun_path, sizeof(addr->sun_path), + "%s/" CONTROL_UNIX_SOCKET_PATH "%s%s%d", + directory, len ? host : "", len ? "." : "", + displayp); + + if(path_len < ssizeof(addr->sun_path)) + switch(mode) + { + case SOCKET_MODE_BIND: +/* Needed for some OSes like Solaris */ +#ifndef SUN_LEN +#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path)) +#endif + if(!bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr))) + is_socket_opened = true; + else if(errno == EADDRINUSE) + { + if(unlink(addr->sun_path)) + warn("error unlinking existing file: %s", strerror(errno)); + if(!bind(csfd, (const struct sockaddr *)addr, SUN_LEN(addr))) + is_socket_opened = true; + } + break; + case SOCKET_MODE_CONNECT: + if(!connect(csfd, (const struct sockaddr *)addr, sizeof(struct sockaddr_un))) + is_socket_opened = true; + break; + } + else + warn("error: path (using %s) of control UNIX domain socket is too long", directory); + } p_delete(&host); - if(path_len >= ssizeof(addr->sun_path)) - { - fprintf(stderr, "error: path of control UNIX domain socket is too long"); - return NULL; - } - - addr->sun_family = AF_UNIX; + if(!is_socket_opened) + p_delete(&addr); return addr; } diff --git a/common/socket.h b/common/socket.h index 55e11271f..6bc724ba6 100644 --- a/common/socket.h +++ b/common/socket.h @@ -22,7 +22,13 @@ #ifndef AWESOME_COMMON_SOCKET_H #define AWESOME_COMMON_SOCKET_H -struct sockaddr_un * socket_getaddr(const char *, const char *); +typedef enum +{ + SOCKET_MODE_BIND, + SOCKET_MODE_CONNECT +} socket_mode_t; + +struct sockaddr_un *socket_open(const int, const char *, const socket_mode_t); int socket_getclient(void); #endif diff --git a/luaa.c b/luaa.c index 87df9f232..a2c8aabd3 100644 --- a/luaa.c +++ b/luaa.c @@ -1115,31 +1115,13 @@ luaA_cs_init(void) if (csfd < 0 || fcntl(csfd, F_SETFD, FD_CLOEXEC) == -1) return; - addr = socket_getaddr(getenv("HOME"), getenv("DISPLAY")); - -/* Needed for some OSes like Solaris */ -#ifndef SUN_LEN -#define SUN_LEN(ptr) ((size_t) (((struct sockaddr_un *) 0)->sun_path) + strlen ((ptr)->sun_path)) -#endif - - if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr))) + if(!(addr = socket_open(csfd, getenv("DISPLAY"), SOCKET_MODE_BIND))) { - if(errno == EADDRINUSE) - { - if(unlink(addr->sun_path)) - warn("error unlinking existing file: %s", strerror(errno)); - if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr))) - return warn("error binding UNIX domain socket: %s", strerror(errno)); - } - else - { - addr = socket_getaddr("/tmp", getenv("DISPLAY")); - if (bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr))) - return warn("error binding UNIX domain socket: %s", strerror(errno)); - } + warn("error binding UNIX domain socket: %s", strerror(errno)); + return; } - listen(csfd, 10); + listen(csfd, 10); ev_io_init(&csio, &luaA_conn_cb, csfd, EV_READ); ev_io_start(EV_DEFAULT_UC_ &csio); ev_unref(EV_DEFAULT_UC);