code: purgatorio

ref: acc58dfee42368825f7595d63240fd6e88559776
dir: /appl/lib/cfgfile.b/

View raw version
implement CfgFile;

#
# Copyright © 1996-1999 Lucent Technologies Inc.  All rights reserved.
# Revisions Copyright © 2000 Vita Nuova Limited.  All rights reserved.
#

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

include "draw.m";

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

include "cfgfile.m";

# Detect/Copy/Create
verify(default: string, path: string): ref Sys->FD
{
	if(sys == nil)
		sys = load Sys Sys->PATH;

	fd := sys->open(path, Sys->ORDWR);
	if(fd == nil) {
		fd = sys->create(path, Sys->ORDWR, 8r666);
		if(fd == nil)
			return nil;
		# copy default configuration file (if present)
		ifd := sys->open(default, Sys->OREAD);
		if(ifd != nil){
			buf := array[Sys->ATOMICIO] of byte;
			while((n := sys->read(ifd, buf, len buf)) > 0)
				if(sys->write(fd, buf, n) != n)
					return nil;
			ifd = nil;
		}
	}
	return fd;
}

init(file: string): ref ConfigFile
{
	sys = load Sys Sys->PATH;
	bufio = load Bufio Bufio->PATH;

	if(sys == nil || bufio == nil)
		return nil;

	me := ref ConfigFile;
	me.file = file;
	me.readonly = 0;
	f := bufio->open(file, Sys->ORDWR);
	if(f == nil) {
		f = bufio->open(file, Sys->OREAD);
		if (f == nil)
			return nil;
		me.readonly = 1;
	}

	while((l := f.gett("\r\n")) != nil) {
		if(l[(len l)-1] == '\n')
			l = l[0:(len l)-1];
		me.lines = l :: me.lines;
	}

	return me;
}

ConfigFile.flush(me: self ref ConfigFile): string
{
	if(me.readonly)
		return "file is read only";
	if((fd := sys->create(me.file,Sys->OWRITE,0644)) == nil)
		return sys->sprint("%r");
	if((f := bufio->fopen(fd,Sys->OWRITE)) == nil)
		return sys->sprint("%r");

	l := me.lines;
	while(l != nil) {
		f.puts(hd l+"\n");
		l = tl l;
	}
	if(f.flush() == -1)
		return sys->sprint("%r");

	return nil;
}

ConfigFile.getcfg(me:self ref ConfigFile, field:string): list of string
{
	l := me.lines;

	while(l != nil) {
		(n,fields) := sys->tokenize(hd l," \t");
		if(n >= 1 && field == hd fields)
			return tl fields;
		l = tl l;
	}
	return nil;
}

ConfigFile.setcfg(me:self ref ConfigFile, field:string, val:string)
{
	l := me.lines;
	newlist: list of string;

	if(me.readonly)
		return; # should return "file is read only";

	matched := 0;

	while(l != nil) {
		(n,fields) := sys->tokenize(hd l," \t");
		if(!matched && n >= 1 && field == hd fields) {
			newlist = field+"\t"+val::newlist;
			matched = 1;
		}
		else
			newlist = hd l::newlist;
		l = tl l;
	}
	if(!matched)
		newlist = field+"\t"+val::newlist;

	me.lines = newlist;
}

ConfigFile.delete(me:self ref ConfigFile, field:string)
{
	l := me.lines;
	newlist: list of string;

	if(me.readonly)
		return; # should return "file is read only";

	matched := 0;

	while(l != nil) {
		(n,fields) := sys->tokenize(hd l," \t");
		if(!matched && n >= 1 && field == hd fields) {
			matched = 1;
		}
		else
			newlist = hd l::newlist;
		l = tl l;
	}

	me.lines = newlist;
}