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.1 (Berkeley) 02/01/90"; 20 #endif /* LIBC_SCCS and not lint */ 21 22 #include <sys/types.h> 23 #include <sys/stat.h> 24 25 static mode_t setbits, clrbits, Xbits; 26 27 mode_t 28 getmode(omode) 29 mode_t omode; 30 { 31 register mode_t newmode; 32 33 newmode = omode & clrbits; 34 newmode |= setbits; 35 if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH)) 36 newmode |= Xbits; 37 return(newmode); 38 } 39 40 #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 41 #define CLR(a) { clrbits |= a; setbits &= ~(a); Xbits &= ~(a); } 42 43 setmode(p) 44 register char *p; 45 { 46 register int perm, who; 47 register char op; 48 mode_t mask; 49 int permXbits; 50 51 /* 52 * get a copy of the mask for the permissions that are mask 53 * relative. Flip the bits, we want what's not set. 54 */ 55 (void)umask(mask = umask(0)); 56 mask = ~mask; 57 58 setbits = clrbits = Xbits = 0; 59 60 /* 61 * if an absolute number, get it and return; disallow non-octal 62 * digits or illegal bits. 63 */ 64 if (isdigit(*p)) { 65 setbits = (mode_t)strtol(p, (char **)0, 8); 66 clrbits = ~(STANDARD_BITS|S_ISTXT); 67 Xbits = 0; 68 while (*++p) 69 if (*p < '0' || *p > '7') 70 return(-1); 71 if (setbits & clrbits) 72 return(-1); 73 return(0); 74 } 75 76 if (!*p) 77 return(-1); 78 /* 79 * accumulate bits to add and subtract from each clause of 80 * the symbolic mode 81 */ 82 for (;;) { 83 for (who = 0;; ++p) 84 switch (*p) { 85 case 'a': 86 who |= STANDARD_BITS; 87 break; 88 case 'u': 89 who |= S_ISUID|S_IRWXU; 90 break; 91 case 'g': 92 who |= S_ISGID|S_IRWXG; 93 break; 94 case 'o': 95 who |= S_IRWXO; 96 break; 97 default: 98 goto getop; 99 } 100 101 getop: if ((op = *p++) != '+' && op != '-' && op != '=') 102 return(-1); 103 104 who &= ~S_ISTXT; 105 for (perm = 0;; ++p) 106 switch (*p) { 107 case 'r': 108 perm |= S_IRUSR|S_IRGRP|S_IROTH; 109 break; 110 case 's': 111 /* if only "other" bits ignore set-id */ 112 if (who & ~S_IRWXO) 113 perm |= S_ISUID|S_ISGID; 114 break; 115 case 't': 116 /* if only "other" bits ignore sticky */ 117 if (who & ~S_IRWXO) { 118 who |= S_ISTXT; 119 perm |= S_ISTXT; 120 } 121 break; 122 case 'w': 123 perm |= S_IWUSR|S_IWGRP|S_IWOTH; 124 break; 125 case 'X': 126 permXbits = S_IXUSR|S_IXGRP|S_IXOTH; 127 break; 128 case 'x': 129 perm |= S_IXUSR|S_IXGRP|S_IXOTH; 130 break; 131 default: 132 goto apply; 133 } 134 135 apply: switch(op) { 136 case '+': 137 /* 138 * If no perm value, skip. If no who value, use umask 139 * bits. Don't bother clearing any bits, getmode 140 * clears first, then sets. 141 */ 142 if (perm || permXbits) { 143 if (!who) 144 who = mask; 145 if (permXbits) 146 Xbits |= who & permXbits; 147 setbits |= who & perm; 148 } 149 break; 150 case '-': 151 /* 152 * If no perm value, skip. If no who value, use 153 * owner, group, and other. 154 */ 155 if (perm) { 156 if (!who) 157 who = S_IRWXU|S_IRWXG|S_IRWXO; 158 CLR(who & perm); 159 } 160 break; 161 case '=': 162 /* 163 * If no who value, clear all the bits. Otherwise, 164 * clear the bits specified by who. 165 */ 166 if (!who) { 167 CLR(STANDARD_BITS); 168 who = mask; 169 } else 170 CLR(who); 171 if (perm) 172 setbits |= who & perm; 173 break; 174 } 175 176 if (!*p) 177 break; 178 if (*p != ',') 179 goto getop; 180 ++p; 181 } 182 clrbits = ~clrbits; 183 return(0); 184 } 185