1*37da2899SCharles.Forsythimplement Chmod; 2*37da2899SCharles.Forsyth 3*37da2899SCharles.Forsythinclude "sys.m"; 4*37da2899SCharles.Forsythinclude "draw.m"; 5*37da2899SCharles.Forsythinclude "string.m"; 6*37da2899SCharles.Forsyth 7*37da2899SCharles.ForsythChmod: module 8*37da2899SCharles.Forsyth{ 9*37da2899SCharles.Forsyth init: fn(ctxt: ref Draw->Context, argv: list of string); 10*37da2899SCharles.Forsyth}; 11*37da2899SCharles.Forsyth 12*37da2899SCharles.Forsythsys: Sys; 13*37da2899SCharles.Forsythstderr: ref Sys->FD; 14*37da2899SCharles.Forsyth 15*37da2899SCharles.Forsythstr: String; 16*37da2899SCharles.Forsyth 17*37da2899SCharles.ForsythUser: con 8r700; 18*37da2899SCharles.ForsythGroup: con 8r070; 19*37da2899SCharles.ForsythOther: con 8r007; 20*37da2899SCharles.ForsythAll: con User | Group | Other; 21*37da2899SCharles.Forsyth 22*37da2899SCharles.ForsythRead: con 8r444; 23*37da2899SCharles.ForsythWrite: con 8r222; 24*37da2899SCharles.ForsythExec: con 8r111; 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsythusage() 27*37da2899SCharles.Forsyth{ 28*37da2899SCharles.Forsyth sys->fprint(stderr, "usage: chmod [8r]777 file ... or chmod [augo][+-=][rwxal] file ...\n"); 29*37da2899SCharles.Forsyth raise "fail:usage"; 30*37da2899SCharles.Forsyth} 31*37da2899SCharles.Forsyth 32*37da2899SCharles.Forsythinit(nil: ref Draw->Context, argv: list of string) 33*37da2899SCharles.Forsyth{ 34*37da2899SCharles.Forsyth sys = load Sys Sys->PATH; 35*37da2899SCharles.Forsyth stderr = sys->fildes(2); 36*37da2899SCharles.Forsyth 37*37da2899SCharles.Forsyth str = load String String->PATH; 38*37da2899SCharles.Forsyth if(str == nil){ 39*37da2899SCharles.Forsyth sys->fprint(stderr, "chmod: cannot load %s: %r\n", String->PATH); 40*37da2899SCharles.Forsyth raise "fail:bad module"; 41*37da2899SCharles.Forsyth } 42*37da2899SCharles.Forsyth 43*37da2899SCharles.Forsyth if(len argv < 3) 44*37da2899SCharles.Forsyth usage(); 45*37da2899SCharles.Forsyth argv = tl argv; 46*37da2899SCharles.Forsyth m := hd argv; 47*37da2899SCharles.Forsyth argv = tl argv; 48*37da2899SCharles.Forsyth 49*37da2899SCharles.Forsyth mask := All; 50*37da2899SCharles.Forsyth if (str->prefix("8r", m)) 51*37da2899SCharles.Forsyth m = m[2:]; 52*37da2899SCharles.Forsyth (mode, s) := str->toint(m, 8); 53*37da2899SCharles.Forsyth if(s != "" || m == ""){ 54*37da2899SCharles.Forsyth ok := 0; 55*37da2899SCharles.Forsyth (ok, mask, mode) = parsemode(m); 56*37da2899SCharles.Forsyth if(!ok){ 57*37da2899SCharles.Forsyth sys->fprint(stderr, "chmod: bad mode '%s'\n", m); 58*37da2899SCharles.Forsyth usage(); 59*37da2899SCharles.Forsyth } 60*37da2899SCharles.Forsyth } 61*37da2899SCharles.Forsyth ndir := sys->nulldir; 62*37da2899SCharles.Forsyth for(; argv != nil; argv = tl argv){ 63*37da2899SCharles.Forsyth f := hd argv; 64*37da2899SCharles.Forsyth (ok, dir) := sys->stat(f); 65*37da2899SCharles.Forsyth if(ok < 0){ 66*37da2899SCharles.Forsyth sys->fprint(stderr, "chmod: cannot stat %s: %r\n", f); 67*37da2899SCharles.Forsyth continue; 68*37da2899SCharles.Forsyth } 69*37da2899SCharles.Forsyth ndir.mode = (dir.mode & ~mask) | (mode & mask); 70*37da2899SCharles.Forsyth if(sys->wstat(f, ndir) < 0) 71*37da2899SCharles.Forsyth sys->fprint(stderr, "chmod: cannot wstat %s: %r\n", f); 72*37da2899SCharles.Forsyth } 73*37da2899SCharles.Forsyth} 74*37da2899SCharles.Forsyth 75*37da2899SCharles.Forsythparsemode(spec: string): (int, int, int) 76*37da2899SCharles.Forsyth{ 77*37da2899SCharles.Forsyth mask := Sys->DMAPPEND | Sys->DMEXCL | Sys->DMTMP; 78*37da2899SCharles.Forsythloop: for(i := 0; i < len spec; i++){ 79*37da2899SCharles.Forsyth case spec[i] { 80*37da2899SCharles.Forsyth 'u' => 81*37da2899SCharles.Forsyth mask |= User; 82*37da2899SCharles.Forsyth 'g' => 83*37da2899SCharles.Forsyth mask |= Group; 84*37da2899SCharles.Forsyth 'o' => 85*37da2899SCharles.Forsyth mask |= Other; 86*37da2899SCharles.Forsyth 'a' => 87*37da2899SCharles.Forsyth mask |= All; 88*37da2899SCharles.Forsyth * => 89*37da2899SCharles.Forsyth break loop; 90*37da2899SCharles.Forsyth } 91*37da2899SCharles.Forsyth } 92*37da2899SCharles.Forsyth if(i == len spec) 93*37da2899SCharles.Forsyth return (0, 0, 0); 94*37da2899SCharles.Forsyth if(i == 0) 95*37da2899SCharles.Forsyth mask |= All; 96*37da2899SCharles.Forsyth 97*37da2899SCharles.Forsyth op := spec[i++]; 98*37da2899SCharles.Forsyth if(op != '+' && op != '-' && op != '=') 99*37da2899SCharles.Forsyth return (0, 0, 0); 100*37da2899SCharles.Forsyth 101*37da2899SCharles.Forsyth mode := 0; 102*37da2899SCharles.Forsyth for(; i < len spec; i++){ 103*37da2899SCharles.Forsyth case spec[i]{ 104*37da2899SCharles.Forsyth 'r' => 105*37da2899SCharles.Forsyth mode |= Read; 106*37da2899SCharles.Forsyth 'w' => 107*37da2899SCharles.Forsyth mode |= Write; 108*37da2899SCharles.Forsyth 'x' => 109*37da2899SCharles.Forsyth mode |= Exec; 110*37da2899SCharles.Forsyth 'a' => 111*37da2899SCharles.Forsyth mode |= Sys->DMAPPEND; 112*37da2899SCharles.Forsyth 'l' => 113*37da2899SCharles.Forsyth mode |= Sys->DMEXCL; 114*37da2899SCharles.Forsyth 't' => 115*37da2899SCharles.Forsyth mode |= Sys->DMTMP; 116*37da2899SCharles.Forsyth * => 117*37da2899SCharles.Forsyth return (0, 0, 0); 118*37da2899SCharles.Forsyth } 119*37da2899SCharles.Forsyth } 120*37da2899SCharles.Forsyth if(op == '+' || op == '-') 121*37da2899SCharles.Forsyth mask &= mode; 122*37da2899SCharles.Forsyth if(op == '-') 123*37da2899SCharles.Forsyth mode = ~mode; 124*37da2899SCharles.Forsyth return (1, mask, mode); 125*37da2899SCharles.Forsyth} 126