A vm/nga-c/dev-unix.c => vm/nga-c/dev-unix.c +220 -0
@@ 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
M vm/nga-c/retro.c => vm/nga-c/retro.c +4 -219
@@ 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!