shithub: lu9-lua

Download patch

ref: 69bb519a5e1b70acc9584353a6b1d896d957c969
parent: 991cff35adeae0b4753bdbacfad4bca5c9da8132
author: kvik <kvik@a-b.xyz>
date: Sun May 9 12:58:59 EDT 2021

io: implement io.popen

--- a/liolib.c
+++ b/liolib.c
@@ -54,7 +54,7 @@
 
 #if !defined(l_popen)		/* { */
 
-#if defined(LUA_USE_POSIX)	/* { */
+#if defined(LUA_USE_POSIX) || defined(LUA_USE_PLAN9)	/* { */
 
 #define l_popen(L,c,m)		(fflush(NULL), popen(c,m))
 #define l_pclose(L,file)	(pclose(file))
--- a/shim.c
+++ b/shim.c
@@ -34,3 +34,94 @@
 	}
 	exits(status);
 }
+
+#define MAXFORKS	30
+#define NSYSFILE	3
+#define	tst(a, b)	(*mode == 'r' ? (b) : (a))
+#define	RDR	0
+#define	WTR	1
+
+struct a_fork {
+	char done;
+	int	fd;
+	int	pid;
+	char status[255+1];
+};
+static struct a_fork the_fork[MAXFORKS];
+
+FILE*
+popen(char *cmd, char *mode)
+{
+	int p[2];
+	int us, them, pid;
+	int i, ind;
+
+	for(ind = 0; ind < MAXFORKS; ind++)
+		if(the_fork[ind].pid == 0)
+			break;
+	if(ind == MAXFORKS)
+		return NULL;
+	if(pipe(p) == -1)
+		return NULL;
+	us = tst(p[WTR], p[RDR]);
+	them = tst(p[RDR], p[WTR]);
+	switch(pid = fork()){
+	case -1:
+		return NULL;
+	case 0:
+		/* us and them reverse roles in child */
+		close(us);
+		dup(them, tst(0, 1));
+		for(i = NSYSFILE; i < FOPEN_MAX; i++)
+			close(i);
+		execl("/bin/rc", "rc", "-c", cmd, NULL);
+		rfork(RFNAMEG);
+		bind("/bin/ape", "/bin", MBEFORE);
+		execl("/bin/rc", "rc", "-c", cmd, NULL);
+		exits("exec failed");
+	default:
+		the_fork[ind].pid = pid;
+		the_fork[ind].fd = us;
+		the_fork[ind].done = 0;
+		close(them);
+		return fdopen(us, mode);
+	}
+	return NULL;
+}
+
+int
+pclose(FILE *file)
+{
+	int f, r, ind;
+	Waitmsg *status;
+
+	f = fileno(file);
+	fclose(file);
+	for(ind = 0; ind < MAXFORKS; ind++)
+		if(the_fork[ind].fd == f && the_fork[ind].pid != 0)
+			break;
+	if(ind == MAXFORKS)
+		return 0;
+	if(!the_fork[ind].done){
+		do{
+			if((status = wait()) == nil)
+				r = -1;
+			else
+				r = status->pid;
+			for(f = 0; f < MAXFORKS; f++){
+				if(r == the_fork[f].pid){
+					the_fork[f].done = 1;
+					strncpy(the_fork[f].status, status->msg, sizeof(the_fork[f].status));
+					break;
+				}
+			}
+			free(status);
+		} while(r != the_fork[ind].pid && r != -1);
+		if(r == -1)
+			strcpy(the_fork[ind].status, "No loved ones to wait for");
+	}
+	the_fork[ind].pid = 0;
+	if(the_fork[ind].status[0] != '\0')
+		return 1;
+	return 0;
+}
--- a/shim/shim.h
+++ b/shim/shim.h
@@ -98,6 +98,8 @@
 
 /** stdio.h **/
 #include "/sys/include/stdio.h"
+FILE *popen(char*, char*);
+int pclose(FILE*);
 
 /** stdlib.h **/
 #define EXIT_SUCCESS 0