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