xref: /inferno-os/appl/cmd/chmod.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
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