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