awesome.spawn: Accept tables as arguments
With this change, awesome.spawn() can be called with a table as its command line argument. This gets rid of lots of problems with escaping the arguments. For example, the following call is now possible: awesome.spawn({ "bash", "-c", "echo \"foo\"" }) Thanks to Ignas Anikevičius for inspiring me to this. Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
parent
4c3bac07ec
commit
3c40d6b470
|
@ -29,7 +29,7 @@ module("awesome")
|
||||||
-- @class function
|
-- @class function
|
||||||
|
|
||||||
--- Spawn a program.
|
--- Spawn a program.
|
||||||
-- @param cmd The command to launch.
|
-- @param cmd The command to launch. Either a string or a table of strings.
|
||||||
-- @param use_sn Use startup-notification, true or false, default to true.
|
-- @param use_sn Use startup-notification, true or false, default to true.
|
||||||
-- @return Process ID if everything is OK, or an error string if an error occured.
|
-- @return Process ID if everything is OK, or an error string if an error occured.
|
||||||
|
|
||||||
|
|
67
spawn.c
67
spawn.c
|
@ -263,29 +263,40 @@ spawn_callback(gpointer user_data)
|
||||||
setsid();
|
setsid();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Spawn a command.
|
/** Parse a command line.
|
||||||
* \param command_line The command line to launch.
|
* \param L The Lua VM state.
|
||||||
* \param error A error pointer to fill with the possible error from
|
* \param idx The index of the argument that we should parse
|
||||||
* g_spawn_async.
|
* \return The argv array for the new process.
|
||||||
* \return g_spawn_async value.
|
|
||||||
*/
|
*/
|
||||||
static GPid
|
static gchar **
|
||||||
spawn_command(const gchar *command_line, GError **error)
|
parse_command(lua_State *L, int idx)
|
||||||
{
|
{
|
||||||
gboolean retval;
|
gchar **argv = NULL;
|
||||||
GPid pid;
|
|
||||||
gchar **argv = 0;
|
|
||||||
|
|
||||||
if(!g_shell_parse_argv(command_line, NULL, &argv, error))
|
if (lua_isstring(L, idx))
|
||||||
return 0;
|
{
|
||||||
|
const char *cmd = luaL_checkstring(L, idx);
|
||||||
|
if(!g_shell_parse_argv(cmd, NULL, &argv, NULL))
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (lua_istable(L, idx))
|
||||||
|
{
|
||||||
|
size_t i, len = luaA_rawlen(L, idx);
|
||||||
|
argv = g_new0(gchar *, len + 1);
|
||||||
|
|
||||||
retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
|
for (i = 0; i < len; i++)
|
||||||
spawn_callback, NULL, &pid, error);
|
{
|
||||||
g_strfreev (argv);
|
lua_rawgeti(L, idx, i+1);
|
||||||
|
argv[i] = g_strdup(lua_tostring(L, -1));
|
||||||
|
lua_pop(L, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
luaL_error(L, "Invalid argument to spawn(), expect string or table");
|
||||||
|
}
|
||||||
|
|
||||||
if (!retval)
|
return argv;
|
||||||
return 0;
|
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Spawn a program.
|
/** Spawn a program.
|
||||||
|
@ -301,27 +312,31 @@ spawn_command(const gchar *command_line, GError **error)
|
||||||
int
|
int
|
||||||
luaA_spawn(lua_State *L)
|
luaA_spawn(lua_State *L)
|
||||||
{
|
{
|
||||||
const char *cmd;
|
gchar **argv = NULL;
|
||||||
bool use_sn = true;
|
bool use_sn = true;
|
||||||
|
gboolean retval;
|
||||||
|
GPid pid;
|
||||||
|
|
||||||
if(lua_gettop(L) >= 2)
|
if(lua_gettop(L) >= 2)
|
||||||
use_sn = luaA_checkboolean(L, 2);
|
use_sn = luaA_checkboolean(L, 2);
|
||||||
|
|
||||||
cmd = luaL_checkstring(L, 1);
|
argv = parse_command(L, 1);
|
||||||
|
if(!argv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
SnLauncherContext *context = NULL;
|
SnLauncherContext *context = NULL;
|
||||||
if(use_sn)
|
if(use_sn)
|
||||||
{
|
{
|
||||||
char *cmdname, *space;
|
char *cmdname, *space;
|
||||||
const char *first_no_space_char = cmd;
|
const char *first_no_space_char = argv[0];
|
||||||
/* Look for the first char which is not space */
|
/* Look for the first char which is not space */
|
||||||
while(*first_no_space_char && *first_no_space_char == ' ')
|
while(*first_no_space_char && *first_no_space_char == ' ')
|
||||||
first_no_space_char++;
|
first_no_space_char++;
|
||||||
/* Look for space in the string to get the command name. */
|
/* Look for space in the string to get the command name. */
|
||||||
if((space = strchr(first_no_space_char, ' ')))
|
if((space = strchr(first_no_space_char, ' ')))
|
||||||
cmdname = a_strndup(cmd, space - cmd);
|
cmdname = a_strndup(argv[0], space - argv[0]);
|
||||||
else
|
else
|
||||||
cmdname = a_strdup(cmd);
|
cmdname = a_strdup(argv[0]);
|
||||||
|
|
||||||
context = sn_launcher_context_new(globalconf.sndisplay, globalconf.default_screen);
|
context = sn_launcher_context_new(globalconf.sndisplay, globalconf.default_screen);
|
||||||
sn_launcher_context_set_name(context, "awesome");
|
sn_launcher_context_set_name(context, "awesome");
|
||||||
|
@ -337,8 +352,10 @@ luaA_spawn(lua_State *L)
|
||||||
}
|
}
|
||||||
|
|
||||||
GError *error = NULL;
|
GError *error = NULL;
|
||||||
GPid pid = spawn_command(cmd, &error);
|
retval = g_spawn_async(NULL, argv, NULL, G_SPAWN_SEARCH_PATH,
|
||||||
if(!pid)
|
spawn_callback, NULL, &pid, &error);
|
||||||
|
g_strfreev(argv);
|
||||||
|
if(!retval)
|
||||||
{
|
{
|
||||||
/* push error on stack */
|
/* push error on stack */
|
||||||
lua_pushstring(L, error->message);
|
lua_pushstring(L, error->message);
|
||||||
|
|
Loading…
Reference in New Issue