code: purgatorio

ref: ec35f468e0eba87c9f09cbbe5fa8af2591e6f914
dir: /appl/cmd/fortune.b/

View raw version
#
#	initially generated by c2l
#

implement Fortune;

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

include "sys.m";
	sys: Sys;
	Dir: import sys;

include "draw.m";

include "bufio.m";
	bufio: Bufio;
	Iobuf: import bufio;

include "rand.m";
	rand: Rand;

include "keyring.m";
include "security.m";

choice: string;
findex := "/lib/games/fortunes.index";
fortunes := "/lib/games/fortunes";

init(nil: ref Draw->Context, args: list of string)
{
	sys = load Sys Sys->PATH;
	bufio = load Bufio Bufio->PATH;
	rand = load Rand Rand->PATH;

	if(args != nil)
		args = tl args;
	if(args != nil)
		filename := hd args;
	else
		filename = fortunes;
	if((f := bufio->open(filename,  Bufio->OREAD)) == nil){
		sys->fprint(sys->fildes(2), "fortune: can't open %s: %r\n", filename);
		raise "fail:open";
	}
	ix, nix: ref Sys->FD;
	length := big 0;
	if(args == nil){
		ix = sys->open(findex, Sys->OREAD);
		if(ix != nil){
			(nil, ixbuf) := sys->fstat(ix);
			(nil, fbuf) := sys->fstat(f.fd);
			if(fbuf.mtime >= ixbuf.mtime){
				ix = nil;
				nix = sys->create(findex, Sys->OWRITE, 8r666);
			}else
				length = ixbuf.length;
		}else
			nix = sys->create(findex, Sys->OWRITE, 8r666);
	}
	off := array[4] of byte;
	if(ix != nil && length != big 0){
		sys->seek(ix, ((big truerand() & ((big 1<<32)-big 1))%length) & ~big 3, 0);
		sys->read(ix, off, 4);
		f.seek(big (int off[0]|int off[1]<<8|int off[2]<<16|int off[3]<<24), 0);
		choice = f.gets('\n');
		if(choice == nil)
			choice = "Misfortune!\n";
	}else{
		rand->init(truerand());
		offs := 0;
		g := bufio->fopen(nix, Bufio->ORDWR);
		for(i := 1;; i++){
			if(nix != nil)
				offs = int f.offset();
			p := f.gets('\n');
			if(p == nil)
				break;
			if(nix != nil){
				off[0] = byte offs;
				off[1] = byte (offs>>8);
				off[2] = byte (offs>>16);
				off[3] = byte (offs>>24);
				g.write(off, 4);
			}
			if(rand->rand(i) == 0)
				choice = p;
		}
		g.flush();
	}
	sys->print("%s", choice);
}

truerand(): int
{
	random := load Random Random->PATH;
	return random->randomint(Random->ReallyRandom);
}