1 /* chmod - Change file modes Author: V. Archer */
3 /* Copyright 1991 by Vincent Archer
4 * You may freely redistribute this software, in source or binary
5 * form, provided that you do not alter this copyright mention in any
17 #include <minix/minlib.h>
21 #define S_ISLNK(mode) 0
25 #define USR_MODES (S_ISUID|S_IRWXU)
26 #define GRP_MODES (S_ISGID|S_IRWXG)
27 #define EXE_MODES (S_IXUSR|S_IXGRP|S_IXOTH)
29 #define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO|S_ISVTX)
31 #define ALL_MODES (USR_MODES|GRP_MODES|S_IRWXO)
35 /* Common variables */
37 mode_t new_mode
, u_mask
;
40 char path
[PATH_MAX
+ 1];
42 int do_change(char *name
);
45 /* Parse a P1003.2 4.7.7-conformant symbolic mode. */
46 mode_t
parsemode(const char *symbolic
, mode_t oldmode
)
48 mode_t who
, mask
, newmode
, tmpmask
;
51 newmode
= oldmode
& ALL_MODES
;
54 for (; *symbolic
; symbolic
++) {
55 if (*symbolic
== 'a') {
59 if (*symbolic
== 'u') {
63 if (*symbolic
== 'g') {
67 if (*symbolic
== 'o') {
73 if (!*symbolic
|| *symbolic
== ',') usage();
75 if (*symbolic
== ',') break;
81 case '=': action
= *symbolic
++;
84 for (; *symbolic
; symbolic
++) {
85 if (*symbolic
== 'u') {
86 tmpmask
= newmode
& S_IRWXU
;
87 mask
|= tmpmask
| (tmpmask
<< 3) | (tmpmask
<< 6);
91 if (*symbolic
== 'g') {
92 tmpmask
= newmode
& S_IRWXG
;
93 mask
|= tmpmask
| (tmpmask
>> 3) | (tmpmask
<< 3);
97 if (*symbolic
== 'o') {
98 tmpmask
= newmode
& S_IRWXO
;
99 mask
|= tmpmask
| (tmpmask
>> 3) | (tmpmask
>> 6);
103 if (*symbolic
== 'r') {
104 mask
|= S_IRUSR
| S_IRGRP
| S_IROTH
;
107 if (*symbolic
== 'w') {
108 mask
|= S_IWUSR
| S_IWGRP
| S_IWOTH
;
111 if (*symbolic
== 'x') {
115 if (*symbolic
== 's') {
116 mask
|= S_ISUID
| S_ISGID
;
119 if (*symbolic
== 'X') {
120 if (S_ISDIR(oldmode
) || (oldmode
& EXE_MODES
))
125 if (*symbolic
== 't') {
141 newmode
|= who
& mask
;
143 newmode
|= mask
& (~u_mask
);
147 newmode
&= ~(who
& mask
);
149 newmode
&= ~mask
| u_mask
;
152 if (*symbolic
) symbolic
++;
158 /* Main module. The single option possible (-R) does not warrant a call to
159 * the getopt() stuff.
161 int main(int argc
, char *argv
[])
168 if (argc
&& strcmp(*argv
, "-R") == 0) {
175 if (!argc
--) usage();
176 if (!strcmp(argv
[0], "--")) { /* Allow chmod -- -r, as in Draft11 example */
177 if (!argc
--) usage();
183 if (*symbolic
>= '0' && *symbolic
<= '7') {
185 while (*symbolic
>= '0' && *symbolic
<= '7')
186 new_mode
= (new_mode
<< 3) | (*symbolic
++ & 07);
187 if (*symbolic
) usage();
188 new_mode
&= ALL_MODES
;
189 symbolic
= (char *) 0;
194 if (do_change(*argv
++)) ex_code
= 1;
199 /* Apply a mode change to a given file system element. */
208 if (lstat(name
, &st
)) {
212 if (S_ISLNK(st
.st_mode
) && rflag
) return(0); /* Note: violates POSIX. */
216 m
= parsemode(symbolic
, st
.st_mode
);
217 if (chmod(name
, m
)) {
223 if (S_ISDIR(st
.st_mode
) && rflag
) {
224 if (!(dirp
= opendir(name
))) {
228 if (name
!= path
) strcpy(path
, name
);
229 namp
= path
+ strlen(path
);
231 while (entp
= readdir(dirp
))
232 if (entp
->d_name
[0] != '.' ||
234 (entp
->d_name
[1] != '.' || entp
->d_name
[2]))) {
235 strcpy(namp
, entp
->d_name
);
236 errors
|= do_change(path
);
245 /* Display Posix prototype */
248 std_err("Usage: chmod [-R] mode file...\n");