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