code: purgatorio

ref: d916a4c3823f55227ffae35738c2497256e307b5
dir: /appl/cmd/emuinit.b/

View raw version
implement Emuinit;
include "sys.m";
	sys: Sys;
include "draw.m";
include "sh.m";
include "arg.m";
	arg: Arg;

Emuinit: module
{
	init: fn();
};

init()
{
	sys = load Sys Sys->PATH;
	sys->bind("#e", "/env", sys->MREPL|sys->MCREATE);	# if #e not configured, that's fine
	args := getenv("emuargs");
	arg = load Arg Arg->PATH;
	if (arg == nil)
		sys->fprint(sys->fildes(2), "emuinit: cannot load %s: %r\n", Arg->PATH);
	else{
		arg->init(args);
		while((c := arg->opt()) != 0)
			case c {
			'g' or 'c' or 'C' or 'm' or 'p' or 'f' or 'r' or 'd' =>
				arg->arg();
	                  }
		args = arg->argv();
	}
	mod: Command;
	(mod, args) = loadmod(args);
	mod->init(nil, args);
}

loadmod(args: list of string): (Command, list of string)
{
	path := Command->PATH;
	if(args != nil)
		path = hd args;
	else
		args = "-l" :: nil;	# add startup option

	# try loading the module directly.
	mod: Command;
	if (path != nil && path[0] == '/')
		mod = load Command path;
	else {
		mod = load Command "/dis/"+path;
		if (mod == nil)
			mod = load Command "/"+path;
	}
	if(mod != nil)
		return (mod, args);

	# if we can't load the module directly, try getting the shell to run it.
	err := sys->sprint("%r");
	mod = load Command Command->PATH;
	if(mod == nil){
		sys->fprint(sys->fildes(2), "emuinit: unable to load %s: %s\n", path, err);
		raise "fail:error";
	}
	return (mod, "sh" :: "-c" :: "$*" :: args);
}

getenv(v: string): list of string
{
	fd := sys->open("#e/"+v, Sys->OREAD);
	if (fd == nil)
		return nil;
	(ok, d) := sys->fstat(fd);
	if(ok == -1)
		return nil;
	buf := array[int d.length] of byte;
	n := sys->read(fd, buf, len buf);
	if (n <= 0)
		return nil;
	return unquoted(string buf[0:n]);
}

unquoted(s: string): list of string
{
	args: list of string;
	word: string;
	inquote := 0;
	for(j := len s; j > 0;){
		c := s[j-1];
		if(c == ' ' || c == '\t' || c == '\n'){
			j--;
			continue;
		}
		for(i := j-1; i >= 0 && ((c = s[i]) != ' ' && c != '\t' && c != '\n' || inquote); i--){	# collect word
			if(c == '\''){
				word = s[i+1:j] + word;
				j = i;
				if(!inquote || i == 0 || s[i-1] != '\'')
					inquote = !inquote;
				else
					i--;
			}
		}
		args = (s[i+1:j]+word) :: args;
		word = nil;
		j = i;
	}
	# if quotes were unbalanced, balance them and try again.
	if(inquote)
		return unquoted(s + "'");
	return args;
}