summaryrefslogtreecommitdiff
path: root/appl/cmd/emuinit.b
diff options
context:
space:
mode:
Diffstat (limited to 'appl/cmd/emuinit.b')
-rw-r--r--appl/cmd/emuinit.b110
1 files changed, 110 insertions, 0 deletions
diff --git a/appl/cmd/emuinit.b b/appl/cmd/emuinit.b
new file mode 100644
index 00000000..56b11521
--- /dev/null
+++ b/appl/cmd/emuinit.b
@@ -0,0 +1,110 @@
+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;
+}