nga-c: split unix device into a separate file
FossilOrigin-Name: 5748427d59ed3bfb9e7697d96ad65d12320cdf430ef60fd7ec9002b08dc58443
This commit is contained in:
parent
15c2e83745
commit
71993e3925
2 changed files with 224 additions and 219 deletions
220
vm/nga-c/dev-unix.c
Normal file
220
vm/nga-c/dev-unix.c
Normal file
|
@ -0,0 +1,220 @@
|
|||
/*---------------------------------------------------------------------
|
||||
Copyright (c) 2008 - 2022, Charles Childers
|
||||
|
||||
Portions are based on Ngaro, which was additionally copyright
|
||||
by the following:
|
||||
|
||||
Copyright (c) 2009 - 2010, Luke Parrish
|
||||
Copyright (c) 2010, Marc Simpson
|
||||
Copyright (c) 2010, Jay Skeer
|
||||
Copyright (c) 2011, Kenneth Keating
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
#ifdef ENABLE_UNIX
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
`unix_open_pipe()` is like `file_open()`, but for pipes. This pulls
|
||||
from the data stack:
|
||||
|
||||
- mode (number, TOS)
|
||||
- executable (string, NOS)
|
||||
|
||||
Modes are:
|
||||
|
||||
| Mode | Corresponds To | Description |
|
||||
| ---- | -------------- | -------------------- |
|
||||
| 0 | r | Open for reading |
|
||||
| 1 | w | Open for writing |
|
||||
| 3 | r+ | Open for read/update |
|
||||
|
||||
The file name should be a NULL terminated string. This will attempt
|
||||
to open the requested file and will return a handle (index number
|
||||
into the `OpenFileHandles` array).
|
||||
|
||||
Once opened, you can use the standard file words to read/write to the
|
||||
process.
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
void unix_open_pipe(NgaState *vm) {
|
||||
CELL slot, mode, name;
|
||||
char *request;
|
||||
slot = files_get_handle(vm);
|
||||
mode = stack_pop(vm);
|
||||
name = stack_pop(vm);
|
||||
request = string_extract(vm, name);
|
||||
if (slot > 0) {
|
||||
if (mode == 0) vm->OpenFileHandles[slot] = popen(request, "r");
|
||||
if (mode == 1) vm->OpenFileHandles[slot] = popen(request, "w");
|
||||
if (mode == 3) vm->OpenFileHandles[slot] = popen(request, "r+");
|
||||
}
|
||||
if (vm->OpenFileHandles[slot] == NULL) {
|
||||
vm->OpenFileHandles[slot] = 0;
|
||||
slot = 0;
|
||||
}
|
||||
stack_push(vm, slot);
|
||||
}
|
||||
|
||||
void unix_close_pipe(NgaState *vm) {
|
||||
pclose(vm->OpenFileHandles[TOS]);
|
||||
vm->OpenFileHandles[TOS] = 0;
|
||||
stack_pop(vm);
|
||||
}
|
||||
|
||||
void unix_system(NgaState *vm) {
|
||||
int ignore = 0;
|
||||
ignore = system(string_extract(vm, stack_pop(vm)));
|
||||
}
|
||||
|
||||
void unix_fork(NgaState *vm) {
|
||||
stack_push(vm, fork());
|
||||
}
|
||||
|
||||
void unix_run_external(NgaState *vm) {
|
||||
char *line, *args[128];
|
||||
int i, status;
|
||||
pid_t pid;
|
||||
|
||||
char **argv = args;
|
||||
line = string_extract(vm, stack_pop(vm));
|
||||
|
||||
for(i = 0; i < 128; i++)
|
||||
args[i] = 0;
|
||||
|
||||
while (*line != '\0') {
|
||||
while (*line == ' ' || *line == '\t' || *line == '\n')
|
||||
*line++ = '\0';
|
||||
*argv++ = line;
|
||||
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
|
||||
line++;
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
printf("*** ERROR: forking child process failed\n");
|
||||
exit(1);
|
||||
}
|
||||
else if (pid == 0) {
|
||||
int e = execvp(*args, args);
|
||||
if (e < 0) {
|
||||
printf("*** ERROR: exec failed with %d\n", e);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
while (wait(&status) != pid)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
UNIX provides `execl` to execute a file, with various forms for
|
||||
arguments provided.
|
||||
|
||||
RRE wraps this in several functions, one for each number of passed
|
||||
arguments. See the Glossary for details on what each takes from the
|
||||
stack. Each of these will return the error code if the execution
|
||||
fails.
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
void unix_exec0(NgaState *vm) {
|
||||
char path[1025];
|
||||
strlcpy(path, string_extract(vm, stack_pop(vm)), 1024);
|
||||
execl(path, path, (char *)0);
|
||||
stack_push(vm, errno);
|
||||
}
|
||||
|
||||
void unix_exec1(NgaState *vm) {
|
||||
char path[1025];
|
||||
char arg0[1025];
|
||||
strlcpy(arg0, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(path, string_extract(vm, stack_pop(vm)), 1024);
|
||||
execl(path, path, arg0, (char *)0);
|
||||
stack_push(vm, errno);
|
||||
}
|
||||
|
||||
void unix_exec2(NgaState *vm) {
|
||||
char path[1025];
|
||||
char arg0[1025], arg1[1025];
|
||||
strlcpy(arg1, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(arg0, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(path, string_extract(vm, stack_pop(vm)), 1024);
|
||||
execl(path, path, arg0, arg1, (char *)0);
|
||||
stack_push(vm, errno);
|
||||
}
|
||||
|
||||
void unix_exec3(NgaState *vm) {
|
||||
char path[1025];
|
||||
char arg0[1025], arg1[1025], arg2[1025];
|
||||
strlcpy(arg2, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(arg1, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(arg0, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(path, string_extract(vm, stack_pop(vm)), 1024);
|
||||
execl(path, path, arg0, arg1, arg2, (char *)0);
|
||||
stack_push(vm, errno);
|
||||
}
|
||||
|
||||
void unix_exit(NgaState *vm) {
|
||||
exit(stack_pop(vm));
|
||||
}
|
||||
|
||||
void unix_getpid(NgaState *vm) {
|
||||
stack_push(vm, getpid());
|
||||
}
|
||||
|
||||
void unix_wait(NgaState *vm) {
|
||||
int a;
|
||||
stack_push(vm, wait(&a));
|
||||
}
|
||||
|
||||
void unix_kill(NgaState *vm) {
|
||||
CELL a;
|
||||
a = stack_pop(vm);
|
||||
kill(stack_pop(vm), a);
|
||||
}
|
||||
|
||||
void unix_write(NgaState *vm) {
|
||||
CELL a, b, c;
|
||||
ssize_t ignore;
|
||||
c = stack_pop(vm);
|
||||
b = stack_pop(vm);
|
||||
a = stack_pop(vm);
|
||||
ignore = write(fileno(vm->OpenFileHandles[c]), string_extract(vm, a), b);
|
||||
}
|
||||
|
||||
void unix_chdir(NgaState *vm) {
|
||||
int ignore;
|
||||
ignore = chdir(string_extract(vm, stack_pop(vm)));
|
||||
}
|
||||
|
||||
void unix_getenv(NgaState *vm) {
|
||||
CELL a, b;
|
||||
a = stack_pop(vm);
|
||||
b = stack_pop(vm);
|
||||
string_inject(vm, getenv(string_extract(vm, b)), a);
|
||||
}
|
||||
|
||||
void unix_putenv(NgaState *vm) {
|
||||
putenv(string_extract(vm, stack_pop(vm)));
|
||||
}
|
||||
|
||||
void unix_sleep(NgaState *vm) {
|
||||
sleep(stack_pop(vm));
|
||||
}
|
||||
|
||||
Handler UnixActions[] = {
|
||||
unix_system, unix_fork, unix_exec0, unix_exec1, unix_exec2,
|
||||
unix_exec3, unix_exit, unix_getpid, unix_wait, unix_kill,
|
||||
unix_open_pipe, unix_close_pipe, unix_write, unix_chdir, unix_getenv,
|
||||
unix_putenv, unix_sleep, unix_run_external
|
||||
};
|
||||
|
||||
void query_unix(NgaState *vm) {
|
||||
stack_push(vm, 3);
|
||||
stack_push(vm, 8);
|
||||
}
|
||||
|
||||
void io_unix(NgaState *vm) {
|
||||
UnixActions[stack_pop(vm)](vm);
|
||||
}
|
||||
#endif
|
223
vm/nga-c/retro.c
223
vm/nga-c/retro.c
|
@ -32,18 +32,6 @@
|
|||
#include <math.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_SOCKETS
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <netinet/in.h>
|
||||
#include <sys/socket.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_UNIX
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_FFI
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
@ -964,213 +952,6 @@ void io_filesystem(NgaState *vm) {
|
|||
}
|
||||
|
||||
|
||||
#ifdef ENABLE_UNIX
|
||||
/*---------------------------------------------------------------------
|
||||
`unix_open_pipe()` is like `file_open()`, but for pipes. This pulls
|
||||
from the data stack:
|
||||
|
||||
- mode (number, TOS)
|
||||
- executable (string, NOS)
|
||||
|
||||
Modes are:
|
||||
|
||||
| Mode | Corresponds To | Description |
|
||||
| ---- | -------------- | -------------------- |
|
||||
| 0 | r | Open for reading |
|
||||
| 1 | w | Open for writing |
|
||||
| 3 | r+ | Open for read/update |
|
||||
|
||||
The file name should be a NULL terminated string. This will attempt
|
||||
to open the requested file and will return a handle (index number
|
||||
into the `OpenFileHandles` array).
|
||||
|
||||
Once opened, you can use the standard file words to read/write to the
|
||||
process.
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
void unix_open_pipe(NgaState *vm) {
|
||||
CELL slot, mode, name;
|
||||
char *request;
|
||||
slot = files_get_handle(vm);
|
||||
mode = stack_pop(vm);
|
||||
name = stack_pop(vm);
|
||||
request = string_extract(vm, name);
|
||||
if (slot > 0) {
|
||||
if (mode == 0) vm->OpenFileHandles[slot] = popen(request, "r");
|
||||
if (mode == 1) vm->OpenFileHandles[slot] = popen(request, "w");
|
||||
if (mode == 3) vm->OpenFileHandles[slot] = popen(request, "r+");
|
||||
}
|
||||
if (vm->OpenFileHandles[slot] == NULL) {
|
||||
vm->OpenFileHandles[slot] = 0;
|
||||
slot = 0;
|
||||
}
|
||||
stack_push(vm, slot);
|
||||
}
|
||||
|
||||
void unix_close_pipe(NgaState *vm) {
|
||||
pclose(vm->OpenFileHandles[TOS]);
|
||||
vm->OpenFileHandles[TOS] = 0;
|
||||
stack_pop(vm);
|
||||
}
|
||||
|
||||
void unix_system(NgaState *vm) {
|
||||
int ignore = 0;
|
||||
ignore = system(string_extract(vm, stack_pop(vm)));
|
||||
}
|
||||
|
||||
void unix_fork(NgaState *vm) {
|
||||
stack_push(vm, fork());
|
||||
}
|
||||
|
||||
void unix_run_external(NgaState *vm) {
|
||||
char *line, *args[128];
|
||||
int i, status;
|
||||
pid_t pid;
|
||||
|
||||
char **argv = args;
|
||||
line = string_extract(vm, stack_pop(vm));
|
||||
|
||||
for(i = 0; i < 128; i++)
|
||||
args[i] = 0;
|
||||
|
||||
while (*line != '\0') {
|
||||
while (*line == ' ' || *line == '\t' || *line == '\n')
|
||||
*line++ = '\0';
|
||||
*argv++ = line;
|
||||
while (*line != '\0' && *line != ' ' && *line != '\t' && *line != '\n')
|
||||
line++;
|
||||
}
|
||||
|
||||
if ((pid = fork()) < 0) {
|
||||
printf("*** ERROR: forking child process failed\n");
|
||||
exit(1);
|
||||
}
|
||||
else if (pid == 0) {
|
||||
int e = execvp(*args, args);
|
||||
if (e < 0) {
|
||||
printf("*** ERROR: exec failed with %d\n", e);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
while (wait(&status) != pid)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
UNIX provides `execl` to execute a file, with various forms for
|
||||
arguments provided.
|
||||
|
||||
RRE wraps this in several functions, one for each number of passed
|
||||
arguments. See the Glossary for details on what each takes from the
|
||||
stack. Each of these will return the error code if the execution
|
||||
fails.
|
||||
---------------------------------------------------------------------*/
|
||||
|
||||
void unix_exec0(NgaState *vm) {
|
||||
char path[1025];
|
||||
strlcpy(path, string_extract(vm, stack_pop(vm)), 1024);
|
||||
execl(path, path, (char *)0);
|
||||
stack_push(vm, errno);
|
||||
}
|
||||
|
||||
void unix_exec1(NgaState *vm) {
|
||||
char path[1025];
|
||||
char arg0[1025];
|
||||
strlcpy(arg0, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(path, string_extract(vm, stack_pop(vm)), 1024);
|
||||
execl(path, path, arg0, (char *)0);
|
||||
stack_push(vm, errno);
|
||||
}
|
||||
|
||||
void unix_exec2(NgaState *vm) {
|
||||
char path[1025];
|
||||
char arg0[1025], arg1[1025];
|
||||
strlcpy(arg1, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(arg0, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(path, string_extract(vm, stack_pop(vm)), 1024);
|
||||
execl(path, path, arg0, arg1, (char *)0);
|
||||
stack_push(vm, errno);
|
||||
}
|
||||
|
||||
void unix_exec3(NgaState *vm) {
|
||||
char path[1025];
|
||||
char arg0[1025], arg1[1025], arg2[1025];
|
||||
strlcpy(arg2, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(arg1, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(arg0, string_extract(vm, stack_pop(vm)), 1024);
|
||||
strlcpy(path, string_extract(vm, stack_pop(vm)), 1024);
|
||||
execl(path, path, arg0, arg1, arg2, (char *)0);
|
||||
stack_push(vm, errno);
|
||||
}
|
||||
|
||||
void unix_exit(NgaState *vm) {
|
||||
exit(stack_pop(vm));
|
||||
}
|
||||
|
||||
void unix_getpid(NgaState *vm) {
|
||||
stack_push(vm, getpid());
|
||||
}
|
||||
|
||||
void unix_wait(NgaState *vm) {
|
||||
int a;
|
||||
stack_push(vm, wait(&a));
|
||||
}
|
||||
|
||||
void unix_kill(NgaState *vm) {
|
||||
CELL a;
|
||||
a = stack_pop(vm);
|
||||
kill(stack_pop(vm), a);
|
||||
}
|
||||
|
||||
void unix_write(NgaState *vm) {
|
||||
CELL a, b, c;
|
||||
ssize_t ignore;
|
||||
c = stack_pop(vm);
|
||||
b = stack_pop(vm);
|
||||
a = stack_pop(vm);
|
||||
ignore = write(fileno(vm->OpenFileHandles[c]), string_extract(vm, a), b);
|
||||
}
|
||||
|
||||
void unix_chdir(NgaState *vm) {
|
||||
int ignore;
|
||||
ignore = chdir(string_extract(vm, stack_pop(vm)));
|
||||
}
|
||||
|
||||
void unix_getenv(NgaState *vm) {
|
||||
CELL a, b;
|
||||
a = stack_pop(vm);
|
||||
b = stack_pop(vm);
|
||||
string_inject(vm, getenv(string_extract(vm, b)), a);
|
||||
}
|
||||
|
||||
void unix_putenv(NgaState *vm) {
|
||||
putenv(string_extract(vm, stack_pop(vm)));
|
||||
}
|
||||
|
||||
void unix_sleep(NgaState *vm) {
|
||||
sleep(stack_pop(vm));
|
||||
}
|
||||
|
||||
Handler UnixActions[] = {
|
||||
unix_system, unix_fork, unix_exec0, unix_exec1, unix_exec2,
|
||||
unix_exec3, unix_exit, unix_getpid, unix_wait, unix_kill,
|
||||
unix_open_pipe, unix_close_pipe, unix_write, unix_chdir, unix_getenv,
|
||||
unix_putenv, unix_sleep, unix_run_external
|
||||
};
|
||||
|
||||
void query_unix(NgaState *vm) {
|
||||
stack_push(vm, 3);
|
||||
stack_push(vm, 8);
|
||||
}
|
||||
|
||||
void io_unix(NgaState *vm) {
|
||||
UnixActions[stack_pop(vm)](vm);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Time and Date Functions --------------------------------------------*/
|
||||
#ifdef ENABLE_CLOCK
|
||||
void clock_time(NgaState *vm) {
|
||||
|
@ -1288,6 +1069,10 @@ void query_rng(NgaState *vm) {
|
|||
#include "dev-sockets.c"
|
||||
#endif
|
||||
|
||||
#ifdef ENABLE_UNIX
|
||||
#include "dev-unix.c"
|
||||
#endif
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------
|
||||
Now on to I/O and extensions!
|
||||
|
|
Loading…
Reference in a new issue