mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 19:19:53 +00:00
Work to replace os.execute command with something safe.
This commit is contained in:
parent
bfd0c08c8f
commit
f63d08efbd
@ -343,9 +343,13 @@ static void dst_quick_asm(
|
|||||||
dst_env_def(env, name, dst_wrap_function(dst_thunk(def)));
|
dst_env_def(env, name, dst_wrap_function(dst_thunk(def)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Macros for easier inline dst assembly */
|
||||||
#define SSS(op, a, b, c) (op | (a << 8) | (b << 16) | (c << 24))
|
#define SSS(op, a, b, c) (op | (a << 8) | (b << 16) | (c << 24))
|
||||||
#define SS(op, a, b) SSS(op, a, b, 0)
|
#define SS(op, a, b) (op | (a << 8) | (b << 16))
|
||||||
#define S(op, a) SSS(op, a, 0, 0)
|
#define SSI(op, a, b, I) (op | (a << 8) | (b << 16) | ((uint32_t)(I) << 24))
|
||||||
|
#define S(op, a) (op | (a << 8))
|
||||||
|
#define SI(op, a, I) (op | (a << 8) | ((uint32_t)(I) << 16))
|
||||||
|
|
||||||
/* Variadic operator assembly. Must be templatized for each different opcode. */
|
/* Variadic operator assembly. Must be templatized for each different opcode. */
|
||||||
/* Reg 0: Argument tuple (args) */
|
/* Reg 0: Argument tuple (args) */
|
||||||
/* Reg 1: Argument count (argn) */
|
/* Reg 1: Argument count (argn) */
|
||||||
@ -354,36 +358,37 @@ static void dst_quick_asm(
|
|||||||
/* Reg 4: Next operand (operand) */
|
/* Reg 4: Next operand (operand) */
|
||||||
/* Reg 5: Loop iterator (i) */
|
/* Reg 5: Loop iterator (i) */
|
||||||
static DST_THREAD_LOCAL uint32_t varop_asm[] = {
|
static DST_THREAD_LOCAL uint32_t varop_asm[] = {
|
||||||
DOP_LENGTH | (1 << 8), /* Put number of arguments in register 1 -> argn = count(args) */
|
SS(DOP_LENGTH, 1, 0), /* Put number of arguments in register 1 -> argn = count(args) */
|
||||||
|
|
||||||
/* Cheack nullary */
|
/* Check nullary */
|
||||||
DOP_EQUALS_IMMEDIATE | (2 << 8) | (1 << 16) | (0 << 24), /* Check if numargs equal to 0 */
|
SSS(DOP_EQUALS_IMMEDIATE, 2, 1, 0), /* Check if numargs equal to 0 */
|
||||||
DOP_JUMP_IF_NOT | (2 << 8) | (3 << 16), /* If not 0, jump to next check */
|
SI(DOP_JUMP_IF_NOT, 2, 3), /* If not 0, jump to next check */
|
||||||
/* Nullary */
|
/* Nullary */
|
||||||
DOP_LOAD_INTEGER | (3 << 8), /* accum = nullary value */
|
SI(DOP_LOAD_INTEGER, 3, 0), /* accum = nullary value */
|
||||||
DOP_RETURN | (3 << 8), /* return accum */
|
S(DOP_RETURN, 3), /* return accum */
|
||||||
|
|
||||||
/* Check unary */
|
/* Check unary */
|
||||||
DOP_EQUALS_IMMEDIATE | (2 << 8) | (1 << 16) | (1 << 24), /* Check if numargs equal to 1 */
|
SSI(DOP_EQUALS_IMMEDIATE, 2, 1, 1), /* Check if numargs equal to 1 */
|
||||||
DOP_JUMP_IF_NOT | (2 << 8) | (5 << 16), /* If not 1, jump to next check */
|
SI(DOP_JUMP_IF_NOT, 2, 5), /* If not 1, jump to next check */
|
||||||
/* Unary */
|
/* Unary */
|
||||||
DOP_LOAD_INTEGER | (3 << 8), /* accum = unary value */
|
S(DOP_LOAD_INTEGER, 3), /* accum = unary value */
|
||||||
DOP_GET_INDEX | (4 << 8) | (0 << 16) | (0 << 24), /* operand = args[0] */
|
SSI(DOP_GET_INDEX, 4, 0, 0), /* operand = args[0] */
|
||||||
DOP_NOOP | (3 << 8) | (3 << 16) | (4 << 24), /* accum = accum op operand */
|
SSS(DOP_NOOP, 3, 3, 4), /* accum = accum op operand */
|
||||||
DOP_RETURN | (3 << 8), /* return accum */
|
S(DOP_RETURN, 3), /* return accum */
|
||||||
|
|
||||||
/* Mutli (2 or more) arity */
|
/* Mutli (2 or more) arity */
|
||||||
/* Prime loop */
|
/* Prime loop */
|
||||||
DOP_GET_INDEX | (3 << 8) | (0 << 16) | (0 << 24), /* accum = args[0] */
|
SSI(DOP_GET_INDEX, 3, 0, 0), /* accum = args[0] */
|
||||||
DOP_LOAD_INTEGER | (5 << 8) | (1 << 16), /* i = 1 */
|
SI(DOP_LOAD_INTEGER, 5, 1), /* i = 1 */
|
||||||
/* Main loop */
|
/* Main loop */
|
||||||
DOP_GET | (4 << 8) | (0 << 16) | (5 << 24), /* operand = args[i] */
|
SSS(DOP_GET, 4, 0, 5), /* operand = args[i] */
|
||||||
DOP_NOOP | (3 << 8) | (3 << 16) | (4 << 24), /* accum = accum op operand */
|
SSS(DOP_NOOP, 3, 3, 4), /* accum = accum op operand */
|
||||||
DOP_ADD_IMMEDIATE | (5 << 8) | (5 << 16) | (1 << 24), /* i++ */
|
SSI(DOP_ADD_IMMEDIATE, 5, 5, 1), /* i++ */
|
||||||
DOP_EQUALS_INTEGER | (2 << 8) | (5 << 16) | (1 << 24), /* jump? = (i == argn) */
|
SSI(DOP_EQUALS_INTEGER, 2, 5, 1), /* jump? = (i == argn) */
|
||||||
DOP_JUMP_IF_NOT | (2 << 8) | ((uint32_t)(-4) << 16), /* if not jump? go back 4 */
|
SI(DOP_JUMP_IF_NOT, 2, -4), /* if not jump? go back 4 */
|
||||||
|
|
||||||
/* Done, do last and return accumulator */
|
/* Done, do last and return accumulator */
|
||||||
DOP_RETURN | (3 << 8) /* return accum */
|
S(DOP_RETURN, 3) /* return accum */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define VAROP_NULLARY_LOC 3
|
#define VAROP_NULLARY_LOC 3
|
||||||
|
111
src/core/os.c
111
src/core/os.c
@ -29,9 +29,112 @@
|
|||||||
#include <direct.h>
|
#include <direct.h>
|
||||||
#else
|
#else
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <stdio.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef DST_WINDOWS
|
||||||
static int os_execute(DstArgs args) {
|
static int os_execute(DstArgs args) {
|
||||||
|
DST_MINARITY(args, 1);
|
||||||
|
DstBuffer *buffer = dst_buffer(10);
|
||||||
|
for (int32_t i = 0; i < args.n; i++) {
|
||||||
|
const uint8_t *argstring;
|
||||||
|
DST_ARG_STRING(argstring, args, i);
|
||||||
|
dst_buffer_push_bytes(buffer, argstring, dst_string_length(argstring));
|
||||||
|
if (i != args.n - 1) {
|
||||||
|
dst_buffer_push_u8(buffer, ' ');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dst_buffer_push_u8(buffer, 0);
|
||||||
|
|
||||||
|
/* Convert to wide chars */
|
||||||
|
wchar_t *sys_str = malloc(buffer->count * sizeof(wchar_t));
|
||||||
|
if (NULL == sys_str) {
|
||||||
|
DST_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
int nwritten = MultiByteToWideChar(
|
||||||
|
CP_UTF8,
|
||||||
|
MB_PRECOMPOSED,
|
||||||
|
buffer->data,
|
||||||
|
buffer->count,
|
||||||
|
sys_str,
|
||||||
|
buffer->count);
|
||||||
|
if (nwritten == 0) {
|
||||||
|
free(sys_str);
|
||||||
|
DST_THROW(args, "could not create process");
|
||||||
|
}
|
||||||
|
|
||||||
|
STARTUPINFO si;
|
||||||
|
PROCESS_INFORMATION pi;
|
||||||
|
|
||||||
|
ZeroMemory(&si, sizeof(si));
|
||||||
|
si.cb = sizeof(si);
|
||||||
|
ZeroMemory(&pi, sizeof(pi));
|
||||||
|
|
||||||
|
// Start the child process.
|
||||||
|
if(!CreateProcess(NULL,
|
||||||
|
sys_str,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
FALSE,
|
||||||
|
0,
|
||||||
|
NULL,
|
||||||
|
NULL,
|
||||||
|
&si,
|
||||||
|
&pi)) {
|
||||||
|
free(sys_str);
|
||||||
|
DST_THROW(args, "could not create process");
|
||||||
|
}
|
||||||
|
free(sys_str);
|
||||||
|
|
||||||
|
// Wait until child process exits.
|
||||||
|
WaitForSingleObject(pi.hProcess, INFINITE);
|
||||||
|
|
||||||
|
// Close process and thread handles.
|
||||||
|
CloseHandle(pi.hProcess);
|
||||||
|
CloseHandle(pi.hThread);
|
||||||
|
DST_RETURN_INTEGER(args, 0);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static int os_execute(DstArgs args) {
|
||||||
|
DST_MINARITY(args, 1);
|
||||||
|
const uint8_t **argv = malloc(sizeof(uint8_t *) * (args.n + 1));
|
||||||
|
if (NULL == argv) {
|
||||||
|
DST_OUT_OF_MEMORY;
|
||||||
|
}
|
||||||
|
for (int32_t i = 0; i < args.n; i++) {
|
||||||
|
DST_ARG_STRING(argv[i], args, i);
|
||||||
|
}
|
||||||
|
argv[args.n] = NULL;
|
||||||
|
|
||||||
|
/* Fork child process */
|
||||||
|
pid_t pid;
|
||||||
|
if (0 == (pid = fork())) {
|
||||||
|
if (-1 == execve((const char *)argv[0], (char **)argv, NULL)) {
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Wait for child process */
|
||||||
|
int status;
|
||||||
|
struct timespec waiter;
|
||||||
|
waiter.tv_sec = 0;
|
||||||
|
waiter.tv_nsec = 200;
|
||||||
|
while (0 == waitpid(pid, &status, WNOHANG)) {
|
||||||
|
waiter.tv_nsec = (waiter.tv_nsec * 3) / 2;
|
||||||
|
/* Keep increasing sleep time by a factor of 3/2
|
||||||
|
* until a maximum */
|
||||||
|
if (waiter.tv_nsec > 4999999)
|
||||||
|
waiter.tv_nsec = 5000000;
|
||||||
|
nanosleep(&waiter, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
DST_RETURN_INTEGER(args, status);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static int os_shell(DstArgs args) {
|
||||||
int nofirstarg = (args.n < 1 || !dst_checktype(args.v[0], DST_STRING));
|
int nofirstarg = (args.n < 1 || !dst_checktype(args.v[0], DST_STRING));
|
||||||
const char *cmd = nofirstarg
|
const char *cmd = nofirstarg
|
||||||
? NULL
|
? NULL
|
||||||
@ -107,7 +210,12 @@ static int os_sleep(DstArgs args) {
|
|||||||
#ifdef DST_WINDOWS
|
#ifdef DST_WINDOWS
|
||||||
Sleep((DWORD) (delay * 1000));
|
Sleep((DWORD) (delay * 1000));
|
||||||
#else
|
#else
|
||||||
usleep((useconds_t)(delay * 1000000));
|
struct timespec ts;
|
||||||
|
ts.tv_sec = (time_t) delay;
|
||||||
|
ts.tv_nsec = (delay <= UINT32_MAX)
|
||||||
|
? (long)((delay - ((uint32_t)delay)) * 1000000000)
|
||||||
|
: 0;
|
||||||
|
nanosleep(&ts, NULL);
|
||||||
#endif
|
#endif
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -129,6 +237,7 @@ static int os_cwd(DstArgs args) {
|
|||||||
|
|
||||||
static const DstReg cfuns[] = {
|
static const DstReg cfuns[] = {
|
||||||
{"os.execute", os_execute},
|
{"os.execute", os_execute},
|
||||||
|
{"os.shell", os_shell},
|
||||||
{"os.exit", os_exit},
|
{"os.exit", os_exit},
|
||||||
{"os.getenv", os_getenv},
|
{"os.getenv", os_getenv},
|
||||||
{"os.setenv", os_setenv},
|
{"os.setenv", os_setenv},
|
||||||
|
Loading…
Reference in New Issue
Block a user