Commit | Line | Data |
---|---|---|
930bce5a TL |
1 | /* |
2 | * chmod [ugoa][+-=][rwxstugo] files | |
3 | * change mode of files | |
4 | */ | |
5 | #include <stdio.h> | |
6 | #include <sys/types.h> | |
7 | #include <sys/stat.h> | |
8 | ||
9 | #define USER 05700 /* user's bits */ | |
10 | #define GROUP 02070 /* group's bits */ | |
11 | #define OTHER 00007 /* other's bits */ | |
12 | #define ALL 01777 /* all (note absence of setuid, etc) */ | |
13 | ||
14 | #define READ 00444 /* read permit */ | |
15 | #define WRITE 00222 /* write permit */ | |
16 | #define EXEC 00111 /* exec permit */ | |
17 | #define SETID 06000 /* set[ug]id */ | |
18 | #define STICKY 01000 /* sticky bit */ | |
19 | ||
20 | char *ms; | |
21 | int um; | |
22 | struct stat st; | |
23 | ||
24 | main(argc,argv) | |
25 | char **argv; | |
26 | { | |
27 | register i; | |
28 | register char *p; | |
29 | int status = 0; | |
30 | ||
31 | if (argc < 3) { | |
32 | fprintf(stderr, "Usage: chmod [ugoa][+-=][rwxstugo] file ...\n"); | |
33 | exit(255); | |
34 | } | |
35 | ms = argv[1]; | |
36 | um = umask(0); | |
37 | newmode(0); | |
38 | for (i = 2; i < argc; i++) { | |
39 | p = argv[i]; | |
40 | if (stat(p, &st) < 0) { | |
41 | fprintf(stderr, "chmod: can't access %s\n", p); | |
42 | ++status; | |
43 | continue; | |
44 | } | |
45 | ms = argv[1]; | |
46 | if (chmod(p, newmode(st.st_mode)) < 0) { | |
47 | fprintf(stderr, "chmod: can't change %s\n", p); | |
48 | ++status; | |
49 | continue; | |
50 | } | |
51 | } | |
52 | exit(status); | |
53 | } | |
54 | ||
55 | newmode(nm) | |
56 | unsigned nm; | |
57 | { | |
58 | register o, m, b; | |
59 | ||
60 | m = abs(); | |
61 | if (!*ms) | |
62 | return(m); | |
63 | do { | |
64 | m = who(); | |
65 | while (o = what()) { | |
66 | b = where(nm); | |
67 | switch (o) { | |
68 | case '+': | |
69 | nm |= b & m; | |
70 | break; | |
71 | case '-': | |
72 | nm &= ~(b & m); | |
73 | break; | |
74 | case '=': | |
75 | nm &= ~m; | |
76 | nm |= b & m; | |
77 | break; | |
78 | } | |
79 | } | |
80 | } while (*ms++ == ','); | |
81 | if (*--ms) { | |
82 | fprintf(stderr, "chmod: invalid mode\n"); | |
83 | exit(255); | |
84 | } | |
85 | return(nm); | |
86 | } | |
87 | ||
88 | abs() | |
89 | { | |
90 | register c, i; | |
91 | ||
92 | i = 0; | |
93 | while ((c = *ms++) >= '0' && c <= '7') | |
94 | i = (i << 3) + (c - '0'); | |
95 | ms--; | |
96 | return(i); | |
97 | } | |
98 | ||
99 | who() | |
100 | { | |
101 | register m; | |
102 | ||
103 | m = 0; | |
104 | for (;;) switch (*ms++) { | |
105 | case 'u': | |
106 | m |= USER; | |
107 | continue; | |
108 | case 'g': | |
109 | m |= GROUP; | |
110 | continue; | |
111 | case 'o': | |
112 | m |= OTHER; | |
113 | continue; | |
114 | case 'a': | |
115 | m |= ALL; | |
116 | continue; | |
117 | default: | |
118 | ms--; | |
119 | if (m == 0) | |
120 | m = ALL & ~um; | |
121 | return m; | |
122 | } | |
123 | } | |
124 | ||
125 | what() | |
126 | { | |
127 | switch (*ms) { | |
128 | case '+': | |
129 | case '-': | |
130 | case '=': | |
131 | return *ms++; | |
132 | } | |
133 | return(0); | |
134 | } | |
135 | ||
136 | where(om) | |
137 | register om; | |
138 | { | |
139 | register m; | |
140 | ||
141 | m = 0; | |
142 | switch (*ms) { | |
143 | case 'u': | |
144 | m = (om & USER) >> 6; | |
145 | goto dup; | |
146 | case 'g': | |
147 | m = (om & GROUP) >> 3; | |
148 | goto dup; | |
149 | case 'o': | |
150 | m = (om & OTHER); | |
151 | dup: | |
152 | m &= (READ|WRITE|EXEC); | |
153 | m |= (m << 3) | (m << 6); | |
154 | ++ms; | |
155 | return m; | |
156 | } | |
157 | for (;;) switch (*ms++) { | |
158 | case 'r': | |
159 | m |= READ; | |
160 | continue; | |
161 | case 'w': | |
162 | m |= WRITE; | |
163 | continue; | |
164 | case 'x': | |
165 | m |= EXEC; | |
166 | continue; | |
167 | case 's': | |
168 | m |= SETID; | |
169 | continue; | |
170 | case 't': | |
171 | m |= STICKY; | |
172 | continue; | |
173 | default: | |
174 | ms--; | |
175 | return m; | |
176 | } | |
177 | } |