Plan 9 from Bell Labs’s /usr/web/sources/contrib/rog/keepalive.b

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


implement Keepalive;
include "sys.m";
	sys:	Sys;
include "draw.m";
include "arg.m";
include "styx.m";
	styx: Styx;
	Rmsg, Tmsg: import styx;

Keepalive: module {
	init:	fn(nil: ref Draw->Context, nil: list of string);
};

interval := 100;
buf := array[256] of byte;
PLACE: con "/n/placeholder";

init(nil: ref Draw->Context, argv: list of string)
{
	sys = load Sys Sys->PATH;
	styx = load Styx Styx->PATH;
	styx->init();
	arg := load Arg Arg->PATH;

	arg->init(argv);
	arg->setusage("keepalive [-t seconds] dir...");
	while((opt := arg->opt()) != 0){
		case opt {
		't' =>
			interval = int arg->earg();
			if(interval <= 0)
				sys->fprint(sys->fildes(2), "keepalive: interval too short\n");
				raise "fail:error";
		* =>
			arg->usage();
		}
	}
	argv = arg->argv();
	fds: list of ref Sys->FD;
	for(; argv != nil; argv = tl argv){
		fd := sys->open(hd argv, Sys->OREAD);
		if(fd == nil)
			sys->fprint(sys->fildes(2), "keepalive: cannot open %q: %r\n", hd argv);
		else
			fds = fd :: fds;
	}
	if(fds == nil)
		raise "fail:error";
	sys->pctl(Sys->NEWPGRP, nil);
	spawn keepalives(fds, sync := chan of int);
	<-sync;
	sys->pipe(p := array[2] of ref Sys->FD);
	spawn dummyserve(p[0], sync);
	p[0] = nil;
	<-sync;
	if(sys->mount(p[1], nil, PLACE, Sys->MAFTER, nil) == -1){
		sys->fprint(sys->fildes(2), "keepalive: cannot mount keepalive onto %s: %r\n", PLACE);
		die();
		raise "fail:error";
	}
}

dummyserve(fd: ref Sys->FD, sync: chan of int)
{
	sys->pctl(Sys->NEWNS|Sys->NEWFD, fd.fd::nil);
	fd = sys->fildes(fd.fd);
	sync <-= 1;
	while((gm := Tmsg.read(fd, 0)) != nil && tagof gm != tagof Tmsg.Readerror){
		pick m := gm {
		Version =>
			reply(fd, ref Rmsg.Version(m.tag, Sys->ATOMICIO, m.version));
		Attach =>
			reply(fd, ref Rmsg.Attach(m.tag, Sys->Qid(big 0, 0, Sys->QTDIR)));
		* =>
			reply(fd, ref Rmsg.Error(m.tag, "i'm just here to be here"));
		}
	}
	die();
}

keepalives(fds: list of ref Sys->FD, sync: chan of int)
{
	sys->pctl(Sys->NEWNS, nil);
	sys->chdir("/");
	sync1 := chan of int;
	for(; fds != nil; fds = tl fds){
		spawn keepalive(hd fds, sync1);
		<-sync1;
	}
	sync <-= 0;
}

keepalive(fd: ref Sys->FD, sync: chan of int)
{
	n: int;

	sys->pctl(Sys->NEWFD, fd.fd :: nil);
	sync <-= 0;
	fd = sys->fildes(fd.fd);
	(ok, info) := sys->fstat(fd);
	isdir := ok && (info.mode & Sys->DMDIR);
	for(;;){
		sys->sleep(interval  * 1000);
		sys->seek(fd, big 0, 0);
		# read all elements of directory in case it's a union.
		do {
			n = sys->read(fd, buf, len buf);
		} while (isdir && n > 0);
		if(n == -1)
			exit;
	}
}

reply(fd: ref Sys->FD, m: ref Rmsg)
{
	p := m.pack();
	sys->write(fd, p, len p);
}

die()
{
	sys->fprint(sys->open("#p/"+string sys->pctl(0, nil)+"/ctl", Sys->OWRITE), "killgrp");
}

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to webmaster@9p.io.