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