Hi,
I've attached two patches. The first adds luadoc.css, awesome, and
awesome-client to .gitignore. The second makes awesome-client into a
full-on REPL in the style of the lua executable: in interactive mode, it
prints the return value of the statement.
- Nathan
>From 3d5c8185a333d1a5543b8beabcfb9b04deb3baad Mon Sep 17 00:00:00 2001
From: Nathan Weizenbaum <[EMAIL PROTECTED]>
Date: Thu, 18 Sep 2008 21:09:50 -0700
Subject: [PATCH] gitignore: add binaries and luadoc.css
Signed-off-by: Nathan Weizenbaum <[EMAIL PROTECTED]>
---
.gitignore | 3 +++
1 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/.gitignore b/.gitignore
index 5bbaf3e..f1485bf 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,6 @@
.*.sw?
build
.build*
+/awesome
+/awesome-client
+/luadoc.css
\ No newline at end of file
--
1.6.0.1.267.gec3a.dirty
>From 9e25a0099209a5db296307f04a6434d8897d6c11 Mon Sep 17 00:00:00 2001
From: Nathan Weizenbaum <[EMAIL PROTECTED]>
Date: Thu, 18 Sep 2008 21:48:55 -0700
Subject: [PATCH] awesome-client, socket, lua: make awesome-client into a true REPL.
After recieving a command from awesome-client, awesome will send
the result of that command in return and awesome-client will print it out.
Signed-off-by: Nathan Weizenbaum <[EMAIL PROTECTED]>
---
awesome-client.c | 88 +++++++++++++++++++++++++++++++++++++++++++++-------
common/socket.c | 37 ++++++++++++++++++++--
common/socket.h | 3 +-
lua.c | 90 +++++++++++++++++++++++++++++++++++++++++++++++++----
4 files changed, 195 insertions(+), 23 deletions(-)
diff --git a/awesome-client.c b/awesome-client.c
index 3af9c87..1b9a68b 100644
--- a/awesome-client.c
+++ b/awesome-client.c
@@ -25,6 +25,7 @@
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
+#include <signal.h>
#include <sys/socket.h>
#include <sys/un.h>
@@ -41,6 +42,47 @@
#define MSG_NOSIGNAL 0
#endif
+struct sockaddr_un *client_addr;
+struct sockaddr_un *addr;
+int csfd;
+
+/** Initialize the client and server socket connections.
+ * If something goes wrong, preserves errno.
+ * \return 0 if everything worked, 1 otherwise.
+ */
+static int
+init_sockets(void)
+{
+ return (csfd = socket_getclient()) < 0 ||
+ !(addr = socket_getaddr_server(getenv("DISPLAY"))) ||
+ !(client_addr = socket_getaddr_client(getpid())) ||
+ bind(csfd, client_addr, sizeof(struct sockaddr_un)) == -1;
+}
+
+
+/** Close the client and server socket connections.
+ */
+static void
+close_sockets(void)
+{
+ if (unlink(client_addr->sun_path))
+ warn("error unlinking UNIX domain socket: %s", strerror(errno));
+
+ close(csfd);
+ p_delete(&addr);
+ p_delete(&client_addr);
+}
+
+
+static void
+handle_sigint(int sig)
+{
+ close_sockets();
+ signal(sig, SIG_DFL);
+ raise(sig);
+}
+
+
/** Send a message to awesome.
* \param msg The message.
* \param msg_len The message length.
@@ -49,14 +91,6 @@
static int
send_msg(const char *msg, ssize_t msg_len)
{
- struct sockaddr_un *addr;
- int csfd, ret_value = EXIT_SUCCESS;
- csfd = socket_getclient();
- addr = socket_getaddr(getenv("DISPLAY"));
-
- if(!addr || csfd < 0)
- return EXIT_FAILURE;
-
if(sendto(csfd, msg, msg_len, MSG_NOSIGNAL,
(const struct sockaddr *) addr, sizeof(struct sockaddr_un)) == -1)
{
@@ -68,13 +102,33 @@ send_msg(const char *msg, ssize_t msg_len)
default:
warn("error sending datagram: %s", strerror(errno));
}
- ret_value = errno;
+ return errno;
}
- close(csfd);
+ return EXIT_SUCCESS;
+}
- p_delete(&addr);
- return ret_value;
+
+/** Recieve a message from awesome.
+ */
+static void
+recv_msg(void)
+{
+ int r;
+ char buf[1024];
+
+ r = recv(csfd, buf, sizeof(buf) - 1, MSG_TRUNC);
+ if (r < 0)
+ {
+ warn("error recieving from UNIX domain socket: %s", strerror(errno));
+ return;
+ }
+
+ if (r >= 0)
+ {
+ buf[r] = '\0';
+ puts(buf);
+ }
}
@@ -104,6 +158,8 @@ main(int argc, char **argv)
int ret_value = EXIT_SUCCESS;
ssize_t len, msg_len = 1;
+ signal(SIGINT, handle_sigint);
+
if(argc == 2)
{
if(!a_strcmp("-v", argv[1]) || !a_strcmp("--version", argv[1]))
@@ -114,6 +170,12 @@ main(int argc, char **argv)
else if(argc > 2)
exit_help(EXIT_SUCCESS);
+ if (init_sockets())
+ {
+ warn("can't connect to UNIX domain socket: %s", strerror(errno));
+ return EXIT_FAILURE;
+ }
+
if(isatty(STDIN_FILENO))
{
char *display = getenv("DISPLAY");
@@ -126,6 +188,7 @@ main(int argc, char **argv)
msg[msg_len] = '\n';
msg[msg_len + 1] = '\0';
send_msg(msg, msg_len + 2);
+ recv_msg();
}
}
else
@@ -155,6 +218,7 @@ main(int argc, char **argv)
p_delete(&msg);
}
+ close_sockets();
return ret_value;
}
diff --git a/common/socket.c b/common/socket.c
index c44bbc1..a57b40e 100644
--- a/common/socket.c
+++ b/common/socket.c
@@ -30,7 +30,8 @@
#include "common/socket.h"
#include "common/util.h"
-#define CONTROL_UNIX_SOCKET_PATH ".awesome_ctl."
+#define CONTROL_UNIX_SOCKET_PATH_SERVER ".awesome_ctl."
+#define CONTROL_UNIX_SOCKET_PATH_CLIENT ".awesome_client."
/** Get a sockaddr_un struct with information feeded for opening a
* communication to the awesome socket for given display
@@ -38,7 +39,7 @@
* \return sockaddr_un struct ready to be used or NULL if a problem occured
*/
struct sockaddr_un *
-socket_getaddr(const char *display)
+socket_getaddr_server(const char *display)
{
char *homedir, *host = NULL;
int screenp = 0, displayp = 0;
@@ -54,7 +55,7 @@ socket_getaddr(const char *display)
/* + 2 for / and . and \0 */
path_len = snprintf(addr->sun_path, sizeof(addr->sun_path),
- "%s/" CONTROL_UNIX_SOCKET_PATH "%s%s%d",
+ "%s/" CONTROL_UNIX_SOCKET_PATH_SERVER "%s%s%d",
homedir, len ? host : "", len ? "." : "",
displayp);
@@ -71,6 +72,36 @@ socket_getaddr(const char *display)
return addr;
}
+/** Get a sockaddr_un struct with information feeded for opening a
+ * communication to the awesome-client socket with given pid
+ * \param pid the process id
+ * \return sockaddr_un struct ready to be used or NULL if a problem occured
+ */
+struct sockaddr_un *
+socket_getaddr_client(int pid)
+{
+ char *homedir = NULL;
+ ssize_t path_len;
+ struct sockaddr_un *addr;
+
+ addr = p_new(struct sockaddr_un, 1);
+ homedir = getenv("HOME");
+
+ path_len = snprintf(addr->sun_path, sizeof(addr->sun_path),
+ "%s/" CONTROL_UNIX_SOCKET_PATH_CLIENT "%d",
+ homedir, pid);
+
+ 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;
+
+ return addr;
+}
+
/** Get a AF_UNIX socket for communicating with awesome
* \return the socket file descriptor
*/
diff --git a/common/socket.h b/common/socket.h
index df131c1..55fd4fb 100644
--- a/common/socket.h
+++ b/common/socket.h
@@ -22,7 +22,8 @@
#ifndef AWESOME_COMMON_SOCKET_H
#define AWESOME_COMMON_SOCKET_H
-struct sockaddr_un * socket_getaddr(const char *);
+struct sockaddr_un * socket_getaddr_server(const char *);
+struct sockaddr_un * socket_getaddr_client(int);
int socket_getclient(void);
#endif
diff --git a/lua.c b/lua.c
index 0e49393..bfe1be5 100644
--- a/lua.c
+++ b/lua.c
@@ -48,6 +48,7 @@
#include "event.h"
#include "layouts/tile.h"
#include "common/socket.h"
+#include "common/buffer.h"
extern awesome_t globalconf;
@@ -714,28 +715,79 @@ luaA_parserc(const char *confpatharg)
/** Parse a command.
* \param cmd The buffer to parse.
- * \return true on succes, false on failure.
+ * \return the number of elements pushed on the stack by the last statement in cmd.
+ * If there's an error, the message is pushed onto the stack and this returns 1.
*/
-static void
+static int
luaA_docmd(const char *cmd)
{
char *p;
+ int newtop, oldtop = lua_gettop(globalconf.L);
while((p = strchr(cmd, '\n')))
{
+ newtop = lua_gettop(globalconf.L);
+ lua_pop(globalconf.L, newtop - oldtop);
+ oldtop = newtop;
+
*p = '\0';
- luaA_dostring(globalconf.L, cmd);
+ if (luaL_dostring(globalconf.L, cmd))
+ {
+ warn("error executing Lua code: %s", lua_tostring(globalconf.L, -1));
+ return 1;
+ }
cmd = p + 1;
}
+ return lua_gettop(globalconf.L) - oldtop;
+}
+
+/** Pushes a Lua array containing the top n elements of the stack.
+ * \param n The number of elements to put in the array.
+ */
+static void
+luaA_array(int n)
+{
+ int i;
+ lua_createtable(globalconf.L, n, 0);
+ lua_insert(globalconf.L, -n - 1);
+
+ for (i = n; i > 0; i--)
+ lua_rawseti(globalconf.L, -i - 1, i);
+}
+
+/** Maps the top n elements of the stack to the result of
+ * applying a function to that element.
+ * \param n The number of elements to map.
+ * \luastack
+ * \lparam The function to map the elements by. This should be
+ * at position -(n + 1).
+ */
+static void
+luaA_map(int n)
+{
+ int i;
+ for (i = 0; i < n; i++)
+ {
+ lua_pushvalue(globalconf.L, -n - 1); /* copy of the function */
+ lua_pushvalue(globalconf.L, -n - 1); /* value to map */
+ lua_pcall(globalconf.L, 1, 1, 0); /* call function */
+ lua_remove(globalconf.L, -n - 1); /* remove old value */
+ }
+ lua_remove(globalconf.L, -n - 1); /* remove function */
}
static void
luaA_cb(EV_P_ ev_io *w, int revents)
{
char buf[1024];
- int r;
+ int r, els;
+ struct sockaddr_un raddr;
+ socklen_t raddr_len;
+ const char *s;
+ size_t len;
+ int csfd;
- switch(r = recv(w->fd, buf, sizeof(buf)-1, MSG_TRUNC))
+ switch(r = recvfrom(w->fd, buf, sizeof(buf)-1, MSG_TRUNC, (struct sockaddr*)&raddr, &raddr_len))
{
case -1:
warn("error reading UNIX domain socket: %s", strerror(errno));
@@ -747,7 +799,31 @@ luaA_cb(EV_P_ ev_io *w, int revents)
if(r >= ssizeof(buf))
break;
buf[r] = '\0';
- luaA_docmd(buf);
+ lua_getglobal(globalconf.L, "table");
+ lua_getfield(globalconf.L, -1, "concat");
+ lua_remove(globalconf.L, -2); /* remove table */
+
+ lua_getglobal(globalconf.L, "tostring");
+ els = luaA_docmd(buf);
+ luaA_map(els); /* map results to strings */
+ luaA_array(els); /* put strings in an array */
+
+ lua_pushstring(globalconf.L, "\t");
+ lua_pcall(globalconf.L, 2, 1, 0); /* concatenate results with tabs */
+
+ s = lua_tolstring(globalconf.L, -1, &len);
+ csfd = socket_getclient();
+ if (csfd < 0)
+ warn("can't create client UNIX domain socket: %s", strerror(errno));
+ else
+ {
+ if (sendto(csfd, s, len, 0, (struct sockaddr*)&raddr, raddr_len) == -1 &&
+ errno != ENOENT) /* the client doesn't create a socket for non-tty */
+ warn("can't connect to client UNIX domain socket: %s", strerror(errno));
+ if (csfd >= 0) close(csfd);
+ }
+
+ lua_pop(globalconf.L, 1); /* pop the string */
}
awesome_refresh(globalconf.connection);
}
@@ -760,7 +836,7 @@ luaA_cs_init(void)
if (csfd < 0 || fcntl(csfd, F_SETFD, FD_CLOEXEC) == -1)
return;
- addr = socket_getaddr(getenv("DISPLAY"));
+ addr = socket_getaddr_server(getenv("DISPLAY"));
if(bind(csfd, (const struct sockaddr *) addr, SUN_LEN(addr)))
{
--
1.6.0.1.267.gec3a.dirty