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