code: plan9front

Download patch

ref: b34fc2a9cfdfec3abe8d1e1831a0ebf9dc50ff07
parent: 3ec59c7b70c227846166bd1783a2859994ff9d21
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Mon Jan 3 13:47:56 EST 2022

ape: allow exporting rc functions in environ[]

--- a/sys/src/ape/lib/ap/plan9/_envsetup.c
+++ b/sys/src/ape/lib/ap/plan9/_envsetup.c
@@ -45,7 +45,7 @@
 	nohandle = 0;
 	fdinited = 0;
 	cnt = 0;
-	dfd = _OPEN("/env", OREAD);
+	dfd = _OPEN("/env", OREAD|OCEXEC);
 	if(dfd < 0)
 		goto done;
 	psize = Envhunk;
@@ -62,21 +62,36 @@
 			ps = realloc(ps, psize);
 			p = ps + i;
 		}
-		strcpy(p, "/env/");
+		memcpy(p, "/env/", 5);
 		memcpy(p+5, d9->name, n+1);
-		f = _OPEN(p, OREAD);
-		memset(p, 0, n+6);
+		f = _OPEN(p, OREAD|OCEXEC);
+		if(f < 0)
+			continue;
+		if(n > 3 && memcmp(d9->name, "fn#", 3)==0){
+			if(m > 3
+			&& _READ(f, p+3, m) == m
+			&& memcmp(p+3, "fn ", 3) == 0
+			&& memcmp(p+3+3, d9->name+3, n-3) == 0
+			&& memchr(p+3+n, '{', m-n) != 0){
+				memcpy(p, "#()", 3);
+				p[3+m] = '\0';
+				p += m+4;
+				cnt++;
+			}
+			_CLOSE(f);
+			continue;
+		}
 		memcpy(p, d9->name, n);
 		p[n] = '=';
-		if(f < 0 || _READ(f, p+n+1, m) != m)
+		if(_READ(f, p+n+1, m) != m)
 			m = 0;
 		_CLOSE(f);
-		if(p[n+m] == 0)
+		if(p[n+m]=='\0')
 			m--;
 		for(i=0; i<m; i++)
-			if(p[n+1+i] == 0)
-				p[n+1+i] = 1;
-		p[n+1+m] = 0;
+			if(p[n+1+i]=='\0')
+				p[n+1+i] = '\1';
+		p[n+1+m] = '\0';
 		if(strcmp(d9->name, "_fdinfo") == 0) {
 			_fdinit(p+n+1, p+n+1+m);
 			fdinited = 1;
--- a/sys/src/ape/lib/ap/plan9/execve.c
+++ b/sys/src/ape/lib/ap/plan9/execve.c
@@ -23,7 +23,7 @@
 	 * in $_fdinfo (for open fd's)
 	 */
 
-	f = _CREATE("/env/_fdinfo", OWRITE, 0666);
+	f = _CREATE("/env/_fdinfo", OWRITE|OCEXEC, 0666);
 	ss = buf;
 	for(i = 0; i<OPEN_MAX; i++){
 		if(i == f)
@@ -65,7 +65,7 @@
 	 * are ignored, in case the current value of the
 	 * variable ignored some.
 	 */
-	f = _CREATE("/env/_sighdlr", OWRITE, 0666);
+	f = _CREATE("/env/_sighdlr", OWRITE|OCEXEC, 0666);
 	if(f >= 0){
 		ss = buf;
 		for(i = 0; i <=MAXSIG; i++) {
@@ -86,32 +86,49 @@
 	}
 	if(envp){
 		for(e = (char**)envp; (ss = *e); e++) {
-			se = strchr(ss, '=');
-			if(!se || ss==se)
-				continue;	/* what is name? value? */
-			n = se-ss;
-			if(n >= sizeof(buf)-5)
-				continue;	/* name too long */
-			strcpy(buf, "/env/");
-			memcpy(buf+5, ss, n);
-			buf[5+n] = 0;
-			f = _CREATE(buf, OWRITE, 0666);
-			if(f < 0)
-				continue;
-			ss = ++se;	/* past = */
-			se += strlen(ss);
-			while((n = (se - ss)) > 0){
-				if(n > sizeof(buf))
-					n = sizeof(buf);
-				/* decode nulls (see _envsetup()) */
-				for(i=0; i<n; i++)
-					if((buf[i] = ss[i]) == 1)
-						buf[i] = 0;
-				if(_WRITE(f, buf, n) != n)
-					break;
-				ss += n;
+			if(strncmp(ss, "#()fn ", 6)==0){
+				if((se = strchr(ss+6, '{'))==0)
+					continue;
+				while(se[-1]==' ') se--;
+				n = se-(ss+6);
+				if(n <= 0 || n >= sizeof(buf)-8)
+					continue;	/* name too long */
+				memcpy(buf, "/env/fn#", 8);
+				memcpy(buf+8, ss+6, n);
+				buf[8+n] = '\0';
+				f = _CREATE(buf, OWRITE|OCEXEC, 0666);
+				if(f < 0)
+					continue;
+				ss += 3;	/* past #() */
+				_WRITE(f, ss, strlen(ss));
+				_CLOSE(f);
+			} else {
+				if((se = strchr(ss, '='))==0)
+					continue;
+				n = se-ss;
+				if(n <= 0 || n >= sizeof(buf)-5)
+					continue;	/* name too long */
+				memcpy(buf, "/env/", 5);
+				memcpy(buf+5, ss, n);
+				buf[5+n] = '\0';
+				f = _CREATE(buf, OWRITE|OCEXEC, 0666);
+				if(f < 0)
+					continue;
+				ss = ++se;	/* past = */
+				se += strlen(se);
+				while((n = (se - ss)) > 0){
+					if(n > sizeof(buf))
+						n = sizeof(buf);
+					/* decode nulls (see _envsetup()) */
+					for(i=0; i<n; i++)
+						if((buf[i] = ss[i]) == 1)
+							buf[i] = 0;
+					if(_WRITE(f, buf, n) != n)
+						break;
+					ss += n;
+				}
+				_CLOSE(f);
 			}
-			_CLOSE(f);
 		}
 	}
 	n = _EXEC(name, argv);