shithub: npe

Download patch

ref: 9080f94b2a14f931f9b2a74470c0e38bee194649
parent: b4fc8112b2c73cdd7dfe21b9b0172b19c5c7ea08
author: Jacob Moody <moody@posixcafe.org>
date: Wed Dec 17 20:28:31 EST 2025

libnpe: add system() wait() and kill()

--- a/include/npe/npe.h
+++ b/include/npe/npe.h
@@ -52,6 +52,12 @@
 #pragma lib "libthread.a"
 #endif
 
+typedef int pid_t;
+#define WNOHANG 0x1
+#define waitpid npe_waitpid
+int npe_waitpid(int wpid, int *status, int options);
+int kill(int pid, int sig);
 extern void (*exit)(int);
+int system(const char *);
 
 #endif
--- a/include/npe/signal.h
+++ b/include/npe/signal.h
@@ -9,6 +9,7 @@
 	/* all are treated as SIGSEGV */
 	SIGINT = 2,
 	SIGILL = 4,
+	SIGKILL = 7,
 	SIGABRT = 6,
 	SIGFPE = 8,
 	SIGSEGV = 11,
--- /dev/null
+++ b/include/npe/sys/wait.h
@@ -1,0 +1,1 @@
+#include <npe.h>
--- /dev/null
+++ b/libnpe/kill.c
@@ -1,0 +1,37 @@
+#include <npe.h>
+#include <signal.h>
+
+static
+char *killnotes[] = {
+	[SIGKILL] = "exit",
+	[SIGTERM] = "term",
+};
+
+static int
+note(int pid, char *msg, char *fmt)
+{
+	int f;
+	char pname[50];
+
+	sprintf(pname, fmt, pid);
+	f = open(pname, OWRITE);
+	if(f < 0){
+		return -1;
+	}
+	if(write(f, msg, strlen(msg)) < 0){
+		close(f);
+		return -1;
+	}
+	close(f);
+	return 0;
+}
+
+int
+kill(int pid, int sig)
+{
+	if(sig < 0 || sig > SIGTERM || killnotes[sig] == nil)
+		return -1;
+	if(pid == 0)
+		return note(getpid(), killnotes[sig], "/proc/%d/notepg");
+	return note(pid, killnotes[sig], "/proc/%d/note");
+}
--- a/libnpe/mkfile
+++ b/libnpe/mkfile
@@ -43,6 +43,7 @@
 	isatty.$O\
 	isinf.$O\
 	isnormal.$O\
+	kill.$O\
 	ldexpf.$O\
 	log1p.$O\
 	localtime.$O\
@@ -68,10 +69,12 @@
 	strerror_r.$O\
 	strftime.$O\
 	strlcpy.$O\
+	system.$O\
 	trunc.$O\
 	unlink.$O\
 	usleep.$O\
 	utime.$O\
+	wait.$O\
 
 UPDATE=\
 	mkfile\
