1*37da2899SCharles.Forsythimplement Install; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsyth# 4*37da2899SCharles.Forsyth# Determine which packages need installing and calls install/inst 5*37da2899SCharles.Forsyth# to actually install each one 6*37da2899SCharles.Forsyth# 7*37da2899SCharles.Forsyth 8*37da2899SCharles.Forsyth# usage: install/install -d -F -g -s -u -i installdir -p platform -r root -P package 9*37da2899SCharles.Forsyth 10*37da2899SCharles.Forsythinclude "sys.m"; 11*37da2899SCharles.Forsyth sys: Sys; 12*37da2899SCharles.Forsythinclude "draw.m"; 13*37da2899SCharles.Forsythinclude "bufio.m"; 14*37da2899SCharles.Forsyth bufio: Bufio; 15*37da2899SCharles.Forsyth Iobuf: import bufio; 16*37da2899SCharles.Forsythinclude "string.m"; 17*37da2899SCharles.Forsyth str: String; 18*37da2899SCharles.Forsythinclude "arg.m"; 19*37da2899SCharles.Forsyth arg: Arg; 20*37da2899SCharles.Forsythinclude "readdir.m"; 21*37da2899SCharles.Forsyth readdir : Readdir; 22*37da2899SCharles.Forsythinclude "sh.m"; 23*37da2899SCharles.Forsyth 24*37da2899SCharles.ForsythInstall: module 25*37da2899SCharles.Forsyth{ 26*37da2899SCharles.Forsyth init: fn(nil: ref Draw->Context, nil: list of string); 27*37da2899SCharles.Forsyth}; 28*37da2899SCharles.Forsyth 29*37da2899SCharles.Forsyth# required dirs, usually in the standard inferno root. 30*37da2899SCharles.Forsyth# The network download doesn't include them because of 31*37da2899SCharles.Forsyth# problems with versions of tar that won't create empty dirs 32*37da2899SCharles.Forsyth# so we'll make sure they exist. 33*37da2899SCharles.Forsyth 34*37da2899SCharles.Forsythreqdirs := array [] of { 35*37da2899SCharles.Forsyth "/mnt", 36*37da2899SCharles.Forsyth "/mnt/wrap", 37*37da2899SCharles.Forsyth "/n", 38*37da2899SCharles.Forsyth "/n/remote", 39*37da2899SCharles.Forsyth "/tmp", 40*37da2899SCharles.Forsyth}; 41*37da2899SCharles.Forsyth 42*37da2899SCharles.ForsythYES, NO, QUIT, ERR : con iota; 43*37da2899SCharles.ForsythINST : con "install/inst"; # actual install program 44*37da2899SCharles.ForsythMTPT : con "/n/remote"; # mount point for user's inferno root 45*37da2899SCharles.Forsyth 46*37da2899SCharles.Forsythdebug := 0; 47*37da2899SCharles.Forsythforce := 0; 48*37da2899SCharles.Forsythexitemu := 0; 49*37da2899SCharles.Forsythuflag := 0; 50*37da2899SCharles.Forsythstderr : ref Sys->FD; 51*37da2899SCharles.Forsythinstalldir := "/install"; 52*37da2899SCharles.Forsythplatform := "Plan9"; 53*37da2899SCharles.Forsythlcplatform : string; 54*37da2899SCharles.Forsythroot := "/usr/inferno"; 55*37da2899SCharles.Forsythlocal: int; 56*37da2899SCharles.Forsythglobal: int = 1; 57*37da2899SCharles.Forsythwaitfd : ref Sys->FD; 58*37da2899SCharles.Forsyth 59*37da2899SCharles.ForsythProduct : adt { 60*37da2899SCharles.Forsyth name : string; 61*37da2899SCharles.Forsyth pkgs : ref Package; 62*37da2899SCharles.Forsyth nxt : ref Product; 63*37da2899SCharles.Forsyth}; 64*37da2899SCharles.Forsyth 65*37da2899SCharles.ForsythPackage : adt { 66*37da2899SCharles.Forsyth name : string; 67*37da2899SCharles.Forsyth nxt : ref Package; 68*37da2899SCharles.Forsyth}; 69*37da2899SCharles.Forsyth 70*37da2899SCharles.Forsythinstprods : ref Product; # products/packages already installed 71*37da2899SCharles.Forsyth 72*37da2899SCharles.Forsyth# platform independent packages 73*37da2899SCharles.Forsythxpkgs := array[] of { "inferno", "utils", "src", "ipaq", "minitel", "sds" }; 74*37da2899SCharles.Forsythypkgs: list of string; 75*37da2899SCharles.Forsyth 76*37da2899SCharles.Forsythinit(nil: ref Draw->Context, args: list of string) 77*37da2899SCharles.Forsyth{ 78*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 79*37da2899SCharles.Forsyth stderr = sys->fildes(2); 80*37da2899SCharles.Forsyth 81*37da2899SCharles.Forsyth # Hack for network download... 82*37da2899SCharles.Forsyth # make sure the dirs we need exist 83*37da2899SCharles.Forsyth for (dirix := 0; dirix < len reqdirs; dirix++) { 84*37da2899SCharles.Forsyth dir := reqdirs[dirix]; 85*37da2899SCharles.Forsyth (exists, nil) := sys->stat(dir); 86*37da2899SCharles.Forsyth if (exists == -1) { 87*37da2899SCharles.Forsyth fd := sys->create(dir, Sys->OREAD, Sys->DMDIR + 8r7775); 88*37da2899SCharles.Forsyth if (fd == nil) 89*37da2899SCharles.Forsyth fatal(sys->sprint("cannot create directory %s: %r\n", dir)); 90*37da2899SCharles.Forsyth fd = nil; 91*37da2899SCharles.Forsyth } 92*37da2899SCharles.Forsyth } 93*37da2899SCharles.Forsyth 94*37da2899SCharles.Forsyth bufio = load Bufio Bufio->PATH; 95*37da2899SCharles.Forsyth if(bufio == nil) 96*37da2899SCharles.Forsyth fatal(sys->sprint("cannot load %s: %r\n", Bufio->PATH)); 97*37da2899SCharles.Forsyth readdir = load Readdir Readdir->PATH; 98*37da2899SCharles.Forsyth if(readdir == nil) 99*37da2899SCharles.Forsyth fatal(sys->sprint("cannot load %s: %r\n", Readdir->PATH)); 100*37da2899SCharles.Forsyth str = load String String->PATH; 101*37da2899SCharles.Forsyth if(str == nil) 102*37da2899SCharles.Forsyth fatal(sys->sprint("cannot load %s: %r\n", String->PATH)); 103*37da2899SCharles.Forsyth arg = load Arg Arg->PATH; 104*37da2899SCharles.Forsyth if(arg == nil) 105*37da2899SCharles.Forsyth fatal(sys->sprint("cannot load %s: %r\n", Arg->PATH)); 106*37da2899SCharles.Forsyth arg->init(args); 107*37da2899SCharles.Forsyth while((c := arg->opt()) != 0) { 108*37da2899SCharles.Forsyth case c { 109*37da2899SCharles.Forsyth 'd' => 110*37da2899SCharles.Forsyth debug = 1; 111*37da2899SCharles.Forsyth 'F' => 112*37da2899SCharles.Forsyth force = 1; 113*37da2899SCharles.Forsyth 's' => 114*37da2899SCharles.Forsyth exitemu = 1; 115*37da2899SCharles.Forsyth 'i' => 116*37da2899SCharles.Forsyth installdir = arg->arg(); 117*37da2899SCharles.Forsyth if (installdir == nil) 118*37da2899SCharles.Forsyth fatal("install directory missing"); 119*37da2899SCharles.Forsyth 'p' => 120*37da2899SCharles.Forsyth platform = arg->arg(); 121*37da2899SCharles.Forsyth if (platform == nil) 122*37da2899SCharles.Forsyth fatal("platform missing"); 123*37da2899SCharles.Forsyth 'P' => 124*37da2899SCharles.Forsyth pkg := arg->arg(); 125*37da2899SCharles.Forsyth if (pkg == nil) 126*37da2899SCharles.Forsyth fatal("package missing"); 127*37da2899SCharles.Forsyth ypkgs = pkg :: ypkgs; 128*37da2899SCharles.Forsyth 'r' => 129*37da2899SCharles.Forsyth root = arg->arg(); 130*37da2899SCharles.Forsyth if (root == nil) 131*37da2899SCharles.Forsyth fatal("inferno root missing"); 132*37da2899SCharles.Forsyth 'u' => 133*37da2899SCharles.Forsyth uflag = 1; 134*37da2899SCharles.Forsyth 'g' => 135*37da2899SCharles.Forsyth global = 0; 136*37da2899SCharles.Forsyth '*' => 137*37da2899SCharles.Forsyth usage(); 138*37da2899SCharles.Forsyth } 139*37da2899SCharles.Forsyth } 140*37da2899SCharles.Forsyth if (arg->argv() != nil) 141*37da2899SCharles.Forsyth usage(); 142*37da2899SCharles.Forsyth lcplatform = str->tolower(platform); 143*37da2899SCharles.Forsyth (ok, dir) := sys->stat(installdir); 144*37da2899SCharles.Forsyth if (ok < 0) 145*37da2899SCharles.Forsyth fatal(sys->sprint("cannot open install directory %s", installdir)); 146*37da2899SCharles.Forsyth nt := lcplatform == "nt"; 147*37da2899SCharles.Forsyth if (nt) { 148*37da2899SCharles.Forsyth # root os of the form ?:/......... 149*37da2899SCharles.Forsyth if (len root < 3 || root[1] != ':' || root[2] != '/') 150*37da2899SCharles.Forsyth fatal(sys->sprint("root %s not of the form ?:/.......", root)); 151*37da2899SCharles.Forsyth spec := root[0:2]; 152*37da2899SCharles.Forsyth root = root[2:]; 153*37da2899SCharles.Forsyth if (sys->bind("#U"+spec, MTPT, Sys->MREPL|Sys->MCREATE) < 0) 154*37da2899SCharles.Forsyth fatal(sys->sprint("cannot bind to drive %s", spec)); 155*37da2899SCharles.Forsyth } 156*37da2899SCharles.Forsyth else { 157*37da2899SCharles.Forsyth if (root[0] != '/') 158*37da2899SCharles.Forsyth fatal(sys->sprint("root %s must be an absolute path name", root)); 159*37da2899SCharles.Forsyth if (sys->bind("#U*", MTPT, Sys->MREPL|Sys->MCREATE) < 0) 160*37da2899SCharles.Forsyth fatal("cannot bind to system root"); 161*37da2899SCharles.Forsyth } 162*37da2899SCharles.Forsyth (ok, dir) = sys->stat(MTPT+root); 163*37da2899SCharles.Forsyth if (ok >= 0) { 164*37da2899SCharles.Forsyth if ((dir.mode & Sys->DMDIR) == 0) 165*37da2899SCharles.Forsyth fatal(sys->sprint("inferno root %s is not a directory", root)); 166*37da2899SCharles.Forsyth } 167*37da2899SCharles.Forsyth else if (sys->create(MTPT+root, Sys->OREAD, 8r775 | Sys->DMDIR) == nil) 168*37da2899SCharles.Forsyth fatal(sys->sprint("cannot create inferno root %s: %r", root)); 169*37da2899SCharles.Forsyth # need a writable tmp directory /tmp in case installing from CD 170*37da2899SCharles.Forsyth (ok, dir) = sys->stat(MTPT+root+"/tmp"); 171*37da2899SCharles.Forsyth if (ok >= 0) { 172*37da2899SCharles.Forsyth if ((dir.mode & Sys->DMDIR) == 0) 173*37da2899SCharles.Forsyth fatal(sys->sprint("inferno root tmp %s is not a directory", root+"/tmp")); 174*37da2899SCharles.Forsyth } 175*37da2899SCharles.Forsyth else if (sys->create(MTPT+root+"/tmp", Sys->OREAD, 8r775 | Sys->DMDIR) == nil) 176*37da2899SCharles.Forsyth fatal(sys->sprint("cannot create inferno root tmp %s: %r", root+"/tmp")); 177*37da2899SCharles.Forsyth if (sys->bind(MTPT+root, MTPT, Sys->MREPL | Sys->MCREATE) < 0) 178*37da2899SCharles.Forsyth fatal("cannot bind inferno root"); 179*37da2899SCharles.Forsyth if (sys->bind(MTPT+"/tmp", "/tmp", Sys->MREPL | Sys->MCREATE) < 0) 180*37da2899SCharles.Forsyth fatal("cannot bind inferno root tmp"); 181*37da2899SCharles.Forsyth root = MTPT; 182*37da2899SCharles.Forsyth 183*37da2899SCharles.Forsyth if (nt || 1) 184*37da2899SCharles.Forsyth local = 1; 185*37da2899SCharles.Forsyth else { 186*37da2899SCharles.Forsyth sys->print("You can either install software specific to %s only or\n", platform); 187*37da2899SCharles.Forsyth sys->print(" install software for all platforms that we support.\n"); 188*37da2899SCharles.Forsyth sys->print("If you are unsure what to do, answer yes to the question following.\n"); 189*37da2899SCharles.Forsyth sys->print(" You can install the remainder of the software at a later date if desired.\n"); 190*37da2899SCharles.Forsyth sys->print("\n"); 191*37da2899SCharles.Forsyth b := bufio->fopen(sys->fildes(0), Bufio->OREAD); 192*37da2899SCharles.Forsyth if (b == nil) 193*37da2899SCharles.Forsyth fatal("cannot open stdin"); 194*37da2899SCharles.Forsyth for (;;) { 195*37da2899SCharles.Forsyth sys->print("Install software specific to %s only ? (yes/no/quit) ", platform); 196*37da2899SCharles.Forsyth resp := getresponse(b); 197*37da2899SCharles.Forsyth ans := answer(resp); 198*37da2899SCharles.Forsyth if (ans == QUIT) 199*37da2899SCharles.Forsyth exit; 200*37da2899SCharles.Forsyth else if (ans == ERR) 201*37da2899SCharles.Forsyth sys->print("bad response %s\n\n", resp); 202*37da2899SCharles.Forsyth else { 203*37da2899SCharles.Forsyth local = ans == YES; 204*37da2899SCharles.Forsyth break; 205*37da2899SCharles.Forsyth } 206*37da2899SCharles.Forsyth } 207*37da2899SCharles.Forsyth } 208*37da2899SCharles.Forsyth instprods = dowraps(root+"/wrap"); 209*37da2899SCharles.Forsyth doprods(installdir); 210*37da2899SCharles.Forsyth if (!nt) 211*37da2899SCharles.Forsyth sys->print("installation complete\n"); 212*37da2899SCharles.Forsyth if (exitemu) 213*37da2899SCharles.Forsyth shutdown(); 214*37da2899SCharles.Forsyth} 215*37da2899SCharles.Forsyth 216*37da2899SCharles.Forsythgetresponse(b : ref Iobuf) : string 217*37da2899SCharles.Forsyth{ 218*37da2899SCharles.Forsyth s := b.gets('\n'); 219*37da2899SCharles.Forsyth while (s != nil && (s[0] == ' ' || s[0] == '\t')) 220*37da2899SCharles.Forsyth s = s[1:]; 221*37da2899SCharles.Forsyth while (s != nil && ((c := s[len s - 1]) == ' ' || c == '\t' || c == '\n')) 222*37da2899SCharles.Forsyth s = s[0: len s - 1]; 223*37da2899SCharles.Forsyth return s; 224*37da2899SCharles.Forsyth} 225*37da2899SCharles.Forsyth 226*37da2899SCharles.Forsythanswer(s : string) : int 227*37da2899SCharles.Forsyth{ 228*37da2899SCharles.Forsyth s = str->tolower(s); 229*37da2899SCharles.Forsyth if (s == "y" || s == "yes") 230*37da2899SCharles.Forsyth return YES; 231*37da2899SCharles.Forsyth if (s == "n" || s == "no") 232*37da2899SCharles.Forsyth return NO; 233*37da2899SCharles.Forsyth if (s == "q" || s == "quit") 234*37da2899SCharles.Forsyth return QUIT; 235*37da2899SCharles.Forsyth return ERR; 236*37da2899SCharles.Forsyth} 237*37da2899SCharles.Forsyth 238*37da2899SCharles.Forsythusage() 239*37da2899SCharles.Forsyth{ 240*37da2899SCharles.Forsyth fatal("Usage: install [-d] [-F] [-s] [-u] [-i installdir ] [-p platform ] [-r root]"); 241*37da2899SCharles.Forsyth} 242*37da2899SCharles.Forsyth 243*37da2899SCharles.Forsythfatal(s : string) 244*37da2899SCharles.Forsyth{ 245*37da2899SCharles.Forsyth sys->fprint(stderr, "install: %s\n", s); 246*37da2899SCharles.Forsyth exit; 247*37da2899SCharles.Forsyth} 248*37da2899SCharles.Forsyth 249*37da2899SCharles.Forsythdowraps(d : string) : ref Product 250*37da2899SCharles.Forsyth{ 251*37da2899SCharles.Forsyth p : ref Product; 252*37da2899SCharles.Forsyth 253*37da2899SCharles.Forsyth # make an inventory of what is already apparently installed 254*37da2899SCharles.Forsyth (dir, n) := readdir->init(d, Readdir->NAME|Readdir->COMPACT); 255*37da2899SCharles.Forsyth for (i := 0; i < n; i++) { 256*37da2899SCharles.Forsyth if (dir[i].mode & Sys->DMDIR) { 257*37da2899SCharles.Forsyth p = ref Product(str->tolower(dir[i].name), nil, p); 258*37da2899SCharles.Forsyth p.pkgs = dowrap(d + "/" + dir[i].name); 259*37da2899SCharles.Forsyth } 260*37da2899SCharles.Forsyth } 261*37da2899SCharles.Forsyth return p; 262*37da2899SCharles.Forsyth} 263*37da2899SCharles.Forsyth 264*37da2899SCharles.Forsythdowrap(d : string) : ref Package 265*37da2899SCharles.Forsyth{ 266*37da2899SCharles.Forsyth p : ref Package; 267*37da2899SCharles.Forsyth 268*37da2899SCharles.Forsyth (dir, n) := readdir->init(d, Readdir->NAME|Readdir->COMPACT); 269*37da2899SCharles.Forsyth for (i := 0; i < n; i++) 270*37da2899SCharles.Forsyth p = ref Package(dir[i].name, p); 271*37da2899SCharles.Forsyth return p; 272*37da2899SCharles.Forsyth} 273*37da2899SCharles.Forsyth 274*37da2899SCharles.Forsythdoprods(d : string) 275*37da2899SCharles.Forsyth{ 276*37da2899SCharles.Forsyth (dir, n) := readdir->init(d, Readdir->NAME|Readdir->COMPACT); 277*37da2899SCharles.Forsyth for (i := 0; i < n; i++) { 278*37da2899SCharles.Forsyth if (dir[i].mode & Sys->DMDIR) 279*37da2899SCharles.Forsyth doprod(str->tolower(dir[i].name), d + "/" + dir[i].name); 280*37da2899SCharles.Forsyth } 281*37da2899SCharles.Forsyth} 282*37da2899SCharles.Forsyth 283*37da2899SCharles.Forsythdoprod(pr : string, d : string) 284*37da2899SCharles.Forsyth{ 285*37da2899SCharles.Forsyth # base package, updates and update packages have the name 286*37da2899SCharles.Forsyth # <timestamp> or <timestamp.gz> 287*37da2899SCharles.Forsyth if (!wanted(pr)) 288*37da2899SCharles.Forsyth return; 289*37da2899SCharles.Forsyth (dir, n) := readdir->init(d, Readdir->NAME|Readdir->COMPACT); 290*37da2899SCharles.Forsyth for (i := 0; i < n; i++) { 291*37da2899SCharles.Forsyth pk := dir[i].name; 292*37da2899SCharles.Forsyth l := len pk; 293*37da2899SCharles.Forsyth if (l >= 4 && pk[l-3:l] == ".gz") 294*37da2899SCharles.Forsyth pk = pk[0:l-3]; 295*37da2899SCharles.Forsyth else if (l >= 5 && (pk[l-4:] == ".tgz" || pk[l-4:] == ".9gz")) 296*37da2899SCharles.Forsyth pk = pk[0:l-4]; 297*37da2899SCharles.Forsyth dopkg(pk, pr, d+"/"+dir[i].name); 298*37da2899SCharles.Forsyth 299*37da2899SCharles.Forsyth } 300*37da2899SCharles.Forsyth} 301*37da2899SCharles.Forsyth 302*37da2899SCharles.Forsythdopkg(pk : string, pr : string, d : string) 303*37da2899SCharles.Forsyth{ 304*37da2899SCharles.Forsyth if (!installed(pk, pr)) 305*37da2899SCharles.Forsyth install(d); 306*37da2899SCharles.Forsyth} 307*37da2899SCharles.Forsyth 308*37da2899SCharles.Forsythinstalled(pkg : string, prd : string) : int 309*37da2899SCharles.Forsyth{ 310*37da2899SCharles.Forsyth for (pr := instprods; pr != nil; pr = pr.nxt) { 311*37da2899SCharles.Forsyth if (pr.name == prd) { 312*37da2899SCharles.Forsyth for (pk := pr.pkgs; pk != nil; pk = pk.nxt) { 313*37da2899SCharles.Forsyth if (pk.name == pkg) 314*37da2899SCharles.Forsyth return 1; 315*37da2899SCharles.Forsyth } 316*37da2899SCharles.Forsyth return 0; 317*37da2899SCharles.Forsyth } 318*37da2899SCharles.Forsyth } 319*37da2899SCharles.Forsyth return 0; 320*37da2899SCharles.Forsyth} 321*37da2899SCharles.Forsyth 322*37da2899SCharles.Forsythlookup(pr : string) : int 323*37da2899SCharles.Forsyth{ 324*37da2899SCharles.Forsyth for (i := 0; i < len xpkgs; i++) { 325*37da2899SCharles.Forsyth if (xpkgs[i] == pr) 326*37da2899SCharles.Forsyth return i; 327*37da2899SCharles.Forsyth } 328*37da2899SCharles.Forsyth return -1; 329*37da2899SCharles.Forsyth} 330*37da2899SCharles.Forsyth 331*37da2899SCharles.Forsythplookup(pr: string): int 332*37da2899SCharles.Forsyth{ 333*37da2899SCharles.Forsyth for(ps := ypkgs; ps != nil; ps = tl ps) 334*37da2899SCharles.Forsyth if(pr == hd ps) 335*37da2899SCharles.Forsyth return 1; 336*37da2899SCharles.Forsyth return 0; 337*37da2899SCharles.Forsyth} 338*37da2899SCharles.Forsyth 339*37da2899SCharles.Forsythwanted(pr : string) : int 340*37da2899SCharles.Forsyth{ 341*37da2899SCharles.Forsyth if (!local || global) 342*37da2899SCharles.Forsyth return 1; 343*37da2899SCharles.Forsyth if(ypkgs != nil) # overrides everything else 344*37da2899SCharles.Forsyth return plookup(pr); 345*37da2899SCharles.Forsyth found := lookup(pr); 346*37da2899SCharles.Forsyth if (found >= 0) 347*37da2899SCharles.Forsyth return 1; 348*37da2899SCharles.Forsyth return pr == lcplatform || prefix(lcplatform, pr); 349*37da2899SCharles.Forsyth} 350*37da2899SCharles.Forsyth 351*37da2899SCharles.Forsythinstall(d : string) 352*37da2899SCharles.Forsyth{ 353*37da2899SCharles.Forsyth if (waitfd == nil) 354*37da2899SCharles.Forsyth waitfd = openwait(sys->pctl(0, nil)); 355*37da2899SCharles.Forsyth sys->fprint(stderr, "installing package %s\n", d); 356*37da2899SCharles.Forsyth if (debug) 357*37da2899SCharles.Forsyth return; 358*37da2899SCharles.Forsyth c := chan of int; 359*37da2899SCharles.Forsyth args := "-t" :: "-v" :: "-r" :: root :: d :: nil; 360*37da2899SCharles.Forsyth if (uflag) 361*37da2899SCharles.Forsyth args = "-u" :: args; 362*37da2899SCharles.Forsyth if (force) 363*37da2899SCharles.Forsyth args = "-F" :: args; 364*37da2899SCharles.Forsyth spawn exec(INST, INST :: args, c); 365*37da2899SCharles.Forsyth execpid := <- c; 366*37da2899SCharles.Forsyth wait(waitfd, execpid); 367*37da2899SCharles.Forsyth} 368*37da2899SCharles.Forsyth 369*37da2899SCharles.Forsythexec(cmd : string, argl : list of string, ci : chan of int) 370*37da2899SCharles.Forsyth{ 371*37da2899SCharles.Forsyth ci <-= sys->pctl(Sys->FORKNS|Sys->NEWFD|Sys->NEWPGRP, 0 :: 1 :: 2 :: stderr.fd :: nil); 372*37da2899SCharles.Forsyth file := cmd; 373*37da2899SCharles.Forsyth if(len file<4 || file[len file-4:] !=".dis") 374*37da2899SCharles.Forsyth file += ".dis"; 375*37da2899SCharles.Forsyth c := load Command file; 376*37da2899SCharles.Forsyth if(c == nil) { 377*37da2899SCharles.Forsyth err := sys->sprint("%r"); 378*37da2899SCharles.Forsyth if(file[0] !='/' && file[0:2] !="./") { 379*37da2899SCharles.Forsyth c = load Command "/dis/"+file; 380*37da2899SCharles.Forsyth if(c == nil) 381*37da2899SCharles.Forsyth err = sys->sprint("%r"); 382*37da2899SCharles.Forsyth } 383*37da2899SCharles.Forsyth if(c == nil) 384*37da2899SCharles.Forsyth fatal(sys->sprint("%s: %s\n", cmd, err)); 385*37da2899SCharles.Forsyth } 386*37da2899SCharles.Forsyth c->init(nil, argl); 387*37da2899SCharles.Forsyth} 388*37da2899SCharles.Forsyth 389*37da2899SCharles.Forsythopenwait(pid : int) : ref Sys->FD 390*37da2899SCharles.Forsyth{ 391*37da2899SCharles.Forsyth w := sys->sprint("#p/%d/wait", pid); 392*37da2899SCharles.Forsyth fd := sys->open(w, Sys->OREAD); 393*37da2899SCharles.Forsyth if (fd == nil) 394*37da2899SCharles.Forsyth fatal("fd == nil in wait"); 395*37da2899SCharles.Forsyth return fd; 396*37da2899SCharles.Forsyth} 397*37da2899SCharles.Forsyth 398*37da2899SCharles.Forsythwait(wfd : ref Sys->FD, wpid : int) 399*37da2899SCharles.Forsyth{ 400*37da2899SCharles.Forsyth n : int; 401*37da2899SCharles.Forsyth 402*37da2899SCharles.Forsyth buf := array[Sys->WAITLEN] of byte; 403*37da2899SCharles.Forsyth status := ""; 404*37da2899SCharles.Forsyth for(;;) { 405*37da2899SCharles.Forsyth if ((n = sys->read(wfd, buf, len buf)) < 0) 406*37da2899SCharles.Forsyth fatal("bad read in wait"); 407*37da2899SCharles.Forsyth status = string buf[0:n]; 408*37da2899SCharles.Forsyth break; 409*37da2899SCharles.Forsyth } 410*37da2899SCharles.Forsyth if (int status != wpid) 411*37da2899SCharles.Forsyth fatal("bad status in wait"); 412*37da2899SCharles.Forsyth if(status[len status - 1] != ':') 413*37da2899SCharles.Forsyth fatal(sys->sprint("%s\n", status)); 414*37da2899SCharles.Forsyth} 415*37da2899SCharles.Forsyth 416*37da2899SCharles.Forsythshutdown() 417*37da2899SCharles.Forsyth{ 418*37da2899SCharles.Forsyth fd := sys->open("/dev/sysctl", sys->OWRITE); 419*37da2899SCharles.Forsyth if(fd == nil) 420*37da2899SCharles.Forsyth fatal("cannot shutdown emu"); 421*37da2899SCharles.Forsyth if (sys->write(fd, array of byte "halt", 4) < 0) 422*37da2899SCharles.Forsyth fatal(sys->sprint("shutdown: write failed: %r\n")); 423*37da2899SCharles.Forsyth} 424*37da2899SCharles.Forsyth 425*37da2899SCharles.Forsythprefix(s, t : string) : int 426*37da2899SCharles.Forsyth{ 427*37da2899SCharles.Forsyth if (len s <= len t) 428*37da2899SCharles.Forsyth return t[0:len s] == s; 429*37da2899SCharles.Forsyth return 0; 430*37da2899SCharles.Forsyth} 431