# 2.11BSD#431 - /usr/src/lib/libc/gen/setmode.c

##### Functions

    getmode           X
    setmode           X

##### Macros

    ADDCMD            X
    CMD2_CLR          X
    CMD2_GBITS        X
    CMD2_OBITS        X
    CMD2_SET          X
    CMD2_UBITS        X
    SET_LEN           X
    SET_LEN_INCR      X
    STANDARD_BITS     X

##### struct's

    bitcmd            X

##### typedef's

    BITCMD            X

       1: /*
       2:  * Copyright (c) 1989, 1993, 1994
       3:  *	The Regents of the University of California.  All rights reserved.
       4:  *
       5:  * This code is derived from software contributed to Berkeley by
       6:  * Dave Borman at Cray Research, Inc.
       7:  *
       8:  * Redistribution and use in source and binary forms, with or without
       9:  * modification, are permitted provided that the following conditions
      10:  * are met:
      11:  * 1. Redistributions of source code must retain the above copyright
      12:  *    notice, this list of conditions and the following disclaimer.
      13:  * 2. Redistributions in binary form must reproduce the above copyright
      14:  *    notice, this list of conditions and the following disclaimer in the
      15:  *    documentation and/or other materials provided with the distribution.
      16:  * 3. All advertising materials mentioning features or use of this software
      17:  *    must display the following acknowledgement:
      18:  *	This product includes software developed by the University of
      19:  *	California, Berkeley and its contributors.
      20:  * 4. Neither the name of the University nor the names of its contributors
      21:  *    may be used to endorse or promote products derived from this software
      22:  *    without specific prior written permission.
      23:  *
      24:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      25:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      26:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      27:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      28:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      29:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      30:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      31:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      32:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      33:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      34:  * SUCH DAMAGE.
      35:  */
      36:
      37: #if defined(LIBC_SCCS) && !defined(lint)
      38: static char sccsid[] = "@(#)setmode.c	8.2.1 (2.11BSD) 1996/2/20";
      39: #endif /* LIBC_SCCS and not lint */
      40:
      41: #include <sys/types.h>
      42: #include <sys/stat.h>
      43:
      44: #include <ctype.h>
      45: #include <errno.h>
      46: #include <signal.h>
      47: #include <sys/stddef.h>
      48: #include <stdlib.h>
      49:
      50: #ifdef SETMODE_DEBUG
      51: #include <stdio.h>
      52: #endif
      53:
      54: #define SET_LEN 6       /* initial # of bitcmd struct to malloc */
      55: #define SET_LEN_INCR 4      /* # of bitcmd structs to add as needed */
      56:
      57: typedef struct bitcmd {
      58:     char    cmd;
      59:     char    cmd2;
      60:     mode_t  bits;
      61: } BITCMD;
      62:
      63: #define CMD2_CLR    0x01
      64: #define CMD2_SET    0x02
      65: #define CMD2_GBITS  0x04
      66: #define CMD2_OBITS  0x08
      67: #define CMD2_UBITS  0x10
      68:
      69: static BITCMD   *addcmd();
      70: static int   compress_mode();
      71: #ifdef SETMODE_DEBUG
      72: static void  dumpmode();
      73: #endif
      74:
      75: /*
      76:  * Given the old mode and an array of bitcmd structures, apply the operations
      77:  * described in the bitcmd structures to the old mode, and return the new mode.
      78:  * Note that there is no '=' command; a strict assignment is just a '-' (clear
      79:  * bits) followed by a '+' (set bits).
      80:  */
      81: mode_t
      82: getmode(bbox, omode)
      83:     void *bbox;
      84:     mode_t omode;
      85: {
      86:     register BITCMD *set;
      87:     register mode_t clrval, newmode, value;
      88:
      89:     set = (BITCMD *)bbox;
      90:     newmode = omode;
      91:     for (value = 0;; set++)
      92:         switch(set->cmd) {
      93:         /*
      94: 		 * When copying the user, group or other bits around, we "know"
      95: 		 * where the bits are in the mode so that we can do shifts to
      96: 		 * copy them around.  If we don't use shifts, it gets real
      97: 		 * grundgy with lots of single bit checks and bit sets.
      98: 		 */
      99:         case 'u':
     100:             value = (newmode & S_IRWXU) >> 6;
     101:             goto common;
     102:
     103:         case 'g':
     104:             value = (newmode & S_IRWXG) >> 3;
     105:             goto common;
     106:
     107:         case 'o':
     108:             value = newmode & S_IRWXO;
     109: common:         if (set->cmd2 & CMD2_CLR) {
     110:                 clrval =
     111:                     (set->cmd2 & CMD2_SET) ?  S_IRWXO : value;
     112:                 if (set->cmd2 & CMD2_UBITS)
     113:                     newmode &= ~((clrval<<6) & set->bits);
     114:                 if (set->cmd2 & CMD2_GBITS)
     115:                     newmode &= ~((clrval<<3) & set->bits);
     116:                 if (set->cmd2 & CMD2_OBITS)
     117:                     newmode &= ~(clrval & set->bits);
     118:             }
     119:             if (set->cmd2 & CMD2_SET) {
     120:                 if (set->cmd2 & CMD2_UBITS)
     121:                     newmode |= (value<<6) & set->bits;
     122:                 if (set->cmd2 & CMD2_GBITS)
     123:                     newmode |= (value<<3) & set->bits;
     124:                 if (set->cmd2 & CMD2_OBITS)
     125:                     newmode |= value & set->bits;
     126:             }
     127:             break;
     128:
     129:         case '+':
     130:             newmode |= set->bits;
     131:             break;
     132:
     133:         case '-':
     134:             newmode &= ~set->bits;
     135:             break;
     136:
     137:         case 'X':
     138:             if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
     139:                 newmode |= set->bits;
     140:             break;
     141:
     142:         case '\0':
     143:         default:
     144: #ifdef SETMODE_DEBUG
     145:             (void)printf("getmode:%04o -> %04o\n", omode, newmode);
     146: #endif
     147:             return (newmode);
     148:         }
     149: }
     150:
     151: #define ADDCMD(a, b, c, d)                      \
     152:     if (set >= endset) {                        \
     153:         register BITCMD *newset;                \
     154:         setlen += SET_LEN_INCR;                 \
     155:         newset = (BITCMD *)realloc(saveset, sizeof(BITCMD) * setlen); \
     156:         if (!saveset)                       \
     157:             return ((void *)NULL);              \
     158:         set = newset + (set - saveset);             \
     159:         saveset = newset;                   \
     160:         endset = newset + (setlen - 2);             \
     161:     }                               \
     162:     set = addcmd(set, (a), (b), (c), (d))
     163:
     164: #define STANDARD_BITS   (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
     165:
     166: void *
     167: setmode(p)
     168:     register char *p;
     169: {
     170:     register int perm, who;
     171:     char op;
     172:     BITCMD *set, *saveset, *endset;
     173: #ifdef  notnow
     174:     sigset_t sigset, sigoset;
     175: #endif
     176:     mode_t mask;
     177:     int equalopdone, permXbits, setlen;
     178:
     179:     if (!*p)
     180:         return ((void *)NULL);
     181:
     182: #ifdef  notnow
     183:     /*
     184: 	 * Get a copy of the mask for the permissions that are mask relative.
     185: 	 * Flip the bits, we want what's not set.  Since it's possible that
     186: 	 * the caller is opening files inside a signal handler, protect them
     187: 	 * as best we can.
     188: 	 */
     189:     sigfillset(&sigset);
     190:         (void)sigprocmask(SIG_BLOCK, &sigset, &sigoset);
     191: #endif
     192:     (void)umask(mask = umask(0));
     193:     mask = ~mask;
     194: #ifdef  notnow
     195:         (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
     196: #endif
     197:
     198:     setlen = SET_LEN + 2;
     199:
     200:     if ((set = (BITCMD *)malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
     201:         return ((void *)NULL);
     202:     saveset = set;
     203:     endset = set + (setlen - 2);
     204:
     205:     /*
     206: 	 * If an absolute number, get it and return; disallow non-octal digits
     207: 	 * or illegal bits.
     208: 	 */
     209:     if (isdigit(*p)) {
     210:         perm = (mode_t)strtol(p, NULL, 8);
     211:         if (perm & ~(STANDARD_BITS|S_ISVTX)) {
     212:             free(saveset);
     213:             return ((void *)NULL);
     214:         }
     215:         while (*++p)
     216:             if (*p < '0' || *p > '7') {
     217:                 free(saveset);
     218:                 return ((void *)NULL);
     219:             }
     220:         ADDCMD('=', (STANDARD_BITS|S_ISVTX), perm, mask);
     221:         return ((void *)saveset);
     222:     }
     223:
     224:     /*
     225: 	 * Build list of structures to set/clear/copy bits as described by
     226: 	 * each clause of the symbolic mode.
     227: 	 */
     228:     for (;;) {
     229:         /* First, find out which bits might be modified. */
     230:         for (who = 0;; ++p) {
     231:             switch (*p) {
     232:             case 'a':
     233:                 who |= STANDARD_BITS;
     234:                 break;
     235:             case 'u':
     236:                 who |= S_ISUID|S_IRWXU;
     237:                 break;
     238:             case 'g':
     239:                 who |= S_ISGID|S_IRWXG;
     240:                 break;
     241:             case 'o':
     242:                 who |= S_IRWXO;
     243:                 break;
     244:             default:
     245:                 goto getop;
     246:             }
     247:         }
     248:
     249: getop:      if ((op = *p++) != '+' && op != '-' && op != '=') {
     250:             free(saveset);
     251:             return ((void *)NULL);
     252:         }
     253:         if (op == '=')
     254:             equalopdone = 0;
     255:
     256:         who &= ~S_ISVTX;
     257:         for (perm = 0, permXbits = 0;; ++p) {
     258:             switch (*p) {
     259:             case 'r':
     260:                 perm |= S_IRUSR|S_IRGRP|S_IROTH;
     261:                 break;
     262:             case 's':
     263:                 /* If only "other" bits ignore set-id. */
     264:                 if (who & ~S_IRWXO)
     265:                     perm |= S_ISUID|S_ISGID;
     266:                 break;
     267:             case 't':
     268:                 /* If only "other" bits ignore sticky. */
     269:                 if (who & ~S_IRWXO) {
     270:                     who |= S_ISVTX;
     271:                     perm |= S_ISVTX;
     272:                 }
     273:                 break;
     274:             case 'w':
     275:                 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
     276:                 break;
     277:             case 'X':
     278:                 permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
     279:                 break;
     280:             case 'x':
     281:                 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
     282:                 break;
     283:             case 'u':
     284:             case 'g':
     285:             case 'o':
     286:                 /*
     287: 				 * When ever we hit 'u', 'g', or 'o', we have
     288: 				 * to flush out any partial mode that we have,
     289: 				 * and then do the copying of the mode bits.
     290: 				 */
     291:                 if (perm) {
     292:                     ADDCMD(op, who, perm, mask);
     293:                     perm = 0;
     294:                 }
     295:                 if (op == '=')
     296:                     equalopdone = 1;
     297:                 if (op == '+' && permXbits) {
     298:                     ADDCMD('X', who, permXbits, mask);
     299:                     permXbits = 0;
     300:                 }
     301:                 ADDCMD(*p, who, op, mask);
     302:                 break;
     303:
     304:             default:
     305:                 /*
     306: 				 * Add any permissions that we haven't already
     307: 				 * done.
     308: 				 */
     309:                 if (perm || (op == '=' && !equalopdone)) {
     310:                     if (op == '=')
     311:                         equalopdone = 1;
     312:                     ADDCMD(op, who, perm, mask);
     313:                     perm = 0;
     314:                 }
     315:                 if (permXbits) {
     316:                     ADDCMD('X', who, permXbits, mask);
     317:                     permXbits = 0;
     318:                 }
     319:                 goto apply;
     320:             }
     321:         }
     322:
     323: apply:      if (!*p)
     324:             break;
     325:         if (*p != ',')
     326:             goto getop;
     327:         ++p;
     328:     }
     329:     set->cmd = 0;
     330: #ifdef SETMODE_DEBUG
     331:     (void)printf("Before compress_mode()\n");
     332:     dumpmode(saveset);
     333: #endif
     334:     compress_mode(saveset);
     335: #ifdef SETMODE_DEBUG
     336:     (void)printf("After compress_mode()\n");
     337:     dumpmode(saveset);
     338: #endif
     339:     return ((void *)saveset);
     340: }
     341:
     342: static BITCMD *
     343: addcmd(set, op, who, oparg, mask)
     344:     BITCMD *set;
     345:     register int oparg, who;
     346:     register int op;
     347:     u_int mask;
     348: {
     349:     switch (op) {
     350:     case '=':
     351:         set->cmd = '-';
     352:         set->bits = who ? who : STANDARD_BITS;
     353:         set++;
     354:
     355:         op = '+';
     356:         /* FALLTHROUGH */
     357:     case '+':
     358:     case '-':
     359:     case 'X':
     360:         set->cmd = op;
     361:         set->bits = (who ? who : mask) & oparg;
     362:         break;
     363:
     364:     case 'u':
     365:     case 'g':
     366:     case 'o':
     367:         set->cmd = op;
     368:         if (who) {
     369:             set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
     370:                     ((who & S_IRGRP) ? CMD2_GBITS : 0) |
     371:                     ((who & S_IROTH) ? CMD2_OBITS : 0);
     372:             set->bits = ~0;
     373:         } else {
     374:             set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
     375:             set->bits = mask;
     376:         }
     377:
     378:         if (oparg == '+')
     379:             set->cmd2 |= CMD2_SET;
     380:         else if (oparg == '-')
     381:             set->cmd2 |= CMD2_CLR;
     382:         else if (oparg == '=')
     383:             set->cmd2 |= CMD2_SET|CMD2_CLR;
     384:         break;
     385:     }
     386:     return (set + 1);
     387: }
     388:
     389: #ifdef SETMODE_DEBUG
     390: static void
     391: dumpmode(set)
     392:     register BITCMD *set;
     393: {
     394:     for (; set->cmd; ++set)
     395:         (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
     396:             set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
     397:             set->cmd2 & CMD2_CLR ? " CLR" : "",
     398:             set->cmd2 & CMD2_SET ? " SET" : "",
     399:             set->cmd2 & CMD2_UBITS ? " UBITS" : "",
     400:             set->cmd2 & CMD2_GBITS ? " GBITS" : "",
     401:             set->cmd2 & CMD2_OBITS ? " OBITS" : "");
     402: }
     403: #endif
     404:
     405: /*
     406:  * Given an array of bitcmd structures, compress by compacting consecutive
     407:  * '+', '-' and 'X' commands into at most 3 commands, one of each.  The 'u',
     408:  * 'g' and 'o' commands continue to be separate.  They could probably be
     409:  * compacted, but it's not worth the effort.
     410:  */
     411: static int
     412: compress_mode(set)
     413:     register BITCMD *set;
     414: {
     415:     register BITCMD *nset;
     416:     register int setbits, clrbits, Xbits, op;
     417:
     418:     for (nset = set;;) {
     419:         /* Copy over any 'u', 'g' and 'o' commands. */
     420:         while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
     421:             *set++ = *nset++;
     422:             if (!op)
     423:                 return;
     424:         }
     425:
     426:         for (setbits = clrbits = Xbits = 0;; nset++) {
     427:             if ((op = nset->cmd) == '-') {
     428:                 clrbits |= nset->bits;
     429:                 setbits &= ~nset->bits;
     430:                 Xbits &= ~nset->bits;
     431:             } else if (op == '+') {
     432:                 setbits |= nset->bits;
     433:                 clrbits &= ~nset->bits;
     434:                 Xbits &= ~nset->bits;
     435:             } else if (op == 'X')
     436:                 Xbits |= nset->bits & ~setbits;
     437:             else
     438:                 break;
     439:         }
     440:         if (clrbits) {
     441:             set->cmd = '-';
     442:             set->cmd2 = 0;
     443:             set->bits = clrbits;
     444:             set++;
     445:         }
     446:         if (setbits) {
     447:             set->cmd = '+';
     448:             set->cmd2 = 0;
     449:             set->bits = setbits;
     450:             set++;
     451:         }
     452:         if (Xbits) {
     453:             set->cmd = 'X';
     454:             set->cmd2 = 0;
     455:             set->bits = Xbits;
     456:             set++;
     457:         }
     458:     }
     459: }

#### Defined functions

addcmd defined in line 342; used 2 times

- in line 69, 162

compress_mode defined in line 411; used 2 times

- in line 70, 334

dumpmode defined in line 390; used 3 times

- in line 72, 332-337(2)

getmode defined in line 81; used 1 times

- in /usr/src/usr.bin/xinstall/xinstall.c line 105

setmode defined in line 166; used 5 times

- in /usr/src/new/jove/fp.c line 125
- in /usr/src/new/jove/jove.c line 619, 666
- in /usr/src/new/kermit5.188/ckufio.c line 608
- in /usr/src/usr.bin/xinstall/xinstall.c line 103

#### Defined variables

sccsid defined in line 38; never used

#### Defined struct's

bitcmd defined in line 57; never used

#### Defined typedef's

BITCMD defined in line 61; used 14 times

- in line 69, 342-344(2), 392, 413-89(3), 153-155(3), 172, 200(2), 415

#### Defined macros

ADDCMD defined in line 151; used 6 times

- in line 220, 292, 298-301(2), 312-316(2)

CMD2_CLR defined in line 63; used 4 times

- in line 109, 381-383(2), 397

CMD2_GBITS defined in line 65; used 5 times

- in line 114, 122, 370-374(2), 400

CMD2_OBITS defined in line 66; used 5 times

- in line 116, 124, 371-374(2), 401

CMD2_SET defined in line 64; used 5 times

- in line 111, 119, 379-383(2), 398

CMD2_UBITS defined in line 67; used 5 times

- in line 112, 120, 369-374(2), 399

SET_LEN defined in line 54; used 1 times

- in line 198

SET_LEN_INCR defined in line 55; used 1 times

- in line 154

STANDARD_BITS defined in line 164; used 4 times

- in line 211, 220, 233, 352

Last modified: 1996-02-20 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1352 |