--- /dev/null
+++ b/libnpe/system.c
@@ -1,0 +1,39 @@
+#include <npe.h>
+
+#undef waitpid
+
+int
+system(char *s)
+{
+	int status;
+	Waitmsg *w;
+	pid_t pid;
+	char cmd[30], *oty;
+
+	if(!s)
+		return 1; /* a command interpreter is available */
+	pid = fork();
+	if(pid == 0){
+		oty = getenv("cputype");
+		if(!oty)
+			return -1;
+		snprintf(cmd, sizeof cmd, "/%s/bin/rc", oty);
+		execl(cmd, "rc", "-c", s, NULL);
+		exits(nil);
+	}
+	if(pid < 0){
+		return -1;
+	}
+	for(;;){
+		w = wait();
+		if(w == nil || w->pid == pid)
+			break;
+	}
+
+	status = -1;
+	if(w != nil){
+		status = w->msg[0] != 0;
+		free(w);
+	}
+	return status;
+}
--- /dev/null
+++ b/libnpe/wait.c
@@ -1,0 +1,143 @@
+#include <npe.h>
+#include <signal.h>
+
+static struct {
+	char	*msg;	/* just check prefix */
+	int	num;
+} sigtab[] = {
+	{"interrupt",				SIGINT},
+	{"sys: trap: illegal instruction",	SIGILL},
+	{"sys: trap: reserved instruction",	SIGILL},
+	{"sys: trap: reserved",			SIGILL},
+	{"sys: trap: arithmetic overflow",	SIGFPE},
+	{"abort",				SIGABRT},
+	{"sys: fp:",				SIGFPE},
+	{"exit",				SIGKILL},
+	{"die",					SIGKILL},
+	{"kill",				SIGKILL},
+	{"sys: trap: bus error",		SIGSEGV},
+	{"sys: trap: address error",		SIGSEGV},
+	{"sys: trap: TLB",			SIGSEGV},
+	{"term",				SIGTERM},
+};
+#define NSIGTAB ((sizeof sigtab)/(sizeof (sigtab[0])))
+
+int
+_stringsig(char *nam)
+{
+	int i;
+
+	for(i = 0; i<NSIGTAB; i++)
+		if(strncmp(nam, sigtab[i].msg, strlen(sigtab[i].msg)) == 0)
+			return sigtab[i].num;
+	return 0;
+}
+
+
+/*
+ * status not yet collected for processes that have exited
+ */
+typedef struct Waited Waited;
+struct Waited {
+	Waitmsg*	msg;
+	Waited*	next;
+};
+static Waited *wd;
+
+static Waitmsg *
+lookpid(int pid)
+{
+	Waited **wl, *w;
+	Waitmsg *msg;
+
+	for(wl = &wd; (w = *wl) != nil; wl = &w->next)
+		if(pid <= 0 || w->msg->pid == pid){
+			msg = w->msg;
+			*wl = w->next;
+			free(w);
+			return msg;
+		}
+	return 0;
+}
+
+static void
+addpid(Waitmsg *msg)
+{
+	Waited *w;
+
+	w = malloc(sizeof(*w));
+	if(w == nil){
+		/* lost it; what can we do? */
+		free(msg);
+		return;
+	}
+	w->msg = msg;
+	w->next = wd;
+	wd = w;
+}
+
+static int
+waitstatus(Waitmsg *w)
+{
+	int r, t;
+	char *bp, *ep;
+
+	r = 0;
+	t = 0;
+	if(w->msg[0]){
+		/* message is 'prog pid:string' */
+		bp = w->msg;
+		while(*bp){
+			if(*bp++ == ':')
+				break;
+		}
+		if(*bp == 0)
+			bp = w->msg;
+		r = strtol(bp, &ep, 10);
+		if(*ep == 0){
+			if(r < 0 || r >= 256)
+				r = 1;
+		}else{
+			t = _stringsig(bp);
+			if(t == 0)
+				r = 1;
+		}
+	}
+	return (r<<8) | t;
+}
+
+int
+npe_waitpid(int wpid, int *status, int options)
+{
+	char pname[50];
+	Dir *d;
+	Waitmsg *w;
+
+	w = lookpid(wpid);
+	if(w == nil){
+		if(options & WNOHANG){
+			snprintf(pname, sizeof(pname), "/proc/%d/wait", getpid());
+			d = dirstat(pname);
+			if(d != nil && d->length == 0){
+				free(d);
+				return 0;
+			}
+			free(d);
+		}
+		for(;;){
+			w = wait();
+			if(w == nil){
+				return -1;
+			}
+			if(wpid <= 0 || w->pid == wpid)
+				break;
+			addpid(w);
+		}
+	}
+	if(status != nil)
+		*status = waitstatus(w);
+	wpid = w->pid;
+	free(w);
+	return wpid;
+
+}
--- a/libnpe_sdl2/_sdl.h
+++ b/libnpe_sdl2/_sdl.h
@@ -10,6 +10,7 @@
 #include <cursor.h>
 #include <plumb.h>
 #include "_npe.h"
+#undef waitpid
 
 struct npe_sdl {
 	Mousectl *mctl;
--