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];