It was possible to create a bad ref
[jimtcl.git] / jim-posix.c
blob7fedf6675adc6f3b2c69ed2af6971d2f0076f011
2 /* Jim - POSIX extension
3 * Copyright 2005 Salvatore Sanfilippo <antirez@invece.org>
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * A copy of the license is also included in the source distribution
12 * of Jim, as a TXT file name called LICENSE.
14 * Unless required by applicable law or agreed to in writing, software
15 * distributed under the License is distributed on an "AS IS" BASIS,
16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 * See the License for the specific language governing permissions and
18 * limitations under the License.
21 #include <sys/types.h>
22 #include <sys/time.h>
23 #include <sys/wait.h>
24 #include <unistd.h>
25 #include <string.h>
26 #include <signal.h>
27 #include <errno.h>
29 #include "jim.h"
31 #ifdef HAVE_SYSINFO
32 #include <sys/sysinfo.h>
33 #endif
35 static void Jim_PosixSetError(Jim_Interp *interp)
37 Jim_SetResultString(interp, strerror(errno), -1);
40 #if defined(HAVE_FORK) && !defined(HAVE_NO_FORK)
41 static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
43 pid_t pid;
45 JIM_NOTUSED(argv);
47 if (argc != 1) {
48 Jim_WrongNumArgs(interp, 1, argv, "");
49 return JIM_ERR;
51 if ((pid = fork()) == -1) {
52 Jim_PosixSetError(interp);
53 return JIM_ERR;
55 Jim_SetResultInt(interp, (jim_wide) pid);
56 return JIM_OK;
58 #endif
61 * os.wait ?-nohang? pid
63 * An interface to waitpid(2)
65 * Returns a 3 element list.
67 * If -nohang is specified, and the process is still alive, returns
69 * {0 none 0}
71 * If the process does not exist or has already been waited for, returns:
73 * {-1 error <error-description>}
75 * If the process exited normally, returns:
77 * {<pid> exit <exit-status>}
79 * If the process terminated on a signal, returns:
81 * {<pid> signal <signal-number>}
83 * Otherwise (core dump, stopped, continued, ...), returns:
85 * {<pid> other 0}
87 static int Jim_PosixWaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
89 int nohang = 0;
90 long pid;
91 int status;
92 Jim_Obj *listObj;
93 const char *type;
94 int value;
96 if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) {
97 nohang = 1;
99 if (argc != nohang + 2) {
100 Jim_WrongNumArgs(interp, 1, argv, "?-nohang? pid");
101 return JIM_ERR;
103 if (Jim_GetLong(interp, argv[nohang + 1], &pid) != JIM_OK) {
104 return JIM_ERR;
107 pid = waitpid(pid, &status, nohang ? WNOHANG : 0);
108 listObj = Jim_NewListObj(interp, NULL, 0);
109 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, pid));
110 if (pid < 0) {
111 type = "error";
112 value = errno;
114 else if (pid == 0) {
115 type = "none";
116 value = 0;
118 else if (WIFEXITED(status)) {
119 type = "exit";
120 value = WEXITSTATUS(status);
122 else if (WIFSIGNALED(status)) {
123 type = "signal";
124 value = WTERMSIG(status);
126 else {
127 type = "other";
128 value = 0;
131 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, type, -1));
132 if (pid < 0) {
133 Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, strerror(value), -1));
135 else {
136 Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value));
138 Jim_SetResult(interp, listObj);
139 return JIM_OK;
142 static int Jim_PosixGetidsCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
144 Jim_Obj *objv[8];
146 if (argc != 1) {
147 Jim_WrongNumArgs(interp, 1, argv, "");
148 return JIM_ERR;
150 objv[0] = Jim_NewStringObj(interp, "uid", -1);
151 objv[1] = Jim_NewIntObj(interp, getuid());
152 objv[2] = Jim_NewStringObj(interp, "euid", -1);
153 objv[3] = Jim_NewIntObj(interp, geteuid());
154 objv[4] = Jim_NewStringObj(interp, "gid", -1);
155 objv[5] = Jim_NewIntObj(interp, getgid());
156 objv[6] = Jim_NewStringObj(interp, "egid", -1);
157 objv[7] = Jim_NewIntObj(interp, getegid());
158 Jim_SetResult(interp, Jim_NewListObj(interp, objv, 8));
159 return JIM_OK;
162 #define JIM_HOST_NAME_MAX 1024
163 static int Jim_PosixGethostnameCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
165 char *buf;
166 int rc = JIM_OK;
168 if (argc != 1) {
169 Jim_WrongNumArgs(interp, 1, argv, "");
170 return JIM_ERR;
172 buf = Jim_Alloc(JIM_HOST_NAME_MAX);
173 if (gethostname(buf, JIM_HOST_NAME_MAX) == -1) {
174 Jim_PosixSetError(interp);
175 rc = JIM_ERR;
177 else {
178 Jim_SetResult(interp, Jim_NewStringObjNoAlloc(interp, buf, -1));
180 return rc;
183 static int Jim_PosixUptimeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
185 #ifdef HAVE_SYSINFO
186 struct sysinfo info;
188 if (argc != 1) {
189 Jim_WrongNumArgs(interp, 1, argv, "");
190 return JIM_ERR;
193 if (sysinfo(&info) == -1) {
194 Jim_PosixSetError(interp);
195 return JIM_ERR;
198 Jim_SetResultInt(interp, info.uptime);
199 #else
200 Jim_SetResultInt(interp, (long)time(NULL));
201 #endif
202 return JIM_OK;
205 static int Jim_PosixPidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
207 if (argc != 1) {
208 Jim_WrongNumArgs(interp, 1, argv, "");
209 return JIM_ERR;
212 Jim_SetResultInt(interp, getpid());
213 return JIM_OK;
216 int Jim_posixInit(Jim_Interp *interp)
218 #ifdef HAVE_FORK
219 Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL);
220 #endif
221 Jim_CreateCommand(interp, "os.wait", Jim_PosixWaitCommand, NULL, NULL);
222 Jim_CreateCommand(interp, "os.getids", Jim_PosixGetidsCommand, NULL, NULL);
223 Jim_CreateCommand(interp, "os.gethostname", Jim_PosixGethostnameCommand, NULL, NULL);
224 Jim_CreateCommand(interp, "os.uptime", Jim_PosixUptimeCommand, NULL, NULL);
225 Jim_CreateCommand(interp, "pid", Jim_PosixPidCommand, NULL, NULL);
226 return JIM_OK;