From 785c41f08939f30fa7cb0648d23903c97eb16905 Mon Sep 17 00:00:00 2001 From: Julien Danjou Date: Tue, 27 May 2008 15:56:14 +0200 Subject: [PATCH] [lua] Add a hook on standard fd activity Signed-off-by: Julien Danjou --- awesome.c | 72 ++++++++++++++++++++++++++++++++++++++++++------ awesomerc.lua.in | 18 ++++++++++++ lua.c | 15 ++++++++++ statusbar.c | 4 +-- structs.h | 2 ++ 5 files changed, 101 insertions(+), 10 deletions(-) diff --git a/awesome.c b/awesome.c index e172da64..0aa64d6f 100644 --- a/awesome.c +++ b/awesome.c @@ -279,12 +279,15 @@ main(int argc, char **argv) char buf[1024]; const char *confpath = NULL; int r, xfd, csfd, dbusfd, i, screen_nbr, opt; - ssize_t cmdlen = 1; + ssize_t len = 1; const xcb_query_extension_reply_t *shape_query, *randr_query; fd_set rd; xcb_generic_event_t *ev; struct sockaddr_un *addr; client_t *c; + int pstdout[2], pstderr[2], + rstderr = -1, rstdout = -1, + a_stderr, a_stdout; static struct option long_options[] = { {"help", 0, NULL, 'h'}, @@ -298,15 +301,15 @@ main(int argc, char **argv) /* save argv */ for(i = 0; i < argc; i++) - cmdlen += a_strlen(argv[i]) + 1; + len += a_strlen(argv[i]) + 1; - globalconf.argv = p_new(char, cmdlen); - a_strcpy(globalconf.argv, cmdlen, argv[0]); + globalconf.argv = p_new(char, len); + a_strcpy(globalconf.argv, len, argv[0]); for(i = 1; i < argc; i++) { - a_strcat(globalconf.argv, cmdlen, " "); - a_strcat(globalconf.argv, cmdlen, argv[i]); + a_strcat(globalconf.argv, len, " "); + a_strcat(globalconf.argv, len, argv[i]); } /* check args */ @@ -376,6 +379,33 @@ main(int argc, char **argv) atom_cache_list_init(&globalconf.atoms); ewmh_init_atoms(); + /* grab stdout and stderr */ + if(pipe(pstdout) == -1) + { + perror("unable to pipe"); + a_stdout = -1; + } + else + { + rstdout = dup(fileno(stdout)); + dup2(pstdout[1], fileno(stdout)); + a_stdout = pstdout[0]; + /* stop making stdout buffered */ + setvbuf(stdout, NULL, _IONBF, 0); + } + + if(pipe(pstderr) == -1) + { + perror("unable to pipe"); + a_stderr = -1; + } + else + { + rstderr = dup(fileno(stderr)); + dup2(pstderr[1], fileno(stderr)); + a_stderr = pstderr[0]; + } + /* init screens struct */ globalconf.screens_info = screensinfo_new(globalconf.connection); globalconf.screens = p_new(screen_t, globalconf.screens_info->nscreen); @@ -486,15 +516,41 @@ main(int argc, char **argv) FD_SET(csfd, &rd); if(dbusfd >= 0) FD_SET(dbusfd, &rd); + if(a_stdout >= 0) + FD_SET(a_stdout, &rd); + if(a_stderr >= 0) + FD_SET(a_stderr, &rd); FD_SET(xfd, &rd); - if(select(MAX(MAX(xfd, csfd), dbusfd) + 1, &rd, NULL, NULL, NULL) == -1) + + if(select(MAX(MAX(MAX(MAX(xfd, csfd), dbusfd), a_stdout), a_stderr) + 1, + &rd, NULL, NULL, NULL) == -1) { if(errno == EINTR) continue; eprint("select failed"); } + + /* Read and write stdout */ + if(a_stdout >= 0 && FD_ISSET(a_stdout, &rd)) + { + len = read(a_stdout, buf, sizeof(buf)); + write(rstdout, buf, len); + /* call hook */ + lua_pushlstring(globalconf.L, buf, len); + luaA_dofunction(globalconf.L, globalconf.hooks.fdactivity, 1); + } + + if(a_stderr >= 0 && FD_ISSET(a_stderr, &rd)) + { + len = read(a_stderr, buf, sizeof(buf)); + write(rstderr, buf, len); + /* call hook */ + lua_pushlstring(globalconf.L, buf, len); + luaA_dofunction(globalconf.L, globalconf.hooks.fdactivity, 1); + } + if(csfd >= 0 && FD_ISSET(csfd, &rd)) - switch(r = recv(csfd, buf, sizeof(buf)-1, MSG_TRUNC)) + switch(r = recv(csfd, buf, sizeof(buf) - 1, MSG_TRUNC)) { case -1: warn("error reading UNIX domain socket: %s", strerror(errno)); diff --git a/awesomerc.lua.in b/awesomerc.lua.in index 58a94910..03db2ca9 100644 --- a/awesomerc.lua.in +++ b/awesomerc.lua.in @@ -87,6 +87,16 @@ for s = 1, awesome.screen_count() do mystatusbar:widget_add(mylayoutbox[s]) mystatusbar:add(s) end + +-- Create a textbox widget for debug messages on screen 1 +mydebugbox = widget.new({ type = "textbox", name = "mydebugbox", align = "left" }) +mydebugbox:set("text", "No debug information.") +mydebugbar = statusbar.new({ position = "off", name = "mydebugbar", + fg = "white", bg = "black" }) +mydebugbar:widget_add(mydebugbox) +mydebugbar:add(1) +awesome.key({ modkey }, "d", function () mydebugbar:position_set("bottom") end) +awesome.key({ modkey, "Control" }, "d", function () mydebugbar:position_set("off") end) -- }}} -- {{{ Mouse bindings @@ -208,12 +218,20 @@ function hook_arrange(screen) mylayoutbox[screen]:set("image", "@iconsdir@/layouts/" .. layout .. "w.png") end +-- Hook function to print errors message +-- WARNING: you should _NOT_ print anything in this function +-- or you go into infinite loop +function hook_fdactivity(text) + mydebugbox:set("text", "" .. text .. "") +end + -- Set up some hooks hooks.focus(hook_focus) hooks.unfocus(hook_unfocus) hooks.newclient(hook_newclient) hooks.mouseover(hook_mouseover) hooks.arrange(hook_arrange) +hooks.fdactivity(hook_fdactivity) -- }}} -- Respect size hints diff --git a/lua.c b/lua.c index acb45849..681a70a5 100644 --- a/lua.c +++ b/lua.c @@ -359,6 +359,20 @@ luaA_hooks_titleupdate(lua_State *L) return 0; } +/** Set the function called on standard file descriptor (stdout and stderr) activity. + * This function is called with the output buffer text as argument. + * \param A function to call on each standard file descriptor activity. + */ +static int +luaA_hooks_fdactivity(lua_State *L) +{ + luaA_checkfunction(L, 1); + if(globalconf.hooks.fdactivity) + luaL_unref(L, LUA_REGISTRYINDEX, globalconf.hooks.fdactivity); + globalconf.hooks.fdactivity = luaL_ref(L, LUA_REGISTRYINDEX); + return 0; +} + /** Set default font. * \param A string with a font name in Pango format. */ @@ -434,6 +448,7 @@ luaA_parserc(const char *rcfile) { "mouseover", luaA_hooks_mouseover }, { "arrange", luaA_hooks_arrange }, { "titleupdate", luaA_hooks_titleupdate }, + { "fdactivity", luaA_hooks_fdactivity }, { NULL, NULL } }; diff --git a/statusbar.c b/statusbar.c index 572d75c6..681aa3df 100644 --- a/statusbar.c +++ b/statusbar.c @@ -43,8 +43,6 @@ statusbar_draw(statusbar_t *statusbar) int left = 0, right = 0; area_t rectangle = { 0, 0, 0, 0, NULL, NULL }; - statusbar->need_update.value = false; - if(!statusbar->position) return; @@ -99,6 +97,8 @@ statusbar_refresh(void *p) pthread_cond_wait(&statusbar->need_update.cond, &statusbar->need_update.lock); statusbar_draw(statusbar); + statusbar->need_update.value = false; + pthread_mutex_unlock(&statusbar->need_update.lock); } diff --git a/structs.h b/structs.h index 727bfe0e..734a200b 100644 --- a/structs.h +++ b/structs.h @@ -429,6 +429,8 @@ struct awesome_t luaA_function arrange; /** Command to run on title change */ luaA_function titleupdate; + /** Command to run on every standard output printing */ + luaA_function fdactivity; } hooks; };