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

This commit is contained in:
cinap_lenrek 2020-02-02 20:31:48 +01:00
parent 023d957e6b
commit be8cbcc852
2 changed files with 44 additions and 30 deletions

View file

@ -18,7 +18,7 @@ listen, listen1, tcp7, tcp9, tcp19, tcp21, tcp23, tcp25, tcp53, tcp110, tcp113,
.PP
.B aux/listen1
[
.B -tv
.B -1tv
]
.RB [ -p
.IR maxprocs ]
@ -237,7 +237,7 @@ modeled from Inferno's
.\" 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
@ -255,6 +255,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.
See

View file

@ -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 @@ main(int argc, char **argv)
ARGBEGIN{
default:
usage();
case '1':
oneshot = 1;
break;
case 't':
trusted = 1;
break;
@ -122,41 +126,47 @@ main(int argc, char **argv)
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");
}
}