diff options
Diffstat (limited to 'libs/luci-lib-nixio/src/process.c')
-rw-r--r-- | libs/luci-lib-nixio/src/process.c | 450 |
1 files changed, 450 insertions, 0 deletions
diff --git a/libs/luci-lib-nixio/src/process.c b/libs/luci-lib-nixio/src/process.c new file mode 100644 index 000000000..5ae9b829e --- /dev/null +++ b/libs/luci-lib-nixio/src/process.c @@ -0,0 +1,450 @@ +/* + * nixio - Linux I/O library for lua + * + * Copyright (C) 2009 Steven Barth <steven@midlink.org> + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "nixio.h" +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <signal.h> + +#define NIXIO_EXECVE 0x01 +#define NIXIO_EXECV 0x02 +#define NIXIO_EXECVP 0x03 + +int nixio__exec(lua_State *L, int m) { + const char *path = luaL_checkstring(L, 1); + const char *arg; + int argn, i; + + if (m == NIXIO_EXECVE) { + luaL_checktype(L, 2, LUA_TTABLE); + argn = lua_objlen(L, 2) + 1; + } else { + argn = lua_gettop(L); + } + + char **args = lua_newuserdata(L, sizeof(char*) * (argn + 1)); + args[argn] = NULL; + args[0] = (char *)path; + + if (m == NIXIO_EXECVE) { + for (i = 1; i < argn; i++) { + lua_rawgeti(L, 2, i); + arg = lua_tostring(L, -1); + luaL_argcheck(L, arg, 2, "invalid argument"); + args[i] = (char *)arg; + } + + if (lua_isnoneornil(L, 3)) { + execv(path, args); + } else { + luaL_checktype(L, 3, LUA_TTABLE); + argn = 0; + lua_pushnil(L); + while (lua_next(L, 3)) { + if (!lua_checkstack(L, 1)) { + lua_settop(L, 0); + return luaL_error(L, "stack overflow"); + } + + if (lua_type(L, -2) != LUA_TSTRING || !lua_isstring(L, -1)) { + return luaL_argerror(L, 3, "invalid environment"); + } + + lua_pushfstring(L, "%s=%s", + lua_tostring(L, -2), lua_tostring(L, -1)); + + lua_insert(L, 5); + lua_pop(L, 1); + argn++; + } + + char **env = lua_newuserdata(L, sizeof(char*) * (argn + 1)); + env[argn] = NULL; + + for (i = 1; i <= argn; i++) { + env[i-1] = (char *)lua_tostring(L, -(i+1)); + } + + execve(path, args, env); + } + } else { + for (i = 2; i <= argn; i++) { + arg = luaL_checkstring(L, i); + args[i-1] = (char *)arg; + } + + if (m == NIXIO_EXECV) { + execv(path, args); + } else { + execvp(path, args); + } + } + + return nixio__perror(L); +} + +#ifndef __WINNT__ +#include <sys/utsname.h> +#include <sys/times.h> +#include <sys/wait.h> +#include <pwd.h> +#include <grp.h> + +static int nixio_fork(lua_State *L) { + pid_t pid = fork(); + if (pid == -1) { + return nixio__perror(L); + } else { + lua_pushinteger(L, pid); + return 1; + } +} + +static int nixio_kill(lua_State *L) { + return nixio__pstatus(L, !kill(luaL_checkint(L, 1), luaL_checkint(L, 2))); +} + +static int nixio_getppid(lua_State *L) { + lua_pushinteger(L, getppid()); + return 1; +} + +static int nixio_getuid(lua_State *L) { + lua_pushinteger(L, getuid()); + return 1; +} + +static int nixio_getgid(lua_State *L) { + lua_pushinteger(L, getgid()); + return 1; +} + +static int nixio_setgid(lua_State *L) { + return nixio__pstatus(L, !setgid(nixio__check_group(L, 1))); +} + +static int nixio_setuid(lua_State *L) { + return nixio__pstatus(L, !setuid(nixio__check_user(L, 1))); +} + +static int nixio_nice(lua_State *L) { + int nval = luaL_checkint(L, 1); + + errno = 0; + nval = nice(nval); + + if (nval == -1 && errno) { + return nixio__perror(L); + } else { + lua_pushinteger(L, nval); + return 1; + } +} + +static int nixio_setsid(lua_State *L) { + pid_t pid = setsid(); + + if (pid == -1) { + return nixio__perror(L); + } else { + lua_pushinteger(L, pid); + return 1; + } +} + +static int nixio_wait(lua_State *L) { + pid_t pidin = luaL_optinteger(L, 1, -1), pidout; + int options = 0, status; + + const int j = lua_gettop(L); + for (int i=2; i<=j; i++) { + const char *flag = luaL_checkstring(L, i); + if (!strcmp(flag, "nohang")) { + options |= WNOHANG; + } else if (!strcmp(flag, "untraced")) { + options |= WUNTRACED; + } else if (!strcmp(flag, "continued")) { + options |= WCONTINUED; + } else { + return luaL_argerror(L, i, + "supported values: nohang, untraced, continued"); + } + } + + do { + pidout = waitpid(pidin, &status, options); + } while (pidout == -1 && errno == EINTR); + + if (pidout == 0) { + lua_pushboolean(L, 0); + return 1; + } else if (pidout == -1) { + return nixio__perror(L); + } else { + lua_pushinteger(L, pidout); + } + + if (WIFEXITED(status)) { + lua_pushliteral(L, "exited"); + lua_pushinteger(L, WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + lua_pushliteral(L, "signaled"); + lua_pushinteger(L, WTERMSIG(status)); + } else if (WIFSTOPPED(status)) { + lua_pushliteral(L, "stopped"); + lua_pushinteger(L, WSTOPSIG(status)); + } else { + return 1; + } + + return 3; +} + +static int nixio_times(lua_State *L) { + struct tms buf; + if (times(&buf) == -1) { + return nixio__perror(L); + } else { + lua_createtable(L, 0, 4); + nixio__pushnumber(L, buf.tms_cstime); + lua_setfield(L, -2, "cstime"); + + nixio__pushnumber(L, buf.tms_cutime); + lua_setfield(L, -2, "cutime"); + + nixio__pushnumber(L, buf.tms_stime); + lua_setfield(L, -2, "stime"); + + nixio__pushnumber(L, buf.tms_utime); + lua_setfield(L, -2, "utime"); + + return 1; + } +} + +static int nixio_uname(lua_State *L) { + struct utsname buf; + if (uname(&buf)) { + return nixio__perror(L); + } + + lua_createtable(L, 0, 5); + + lua_pushstring(L, buf.machine); + lua_setfield(L, -2, "machine"); + + lua_pushstring(L, buf.version); + lua_setfield(L, -2, "version"); + + lua_pushstring(L, buf.release); + lua_setfield(L, -2, "release"); + + lua_pushstring(L, buf.nodename); + lua_setfield(L, -2, "nodename"); + + lua_pushstring(L, buf.sysname); + lua_setfield(L, -2, "sysname"); + + return 1; +} + +#endif /* !__WINNT__ */ + +static int nixio_chdir(lua_State *L) { + return nixio__pstatus(L, !chdir(luaL_checkstring(L, 1))); +} + +static int nixio_signal(lua_State *L) { + int sig = luaL_checkinteger(L, 1); + const char *val = luaL_checkstring(L, 2); + + if (!strcmp(val, "ign") || !strcmp(val, "ignore")) { + return nixio__pstatus(L, signal(sig, SIG_IGN) != SIG_ERR); + } else if (!strcmp(val, "dfl") || !strcmp(val, "default")) { + return nixio__pstatus(L, signal(sig, SIG_DFL) != SIG_ERR); + } else { + return luaL_argerror(L, 2, "supported values: ign, dfl"); + } +} + +static int nixio_getpid(lua_State *L) { + lua_pushinteger(L, getpid()); + return 1; +} + +static int nixio_getenv(lua_State *L) { + const char *key = luaL_optstring(L, 1, NULL); + if (key) { + const char *val = getenv(key); + if (val) { + lua_pushstring(L, val); + } else { + lua_pushnil(L); + } + } else { + lua_newtable(L); + extern char **environ; + for (char **c = environ; *c; c++) { + const char *delim = strchr(*c, '='); + if (!delim) { + return luaL_error(L, "invalid environment"); + } + lua_pushlstring(L, *c, delim-*c); + lua_pushstring(L, delim + 1); + lua_rawset(L, -3); + } + } + return 1; +} + +static int nixio_setenv(lua_State *L) { + const char *key = luaL_checkstring(L, 1); + const char *val = luaL_optstring(L, 2, NULL); + return nixio__pstatus(L, (val) ? !setenv(key, val, 1) : !unsetenv(key)); +} + +static int nixio_exec(lua_State *L) { + return nixio__exec(L, NIXIO_EXECV); +} + +static int nixio_execp(lua_State *L) { + return nixio__exec(L, NIXIO_EXECVP); +} + +static int nixio_exece(lua_State *L) { + return nixio__exec(L, NIXIO_EXECVE); +} + +static int nixio_getcwd(lua_State *L) { + char path[PATH_MAX]; + + if (getcwd(path, sizeof(path))) { + lua_pushstring(L, path); + return 1; + } else { + return nixio__perror(L); + } +} + +static int nixio_umask(lua_State *L) { + char mask[9]; + lua_pushinteger(L, + nixio__mode_write(umask(nixio__check_mode(L, 1, -1)), mask)); + lua_pushlstring(L, mask, 9); + return 2; +} + +#ifdef __linux__ + +#include <sys/sysinfo.h> + +static int nixio_sysinfo(lua_State *L) { + struct sysinfo info; + if (sysinfo(&info)) { + return nixio__perror(L); + } + + lua_createtable(L, 0, 12); + + nixio__pushnumber(L, info.bufferram); + lua_setfield(L, -2, "bufferram"); + + nixio__pushnumber(L, info.freehigh); + lua_setfield(L, -2, "freehigh"); + + nixio__pushnumber(L, info.freeram); + lua_setfield(L, -2, "freeram"); + + nixio__pushnumber(L, info.freeswap); + lua_setfield(L, -2, "freeswap"); + + lua_createtable(L, 0, 3); + for (int i=0; i<3; i++) { + lua_pushnumber(L, info.loads[i] / 65536.); + lua_rawseti(L, -2, i+1); + } + lua_setfield(L, -2, "loads"); + + lua_pushinteger(L, info.mem_unit); + lua_setfield(L, -2, "mem_unit"); + + lua_pushinteger(L, info.procs); + lua_setfield(L, -2, "procs"); + + nixio__pushnumber(L, info.sharedram); + lua_setfield(L, -2, "sharedram"); + + nixio__pushnumber(L, info.totalhigh); + lua_setfield(L, -2, "totalhigh"); + + nixio__pushnumber(L, info.totalram); + lua_setfield(L, -2, "totalram"); + + nixio__pushnumber(L, info.totalswap); + lua_setfield(L, -2, "totalswap"); + + lua_pushinteger(L, info.uptime); + lua_setfield(L, -2, "uptime"); + + return 1; +} + +#endif + + +/* module table */ +static const luaL_reg R[] = { +#ifdef __linux__ + {"sysinfo", nixio_sysinfo}, +#endif +#ifndef __WINNT__ + {"fork", nixio_fork}, + {"kill", nixio_kill}, + {"nice", nixio_nice}, + {"getppid", nixio_getppid}, + {"getuid", nixio_getuid}, + {"getgid", nixio_getgid}, + {"setuid", nixio_setuid}, + {"setgid", nixio_setgid}, + {"setsid", nixio_setsid}, + {"wait", nixio_wait}, + {"waitpid", nixio_wait}, + {"times", nixio_times}, + {"uname", nixio_uname}, +#endif + {"chdir", nixio_chdir}, + {"signal", nixio_signal}, + {"getpid", nixio_getpid}, + {"getenv", nixio_getenv}, + {"setenv", nixio_setenv}, + {"putenv", nixio_setenv}, + {"exec", nixio_exec}, + {"execp", nixio_execp}, + {"exece", nixio_exece}, + {"getcwd", nixio_getcwd}, + {"umask", nixio_umask}, + {NULL, NULL} +}; + +void nixio_open_process(lua_State *L) { + luaL_register(L, NULL, R); +} |