|
|
1.1 root 1: /*
2: * Chmod -- change the mode of
3: * files (both symbolic and octal)
4: * I really don't like the syntax though.
5: */
6:
7: #include <stdio.h>
8: #include <sys/stat.h>
9:
10: /* Masks by types of permissions */
11: #define AEXEC (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))
12: #define AREAD (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6))
13: #define AWRITE (S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6))
14: #define ASUID (S_ISUID|S_ISGID)
15: #define ATEXT S_ISVTX
16:
17: /* Masks by types of users */
18: #define AOWN (S_ISUID|S_ISVTX|S_IREAD|S_IWRITE|S_IEXEC)
19: #define AGRP (S_ISGID|S_ISVTX|(S_IREAD>>3)|(S_IWRITE>>3)|(S_IEXEC>>3))
20: #define AOTH (S_ISVTX|(S_IREAD>>6)|(S_IWRITE>>6)|(S_IEXEC>>6))
21: #define AALL (AOWN|AGRP|AOTH)
22:
23: short int uid;
24:
25: char stickwarn[] = "\
26: chmod: Warning: non-super user may not set sticky bit\n\
27: ";
28:
29: main(argc, argv)
30: char *argv[];
31: {
32: register int i;
33: register char *fn;
34: int status = 0;
35:
36: if (argc < 3)
37: usage();
38: uid = getuid();
39: for (i=2; i<argc; i++) {
40: fn = argv[i];
41: if (chmod(fn, readmode(argv[1], fn)) < 0) {
42: perror(fn);
43: status = 2;
44: }
45: }
46: exit (status);
47: }
48:
49: /*
50: * Read in the symbolic mode and
51: * set the variables `who', `op',
52: * and `mode'.
53: * Knows about the old octal modes as well.
54: */
55: readmode(s, file)
56: register char *s;
57: char *file;
58: {
59: register int c;
60: register int mode;
61: register int op;
62: register int m1, m2;
63: struct stat sb;
64:
65: mode = 0;
66: if (*s>='0' && *s<='7') {
67: while (*s != '\0') {
68: if (*s<'0' || *s>'7')
69: omusage();
70: mode = (mode<<3) | *s++-'0';
71: }
72: checkmode(mode);
73: return (mode);
74: }
75: sb.st_mode = 0;
76: stat(file, &sb);
77: mode = sb.st_mode;
78: newsym:
79: m1 = 0;
80: for (;;) {
81: switch (*s++) {
82: case 'u':
83: m1 |= AOWN;
84: continue;
85:
86: case 'g':
87: m1 |= AGRP;
88: continue;
89:
90: case 'o':
91: m1 |= AOTH;
92: continue;
93:
94: case 'a':
95: m1 |= AALL;
96: continue;
97:
98: default:
99: s--;
100: break;
101: }
102: break;
103: }
104: if (m1 == 0) {
105: m1 = AALL&~getumask();
106: }
107: newop:
108: if ((c = *s++)=='=' || c=='+' || c=='-')
109: op = c;
110: else
111: smusage();
112: m2 = 0;
113: for (;;) {
114: switch (*s++) {
115: case 'r':
116: m2 |= AREAD;
117: continue;
118:
119: case 'w':
120: m2 |= AWRITE;
121: continue;
122:
123: case 'x':
124: m2 |= AEXEC;
125: continue;
126:
127: case 's':
128: m2 |= ASUID;
129: continue;
130:
131: case 't':
132: m2 |= ATEXT;
133: continue;
134:
135: case 'u':
136: m2 |= mrepl(mode&AOWN);
137: continue;
138:
139: case 'g':
140: m2 |= mrepl((mode&AGRP)<<3);
141: continue;
142:
143: case 'o':
144: m2 |= mrepl((mode&AOTH)<<6);
145: continue;
146:
147: default:
148: s--;
149: break;
150: }
151: break;
152: }
153: switch (op) {
154: case '-':
155: mode &= ~(m1&m2);
156: break;
157:
158: case '+':
159: mode |= m1&m2;
160: break;
161:
162: case '=':
163: mode = (mode&~m1) | (m1&m2);
164: break;
165: }
166: if (*s == '\0') {
167: checkmode(mode);
168: return (mode);
169: }
170: if (*s=='+' || *s=='-' || *s=='=')
171: goto newop;
172: if (*s++ == ',')
173: goto newsym;
174: smusage();
175: }
176:
177: /*
178: * Get the value of the umask setting.
179: */
180: getumask()
181: {
182: register int omask;
183:
184: omask = umask(0);
185: umask(omask);
186: return (omask);
187: }
188:
189: /*
190: * Check the mode to see if any problem
191: * bits are on. For now, this is
192: * S_ISVTX for non-super-users.
193: */
194: checkmode(mode)
195: register int mode;
196: {
197: static int beenhere;
198:
199: if (!beenhere && uid!=0 && mode&S_ISVTX) {
200: fprintf(stderr, stickwarn);
201: beenhere++;
202: }
203: }
204:
205: /*
206: * Replicate the 3-bits of the mode from
207: * the owner position to all positions.
208: */
209: mrepl(m)
210: register int m;
211: {
212: register int m1;
213:
214: m1 = m&AOWN;
215: m = m1 | (m1>>3) | (m1>>6);
216: if (m1 & S_ISUID)
217: m |= S_ISGID;
218: return (m);
219: }
220:
221: usage()
222: {
223: fprintf(stderr, "Usage: chmod mode file ...\n");
224: exit(1);
225: }
226:
227: smusage()
228: {
229: fprintf(stderr, "chmod: badly formed symbolic mode\n");
230: exit(1);
231: }
232:
233: omusage()
234: {
235: fprintf(stderr, "chmod: badly formed octal mode\n");
236: exit(1);
237: }
238:
239:
240:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.