Add spl's around queue manipulation
[unix-history] / usr / src / bin / chmod / chmod.c
CommitLineData
358d0c96 1static char *sccsid = "@(#)chmod.c 4.4 %G%";
473911a1
KL
2
3/*
4 * chmod options mode files
5 * where
6 * mode is [ugoa][+-=][rwxstugo] or a octal number
7 * options are -R
8 */
9#include <stdio.h>
10#include <sys/types.h>
11#include <sys/stat.h>
12#include <sys/dir.h>
13
14#define USER 05700 /* user's bits */
15#define GROUP 02070 /* group's bits */
16#define OTHER 00007 /* other's bits */
17#define ALL 01777 /* all (note absence of setuid, etc) */
18
19#define READ 00444 /* read permit */
20#define WRITE 00222 /* write permit */
21#define EXEC 00111 /* exec permit */
22#define SETID 06000 /* set[ug]id */
23#define STICKY 01000 /* sticky bit */
24
25char *modestring, *ms;
26int um;
27int status;
8e2196fc 28int rflag, debug, Xflag;
473911a1
KL
29
30main(argc,argv)
31char **argv;
32{
33 register i;
8e2196fc 34 register char *p, *flags;
473911a1
KL
35 struct stat st;
36
37 if (argc < 3) {
38 fprintf(stderr
8e2196fc 39 ,"Usage: chmod [-RX] [ugoa][+-=][rwxstugo] file ...\n");
473911a1
KL
40 exit(-1);
41 }
8e2196fc 42
473911a1 43 argv++, --argc;
8e2196fc
KL
44 if (*argv[0] == '-') {
45 for (flags = argv[0]; *flags; ++flags)
46 switch (*flags) {
47 case '-': break;
48 case 'R': rflag++; break;
49 case 'X': Xflag++; break;
50 }
51 argv++, argc--;
473911a1 52 }
8e2196fc 53
473911a1
KL
54 modestring = argv[0];
55
56 um = umask(0);
57 (void) newmode(0);
58 for (i = 1; i < argc; i++) {
59 p = argv[i];
358d0c96 60 if (stat(p, &st) < 0) {
473911a1
KL
61 fprintf(stderr, "chmod: can't access %s\n", p);
62 ++status;
63 continue;
64 }
65 if (rflag && st.st_mode & S_IFDIR) {
66 status += chmodr(p, newmode(st.st_mode));
67 } else if (chmod(p, newmode(st.st_mode)) < 0) {
68 fprintf(stderr, "chmod: can't change %s\n", p);
69 ++status;
70 continue;
71 }
72 }
73 exit(status);
74}
75
76chmodr(dir, mode)
77 char *dir;
78{
79#define CHECK(name,sbuf)\
358d0c96 80 if (stat(name, sbuf) < 0) {\
473911a1
KL
81 fprintf(stderr, "chmod: can't access %s\n", dp->d_name);\
82 return(1);\
83 }
84
85 register DIR *dirp;
86 register struct direct *dp;
87 register struct stat st;
88 char savedir[1024];
89
90 if (getwd(savedir) == 0) {
91 fprintf(stderr, "chmod: %s\n", savedir);
92 exit(255);
93 }
94
95 /*
96 ** chmod what we are given before doing it's contents
97 */
98 chmod(dir, newmode(mode));
99
100 chdir(dir);
101 if ((dirp = opendir(".")) == NULL) {
102 perror(dir);
103 return(1);
104 }
105 dp = readdir(dirp);
106 dp = readdir(dirp); /* read "." and ".." */
107 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
108 CHECK(dp->d_name, &st);
109 chmod(dp->d_name, newmode(st.st_mode));
110 if (st.st_mode & S_IFDIR)
111 chmodr(dp->d_name, mode);
112 }
113 closedir(dirp);
114 chdir(savedir);
115 return(0);
116}
117
118newmode(nm)
119unsigned nm;
120{
121 register o, m, b;
122 int savem;
123
124 ms = modestring;
125 savem = nm;
126 m = abs();
127 if (!*ms) {
128 nm = m;
129 goto ret;
130 }
131 do {
132 m = who();
133 while (o = what()) {
134 b = where(nm);
135 switch (o) {
136 case '+':
137 nm |= b & m;
138 break;
139 case '-':
140 nm &= ~(b & m);
141 break;
142 case '=':
143 nm &= ~m;
144 nm |= b & m;
145 break;
146 }
147 }
148 } while (*ms++ == ',');
149 if (*--ms) {
150 fprintf(stderr, "chmod: invalid mode\n");
151 exit(255);
152 }
153ret:
8e2196fc
KL
154 if (Xflag && ((savem & S_IFDIR) || (savem & S_IEXEC)))
155 nm = nm | ((nm & 0444) >> 2);
473911a1
KL
156 return(nm);
157}
158
159abs()
160{
161 register c, i;
162
163 i = 0;
164 while ((c = *ms++) >= '0' && c <= '7')
165 i = (i << 3) + (c - '0');
166 ms--;
167 return(i);
168}
169
170who()
171{
172 register m;
173
174 m = 0;
175 for (;;) switch (*ms++) {
176 case 'u':
177 m |= USER;
178 continue;
179 case 'g':
180 m |= GROUP;
181 continue;
182 case 'o':
183 m |= OTHER;
184 continue;
185 case 'a':
186 m |= ALL;
187 continue;
188 default:
189 ms--;
190 if (m == 0)
191 m = ALL & ~um;
192 return m;
193 }
194}
195
196what()
197{
198
199 switch (*ms) {
200 case '+':
201 case '-':
202 case '=':
203 return *ms++;
204 }
205 return(0);
206}
207
208where(om)
209register om;
210{
211 register m;
212
213 m = 0;
214 switch (*ms) {
215 case 'u':
216 m = (om & USER) >> 6;
217 goto dup;
218 case 'g':
219 m = (om & GROUP) >> 3;
220 goto dup;
221 case 'o':
222 m = (om & OTHER);
223 dup:
224 m &= (READ|WRITE|EXEC);
225 m |= (m << 3) | (m << 6);
226 ++ms;
227 return m;
228 }
229 for (;;) switch (*ms++) {
230 case 'r':
231 m |= READ;
232 continue;
233 case 'w':
234 m |= WRITE;
235 continue;
236 case 'x':
237 m |= EXEC;
238 continue;
358d0c96
RC
239 case 'X':
240 Xflag++;
241 continue;
473911a1
KL
242 case 's':
243 m |= SETID;
244 continue;
245 case 't':
246 m |= STICKY;
247 continue;
248 default:
249 ms--;
250 return m;
251 }
252}