13e12c5d1SDavid du Colombier #include <u.h>
23e12c5d1SDavid du Colombier #include <libc.h>
33e12c5d1SDavid du Colombier
43e12c5d1SDavid du Colombier #define U(x) (x<<6)
53e12c5d1SDavid du Colombier #define G(x) (x<<3)
63e12c5d1SDavid du Colombier #define O(x) (x)
73e12c5d1SDavid du Colombier #define A(x) (U(x)|G(x)|O(x))
83e12c5d1SDavid du Colombier
99a747e4fSDavid du Colombier #define DMRWE (DMREAD|DMWRITE|DMEXEC)
103e12c5d1SDavid du Colombier
113e12c5d1SDavid du Colombier int parsemode(char *, ulong *, ulong *);
123e12c5d1SDavid du Colombier
133e12c5d1SDavid du Colombier void
main(int argc,char * argv[])143e12c5d1SDavid du Colombier main(int argc, char *argv[])
153e12c5d1SDavid du Colombier {
163e12c5d1SDavid du Colombier int i;
179a747e4fSDavid du Colombier Dir *dir, ndir;
183e12c5d1SDavid du Colombier ulong mode, mask;
193e12c5d1SDavid du Colombier char *p;
203e12c5d1SDavid du Colombier
217dd7cddfSDavid du Colombier if(argc < 3){
22*b7327ca2SDavid du Colombier fprint(2, "usage: chmod 0777 file ... or chmod [who]op[rwxalt] file ...\n");
233e12c5d1SDavid du Colombier exits("usage");
243e12c5d1SDavid du Colombier }
253e12c5d1SDavid du Colombier mode = strtol(argv[1], &p, 8);
263e12c5d1SDavid du Colombier if(*p == 0)
279a747e4fSDavid du Colombier mask = A(DMRWE);
283e12c5d1SDavid du Colombier else if(!parsemode(argv[1], &mask, &mode)){
293e12c5d1SDavid du Colombier fprint(2, "chmod: bad mode: %s\n", argv[1]);
303e12c5d1SDavid du Colombier exits("mode");
313e12c5d1SDavid du Colombier }
329a747e4fSDavid du Colombier nulldir(&ndir);
333e12c5d1SDavid du Colombier for(i=2; i<argc; i++){
349a747e4fSDavid du Colombier dir = dirstat(argv[i]);
359a747e4fSDavid du Colombier if(dir == nil){
369a747e4fSDavid du Colombier fprint(2, "chmod: can't stat %s: %r\n", argv[i]);
373e12c5d1SDavid du Colombier continue;
383e12c5d1SDavid du Colombier }
399a747e4fSDavid du Colombier ndir.mode = (dir->mode & ~mask) | (mode & mask);
409a747e4fSDavid du Colombier free(dir);
419a747e4fSDavid du Colombier if(dirwstat(argv[i], &ndir)==-1){
429a747e4fSDavid du Colombier fprint(2, "chmod: can't wstat %s: %r\n", argv[i]);
433e12c5d1SDavid du Colombier continue;
443e12c5d1SDavid du Colombier }
453e12c5d1SDavid du Colombier }
463e12c5d1SDavid du Colombier exits(0);
473e12c5d1SDavid du Colombier }
483e12c5d1SDavid du Colombier
493e12c5d1SDavid du Colombier int
parsemode(char * spec,ulong * pmask,ulong * pmode)503e12c5d1SDavid du Colombier parsemode(char *spec, ulong *pmask, ulong *pmode)
513e12c5d1SDavid du Colombier {
523e12c5d1SDavid du Colombier ulong mode, mask;
533e12c5d1SDavid du Colombier int done, op;
543e12c5d1SDavid du Colombier char *s;
553e12c5d1SDavid du Colombier
563e12c5d1SDavid du Colombier s = spec;
57e44fe4caSDavid du Colombier mask = DMAPPEND | DMEXCL | DMTMP;
583e12c5d1SDavid du Colombier for(done=0; !done; ){
593e12c5d1SDavid du Colombier switch(*s){
603e12c5d1SDavid du Colombier case 'u':
619a747e4fSDavid du Colombier mask |= U(DMRWE); break;
623e12c5d1SDavid du Colombier case 'g':
639a747e4fSDavid du Colombier mask |= G(DMRWE); break;
643e12c5d1SDavid du Colombier case 'o':
659a747e4fSDavid du Colombier mask |= O(DMRWE); break;
663e12c5d1SDavid du Colombier case 'a':
679a747e4fSDavid du Colombier mask |= A(DMRWE); break;
683e12c5d1SDavid du Colombier case 0:
693e12c5d1SDavid du Colombier return 0;
703e12c5d1SDavid du Colombier default:
713e12c5d1SDavid du Colombier done = 1;
723e12c5d1SDavid du Colombier }
733e12c5d1SDavid du Colombier if(!done)
743e12c5d1SDavid du Colombier s++;
753e12c5d1SDavid du Colombier }
763e12c5d1SDavid du Colombier if(s == spec)
779a747e4fSDavid du Colombier mask |= A(DMRWE);
783e12c5d1SDavid du Colombier op = *s++;
793e12c5d1SDavid du Colombier if(op != '+' && op != '-' && op != '=')
803e12c5d1SDavid du Colombier return 0;
813e12c5d1SDavid du Colombier mode = 0;
823e12c5d1SDavid du Colombier for(; *s ; s++){
833e12c5d1SDavid du Colombier switch(*s){
843e12c5d1SDavid du Colombier case 'r':
859a747e4fSDavid du Colombier mode |= A(DMREAD); break;
863e12c5d1SDavid du Colombier case 'w':
879a747e4fSDavid du Colombier mode |= A(DMWRITE); break;
883e12c5d1SDavid du Colombier case 'x':
899a747e4fSDavid du Colombier mode |= A(DMEXEC); break;
903e12c5d1SDavid du Colombier case 'a':
919a747e4fSDavid du Colombier mode |= DMAPPEND; break;
923e12c5d1SDavid du Colombier case 'l':
939a747e4fSDavid du Colombier mode |= DMEXCL; break;
94e44fe4caSDavid du Colombier case 't':
95e44fe4caSDavid du Colombier mode |= DMTMP; break;
963e12c5d1SDavid du Colombier default:
973e12c5d1SDavid du Colombier return 0;
983e12c5d1SDavid du Colombier }
993e12c5d1SDavid du Colombier }
1003e12c5d1SDavid du Colombier if(*s != 0)
1013e12c5d1SDavid du Colombier return 0;
1023e12c5d1SDavid du Colombier if(op == '+' || op == '-')
1033e12c5d1SDavid du Colombier mask &= mode;
1043e12c5d1SDavid du Colombier if(op == '-')
1053e12c5d1SDavid du Colombier mode = ~mode;
1063e12c5d1SDavid du Colombier *pmask = mask;
1073e12c5d1SDavid du Colombier *pmode = mode;
1083e12c5d1SDavid du Colombier return 1;
1093e12c5d1SDavid du Colombier }
110