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