more complete make example

This commit is contained in:
~d6 2023-12-01 20:29:21 -05:00
parent d11768a256
commit 8360ee899b
3 changed files with 46 additions and 36 deletions

View File

@ -32,6 +32,8 @@ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE.
*/
#define CONSOLE_DEBUG 0
static UxnSubprocess children[CONSOLE_MAX_CHILDREN];
static char *fork_args[4] = {"/bin/sh", "-c", "", NULL};
static int to_child_fd[2], from_child_fd[2];
@ -41,7 +43,6 @@ static UxnSubprocess*
find_child_by_pid(pid_t pid)
{
for(int n = 0; n < CONSOLE_MAX_CHILDREN; n++) {
//fprintf(stderr, "child %d has pid %d [%d] (looking for %d)\n", n, children[n].pid, children[n].running, pid);
if(children[n].pid == pid)
return &children[n];
}
@ -60,11 +61,11 @@ handle_sigchld(int sig)
pid_t pid;
int n, wstatus;
while((pid = waitpid(-1, &wstatus, WNOHANG)) > 0) {
//fprintf(stderr, "waitpid got something: %d\n", pid);
UxnSubprocess *child = find_child_by_pid(pid);
if (child != NULL) {
fprintf(stderr, "handle_sigchld: child %d (%d)\n", child->id, pid);
child->running = WEXITSTATUS(wstatus) - 256;
if(CONSOLE_DEBUG)
fprintf(stderr, "handle_sigchld: %d -> child %d (%d) -> %d\n", sig, child->id, pid, child->running);
if(child_ptys(child->mode))
close(child->pty);
else {
@ -76,7 +77,8 @@ handle_sigchld(int sig)
return;
}
}
fprintf(stderr, "handle_sigchld: no child found", sig);
if(CONSOLE_DEBUG)
fprintf(stderr, "handle_sigchld: no child found", sig);
}
static void
@ -145,7 +147,8 @@ start_fork_pipe(UxnSubprocess *child, int mode)
child->fd_out = child_writes(mode) ? from_child_fd[0] : -1;
child->pty = -1;
} while (child->pid != pid);
fprintf(stderr, "child has pid %d\n", child->pid);
if(CONSOLE_DEBUG)
fprintf(stderr, "child has pid %d\n", child->pid);
if(child_reads(mode)) close(to_child_fd[0]);
if(child_writes(mode)) close(from_child_fd[1]);
}
@ -176,9 +179,11 @@ host_execute(Uxn *u, Uint8 *d)
UxnSubprocess *child = &children[opts & 0x3];
fork_args[2] = cmd;
fprintf(stderr, "running execute: %s (#%02x)\n", cmd, opts);
if(CONSOLE_DEBUG)
fprintf(stderr, "running execute: %s (#%02x)\n", cmd, opts);
if(child->pid) {
fprintf(stderr, " killing previous child: %d\n", child->pid);
if(CONSOLE_DEBUG)
fprintf(stderr, " killing previous child: %d\n", child->pid);
kill(child->pid, 9);
}
@ -272,9 +277,12 @@ UxnSubprocess
void
console_monitor(Uxn *u)
{
fflush(stdout);
for(int n = 0; n < CONSOLE_MAX_CHILDREN; n++) {
UxnSubprocess *child = &children[n];
if(child->running < 0) {
/* printf("child ready for clean up: %d\n", n); */
/* fflush(stdout); */
Uint8 status = child->running + 256;
child->running = 0;
console_input(u, status, CONSOLE_CHILD_EXIT | n);
@ -304,8 +312,6 @@ console_listen(Uxn *u, int i, int argc, char **argv)
Uint8
console_dei(Uxn *u, Uint8 addr)
{
/* for(int n = 0; n < 3; n++) */
/* fprintf(stderr, "child %d has pid %d (%d)\n", n, children[n].pid, children[n].running); */
Uint8 port = addr & 0x0f, *d = &u->dev[addr & 0xf0];
return d[port];
}
@ -313,8 +319,6 @@ console_dei(Uxn *u, Uint8 addr)
void
console_deo(Uxn *u, Uint8 *d, Uint8 port)
{
/* for(int n = 0; n < 3; n++) */
/* fprintf(stderr, "child %d has pid %d (%d)\n", n, children[n].pid, children[n].running); */
switch(port) {
case 0x8: std_put(d[port], stdout); break;
case 0x9: std_put(d[port], stderr); break;

View File

@ -64,11 +64,11 @@ init_rfds(fd_set *rfds)
FD_ZERO(rfds);
FD_SET(0, rfds);
nfds = 1;
/* for(i = 0; i < 4; i++) { */
/* int fd = get_child(i)->fd_out; */
/* FD_SET(fd, rfds); */
/* if (fd >= nfds) nfds = fd + 1; */
/* } */
for(i = 0; i < 4; i++) {
int fd = get_child(i)->fd_out;
FD_SET(fd, rfds);
if (fd >= nfds) nfds = fd + 1;
}
return nfds;
}
@ -84,14 +84,14 @@ emu_run(Uxn *u)
tv.tv_sec = 0;
tv.tv_usec = 1000;
int retval = select(nfds, &rfds, NULL, NULL, &tv);
if(retval <= 0)
continue;
if (FD_ISSET(0, &rfds))
handle_input(u, 0, CONSOLE_STDIN, CONSOLE_STDIN_END);
for(i = 0; i < 4; i++) {
int fd = get_child(i)->fd_out;
if (fd > 2 && FD_ISSET(fd, &rfds))
handle_input(u, fd, CONSOLE_CHILD_DATA | i, CONSOLE_CHILD_END | i);
if(retval > 0) {
if (FD_ISSET(0, &rfds))
handle_input(u, 0, CONSOLE_STDIN, CONSOLE_STDIN_END);
for(i = 0; i < 4; i++) {
int fd = get_child(i)->fd_out;
if (fd > 2 && FD_ISSET(fd, &rfds))
handle_input(u, fd, CONSOLE_CHILD_DATA | i, CONSOLE_CHILD_END | i);
}
}
console_monitor(u);
}

View File

@ -1,33 +1,39 @@
|00 @System [
&vector $2 &expansion $2 &title $2 &metadata $2
&red $2 &green $2 &blue $2 &debug $1 &exit $1 ]
|10 @Console [
&vector $2 &stdin $1 &pad1 $1 &proc-get $1 &host-get $1 &pad2 $1 &type $1
&stdout $1 &stderr $1 &proc-put $1 &pad3 $1 &param $2 &opts $1 &host-put $1
]
&stdout $1 &stderr $1 &proc-put $1 &pad3 $1 &param $2 &opts $1 &host-put $1 ]
|0100 ( -- BRK )
;on-console .Console/vector DEO2 ( ; set up console vector callback )
BRK ( ; do other initialization )
@on-console ( -- BRK )
LIT "? .Console/stdout DEO
.Console/type DEI #81 EQU ?on-exit ( ; 0x41 signals child 1's exit )
.Console/type DEI #01 EQU ?on-stdin ( ; handle stdin )
BRK ( ; handle other console input )
@on-stdin
.Console/stdin DEI #0a NEQ
?{ run-make } BRK
@on-exit ( -- BRK )
.Console/host-get DEI ( ; read child 1's exit code )
?{ display-success-msg BRK } ( ; zero exit code means success )
display-failure-msg BRK ( ; non-zero exit code means failure )
@run-make ( -- )
;make-cmd .Console/param DEO2 ( ; set up make to run )
#01 .Console/opts DEO ( ; use child without pipelines )
#01 .Console/host-put DEO JMP2r ( ; run the command now and return )
@on-stdin
.Console/stdin DEI DUP #0a NEQ ?parse ( c^ ; parse input char if not newline )
POP LIT [ &q $1 ] ?exit ( ; exit if last char was 'q' )
;make-cmd .Console/param DEO2 ( ; set up make to run )
#01 .Console/opts DEO ( ; use child 1 without pipelines )
#01 .Console/host-put DEO BRK ( ; run the command now and return )
@make-cmd "pwd 00 ( ; buffer containing cmd to run )
@parse ( c^ -> BRK )
LIT "q EQU ,on-stdin/q STR BRK
@exit ( -> BRK )
#80 .System/exit DEO BRK
@make-cmd "make 00 ( ; buffer containing cmd to run )
@display-success-msg
LIT ". .Console/stdout DEO