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