|
|
1.1 root 1: /*
2: * Copyright (c) 1989 The Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted
6: * provided that: (1) source distributions retain this entire copyright
7: * notice and comment, and (2) distributions including binaries display
8: * the following acknowledgement: ``This product includes software
9: * developed by the University of California, Berkeley and its contributors''
10: * in the documentation or other materials provided with the distribution
11: * and in all advertising materials mentioning features or use of this
12: * software. Neither the name of the University nor the names of its
13: * contributors may be used to endorse or promote products derived
14: * from this software without specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17: * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #if defined(LIBC_SCCS) && !defined(lint)
21: static char sccsid[] = "@(#)setmode.c 5.3 (Berkeley) 6/1/90";
22: #endif /* LIBC_SCCS and not lint */
23:
24: #include <sys/types.h>
25: #include <sys/stat.h>
26: #include <errno.h>
27: #include <stdio.h>
28:
29: #define setbits set[0]
30: #define clrbits set[1]
31: #define Xbits set[2]
32:
33: mode_t
34: getmode(set, omode)
35: mode_t *set, omode;
36: {
37: register mode_t newmode;
38:
39: newmode = omode & clrbits;
40: newmode |= setbits;
41: if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
42: newmode |= Xbits;
43: return(newmode);
44: }
45:
46: #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
47: #define CLR(a) { clrbits |= a; setbits &= ~(a); Xbits &= ~(a); }
48:
49: mode_t *
50: setmode(p)
51: register char *p;
52: {
53: extern int errno;
54: register int perm, who;
55: register char op;
56: mode_t mask, *set;
57: int permXbits;
58: char *malloc();
59:
60: /*
61: * get a copy of the mask for the permissions that are mask
62: * relative. Flip the bits, we want what's not set.
63: */
64: (void)umask(mask = umask(0));
65: mask = ~mask;
66:
67: if (!(set = (mode_t *)malloc((u_int)(sizeof(mode_t) * 3)))) {
68: errno = ENOMEM;
69: return(NULL);
70: }
71:
72: setbits = clrbits = Xbits = 0;
73:
74: /*
75: * if an absolute number, get it and return; disallow non-octal
76: * digits or illegal bits.
77: */
78: if (isdigit(*p)) {
79: setbits = (mode_t)strtol(p, (char **)0, 8);
80: clrbits = ~(STANDARD_BITS|S_ISTXT);
81: Xbits = 0;
82: while (*++p)
83: if (*p < '0' || *p > '7')
84: return(NULL);
85: if (setbits & clrbits)
86: return(NULL);
87: return(set);
88: }
89:
90: if (!*p)
91: return(NULL);
92: /*
93: * accumulate bits to add and subtract from each clause of
94: * the symbolic mode
95: */
96: for (;;) {
97: for (who = 0;; ++p)
98: switch (*p) {
99: case 'a':
100: who |= STANDARD_BITS;
101: break;
102: case 'u':
103: who |= S_ISUID|S_IRWXU;
104: break;
105: case 'g':
106: who |= S_ISGID|S_IRWXG;
107: break;
108: case 'o':
109: who |= S_IRWXO;
110: break;
111: default:
112: goto getop;
113: }
114:
115: getop: if ((op = *p++) != '+' && op != '-' && op != '=')
116: return(NULL);
117:
118: who &= ~S_ISTXT;
119: for (perm = 0;; ++p)
120: switch (*p) {
121: case 'r':
122: perm |= S_IRUSR|S_IRGRP|S_IROTH;
123: break;
124: case 's':
125: /* if only "other" bits ignore set-id */
126: if (who & ~S_IRWXO)
127: perm |= S_ISUID|S_ISGID;
128: break;
129: case 't':
130: /* if only "other" bits ignore sticky */
131: if (who & ~S_IRWXO) {
132: who |= S_ISTXT;
133: perm |= S_ISTXT;
134: }
135: break;
136: case 'w':
137: perm |= S_IWUSR|S_IWGRP|S_IWOTH;
138: break;
139: case 'X':
140: permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
141: break;
142: case 'x':
143: perm |= S_IXUSR|S_IXGRP|S_IXOTH;
144: break;
145: default:
146: goto apply;
147: }
148:
149: apply: switch(op) {
150: case '+':
151: /*
152: * If no perm value, skip. If no who value, use umask
153: * bits. Don't bother clearing any bits, getmode
154: * clears first, then sets.
155: */
156: if (perm || permXbits) {
157: if (!who)
158: who = mask;
159: if (permXbits)
160: Xbits |= who & permXbits;
161: setbits |= who & perm;
162: }
163: break;
164: case '-':
165: /*
166: * If no perm value, skip. If no who value, use
167: * owner, group, and other.
168: */
169: if (perm) {
170: if (!who)
171: who = S_IRWXU|S_IRWXG|S_IRWXO;
172: CLR(who & perm);
173: }
174: break;
175: case '=':
176: /*
177: * If no who value, clear all the bits. Otherwise,
178: * clear the bits specified by who.
179: */
180: if (!who) {
181: CLR(STANDARD_BITS);
182: who = mask;
183: } else
184: CLR(who);
185: if (perm)
186: setbits |= who & perm;
187: break;
188: }
189:
190: if (!*p)
191: break;
192: if (*p != ',')
193: goto getop;
194: ++p;
195: }
196: clrbits = ~clrbits;
197: return(set);
198: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.