19fa10ef2cdfd7e7e658e8c1e51f5c0abbacd3ba
[project/luci.git] / libs / nixio / src / process.c
1 /*
2  * nixio - Linux I/O library for lua
3  *
4  *   Copyright (C) 2009 Steven Barth <steven@midlink.org>
5  *
6  *  Licensed under the Apache License, Version 2.0 (the "License");
7  *  you may not use this file except in compliance with the License.
8  *  You may obtain a copy of the License at
9  *
10  *      http://www.apache.org/licenses/LICENSE-2.0
11  *
12  *  Unless required by applicable law or agreed to in writing, software
13  *  distributed under the License is distributed on an "AS IS" BASIS,
14  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  *  See the License for the specific language governing permissions and
16  *  limitations under the License.
17  */
18
19 #include "nixio.h"
20 #include <pwd.h>
21 #include <grp.h>
22 #include <unistd.h>
23 #include <errno.h>
24 #include <string.h>
25 #include <sys/wait.h>
26 #include <sys/types.h>
27
28 static int nixio_fork(lua_State *L) {
29         pid_t pid = fork();
30         if (pid == -1) {
31                 return nixio__perror(L);
32         } else {
33                 lua_pushinteger(L, pid);
34                 return 1;
35         }
36 }
37
38 static int nixio_wait(lua_State *L) {
39         pid_t pidin = luaL_optinteger(L, 1, -1), pidout;
40         int options = 0, status;
41
42         const int j = lua_gettop(L);
43         for (int i=2; i<=j; i++) {
44                 const char *flag = luaL_checkstring(L, i);
45                 if (!strcmp(flag, "nohang")) {
46                         options |= WNOHANG;
47                 } else if (!strcmp(flag, "untraced")) {
48                         options |= WUNTRACED;
49                 } else if (!strcmp(flag, "continued")) {
50                         options |= WCONTINUED;
51                 } else {
52                         return luaL_argerror(L, i,
53                                         "supported values: nohang, untraced, continued");
54                 }
55         }
56
57         do {
58                 pidout = waitpid(pidin, &status, options);
59         } while (pidout == -1 && errno == EINTR);
60
61         if (pidout == -1) {
62                 return nixio__perror(L);
63         } else {
64                 lua_pushinteger(L, pidout);
65         }
66
67         if (WIFEXITED(status)) {
68                 lua_pushliteral(L, "exited");
69                 lua_pushinteger(L, WEXITSTATUS(status));
70     } else if (WIFSIGNALED(status)) {
71         lua_pushliteral(L, "signaled");
72         lua_pushinteger(L, WTERMSIG(status));
73     } else if (WIFSTOPPED(status)) {
74         lua_pushliteral(L, "stopped");
75         lua_pushinteger(L, WSTOPSIG(status));
76     } else {
77         return 1;
78     }
79
80     return 3;
81 }
82
83 static int nixio_kill(lua_State *L) {
84         return nixio__pstatus(L, !kill(luaL_checkint(L, 1), luaL_checkint(L, 2)));
85 }
86
87 static int nixio_getpid(lua_State *L) {
88         lua_pushinteger(L, getpid());
89         return 1;
90 }
91
92 static int nixio_getppid(lua_State *L) {
93         lua_pushinteger(L, getppid());
94         return 1;
95 }
96
97 static int nixio_getuid(lua_State *L) {
98         lua_pushinteger(L, getuid());
99         return 1;
100 }
101
102 static int nixio_getgid(lua_State *L) {
103         lua_pushinteger(L, getgid());
104         return 1;
105 }
106
107 static int nixio_setgid(lua_State *L) {
108         gid_t gid;
109         if (lua_isstring(L, 1)) {
110                 struct group *g = getgrnam(lua_tostring(L, 1));
111                 gid = (!g) ? -1 : g->gr_gid;
112         } else if (lua_isnumber(L, 1)) {
113                 gid = lua_tointeger(L, 1);
114         } else {
115                 return luaL_argerror(L, 1, "supported values: <groupname>, <gid>");
116         }
117
118         return nixio__pstatus(L, !setgid(gid));
119 }
120
121 static int nixio_setuid(lua_State *L) {
122         uid_t uid;
123         if (lua_isstring(L, 1)) {
124                 struct passwd *p = getpwnam(lua_tostring(L, 1));
125                 uid = (!p) ? -1 : p->pw_uid;
126         } else if (lua_isnumber(L, 1)) {
127                 uid = lua_tointeger(L, 1);
128         } else {
129                 return luaL_argerror(L, 1, "supported values: <username>, <uid>");
130         }
131
132         return nixio__pstatus(L, !setuid(uid));
133 }
134
135
136 /* module table */
137 static const luaL_reg R[] = {
138         {"fork",                nixio_fork},
139         {"wait",                nixio_wait},
140         {"kill",                nixio_kill},
141         {"getpid",              nixio_getpid},
142         {"getppid",             nixio_getppid},
143         {"getuid",              nixio_getuid},
144         {"getgid",              nixio_getgid},
145         {"setuid",              nixio_setuid},
146         {"setgid",              nixio_setgid},
147         {NULL,                  NULL}
148 };
149
150 void nixio_open_process(lua_State *L) {
151         luaL_register(L, NULL, R);
152 }