1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char sccsid[] = "@(#)chmod.c 5.5 (Berkeley) 5/22/86";
9: #endif
10:
11: /*
12: * chmod options mode files
13: * where
14: * mode is [ugoa][+-=][rwxXstugo] or an octal number
15: * options are -Rf
16: */
17: #include <stdio.h>
18: #include <sys/types.h>
19: #include <sys/stat.h>
20: #include <sys/dir.h>
21:
22: char *modestring, *ms;
23: int um;
24: int status;
25: int fflag;
26: int rflag;
27:
28: main(argc, argv)
29: char *argv[];
30: {
31: register char *p, *flags;
32: register int i;
33: struct stat st;
34:
35: if (argc < 3) {
36: fprintf(stderr,
37: "Usage: chmod [-Rf] [ugoa][+-=][rwxXstugo] file ...\n");
38: exit(-1);
39: }
40: argv++, --argc;
41: while (argc > 0 && argv[0][0] == '-') {
42: for (p = &argv[0][1]; *p; p++) switch (*p) {
43:
44: case 'R':
45: rflag++;
46: break;
47:
48: case 'f':
49: fflag++;
50: break;
51:
52: default:
53: goto done;
54: }
55: argc--, argv++;
56: }
57: done:
58: modestring = argv[0];
59: um = umask(0);
60: (void) newmode(0);
61: for (i = 1; i < argc; i++) {
62: p = argv[i];
63: /* do stat for directory arguments */
64: if (lstat(p, &st) < 0) {
65: status += Perror(p);
66: continue;
67: }
68: if (rflag && (st.st_mode&S_IFMT) == S_IFDIR) {
69: status += chmodr(p, newmode(st.st_mode));
70: continue;
71: }
72: if ((st.st_mode&S_IFMT) == S_IFLNK && stat(p, &st) < 0) {
73: status += Perror(p);
74: continue;
75: }
76: if (chmod(p, newmode(st.st_mode)) < 0) {
77: status += Perror(p);
78: continue;
79: }
80: }
81: exit(status);
82: }
83:
84: chmodr(dir, mode)
85: char *dir;
86: {
87: register DIR *dirp;
88: register struct direct *dp;
89: register struct stat st;
90: char savedir[1024];
91: int ecode;
92:
93: if (getwd(savedir) == 0)
94: fatal(255, "%s", savedir);
95: /*
96: * Change what we are given before doing it's contents
97: */
98: if (chmod(dir, newmode(mode)) < 0 && Perror(dir))
99: return (1);
100: if (chdir(dir) < 0) {
101: Perror(dir);
102: return (1);
103: }
104: if ((dirp = opendir(".")) == NULL) {
105: Perror(dir);
106: return (1);
107: }
108: dp = readdir(dirp);
109: dp = readdir(dirp); /* read "." and ".." */
110: ecode = 0;
111: for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
112: if (lstat(dp->d_name, &st) < 0) {
113: ecode = Perror(dp->d_name);
114: if (ecode)
115: break;
116: continue;
117: }
118: if ((st.st_mode&S_IFMT) == S_IFDIR) {
119: ecode = chmodr(dp->d_name, newmode(st.st_mode));
120: if (ecode)
121: break;
122: continue;
123: }
124: if ((st.st_mode&S_IFMT) == S_IFLNK)
125: continue;
126: if (chmod(dp->d_name, newmode(st.st_mode)) < 0 &&
127: (ecode = Perror(dp->d_name)))
128: break;
129: }
130: closedir(dirp);
131: if (chdir(savedir) < 0)
132: fatal(255, "can't change back to %s", savedir);
133: return (ecode);
134: }
135:
136: error(fmt, a)
137: char *fmt, *a;
138: {
139:
140: if (!fflag) {
141: fprintf(stderr, "chmod: ");
142: fprintf(stderr, fmt, a);
143: putc('\n', stderr);
144: }
145: return (!fflag);
146: }
147:
148: fatal(status, fmt, a)
149: int status;
150: char *fmt, *a;
151: {
152:
153: fflag = 0;
154: (void) error(fmt, a);
155: exit(status);
156: }
157:
158: Perror(s)
159: char *s;
160: {
161:
162: if (!fflag) {
163: fprintf(stderr, "chmod: ");
164: perror(s);
165: }
166: return (!fflag);
167: }
168:
169: newmode(nm)
170: unsigned nm;
171: {
172: register o, m, b;
173: int savem;
174:
175: ms = modestring;
176: savem = nm;
177: m = abs();
178: if (*ms == '\0')
179: return (m);
180: do {
181: m = who();
182: while (o = what()) {
183: b = where(nm);
184: switch (o) {
185: case '+':
186: nm |= b & m;
187: break;
188: case '-':
189: nm &= ~(b & m);
190: break;
191: case '=':
192: nm &= ~m;
193: nm |= b & m;
194: break;
195: }
196: }
197: } while (*ms++ == ',');
198: if (*--ms)
199: fatal(255, "invalid mode");
200: return (nm);
201: }
202:
203: abs()
204: {
205: register c, i;
206:
207: i = 0;
208: while ((c = *ms++) >= '0' && c <= '7')
209: i = (i << 3) + (c - '0');
210: ms--;
211: return (i);
212: }
213:
214: #define USER 05700 /* user's bits */
215: #define GROUP 02070 /* group's bits */
216: #define OTHER 00007 /* other's bits */
217: #define ALL 01777 /* all (note absence of setuid, etc) */
218:
219: #define READ 00444 /* read permit */
220: #define WRITE 00222 /* write permit */
221: #define EXEC 00111 /* exec permit */
222: #define SETID 06000 /* set[ug]id */
223: #define STICKY 01000 /* sticky bit */
224:
225: who()
226: {
227: register m;
228:
229: m = 0;
230: for (;;) switch (*ms++) {
231: case 'u':
232: m |= USER;
233: continue;
234: case 'g':
235: m |= GROUP;
236: continue;
237: case 'o':
238: m |= OTHER;
239: continue;
240: case 'a':
241: m |= ALL;
242: continue;
243: default:
244: ms--;
245: if (m == 0)
246: m = ALL & ~um;
247: return (m);
248: }
249: }
250:
251: what()
252: {
253:
254: switch (*ms) {
255: case '+':
256: case '-':
257: case '=':
258: return (*ms++);
259: }
260: return (0);
261: }
262:
263: where(om)
264: register om;
265: {
266: register m;
267:
268: m = 0;
269: switch (*ms) {
270: case 'u':
271: m = (om & USER) >> 6;
272: goto dup;
273: case 'g':
274: m = (om & GROUP) >> 3;
275: goto dup;
276: case 'o':
277: m = (om & OTHER);
278: dup:
279: m &= (READ|WRITE|EXEC);
280: m |= (m << 3) | (m << 6);
281: ++ms;
282: return (m);
283: }
284: for (;;) switch (*ms++) {
285: case 'r':
286: m |= READ;
287: continue;
288: case 'w':
289: m |= WRITE;
290: continue;
291: case 'x':
292: m |= EXEC;
293: continue;
294: case 'X':
295: if ((om & S_IFDIR) || (om & EXEC))
296: m |= EXEC;
297: continue;
298: case 's':
299: m |= SETID;
300: continue;
301: case 't':
302: m |= STICKY;
303: continue;
304: default:
305: ms--;
306: return (m);
307: }
308: }
Defined functions
abs
defined in line
203; used 1 times
main
defined in line
28;
never used
what
defined in line
251; used 1 times
who
defined in line
225; used 1 times
Defined variables
fflag
defined in line
25; used 6 times
ms
defined in line
22; used 14 times
rflag
defined in line
26; used 2 times
sccsid
defined in line
8;
never used
um
defined in line
23; used 2 times
Defined macros
ALL
defined in line
217; used 2 times
EXEC
defined in line
221; used 4 times
READ
defined in line
219; used 2 times
USER
defined in line
214; used 2 times