[asterisk-commits] mnicholson: branch mnicholson/asttest r191092 - in /team/mnicholson/asttest/a...
SVN commits to the Asterisk project
asterisk-commits at lists.digium.com
Wed Apr 29 11:38:05 CDT 2009
Author: mnicholson
Date: Wed Apr 29 11:38:00 2009
New Revision: 191092
URL: http://svn.digium.com/svn-view/asterisk?view=rev&rev=191092
Log:
Completed implementation of asterisk:spawn(). It should be possible to start
and stop asterisk in a sandbox now.
Added:
team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/
team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/test.lua (with props)
Modified:
team/mnicholson/asttest/asttest/lua/astlib.c
team/mnicholson/asttest/asttest/lua/astlib.lua
Modified: team/mnicholson/asttest/asttest/lua/astlib.c
URL: http://svn.digium.com/svn-view/asterisk/team/mnicholson/asttest/asttest/lua/astlib.c?view=diff&rev=191092&r1=191091&r2=191092
==============================================================================
--- team/mnicholson/asttest/asttest/lua/astlib.c (original)
+++ team/mnicholson/asttest/asttest/lua/astlib.c Wed Apr 29 11:38:00 2009
@@ -24,9 +24,12 @@
#include <dirent.h>
#include <errno.h>
+#include <signal.h>
+#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
+#include <sys/wait.h>
#include <unistd.h>
/*!
@@ -117,11 +120,78 @@
return -1;
}
-static int spawn_asterisk(lua_State *L) {
+/*!
+ * \brief Recursively unlink a path.
+ * \param L the lua state to use
+ * \param path the file or directory to unlink
+ *
+ * This function unlinks the given file or directory. If path is a directory,
+ * all of the items in the directory will be recursively unlinked.
+ *
+ * \note On error an error message is pushed onto the given lua stack.
+ *
+ * \retval 0 success
+ * \retval -1 error
+ */
+static int recursive_unlink(lua_State *L, const char *path) {
+ DIR *dir;
+ struct dirent *d;
+ char dir_path[PATH_MAX];
+ struct stat st;
+
+ if (stat(path, &st)) {
+ if (errno == ENOENT)
+ return 0;
+
+ lua_pushstring(L, "error with stat for '");
+ lua_pushstring(L, path);
+ lua_pushstring(L, "': ");
+ lua_pushstring(L, strerror(errno));
+ lua_concat(L, 4);
+ return -1;
+ }
+
+ if (S_ISDIR(st.st_mode)) {
+ if (!(dir = opendir(path))) {
+ lua_pushstring(L, "error opening dir '");
+ lua_pushstring(L, path);
+ lua_pushstring(L, "': ");
+ lua_pushstring(L, strerror(errno));
+ lua_concat(L, 4);
+ return -1;
+ }
+
+ while ((d = readdir(dir))) {
+ snprintf(dir_path, sizeof(dir_path), "%s/%s", path, d->d_name);
+
+ if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, "..")) {
+ continue;
+ }
+
+ if (recursive_unlink(L, dir_path)) {
+ closedir(dir);
+ return -1;
+ }
+ }
+
+ closedir(dir);
+ rmdir(path);
+ } else {
+ if (unlink(path)) {
+ lua_pushstring(L, "error unlinking path '");
+ lua_pushstring(L, path);
+ lua_pushstring(L, "': ");
+ lua_pushstring(L, strerror(errno));
+ lua_concat(L, 4);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+static int new_asterisk(lua_State *L) {
int asterisk_count;
- const char *asterisk_path;
- char dir_path[PATH_MAX];
- mode_t dir_mode = S_IRWXU | S_IRGRP| S_IXGRP| S_IROTH | S_IXOTH;
/* get the index for this instance */
lua_getfield(L, LUA_REGISTRYINDEX, "astlib_count");
@@ -132,47 +202,262 @@
lua_setfield(L, LUA_REGISTRYINDEX, "astlib_count");
lua_pop(L, 1);
+ /* create a new table and set some initial values */
+ lua_newtable(L);
+
+ lua_pushliteral(L, "tmp/ast");
+ lua_pushinteger(L, asterisk_count);
+ lua_concat(L, 2);
+ lua_setfield(L, -2, "work_area");
+
+ lua_pushinteger(L, asterisk_count);
+ lua_setfield(L, -2, "index");
+
+ lua_getfield(L, LUA_REGISTRYINDEX, "astlib_path");
+ lua_pushliteral(L, "/sbin/asterisk");
+ lua_concat(L, 2);
+ lua_setfield(L, -2, "asterisk_binary");
+ return 1;
+}
+
+static int clean_work_area(lua_State *L) {
+ const char *work_area;
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ /* get the work area for this instance */
+ lua_getfield(L, 1, "work_area");
+ work_area = lua_tostring(L, -1);
+
+ if (recursive_unlink(L, work_area)) {
+ lua_pushstring(L, "\nerror cleaning work area");
+ lua_concat(L, 2);
+ return lua_error(L);
+ }
+
+ return 0;
+}
+
+static int create_work_area(lua_State *L) {
+ const char *work_area;
+ const char *asterisk_path;
+ mode_t dir_mode = S_IRWXU | S_IRGRP| S_IXGRP| S_IROTH | S_IXOTH;
+
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ /* get the work area for this instance */
+ lua_getfield(L, 1, "work_area");
+ work_area = lua_tostring(L, -1);
+
+ /* get the asterisk path */
lua_getfield(L, LUA_REGISTRYINDEX, "astlib_path");
asterisk_path = lua_tostring(L, -1);
- snprintf(dir_path, sizeof(dir_path), "tmp/ast%d", asterisk_count);
if (mkdir("tmp", dir_mode) && errno != EEXIST) {
- lua_pop(L, 1); /* remove the astlib_path */
- lua_pushstring(L, "error creating tmp directory while spawning asterisk: ");
+ lua_pushstring(L, "error creating tmp directory for work area: ");
lua_pushstring(L, strerror(errno));
lua_concat(L, 2);
return lua_error(L);
}
- if (mkdir(dir_path, dir_mode)) {
- lua_pop(L, 1); /* remove the astlib_path */
- lua_pushstring(L, "error spawning asterisk, unable to create working dir (");
- lua_pushstring(L, dir_path);
+ if (mkdir(work_area, dir_mode)) {
+ lua_pushstring(L, "unable to create work area (");
+ lua_pushstring(L, work_area);
lua_pushstring(L, "): ");
lua_pushstring(L, strerror(errno));
lua_concat(L, 4);
return lua_error(L);
}
- if (symlink_copy_dir(L, asterisk_path, dir_path)) {
- lua_remove(L, -2); /* remove the astlib_path */
- lua_pushstring(L, "\nerror initilizing working environment");
+ if (symlink_copy_dir(L, asterisk_path, work_area)) {
+ lua_pushstring(L, "\nerror initilizing work area");
lua_concat(L, 2);
return lua_error(L);
}
- lua_pop(L, 1); /* remove the astlib_path */
-
- /* XXX now start asterisk */
return 0;
}
+static int spawn_asterisk(lua_State *L) {
+ const char *asterisk;
+ const char *asterisk_conf;
+ pid_t pid;
+ pid_t *p;
+
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ /* XXX maybe see if pid is set. Right now, if pid is set, the previous
+ * asterisk process will be killed (during gc) and a new one will
+ * replace it. */
+
+ /* get the index for this instance */
+ lua_getfield(L, 1, "asterisk_binary");
+ asterisk = lua_tostring(L, -1);
+
+ /* get the location of the asterisk.conf file */
+ lua_getfield(L, 1, "asterisk_conf");
+ asterisk_conf = lua_tostring(L, -1);
+
+ /* start asterisk */
+ pid = fork();
+ if (pid == 0) {
+ execl(asterisk, asterisk, "-f", "-g", "-m", "-C", asterisk_conf, (char *) NULL);
+ exit(1);
+ } else if (pid == -1) {
+ lua_pushliteral(L, "error spawning asterisk (fork error): ");
+ lua_pushstring(L, strerror(errno));
+ lua_concat(L, 2);
+ return lua_error(L);
+ }
+
+ /* store the pid */
+ lua_pushliteral(L, "pid");
+ p = lua_newuserdata(L, sizeof(pid_t));
+ *p = pid;
+ luaL_getmetatable(L, "astlib_pid");
+ lua_setmetatable(L, -2);
+ lua_rawset(L, 1);
+
+ return 0;
+}
+
+static int pid_gc(lua_State *L) {
+ pid_t *p = luaL_checkudata(L, 1, "astlib_pid");
+ if (kill(*p, SIGTERM)) {
+ return 0;
+ }
+#if 0 /* XXX maybe we should also do SIGKILL here? */
+ sleep(1);
+ kill(*p, SIGKILL);
+#endif
+ waitpid(*p, NULL, 0);
+ return 0;
+}
+
+static int wait_asterisk(lua_State *L) {
+ pid_t pid;
+ int status;
+
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ /* get the pid of this process */
+ lua_getfield(L, 1, "pid");
+ if (lua_isnil(L, -1)) {
+ /* no process found */
+ lua_pushnil(L);
+ lua_pushliteral(L, "error");
+ return 2;
+ }
+ pid = *(pid_t *) lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ if (waitpid(pid, &status, 0) == -1) {
+ if (WIFEXITED(status)) {
+ lua_pushinteger(L, WEXITSTATUS(status));
+ lua_pushnil(L);
+ } else if (WIFSIGNALED(status)) {
+ lua_pushnil(L);
+ if (WCOREDUMP(status))
+ lua_pushliteral(L, "core");
+ else
+ lua_pushinteger(L, WTERMSIG(status));
+ } else {
+ lua_pushliteral(L, "unknown error running waitpid for asterisk");
+ return lua_error(L);
+ }
+ }
+
+ /* unset the pid */
+ lua_pushliteral(L, "pid");
+ lua_pushnil(L);
+ lua_rawset(L, 1);
+
+ return 2;
+}
+
+static int kill_asterisk(lua_State *L) {
+ pid_t pid;
+
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ /* get the pid of this process */
+ lua_getfield(L, 1, "pid");
+ if (lua_isnil(L, -1)) {
+ /* no process found */
+ lua_pushnil(L);
+ lua_pushliteral(L, "error");
+ return 2;
+ }
+ pid = *(pid_t *) lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ if (kill(pid, SIGKILL)) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "error");
+ lua_pushstring(L, strerror(errno));
+ lua_pushinteger(L, errno);
+ return 4;
+ }
+
+ lua_pushcfunction(L, wait_asterisk);
+ lua_pushvalue(L, 1);
+ lua_call(L, 1, 2);
+ return 2;
+}
+
+static int terminate_asterisk(lua_State *L) {
+ pid_t pid;
+
+ luaL_checktype(L, 1, LUA_TTABLE);
+
+ /* get the pid of this process */
+ lua_getfield(L, 1, "pid");
+ if (lua_isnil(L, -1)) {
+ /* no process found */
+ lua_pushnil(L);
+ lua_pushliteral(L, "error");
+ return 2;
+ }
+ pid = *(pid_t *) lua_touserdata(L, -1);
+ lua_pop(L, 1);
+
+ if (kill(pid, SIGTERM)) {
+ lua_pushnil(L);
+ lua_pushliteral(L, "error");
+ lua_pushstring(L, strerror(errno));
+ lua_pushinteger(L, errno);
+ return 4;
+ }
+
+ lua_pushcfunction(L, wait_asterisk);
+ lua_pushvalue(L, 1);
+ lua_call(L, 1, 2);
+ return 2;
+}
+
+static int unlink_file(lua_State *L) {
+ const char *file = luaL_checkstring(L, 1);
+ lua_pushinteger(L, unlink(file));
+ return 1;
+}
+
static luaL_Reg astlib[] = {
+ {"unlink", unlink_file},
{NULL, NULL},
};
+static luaL_Reg asterisk_pid[] = {
+ {"__gc", pid_gc},
+ {NULL, NULL},
+};
+
static luaL_Reg asterisk_table[] = {
- {"spawn", spawn_asterisk},
+ {"_new", new_asterisk},
+ {"_clean_work_area", clean_work_area},
+ {"_create_work_area", create_work_area},
+ {"_spawn", spawn_asterisk},
+ {"wait", wait_asterisk},
+ {"term", terminate_asterisk},
+ {"kill", kill_asterisk},
{NULL, NULL},
};
@@ -193,7 +478,12 @@
lua_pushstring(L, asterisk_path);
lua_setfield(L, -2, "path");
- /* set up the 'asterisk' table and add the spawn function to it */
+ /* set up the pid metatable */
+ luaL_newmetatable(L, "astlib_pid");
+ luaL_register(L, NULL, asterisk_pid);
+ lua_pop(L, 1);
+
+ /* set up the 'asterisk' table and add some functions to it */
lua_newtable(L);
luaL_register(L, NULL, asterisk_table);
lua_setfield(L, -2, "asterisk");
Modified: team/mnicholson/asttest/asttest/lua/astlib.lua
URL: http://svn.digium.com/svn-view/asterisk/team/mnicholson/asttest/asttest/lua/astlib.lua?view=diff&rev=191092&r1=191091&r2=191092
==============================================================================
--- team/mnicholson/asttest/asttest/lua/astlib.lua (original)
+++ team/mnicholson/asttest/asttest/lua/astlib.lua Wed Apr 29 11:38:00 2009
@@ -25,12 +25,24 @@
--
-- asterisk table is created in astlib.c
function asterisk:new()
- local a = {
- configs = {},
- }
+ local a = self:_new()
+ a.configs = {}
+ a.asterisk_conf = a.work_area .. "/etc/asterisk/asterisk.conf"
+
setmetatable(a, self)
self.__index = self
return a
+end
+
+function asterisk:spawn()
+ self:_clean_work_area()
+ self:_create_work_area()
+ self:_spawn()
+end
+
+function asterisk:spawn_and_wait()
+ self:spawn()
+ self:wait()
end
function asterisk:__newindex(conffile_name, conffile)
@@ -38,6 +50,9 @@
error("got " .. type(conffile) .. " expected type config")
end
self.configs[conffile_name] = conffile
+ if conffile.name == "asterisk.conf" then
+ self.asterisk_conf = conffile.filename
+ end
end
function asterisk:__index(conffile_name)
@@ -45,15 +60,16 @@
end
function asterisk:new_config(name)
- c = config:new(name)
+ c = config:new(name, self.work_area .. "/etc/asterisk/" .. name)
self[name] = c
return c
end
config = {}
-function config:new(name)
+function config:new(name, filename)
local ac = {
name = name,
+ filename = filename or name,
sections = {},
section_index = {},
}
@@ -88,8 +104,11 @@
function config:write(filename)
if not filename then
- filename = self.name
+ filename = self.filename
end
+
+ -- remove any existing file or symlink
+ unlink(filename)
f, e = io.open(filename, "w")
if not f then
Added: team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/test.lua
URL: http://svn.digium.com/svn-view/asterisk/team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/test.lua?view=auto&rev=191092
==============================================================================
--- team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/test.lua (added)
+++ team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/test.lua Wed Apr 29 11:38:00 2009
@@ -1,0 +1,5 @@
+-- test spawning asterisk
+
+a = ast.new()
+a:spawn()
+
Propchange: team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/test.lua
------------------------------------------------------------------------------
svn:eol-style = native
Propchange: team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/test.lua
------------------------------------------------------------------------------
svn:keywords = Author Date Id Revision
Propchange: team/mnicholson/asttest/asttest/self-tests/spawn_asterisk/test.lua
------------------------------------------------------------------------------
svn:mime-type = text/plain
More information about the asterisk-commits
mailing list