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

Reply via email to