diff options
Diffstat (limited to 'jim-posix.c')
-rw-r--r-- | jim-posix.c | 88 |
1 files changed, 86 insertions, 2 deletions
diff --git a/jim-posix.c b/jim-posix.c index e8cb6e6..e199848 100644 --- a/jim-posix.c +++ b/jim-posix.c @@ -19,6 +19,7 @@ #include <sys/types.h> #include <sys/time.h> +#include <sys/wait.h> #include <unistd.h> #include <string.h> #include <signal.h> @@ -47,7 +48,7 @@ static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, return JIM_ERR; } if ((pid = fork()) == -1) { - Jim_SetResultString(interp, strerror(errno), -1); + Jim_PosixSetError(interp); return JIM_ERR; } Jim_SetResult(interp, Jim_NewIntObj(interp, (jim_wide)pid)); @@ -55,6 +56,89 @@ static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, #endif } +/* + * os.wait ?-nohang? pid + * + * An interface to waitpid(2) + * + * Returns a 3 element list. + * + * If -nohang is specified, and the process is still alive, returns + * + * {0 none 0} + * + * If the process does not exist or has already been waited for, returns: + * + * {-1 error <error-description>} + * + * If the process exited normally, returns: + * + * {<pid> exit <exit-status>} + * + * If the process terminated on a signal, returns: + * + * {<pid> signal <signal-number>} + * + * Otherwise (core dump, stopped, continued, ...), returns: + * + * {<pid> other 0} + */ +static int Jim_PosixWaitCommand(Jim_Interp *interp, int argc, + Jim_Obj *const *argv) +{ + int nohang = 0; + long pid; + int status; + Jim_Obj *listObj; + const char *type; + int value; + + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nohang")) { + nohang = 1; + } + if (argc != nohang + 2) { + Jim_WrongNumArgs(interp, 1, argv, "?-nohang? pid"); + return JIM_ERR; + } + if (Jim_GetLong(interp, argv[nohang + 1], &pid) != JIM_OK) { + return JIM_ERR; + } + + pid = waitpid(pid, &status, nohang ? WNOHANG : 0); + listObj = Jim_NewListObj(interp, NULL, 0); + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, pid)); + if (pid < 0) { + type = "error"; + value = errno; + } + else if (pid == 0) { + type = "none"; + value = 0; + } + else if (WIFEXITED(status)) { + type = "exit"; + value = WEXITSTATUS(status); + } + else if (WIFSIGNALED(status)) { + type = "signal"; + value = WTERMSIG(status); + } + else { + type = "other"; + value = 0; + } + + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, type, -1)); + if (pid < 0) { + Jim_ListAppendElement(interp, listObj, Jim_NewStringObj(interp, strerror(value), -1)); + } + else { + Jim_ListAppendElement(interp, listObj, Jim_NewIntObj(interp, value)); + } + Jim_SetResult(interp, listObj); + return JIM_OK; +} + static int Jim_PosixGetidsCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { @@ -104,12 +188,12 @@ static int Jim_PosixPidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg return JIM_OK; } -// end added int Jim_posixInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "posix", "1.0", JIM_ERRMSG) != JIM_OK) return JIM_ERR; Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL); + Jim_CreateCommand(interp, "os.wait", Jim_PosixWaitCommand, NULL, NULL); Jim_CreateCommand(interp, "os.getids", Jim_PosixGetidsCommand, NULL, NULL); Jim_CreateCommand(interp, "os.gethostname", Jim_PosixGethostnameCommand, NULL, NULL); Jim_CreateCommand(interp, "pid", Jim_PosixPidCommand, NULL, NULL); |