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 _PROTOTYPE(int main
, (int argc
, char **argv
));
43 _PROTOTYPE(mode_t parsemode
, (char *symbolic
, mode_t oldmode
));
44 _PROTOTYPE(int do_change
, (char *name
));
45 _PROTOTYPE(void usage
, (void));
47 /* Parse a P1003.2 4.7.7-conformant symbolic mode. */
48 mode_t
parsemode(char *symbolic
, mode_t oldmode
)
50 mode_t who
, mask
, newmode
, tmpmask
;
53 newmode
= oldmode
& ALL_MODES
;
56 for (; *symbolic
; symbolic
++) {
57 if (*symbolic
== 'a') {
61 if (*symbolic
== 'u') {
65 if (*symbolic
== 'g') {
69 if (*symbolic
== 'o') {
75 if (!*symbolic
|| *symbolic
== ',') usage();
77 if (*symbolic
== ',') break;
83 case '=': action
= *symbolic
++;
86 for (; *symbolic
; symbolic
++) {
87 if (*symbolic
== 'u') {
88 tmpmask
= newmode
& S_IRWXU
;
89 mask
|= tmpmask
| (tmpmask
<< 3) | (tmpmask
<< 6);
93 if (*symbolic
== 'g') {
94 tmpmask
= newmode
& S_IRWXG
;
95 mask
|= tmpmask
| (tmpmask
>> 3) | (tmpmask
<< 3);
99 if (*symbolic
== 'o') {
100 tmpmask
= newmode
& S_IRWXO
;
101 mask
|= tmpmask
| (tmpmask
>> 3) | (tmpmask
>> 6);
105 if (*symbolic
== 'r') {
106 mask
|= S_IRUSR
| S_IRGRP
| S_IROTH
;
109 if (*symbolic
== 'w') {
110 mask
|= S_IWUSR
| S_IWGRP
| S_IWOTH
;
113 if (*symbolic
== 'x') {
117 if (*symbolic
== 's') {
118 mask
|= S_ISUID
| S_ISGID
;
121 if (*symbolic
== 'X') {
122 if (S_ISDIR(oldmode
) || (oldmode
& EXE_MODES
))
127 if (*symbolic
== 't') {
143 newmode
|= who
& mask
;
145 newmode
|= mask
& (~u_mask
);
149 newmode
&= ~(who
& mask
);
151 newmode
&= ~mask
| u_mask
;
154 if (*symbolic
) symbolic
++;
160 /* Main module. The single option possible (-R) does not warrant a call to
161 * the getopt() stuff.
172 if (argc
&& strcmp(*argv
, "-R") == 0) {
179 if (!argc
--) usage();
180 if (!strcmp(argv
[0], "--")) { /* Allow chmod -- -r, as in Draft11 example */
181 if (!argc
--) usage();
187 if (*symbolic
>= '0' && *symbolic
<= '7') {
189 while (*symbolic
>= '0' && *symbolic
<= '7')
190 new_mode
= (new_mode
<< 3) | (*symbolic
++ & 07);
191 if (*symbolic
) usage();
192 new_mode
&= ALL_MODES
;
193 symbolic
= (char *) 0;
198 if (do_change(*argv
++)) ex_code
= 1;
203 /* Apply a mode change to a given file system element. */
212 if (lstat(name
, &st
)) {
216 if (S_ISLNK(st
.st_mode
) && rflag
) return(0); /* Note: violates POSIX. */
220 m
= parsemode(symbolic
, st
.st_mode
);
221 if (chmod(name
, m
)) {
227 if (S_ISDIR(st
.st_mode
) && rflag
) {
228 if (!(dirp
= opendir(name
))) {
232 if (name
!= path
) strcpy(path
, name
);
233 namp
= path
+ strlen(path
);
235 while (entp
= readdir(dirp
))
236 if (entp
->d_name
[0] != '.' ||
238 (entp
->d_name
[1] != '.' || entp
->d_name
[2]))) {
239 strcpy(namp
, entp
->d_name
);
240 errors
|= do_change(path
);
249 /* Display Posix prototype */
252 std_err("Usage: chmod [-R] mode file...\n");