fixed font swapping to not forget name of font that was in old position
[unix-history] / usr / src / bin / chmod / chmod.c
CommitLineData
e4261a61 1static char *sccsid = "@(#)chmod.c 4.5 %G%";
473911a1
KL
2
3/*
4 * chmod options mode files
5 * where
e4261a61 6 * mode is [ugoa][+-=][rwxXstugo] or a octal number
473911a1
KL
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;
e4261a61 28int rflag, debug;
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
e4261a61 37usage:
473911a1
KL
38 if (argc < 3) {
39 fprintf(stderr
e4261a61 40 ,"Usage: chmod [-R] [ugoa][+-=][rwxXstugo] file ...\n");
473911a1
KL
41 exit(-1);
42 }
8e2196fc 43
473911a1 44 argv++, --argc;
8e2196fc
KL
45 if (*argv[0] == '-') {
46 for (flags = argv[0]; *flags; ++flags)
47 switch (*flags) {
48 case '-': break;
49 case 'R': rflag++; break;
e4261a61 50 default: argc = 0; goto usage;
8e2196fc
KL
51 }
52 argv++, argc--;
473911a1 53 }
8e2196fc 54
473911a1
KL
55 modestring = argv[0];
56
57 um = umask(0);
58 (void) newmode(0);
59 for (i = 1; i < argc; i++) {
60 p = argv[i];
358d0c96 61 if (stat(p, &st) < 0) {
473911a1
KL
62 fprintf(stderr, "chmod: can't access %s\n", p);
63 ++status;
64 continue;
65 }
66 if (rflag && st.st_mode & S_IFDIR) {
67 status += chmodr(p, newmode(st.st_mode));
68 } else if (chmod(p, newmode(st.st_mode)) < 0) {
69 fprintf(stderr, "chmod: can't change %s\n", p);
70 ++status;
71 continue;
72 }
73 }
74 exit(status);
75}
76
77chmodr(dir, mode)
78 char *dir;
79{
473911a1
KL
80 register DIR *dirp;
81 register struct direct *dp;
82 register struct stat st;
83 char savedir[1024];
84
85 if (getwd(savedir) == 0) {
86 fprintf(stderr, "chmod: %s\n", savedir);
87 exit(255);
88 }
89
90 /*
91 ** chmod what we are given before doing it's contents
92 */
93 chmod(dir, newmode(mode));
94
95 chdir(dir);
96 if ((dirp = opendir(".")) == NULL) {
97 perror(dir);
98 return(1);
99 }
100 dp = readdir(dirp);
101 dp = readdir(dirp); /* read "." and ".." */
102 for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
e4261a61
KM
103 if (stat(dp->d_name, &st) < 0) {
104 fprintf(stderr, "chmod: can't access %s\n", dp->d_name);
105 return(1);
106 }
473911a1
KL
107 chmod(dp->d_name, newmode(st.st_mode));
108 if (st.st_mode & S_IFDIR)
109 chmodr(dp->d_name, mode);
110 }
111 closedir(dirp);
112 chdir(savedir);
113 return(0);
114}
115
116newmode(nm)
117unsigned nm;
118{
119 register o, m, b;
120 int savem;
121
122 ms = modestring;
123 savem = nm;
124 m = abs();
e4261a61
KM
125 if (!*ms)
126 return(m);
473911a1
KL
127 do {
128 m = who();
129 while (o = what()) {
130 b = where(nm);
131 switch (o) {
132 case '+':
133 nm |= b & m;
134 break;
135 case '-':
136 nm &= ~(b & m);
137 break;
138 case '=':
139 nm &= ~m;
140 nm |= b & m;
141 break;
142 }
143 }
144 } while (*ms++ == ',');
145 if (*--ms) {
146 fprintf(stderr, "chmod: invalid mode\n");
147 exit(255);
148 }
473911a1
KL
149 return(nm);
150}
151
152abs()
153{
154 register c, i;
155
156 i = 0;
157 while ((c = *ms++) >= '0' && c <= '7')
158 i = (i << 3) + (c - '0');
159 ms--;
160 return(i);
161}
162
163who()
164{
165 register m;
166
167 m = 0;
168 for (;;) switch (*ms++) {
169 case 'u':
170 m |= USER;
171 continue;
172 case 'g':
173 m |= GROUP;
174 continue;
175 case 'o':
176 m |= OTHER;
177 continue;
178 case 'a':
179 m |= ALL;
180 continue;
181 default:
182 ms--;
183 if (m == 0)
184 m = ALL & ~um;
185 return m;
186 }
187}
188
189what()
190{
191
192 switch (*ms) {
193 case '+':
194 case '-':
195 case '=':
196 return *ms++;
197 }
198 return(0);
199}
200
201where(om)
202register om;
203{
204 register m;
205
206 m = 0;
207 switch (*ms) {
208 case 'u':
209 m = (om & USER) >> 6;
210 goto dup;
211 case 'g':
212 m = (om & GROUP) >> 3;
213 goto dup;
214 case 'o':
215 m = (om & OTHER);
216 dup:
217 m &= (READ|WRITE|EXEC);
218 m |= (m << 3) | (m << 6);
219 ++ms;
220 return m;
221 }
222 for (;;) switch (*ms++) {
223 case 'r':
224 m |= READ;
225 continue;
226 case 'w':
227 m |= WRITE;
228 continue;
229 case 'x':
230 m |= EXEC;
231 continue;
358d0c96 232 case 'X':
e4261a61
KM
233 if ((om & S_IFDIR) || (om & EXEC))
234 m |= EXEC;
358d0c96 235 continue;
473911a1
KL
236 case 's':
237 m |= SETID;
238 continue;
239 case 't':
240 m |= STICKY;
241 continue;
242 default:
243 ms--;
244 return m;
245 }
246}