commit b3f207b

Devine Lu Linvega  ·  2024-07-15 18:47:24 +0000 UTC
parent 6b33519
Moved unix specific console tools in etc
5 files changed,  +247, -185
+226, -0
  1@@ -0,0 +1,226 @@
  2+#undef _POSIX_C_SOURCE
  3+#define _POSIX_C_SOURCE 200112L
  4+
  5+#include <signal.h>
  6+#include <stdio.h>
  7+#include <stdlib.h>
  8+#include <sys/select.h>
  9+#include <sys/wait.h>
 10+#include <unistd.h>
 11+
 12+#ifdef __linux
 13+#include <pty.h>
 14+#endif
 15+
 16+#ifdef __NetBSD__
 17+#include <sys/ioctl.h>
 18+#include <util.h>
 19+#endif
 20+
 21+#include "../uxn.h"
 22+#include "console.h"
 23+
 24+/*
 25+Copyright (c) 2022-2023 Devine Lu Linvega, Andrew Alderwick
 26+
 27+Permission to use, copy, modify, and distribute this software for any
 28+purpose with or without fee is hereby granted, provided that the above
 29+copyright notice and this permission notice appear in all copies.
 30+
 31+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 32+WITH REGARD TO THIS SOFTWARE.
 33+*/
 34+
 35+/* process */
 36+static char *fork_args[32];
 37+static int child_mode;
 38+static int pty_fd;
 39+static int to_child_fd[2];
 40+static int from_child_fd[2];
 41+static int saved_in;
 42+static int saved_out;
 43+static pid_t child_pid;
 44+struct winsize ws = {24, 80, 8, 12};
 45+
 46+static void
 47+parse_args(Uint8 *d)
 48+{
 49+	Uint8 *port_addr = d + 0x3;
 50+	int addr = PEEK2(port_addr);
 51+	char *pos = (char *)&uxn.ram[addr];
 52+	int i = 0;
 53+	do {
 54+		fork_args[i++] = pos;
 55+		while(*pos != 0) pos++;
 56+		pos++;
 57+	} while(*pos != '\0');
 58+	fork_args[i] = NULL;
 59+}
 60+
 61+/* call after we're sure the process has exited */
 62+static void
 63+clean_after_child(void)
 64+{
 65+	child_pid = 0;
 66+	if(child_mode >= 0x80) {
 67+		close(pty_fd);
 68+		dup2(saved_in, 0);
 69+		dup2(saved_out, 1);
 70+	} else {
 71+		if(child_mode & 0x01) {
 72+			close(to_child_fd[1]);
 73+			dup2(saved_out, 1);
 74+		}
 75+		if(child_mode & 0x06) {
 76+			close(from_child_fd[0]);
 77+			dup2(saved_in, 0);
 78+		}
 79+	}
 80+	child_mode = 0;
 81+	saved_in = -1;
 82+	saved_out = -1;
 83+}
 84+
 85+int
 86+console_input(Uint8 c, int type)
 87+{
 88+	uxn.dev[0x12] = c;
 89+	uxn.dev[0x17] = type;
 90+	return uxn_eval(PEEK2(&uxn.dev[0x10]));
 91+}
 92+
 93+void
 94+console_listen(int i, int argc, char **argv)
 95+{
 96+	for(; i < argc; i++) {
 97+		char *p = argv[i];
 98+		while(*p) console_input(*p++, CONSOLE_ARG);
 99+		console_input('\n', i == argc - 1 ? CONSOLE_END : CONSOLE_EOA);
100+	}
101+}
102+
103+static void
104+start_fork_pty(Uint8 *d)
105+{
106+	int fd = -1;
107+	pid_t pid = forkpty(&fd, NULL, NULL, NULL);
108+	if(pid < 0) { /* failure */
109+		d[0x6] = 0xff;
110+		fprintf(stderr, "fork failure\n");
111+	} else if(pid == 0) { /* child */
112+		setenv("TERM", "ansi", 1);
113+		execvp(fork_args[0], fork_args);
114+		d[0x6] = 0xff;
115+		fprintf(stderr, "exec failure\n");
116+	} else { /*parent*/
117+		child_pid = pid;
118+		pty_fd = fd;
119+		ioctl(fd, TIOCSWINSZ, &ws);
120+		saved_in = dup(0);
121+		saved_out = dup(1);
122+		dup2(fd, 0);
123+		dup2(fd, 1);
124+	}
125+}
126+
127+static void
128+start_fork_pipe(Uint8 *d)
129+{
130+	pid_t pid;
131+	if(child_mode & 0x01) {
132+		/* parent writes to child's stdin */
133+		if(pipe(to_child_fd) == -1) {
134+			d[0x6] = 0xff;
135+			fprintf(stderr, "pipe error: to child\n");
136+			return;
137+		}
138+	}
139+	if(child_mode & 0x06) {
140+		/* parent reads from child's stdout and/or stderr */
141+		if(pipe(from_child_fd) == -1) {
142+			d[0x6] = 0xff;
143+			fprintf(stderr, "pipe error: from child\n");
144+			return;
145+		}
146+	}
147+	pid = fork();
148+	if(pid < 0) { /* failure */
149+		d[0x6] = 0xff;
150+		fprintf(stderr, "fork failure\n");
151+	} else if(pid == 0) { /* child */
152+		if(child_mode & 0x01) {
153+			dup2(to_child_fd[0], 0);
154+			close(to_child_fd[1]);
155+		}
156+		if(child_mode & 0x06) {
157+			if(child_mode & 0x02) dup2(from_child_fd[1], 1);
158+			if(child_mode & 0x04) dup2(from_child_fd[1], 2);
159+			close(from_child_fd[0]);
160+		}
161+		execvp(fork_args[0], fork_args);
162+		d[0x6] = 0xff;
163+		fprintf(stderr, "exec failure\n");
164+	} else { /*parent*/
165+		child_pid = pid;
166+		if(child_mode & 0x01) {
167+			saved_out = dup(1);
168+			dup2(to_child_fd[1], 1);
169+			close(to_child_fd[0]);
170+		}
171+		if(child_mode & 0x06) {
172+			saved_in = dup(0);
173+			dup2(from_child_fd[0], 0);
174+			close(from_child_fd[1]);
175+		}
176+	}
177+}
178+
179+static void
180+kill_child(Uint8 *d, int options)
181+{
182+	int wstatus;
183+	if(child_pid) {
184+		kill(child_pid, 9);
185+		if(waitpid(child_pid, &wstatus, options)) {
186+			d[0x6] = 1;
187+			d[0x7] = WEXITSTATUS(wstatus);
188+			clean_after_child();
189+		}
190+	}
191+}
192+
193+static void
194+start_fork(Uint8 *d)
195+{
196+	fflush(stderr);
197+	kill_child(d, 0);
198+	child_mode = d[0x5];
199+	parse_args(d);
200+	if(child_mode >= 0x80)
201+		start_fork_pty(d);
202+	else
203+		start_fork_pipe(d);
204+}
205+
206+Uint8
207+console_dei(Uint8 addr)
208+{
209+	Uint8 port = addr & 0x0f, *d = &uxn.dev[addr & 0xf0];
210+	switch(port) {
211+	case 0x6:
212+	case 0x7: kill_child(d, WNOHANG);
213+	}
214+	return d[port];
215+}
216+
217+void
218+console_deo(Uint8 addr)
219+{
220+	FILE *fd;
221+	switch(addr) {
222+	case 0x15: /* Console/dead */ start_fork(&uxn.dev[0x10]); break;
223+	case 0x16: /* Console/exit*/ kill_child(&uxn.dev[0x10], 0); break;
224+	case 0x18: fd = stdout, fputc(uxn.dev[0x18], fd), fflush(fd); break;
225+	case 0x19: fd = stderr, fputc(uxn.dev[0x19], fd), fflush(fd); break;
226+	}
227+}
+20, -0
 1@@ -0,0 +1,20 @@
 2+/*
 3+Copyright (c) 2021 Devine Lu Linvega, Andrew Alderwick
 4+
 5+Permission to use, copy, modify, and distribute this software for any
 6+purpose with or without fee is hereby granted, provided that the above
 7+copyright notice and this permission notice appear in all copies.
 8+
 9+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10+WITH REGARD TO THIS SOFTWARE.
11+*/
12+
13+#define CONSOLE_STD 0x1
14+#define CONSOLE_ARG 0x2
15+#define CONSOLE_EOA 0x3
16+#define CONSOLE_END 0x4
17+
18+int console_input(Uint8 c, int type);
19+void console_listen(int i, int argc, char **argv);
20+Uint8 console_dei(Uint8 addr);
21+void console_deo(Uint8 addr);
+1, -183
  1@@ -1,27 +1,11 @@
  2-#undef _POSIX_C_SOURCE
  3-#define _POSIX_C_SOURCE 200112L
  4-
  5-#include <signal.h>
  6 #include <stdio.h>
  7 #include <stdlib.h>
  8-#include <sys/select.h>
  9-#include <sys/wait.h>
 10-#include <unistd.h>
 11-
 12-#ifdef __linux
 13-#include <pty.h>
 14-#endif
 15-
 16-#ifdef __NetBSD__
 17-#include <sys/ioctl.h>
 18-#include <util.h>
 19-#endif
 20 
 21 #include "../uxn.h"
 22 #include "console.h"
 23 
 24 /*
 25-Copyright (c) 2022-2023 Devine Lu Linvega, Andrew Alderwick
 26+Copyright (c) 2022-2024 Devine Lu Linvega, Andrew Alderwick
 27 
 28 Permission to use, copy, modify, and distribute this software for any
 29 purpose with or without fee is hereby granted, provided that the above
 30@@ -31,56 +15,6 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
 31 WITH REGARD TO THIS SOFTWARE.
 32 */
 33 
 34-/* process */
 35-static char *fork_args[32];
 36-static int child_mode;
 37-static int pty_fd;
 38-static int to_child_fd[2];
 39-static int from_child_fd[2];
 40-static int saved_in;
 41-static int saved_out;
 42-static pid_t child_pid;
 43-struct winsize ws = {24, 80, 8, 12};
 44-
 45-static void
 46-parse_args(Uint8 *d)
 47-{
 48-	Uint8 *port_addr = d + 0x3;
 49-	int addr = PEEK2(port_addr);
 50-	char *pos = (char *)&uxn.ram[addr];
 51-	int i = 0;
 52-	do {
 53-		fork_args[i++] = pos;
 54-		while(*pos != 0) pos++;
 55-		pos++;
 56-	} while(*pos != '\0');
 57-	fork_args[i] = NULL;
 58-}
 59-
 60-/* call after we're sure the process has exited */
 61-static void
 62-clean_after_child(void)
 63-{
 64-	child_pid = 0;
 65-	if(child_mode >= 0x80) {
 66-		close(pty_fd);
 67-		dup2(saved_in, 0);
 68-		dup2(saved_out, 1);
 69-	} else {
 70-		if(child_mode & 0x01) {
 71-			close(to_child_fd[1]);
 72-			dup2(saved_out, 1);
 73-		}
 74-		if(child_mode & 0x06) {
 75-			close(from_child_fd[0]);
 76-			dup2(saved_in, 0);
 77-		}
 78-	}
 79-	child_mode = 0;
 80-	saved_in = -1;
 81-	saved_out = -1;
 82-}
 83-
 84 int
 85 console_input(Uint8 c, int type)
 86 {
 87@@ -99,127 +33,11 @@ console_listen(int i, int argc, char **argv)
 88 	}
 89 }
 90 
 91-static void
 92-start_fork_pty(Uint8 *d)
 93-{
 94-	int fd = -1;
 95-	pid_t pid = forkpty(&fd, NULL, NULL, NULL);
 96-	if(pid < 0) { /* failure */
 97-		d[0x6] = 0xff;
 98-		fprintf(stderr, "fork failure\n");
 99-	} else if(pid == 0) { /* child */
100-		setenv("TERM", "ansi", 1);
101-		execvp(fork_args[0], fork_args);
102-		d[0x6] = 0xff;
103-		fprintf(stderr, "exec failure\n");
104-	} else { /*parent*/
105-		child_pid = pid;
106-		pty_fd = fd;
107-		ioctl(fd, TIOCSWINSZ, &ws);
108-		saved_in = dup(0);
109-		saved_out = dup(1);
110-		dup2(fd, 0);
111-		dup2(fd, 1);
112-	}
113-}
114-
115-static void
116-start_fork_pipe(Uint8 *d)
117-{
118-	pid_t pid;
119-	if(child_mode & 0x01) {
120-		/* parent writes to child's stdin */
121-		if(pipe(to_child_fd) == -1) {
122-			d[0x6] = 0xff;
123-			fprintf(stderr, "pipe error: to child\n");
124-			return;
125-		}
126-	}
127-	if(child_mode & 0x06) {
128-		/* parent reads from child's stdout and/or stderr */
129-		if(pipe(from_child_fd) == -1) {
130-			d[0x6] = 0xff;
131-			fprintf(stderr, "pipe error: from child\n");
132-			return;
133-		}
134-	}
135-	pid = fork();
136-	if(pid < 0) { /* failure */
137-		d[0x6] = 0xff;
138-		fprintf(stderr, "fork failure\n");
139-	} else if(pid == 0) { /* child */
140-		if(child_mode & 0x01) {
141-			dup2(to_child_fd[0], 0);
142-			close(to_child_fd[1]);
143-		}
144-		if(child_mode & 0x06) {
145-			if(child_mode & 0x02) dup2(from_child_fd[1], 1);
146-			if(child_mode & 0x04) dup2(from_child_fd[1], 2);
147-			close(from_child_fd[0]);
148-		}
149-		execvp(fork_args[0], fork_args);
150-		d[0x6] = 0xff;
151-		fprintf(stderr, "exec failure\n");
152-	} else { /*parent*/
153-		child_pid = pid;
154-		if(child_mode & 0x01) {
155-			saved_out = dup(1);
156-			dup2(to_child_fd[1], 1);
157-			close(to_child_fd[0]);
158-		}
159-		if(child_mode & 0x06) {
160-			saved_in = dup(0);
161-			dup2(from_child_fd[0], 0);
162-			close(from_child_fd[1]);
163-		}
164-	}
165-}
166-
167-static void
168-kill_child(Uint8 *d, int options)
169-{
170-	int wstatus;
171-	if(child_pid) {
172-		kill(child_pid, 9);
173-		if(waitpid(child_pid, &wstatus, options)) {
174-			d[0x6] = 1;
175-			d[0x7] = WEXITSTATUS(wstatus);
176-			clean_after_child();
177-		}
178-	}
179-}
180-
181-static void
182-start_fork(Uint8 *d)
183-{
184-	fflush(stderr);
185-	kill_child(d, 0);
186-	child_mode = d[0x5];
187-	parse_args(d);
188-	if(child_mode >= 0x80)
189-		start_fork_pty(d);
190-	else
191-		start_fork_pipe(d);
192-}
193-
194-Uint8
195-console_dei(Uint8 addr)
196-{
197-	Uint8 port = addr & 0x0f, *d = &uxn.dev[addr & 0xf0];
198-	switch(port) {
199-	case 0x6:
200-	case 0x7: kill_child(d, WNOHANG);
201-	}
202-	return d[port];
203-}
204-
205 void
206 console_deo(Uint8 addr)
207 {
208 	FILE *fd;
209 	switch(addr) {
210-	case 0x15: /* Console/dead */ start_fork(&uxn.dev[0x10]); break;
211-	case 0x16: /* Console/exit*/ kill_child(&uxn.dev[0x10], 0); break;
212 	case 0x18: fd = stdout, fputc(uxn.dev[0x18], fd), fflush(fd); break;
213 	case 0x19: fd = stderr, fputc(uxn.dev[0x19], fd), fflush(fd); break;
214 	}
+0, -1
1@@ -49,7 +49,6 @@ emu_dei(Uint8 addr)
2 {
3 	switch(addr & 0xf0) {
4 	case 0x00: return system_dei(addr);
5-	case 0x10: return console_dei(addr);
6 	case 0x20: return screen_dei(addr);
7 	case 0xc0: return datetime_dei(addr);
8 	}
+0, -1
1@@ -25,7 +25,6 @@ emu_dei(Uint8 addr)
2 {
3 	switch(addr & 0xf0) {
4 	case 0x00: return system_dei(addr);
5-	case 0x10: return console_dei(addr);
6 	case 0xc0: return datetime_dei(addr);
7 	}
8 	return uxn.dev[addr];