Moved unix specific console tools in etc
This commit is contained in:
parent
6b335197da
commit
b3f207b974
|
@ -0,0 +1,226 @@
|
||||||
|
#undef _POSIX_C_SOURCE
|
||||||
|
#define _POSIX_C_SOURCE 200112L
|
||||||
|
|
||||||
|
#include <signal.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#ifdef __linux
|
||||||
|
#include <pty.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __NetBSD__
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <util.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "../uxn.h"
|
||||||
|
#include "console.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
Copyright (c) 2022-2023 Devine Lu Linvega, Andrew Alderwick
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* process */
|
||||||
|
static char *fork_args[32];
|
||||||
|
static int child_mode;
|
||||||
|
static int pty_fd;
|
||||||
|
static int to_child_fd[2];
|
||||||
|
static int from_child_fd[2];
|
||||||
|
static int saved_in;
|
||||||
|
static int saved_out;
|
||||||
|
static pid_t child_pid;
|
||||||
|
struct winsize ws = {24, 80, 8, 12};
|
||||||
|
|
||||||
|
static void
|
||||||
|
parse_args(Uint8 *d)
|
||||||
|
{
|
||||||
|
Uint8 *port_addr = d + 0x3;
|
||||||
|
int addr = PEEK2(port_addr);
|
||||||
|
char *pos = (char *)&uxn.ram[addr];
|
||||||
|
int i = 0;
|
||||||
|
do {
|
||||||
|
fork_args[i++] = pos;
|
||||||
|
while(*pos != 0) pos++;
|
||||||
|
pos++;
|
||||||
|
} while(*pos != '\0');
|
||||||
|
fork_args[i] = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* call after we're sure the process has exited */
|
||||||
|
static void
|
||||||
|
clean_after_child(void)
|
||||||
|
{
|
||||||
|
child_pid = 0;
|
||||||
|
if(child_mode >= 0x80) {
|
||||||
|
close(pty_fd);
|
||||||
|
dup2(saved_in, 0);
|
||||||
|
dup2(saved_out, 1);
|
||||||
|
} else {
|
||||||
|
if(child_mode & 0x01) {
|
||||||
|
close(to_child_fd[1]);
|
||||||
|
dup2(saved_out, 1);
|
||||||
|
}
|
||||||
|
if(child_mode & 0x06) {
|
||||||
|
close(from_child_fd[0]);
|
||||||
|
dup2(saved_in, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
child_mode = 0;
|
||||||
|
saved_in = -1;
|
||||||
|
saved_out = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
console_input(Uint8 c, int type)
|
||||||
|
{
|
||||||
|
uxn.dev[0x12] = c;
|
||||||
|
uxn.dev[0x17] = type;
|
||||||
|
return uxn_eval(PEEK2(&uxn.dev[0x10]));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_listen(int i, int argc, char **argv)
|
||||||
|
{
|
||||||
|
for(; i < argc; i++) {
|
||||||
|
char *p = argv[i];
|
||||||
|
while(*p) console_input(*p++, CONSOLE_ARG);
|
||||||
|
console_input('\n', i == argc - 1 ? CONSOLE_END : CONSOLE_EOA);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_fork_pty(Uint8 *d)
|
||||||
|
{
|
||||||
|
int fd = -1;
|
||||||
|
pid_t pid = forkpty(&fd, NULL, NULL, NULL);
|
||||||
|
if(pid < 0) { /* failure */
|
||||||
|
d[0x6] = 0xff;
|
||||||
|
fprintf(stderr, "fork failure\n");
|
||||||
|
} else if(pid == 0) { /* child */
|
||||||
|
setenv("TERM", "ansi", 1);
|
||||||
|
execvp(fork_args[0], fork_args);
|
||||||
|
d[0x6] = 0xff;
|
||||||
|
fprintf(stderr, "exec failure\n");
|
||||||
|
} else { /*parent*/
|
||||||
|
child_pid = pid;
|
||||||
|
pty_fd = fd;
|
||||||
|
ioctl(fd, TIOCSWINSZ, &ws);
|
||||||
|
saved_in = dup(0);
|
||||||
|
saved_out = dup(1);
|
||||||
|
dup2(fd, 0);
|
||||||
|
dup2(fd, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_fork_pipe(Uint8 *d)
|
||||||
|
{
|
||||||
|
pid_t pid;
|
||||||
|
if(child_mode & 0x01) {
|
||||||
|
/* parent writes to child's stdin */
|
||||||
|
if(pipe(to_child_fd) == -1) {
|
||||||
|
d[0x6] = 0xff;
|
||||||
|
fprintf(stderr, "pipe error: to child\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(child_mode & 0x06) {
|
||||||
|
/* parent reads from child's stdout and/or stderr */
|
||||||
|
if(pipe(from_child_fd) == -1) {
|
||||||
|
d[0x6] = 0xff;
|
||||||
|
fprintf(stderr, "pipe error: from child\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pid = fork();
|
||||||
|
if(pid < 0) { /* failure */
|
||||||
|
d[0x6] = 0xff;
|
||||||
|
fprintf(stderr, "fork failure\n");
|
||||||
|
} else if(pid == 0) { /* child */
|
||||||
|
if(child_mode & 0x01) {
|
||||||
|
dup2(to_child_fd[0], 0);
|
||||||
|
close(to_child_fd[1]);
|
||||||
|
}
|
||||||
|
if(child_mode & 0x06) {
|
||||||
|
if(child_mode & 0x02) dup2(from_child_fd[1], 1);
|
||||||
|
if(child_mode & 0x04) dup2(from_child_fd[1], 2);
|
||||||
|
close(from_child_fd[0]);
|
||||||
|
}
|
||||||
|
execvp(fork_args[0], fork_args);
|
||||||
|
d[0x6] = 0xff;
|
||||||
|
fprintf(stderr, "exec failure\n");
|
||||||
|
} else { /*parent*/
|
||||||
|
child_pid = pid;
|
||||||
|
if(child_mode & 0x01) {
|
||||||
|
saved_out = dup(1);
|
||||||
|
dup2(to_child_fd[1], 1);
|
||||||
|
close(to_child_fd[0]);
|
||||||
|
}
|
||||||
|
if(child_mode & 0x06) {
|
||||||
|
saved_in = dup(0);
|
||||||
|
dup2(from_child_fd[0], 0);
|
||||||
|
close(from_child_fd[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
kill_child(Uint8 *d, int options)
|
||||||
|
{
|
||||||
|
int wstatus;
|
||||||
|
if(child_pid) {
|
||||||
|
kill(child_pid, 9);
|
||||||
|
if(waitpid(child_pid, &wstatus, options)) {
|
||||||
|
d[0x6] = 1;
|
||||||
|
d[0x7] = WEXITSTATUS(wstatus);
|
||||||
|
clean_after_child();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
start_fork(Uint8 *d)
|
||||||
|
{
|
||||||
|
fflush(stderr);
|
||||||
|
kill_child(d, 0);
|
||||||
|
child_mode = d[0x5];
|
||||||
|
parse_args(d);
|
||||||
|
if(child_mode >= 0x80)
|
||||||
|
start_fork_pty(d);
|
||||||
|
else
|
||||||
|
start_fork_pipe(d);
|
||||||
|
}
|
||||||
|
|
||||||
|
Uint8
|
||||||
|
console_dei(Uint8 addr)
|
||||||
|
{
|
||||||
|
Uint8 port = addr & 0x0f, *d = &uxn.dev[addr & 0xf0];
|
||||||
|
switch(port) {
|
||||||
|
case 0x6:
|
||||||
|
case 0x7: kill_child(d, WNOHANG);
|
||||||
|
}
|
||||||
|
return d[port];
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
console_deo(Uint8 addr)
|
||||||
|
{
|
||||||
|
FILE *fd;
|
||||||
|
switch(addr) {
|
||||||
|
case 0x15: /* Console/dead */ start_fork(&uxn.dev[0x10]); break;
|
||||||
|
case 0x16: /* Console/exit*/ kill_child(&uxn.dev[0x10], 0); break;
|
||||||
|
case 0x18: fd = stdout, fputc(uxn.dev[0x18], fd), fflush(fd); break;
|
||||||
|
case 0x19: fd = stderr, fputc(uxn.dev[0x19], fd), fflush(fd); break;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2021 Devine Lu Linvega, Andrew Alderwick
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define CONSOLE_STD 0x1
|
||||||
|
#define CONSOLE_ARG 0x2
|
||||||
|
#define CONSOLE_EOA 0x3
|
||||||
|
#define CONSOLE_END 0x4
|
||||||
|
|
||||||
|
int console_input(Uint8 c, int type);
|
||||||
|
void console_listen(int i, int argc, char **argv);
|
||||||
|
Uint8 console_dei(Uint8 addr);
|
||||||
|
void console_deo(Uint8 addr);
|
|
@ -1,27 +1,11 @@
|
||||||
#undef _POSIX_C_SOURCE
|
|
||||||
#define _POSIX_C_SOURCE 200112L
|
|
||||||
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <sys/select.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifdef __linux
|
|
||||||
#include <pty.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef __NetBSD__
|
|
||||||
#include <sys/ioctl.h>
|
|
||||||
#include <util.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include "../uxn.h"
|
#include "../uxn.h"
|
||||||
#include "console.h"
|
#include "console.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2022-2023 Devine Lu Linvega, Andrew Alderwick
|
Copyright (c) 2022-2024 Devine Lu Linvega, Andrew Alderwick
|
||||||
|
|
||||||
Permission to use, copy, modify, and distribute this software for any
|
Permission to use, copy, modify, and distribute this software for any
|
||||||
purpose with or without fee is hereby granted, provided that the above
|
purpose with or without fee is hereby granted, provided that the above
|
||||||
|
@ -31,56 +15,6 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
WITH REGARD TO THIS SOFTWARE.
|
WITH REGARD TO THIS SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* process */
|
|
||||||
static char *fork_args[32];
|
|
||||||
static int child_mode;
|
|
||||||
static int pty_fd;
|
|
||||||
static int to_child_fd[2];
|
|
||||||
static int from_child_fd[2];
|
|
||||||
static int saved_in;
|
|
||||||
static int saved_out;
|
|
||||||
static pid_t child_pid;
|
|
||||||
struct winsize ws = {24, 80, 8, 12};
|
|
||||||
|
|
||||||
static void
|
|
||||||
parse_args(Uint8 *d)
|
|
||||||
{
|
|
||||||
Uint8 *port_addr = d + 0x3;
|
|
||||||
int addr = PEEK2(port_addr);
|
|
||||||
char *pos = (char *)&uxn.ram[addr];
|
|
||||||
int i = 0;
|
|
||||||
do {
|
|
||||||
fork_args[i++] = pos;
|
|
||||||
while(*pos != 0) pos++;
|
|
||||||
pos++;
|
|
||||||
} while(*pos != '\0');
|
|
||||||
fork_args[i] = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* call after we're sure the process has exited */
|
|
||||||
static void
|
|
||||||
clean_after_child(void)
|
|
||||||
{
|
|
||||||
child_pid = 0;
|
|
||||||
if(child_mode >= 0x80) {
|
|
||||||
close(pty_fd);
|
|
||||||
dup2(saved_in, 0);
|
|
||||||
dup2(saved_out, 1);
|
|
||||||
} else {
|
|
||||||
if(child_mode & 0x01) {
|
|
||||||
close(to_child_fd[1]);
|
|
||||||
dup2(saved_out, 1);
|
|
||||||
}
|
|
||||||
if(child_mode & 0x06) {
|
|
||||||
close(from_child_fd[0]);
|
|
||||||
dup2(saved_in, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
child_mode = 0;
|
|
||||||
saved_in = -1;
|
|
||||||
saved_out = -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
console_input(Uint8 c, int type)
|
console_input(Uint8 c, int type)
|
||||||
{
|
{
|
||||||
|
@ -99,127 +33,11 @@ console_listen(int i, int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
start_fork_pty(Uint8 *d)
|
|
||||||
{
|
|
||||||
int fd = -1;
|
|
||||||
pid_t pid = forkpty(&fd, NULL, NULL, NULL);
|
|
||||||
if(pid < 0) { /* failure */
|
|
||||||
d[0x6] = 0xff;
|
|
||||||
fprintf(stderr, "fork failure\n");
|
|
||||||
} else if(pid == 0) { /* child */
|
|
||||||
setenv("TERM", "ansi", 1);
|
|
||||||
execvp(fork_args[0], fork_args);
|
|
||||||
d[0x6] = 0xff;
|
|
||||||
fprintf(stderr, "exec failure\n");
|
|
||||||
} else { /*parent*/
|
|
||||||
child_pid = pid;
|
|
||||||
pty_fd = fd;
|
|
||||||
ioctl(fd, TIOCSWINSZ, &ws);
|
|
||||||
saved_in = dup(0);
|
|
||||||
saved_out = dup(1);
|
|
||||||
dup2(fd, 0);
|
|
||||||
dup2(fd, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
start_fork_pipe(Uint8 *d)
|
|
||||||
{
|
|
||||||
pid_t pid;
|
|
||||||
if(child_mode & 0x01) {
|
|
||||||
/* parent writes to child's stdin */
|
|
||||||
if(pipe(to_child_fd) == -1) {
|
|
||||||
d[0x6] = 0xff;
|
|
||||||
fprintf(stderr, "pipe error: to child\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(child_mode & 0x06) {
|
|
||||||
/* parent reads from child's stdout and/or stderr */
|
|
||||||
if(pipe(from_child_fd) == -1) {
|
|
||||||
d[0x6] = 0xff;
|
|
||||||
fprintf(stderr, "pipe error: from child\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
pid = fork();
|
|
||||||
if(pid < 0) { /* failure */
|
|
||||||
d[0x6] = 0xff;
|
|
||||||
fprintf(stderr, "fork failure\n");
|
|
||||||
} else if(pid == 0) { /* child */
|
|
||||||
if(child_mode & 0x01) {
|
|
||||||
dup2(to_child_fd[0], 0);
|
|
||||||
close(to_child_fd[1]);
|
|
||||||
}
|
|
||||||
if(child_mode & 0x06) {
|
|
||||||
if(child_mode & 0x02) dup2(from_child_fd[1], 1);
|
|
||||||
if(child_mode & 0x04) dup2(from_child_fd[1], 2);
|
|
||||||
close(from_child_fd[0]);
|
|
||||||
}
|
|
||||||
execvp(fork_args[0], fork_args);
|
|
||||||
d[0x6] = 0xff;
|
|
||||||
fprintf(stderr, "exec failure\n");
|
|
||||||
} else { /*parent*/
|
|
||||||
child_pid = pid;
|
|
||||||
if(child_mode & 0x01) {
|
|
||||||
saved_out = dup(1);
|
|
||||||
dup2(to_child_fd[1], 1);
|
|
||||||
close(to_child_fd[0]);
|
|
||||||
}
|
|
||||||
if(child_mode & 0x06) {
|
|
||||||
saved_in = dup(0);
|
|
||||||
dup2(from_child_fd[0], 0);
|
|
||||||
close(from_child_fd[1]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
kill_child(Uint8 *d, int options)
|
|
||||||
{
|
|
||||||
int wstatus;
|
|
||||||
if(child_pid) {
|
|
||||||
kill(child_pid, 9);
|
|
||||||
if(waitpid(child_pid, &wstatus, options)) {
|
|
||||||
d[0x6] = 1;
|
|
||||||
d[0x7] = WEXITSTATUS(wstatus);
|
|
||||||
clean_after_child();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
start_fork(Uint8 *d)
|
|
||||||
{
|
|
||||||
fflush(stderr);
|
|
||||||
kill_child(d, 0);
|
|
||||||
child_mode = d[0x5];
|
|
||||||
parse_args(d);
|
|
||||||
if(child_mode >= 0x80)
|
|
||||||
start_fork_pty(d);
|
|
||||||
else
|
|
||||||
start_fork_pipe(d);
|
|
||||||
}
|
|
||||||
|
|
||||||
Uint8
|
|
||||||
console_dei(Uint8 addr)
|
|
||||||
{
|
|
||||||
Uint8 port = addr & 0x0f, *d = &uxn.dev[addr & 0xf0];
|
|
||||||
switch(port) {
|
|
||||||
case 0x6:
|
|
||||||
case 0x7: kill_child(d, WNOHANG);
|
|
||||||
}
|
|
||||||
return d[port];
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
console_deo(Uint8 addr)
|
console_deo(Uint8 addr)
|
||||||
{
|
{
|
||||||
FILE *fd;
|
FILE *fd;
|
||||||
switch(addr) {
|
switch(addr) {
|
||||||
case 0x15: /* Console/dead */ start_fork(&uxn.dev[0x10]); break;
|
|
||||||
case 0x16: /* Console/exit*/ kill_child(&uxn.dev[0x10], 0); break;
|
|
||||||
case 0x18: fd = stdout, fputc(uxn.dev[0x18], fd), fflush(fd); break;
|
case 0x18: fd = stdout, fputc(uxn.dev[0x18], fd), fflush(fd); break;
|
||||||
case 0x19: fd = stderr, fputc(uxn.dev[0x19], fd), fflush(fd); break;
|
case 0x19: fd = stderr, fputc(uxn.dev[0x19], fd), fflush(fd); break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,6 @@ emu_dei(Uint8 addr)
|
||||||
{
|
{
|
||||||
switch(addr & 0xf0) {
|
switch(addr & 0xf0) {
|
||||||
case 0x00: return system_dei(addr);
|
case 0x00: return system_dei(addr);
|
||||||
case 0x10: return console_dei(addr);
|
|
||||||
case 0x20: return screen_dei(addr);
|
case 0x20: return screen_dei(addr);
|
||||||
case 0xc0: return datetime_dei(addr);
|
case 0xc0: return datetime_dei(addr);
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,7 +25,6 @@ emu_dei(Uint8 addr)
|
||||||
{
|
{
|
||||||
switch(addr & 0xf0) {
|
switch(addr & 0xf0) {
|
||||||
case 0x00: return system_dei(addr);
|
case 0x00: return system_dei(addr);
|
||||||
case 0x10: return console_dei(addr);
|
|
||||||
case 0xc0: return datetime_dei(addr);
|
case 0xc0: return datetime_dei(addr);
|
||||||
}
|
}
|
||||||
return uxn.dev[addr];
|
return uxn.dev[addr];
|
||||||
|
|
Loading…
Reference in New Issue