code: 9ferno

Download patch

ref: d101aedac2ab53085aace1464d4f48a9d252b337
parent: caef73363f896a1405ce6b9b6435f91e47a9b188
author: 9ferno <gophone2015@gmail.com>
date: Fri Sep 3 01:34:19 EDT 2021

added trampoline

--- a/appl/cmd/mkfile
+++ b/appl/cmd/mkfile
@@ -163,6 +163,7 @@
 	touchcal.dis\
 	tokenize.dis\
 	tr.dis\
+	trampoline.dis\
 	trfs.dis\
 	tsort.dis\
 	ttffs.dis\
--- /dev/null
+++ b/appl/cmd/trampoline.b
@@ -1,0 +1,94 @@
+implement Trampoline;
+
+include "sys.m";
+	sys: Sys;
+	read, write: import sys;
+
+include "draw.m";
+
+include "dial.m";
+	dial: Dial;
+	Connection: import dial;
+
+# dial'ing an address returns an fd
+#	write everything from our stdin to that fd
+#	write everything from that fd to our stdout
+Trampoline: module
+{
+	init:	fn(nil: ref Draw->Context, nil: list of string);
+};
+
+File: adt
+{
+	fd:	ref Sys->FD;
+	name:	string;
+};
+
+usage()
+{
+	sys->fprint(sys->fildes(2), "Usage: trampoline addr\n");
+	raise "fail:usage";
+}
+
+init(nil: ref Draw->Context, args: list of string)
+{
+	sys = load Sys Sys->PATH;
+	dial = load Dial Dial->PATH;
+	if(dial == nil)
+		error(sys->sprint("can't load %s: %r", Dial->PATH));
+
+	for(as:=args; as != nil; as = tl as){
+		sys->print("arg %s\n", hd as);
+	}
+	if(len args != 2)
+		usage();
+	args = tl args;
+	addr := hd args;
+
+	sys->pctl(sys->NEWPGRP, nil);
+	connection := dial->dial(addr, nil);
+
+	chan1 := chan of int;
+	chan2 := chan of int;
+	spawn xfer(sys->fildes(0), connection.dfd, chan1);
+	pids : list of int;
+	pid := <-chan1;
+	if(pid)
+		pids = pid :: nil;
+	spawn xfer(connection.dfd, sys->fildes(1), chan2);
+	pid = <-chan2;
+	if(pid)
+		pids = pid :: pids;
+
+	alt
+	{
+		<- chan1 => ;
+		<- chan2 => ;
+	}
+	for(; pids != nil; pids = tl pids)
+		kill(hd pids);
+}
+
+xfer(rfd, wfd: ref Sys->FD, c: chan of int)
+{
+	c <-= sys->pctl(0, nil);
+	buf := array[2048] of {* => byte 0};
+	while((r := read(rfd, buf, len buf)) > 0){
+		w := write(wfd, buf, r);
+		if(w != r)
+			error(sys->sprint("xfer r %d w %d\n", r, w));
+	}
+}
+
+error(s: string)
+{
+	sys->fprint(sys->fildes(2), "tee: %s\n", s);
+	raise "fail:error";
+}
+
+kill(pid: int)
+{
+	fd := sys->open("#p/"+string pid+"/ctl", Sys->OWRITE);
+	if(fd != nil)
+		sys->fprint(fd, "kill");
+}