shithub: riscv

Download patch

ref: be8cbcc8524cee8328bce97200f5d7e22abbb3da
parent: 023d957e6b80f88584fdff30a95be6330613b27a
author: cinap_lenrek <[email protected]>
date: Sun Feb 2 15:31:48 EST 2020

listen(1): implement one-shot mode flag for listen1 (thanks kivik)

--- a/sys/man/8/listen
+++ b/sys/man/8/listen
@@ -18,7 +18,7 @@
 .PP
 .B aux/listen1
 [
-.B -tv
+.B -1tv
 ]
 .RB [ -p
 .IR maxprocs ]
@@ -237,7 +237,7 @@
 .\" write out this way so automatic programs
 .\" don't try to make it into a real man page reference.
 \fIlisten\fR(1).
-announces on
+It announces on
 .IR address ,
 running
 .I cmd
@@ -254,6 +254,10 @@
 is to become
 .B none
 before listening.
+Option
+.B -1
+arms a one-shot listener; it terminates listen1
+upon receiving a single call.
 Option
 .B -v
 causes verbose logging on standard output.
--- a/sys/src/cmd/aux/listen1.c
+++ b/sys/src/cmd/aux/listen1.c
@@ -5,12 +5,13 @@
 int maxprocs;
 int verbose;
 int trusted;
+int oneshot;
 char *nsfile;
 
 void
 usage(void)
 {
-	fprint(2, "usage: listen1 [-tv] [-p maxprocs] [-n namespace] address cmd args...\n");
+	fprint(2, "usage: listen1 [-1tv] [-p maxprocs] [-n namespace] address cmd args...\n");
 	exits("usage");
 }
 
@@ -61,6 +62,9 @@
 	ARGBEGIN{
 	default:
 		usage();
+	case '1':
+		oneshot = 1;
+		break;
 	case 't':
 		trusted = 1;
 		break;
@@ -122,41 +126,47 @@
 		if(nctl < 0)
 			sysfatal("listen %s: %r", argv[0]);
 
+		if(!oneshot)
 		switch(rfork(RFFDG|RFPROC|RFMEM|RFENVG|RFNAMEG|RFNOTEG|RFREND|nowait)){
+		case 0:
+			break;
 		case -1:
 			reject(nctl, ndir, "host overloaded");
 			close(nctl);
 			continue;
-		case 0:
-			fd = accept(nctl, ndir);
-			if(fd < 0){
-				fprint(2, "accept %s: can't open  %s/data: %r\n",
-					argv[0], ndir);
-				_exits(0);
-			}
-			print("incoming call for %s from %s in %s\n", argv[0],
-				remoteaddr(ndir), ndir);
-			fprint(nctl, "keepalive");
-			close(ctl);
-			close(nctl);
-			if(wfd >= 0)
-				close(wfd);
-			putenv("net", ndir);
-			snprint(data, sizeof data, "%s/data", ndir);
-			bind(data, "/dev/cons", MREPL);
-			dup(fd, 0);
-			dup(fd, 1);
-			/* dup(fd, 2); keep stderr */
-			close(fd);
-			exec(argv[1], argv+1);
-			if(argv[1][0] != '/')
-				exec(smprint("/bin/%s", argv[1]), argv+1);
-			fprint(2, "%s: exec: %r\n", argv0);
-			exits(nil);
 		default:
 			close(nctl);
 			procs++;
-			break;
+			continue;
 		}
+
+		fd = accept(nctl, ndir);
+		if(fd < 0){
+			fprint(2, "accept %s: can't open  %s/data: %r\n", argv[0], ndir);
+			if(oneshot){
+				close(nctl);
+				continue;
+			}
+			exits("accept");
+		}
+
+		print("incoming call for %s from %s in %s\n", argv[0], remoteaddr(ndir), ndir);
+		fprint(nctl, "keepalive");
+		close(ctl);
+		close(nctl);
+		if(wfd >= 0)
+			close(wfd);
+		putenv("net", ndir);
+		snprint(data, sizeof data, "%s/data", ndir);
+		bind(data, "/dev/cons", MREPL);
+		dup(fd, 0);
+		dup(fd, 1);
+		/* dup(fd, 2); keep stderr */
+		close(fd);
+		exec(argv[1], argv+1);
+		if(argv[1][0] != '/')
+			exec(smprint("/bin/%s", argv[1]), argv+1);
+		fprint(2, "%s: exec: %r\n", argv0);
+		exits("exec");
 	}
 }