xref: /inferno-os/appl/cmd/emuinit.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1implement Emuinit;
2include "sys.m";
3	sys: Sys;
4include "draw.m";
5include "sh.m";
6include "arg.m";
7	arg: Arg;
8
9Emuinit: module
10{
11	init: fn();
12};
13
14init()
15{
16	sys = load Sys Sys->PATH;
17	sys->bind("#e", "/env", sys->MREPL|sys->MCREATE);	# if #e not configured, that's fine
18	args := getenv("emuargs");
19	arg = load Arg Arg->PATH;
20	if (arg == nil)
21		sys->fprint(sys->fildes(2), "emuinit: cannot load %s: %r\n", Arg->PATH);
22	else{
23		arg->init(args);
24		while((c := arg->opt()) != 0)
25			case c {
26			'g' or 'c' or 'C' or 'm' or 'p' or 'f' or 'r' or 'd' =>
27				arg->arg();
28	                  }
29		args = arg->argv();
30	}
31	mod: Command;
32	(mod, args) = loadmod(args);
33	mod->init(nil, args);
34}
35
36loadmod(args: list of string): (Command, list of string)
37{
38	path := Command->PATH;
39	if(args != nil)
40		path = hd args;
41	else
42		args = "-l" :: nil;	# add startup option
43
44	# try loading the module directly.
45	mod: Command;
46	if (path != nil && path[0] == '/')
47		mod = load Command path;
48	else {
49		mod = load Command "/dis/"+path;
50		if (mod == nil)
51			mod = load Command "/"+path;
52	}
53	if(mod != nil)
54		return (mod, args);
55
56	# if we can't load the module directly, try getting the shell to run it.
57	err := sys->sprint("%r");
58	mod = load Command Command->PATH;
59	if(mod == nil){
60		sys->fprint(sys->fildes(2), "emuinit: unable to load %s: %s\n", path, err);
61		raise "fail:error";
62	}
63	return (mod, "sh" :: "-c" :: "$*" :: args);
64}
65
66getenv(v: string): list of string
67{
68	fd := sys->open("#e/"+v, Sys->OREAD);
69	if (fd == nil)
70		return nil;
71	(ok, d) := sys->fstat(fd);
72	if(ok == -1)
73		return nil;
74	buf := array[int d.length] of byte;
75	n := sys->read(fd, buf, len buf);
76	if (n <= 0)
77		return nil;
78	return unquoted(string buf[0:n]);
79}
80
81unquoted(s: string): list of string
82{
83	args: list of string;
84	word: string;
85	inquote := 0;
86	for(j := len s; j > 0;){
87		c := s[j-1];
88		if(c == ' ' || c == '\t' || c == '\n'){
89			j--;
90			continue;
91		}
92		for(i := j-1; i >= 0 && ((c = s[i]) != ' ' && c != '\t' && c != '\n' || inquote); i--){	# collect word
93			if(c == '\''){
94				word = s[i+1:j] + word;
95				j = i;
96				if(!inquote || i == 0 || s[i-1] != '\'')
97					inquote = !inquote;
98				else
99					i--;
100			}
101		}
102		args = (s[i+1:j]+word) :: args;
103		word = nil;
104		j = i;
105	}
106	# if quotes were unbalanced, balance them and try again.
107	if(inquote)
108		return unquoted(s + "'");
109	return args;
110}
111