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 <acornejo@gmail.com> Signed-off-by: Julien Danjou <julien@danjou.info>
This commit is contained in:
parent
f0bb0b374b
commit
2689852e45
|
@ -56,17 +56,9 @@ sockets_init(void)
|
||||||
if((csfd = socket_getclient()) < 0)
|
if((csfd = socket_getclient()) < 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(!(addr = socket_getaddr(getenv("HOME"), display)))
|
if(!(addr = socket_open(csfd, display, SOCKET_MODE_CONNECT)))
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <xcb/xcb.h>
|
#include <xcb/xcb.h>
|
||||||
|
|
||||||
|
@ -32,41 +33,75 @@
|
||||||
|
|
||||||
#define CONTROL_UNIX_SOCKET_PATH ".awesome_ctl."
|
#define CONTROL_UNIX_SOCKET_PATH ".awesome_ctl."
|
||||||
|
|
||||||
/** Get a sockaddr_un struct with information feeded for opening a
|
/** Open a communication socket with awesome for a given display.
|
||||||
* communication to the awesome socket for given display
|
* \param csfd The socket file descriptor.
|
||||||
* \param directory Where socket is created.
|
|
||||||
* \param display the display number
|
* \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 *
|
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;
|
char *host = NULL;
|
||||||
int screenp = 0, displayp = 0;
|
int screenp = 0, displayp = 0;
|
||||||
|
bool is_socket_opened = false;
|
||||||
ssize_t path_len, len;
|
ssize_t path_len, len;
|
||||||
struct sockaddr_un *addr;
|
struct sockaddr_un *addr;
|
||||||
|
const char *fallback[] = { ":HOME", ":TMPDIR", "/tmp", NULL }, *directory;
|
||||||
|
|
||||||
addr = p_new(struct sockaddr_un, 1);
|
addr = p_new(struct sockaddr_un, 1);
|
||||||
|
addr->sun_family = AF_UNIX;
|
||||||
|
|
||||||
xcb_parse_display(NULL, &host, &displayp, &screenp);
|
xcb_parse_display(NULL, &host, &displayp, &screenp);
|
||||||
|
|
||||||
len = a_strlen(host);
|
len = a_strlen(host);
|
||||||
|
|
||||||
/* + 2 for / and . and \0 */
|
for(int i = 0; fallback[i] && !is_socket_opened; i++)
|
||||||
path_len = snprintf(addr->sun_path, sizeof(addr->sun_path),
|
{
|
||||||
"%s/" CONTROL_UNIX_SOCKET_PATH "%s%s%d",
|
if(fallback[i][0] == ':')
|
||||||
directory, len ? host : "", len ? "." : "",
|
{
|
||||||
displayp);
|
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);
|
p_delete(&host);
|
||||||
|
|
||||||
if(path_len >= ssizeof(addr->sun_path))
|
if(!is_socket_opened)
|
||||||
{
|
p_delete(&addr);
|
||||||
fprintf(stderr, "error: path of control UNIX domain socket is too long");
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr->sun_family = AF_UNIX;
|
|
||||||
|
|
||||||
return addr;
|
return addr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,13 @@
|
||||||
#ifndef AWESOME_COMMON_SOCKET_H
|
#ifndef AWESOME_COMMON_SOCKET_H
|
||||||
#define 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);
|
int socket_getclient(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
26
luaa.c
26
luaa.c
|
@ -1115,31 +1115,13 @@ luaA_cs_init(void)
|
||||||
if (csfd < 0 || fcntl(csfd, F_SETFD, FD_CLOEXEC) == -1)
|
if (csfd < 0 || fcntl(csfd, F_SETFD, FD_CLOEXEC) == -1)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
addr = socket_getaddr(getenv("HOME"), getenv("DISPLAY"));
|
if(!(addr = socket_open(csfd, getenv("DISPLAY"), 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)))
|
|
||||||
{
|
{
|
||||||
if(errno == EADDRINUSE)
|
warn("error binding UNIX domain socket: %s", strerror(errno));
|
||||||
{
|
return;
|
||||||
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));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
listen(csfd, 10);
|
|
||||||
|
|
||||||
|
listen(csfd, 10);
|
||||||
ev_io_init(&csio, &luaA_conn_cb, csfd, EV_READ);
|
ev_io_init(&csio, &luaA_conn_cb, csfd, EV_READ);
|
||||||
ev_io_start(EV_DEFAULT_UC_ &csio);
|
ev_io_start(EV_DEFAULT_UC_ &csio);
|
||||||
ev_unref(EV_DEFAULT_UC);
|
ev_unref(EV_DEFAULT_UC);
|
||||||
|
|
Loading…
Reference in New Issue