# 2.11BSD#431 - /usr/src/bin/chmod.c

##### Functions

    Perror            X
    abs               X
    chmodr            X
    error             X
    fatal             X
    main              X
    newmode           X
    what              X
    where             X
    who               X

##### Variables

    fflag             X
    modestring        X
    ms                X
    rflag             X
    status            X
    um                X

##### Macros

    ALL               X
    EXEC              X
    GROUP             X
    OTHER             X
    READ              X
    SETID             X
    STICKY            X
    USER              X
    WRITE             X

       1: /*
       2:  * Copyright (c) 1980 Regents of the University of California.
       3:  * All rights reserved.  The Berkeley software License Agreement
       4:  * specifies the terms and conditions for redistribution.
       5:  */
       6:
       7: #if !defined(lint) && defined(DOSCCS)
       8: static char sccsid[] = "@(#)chmod.c	5.5.1 (2.11BSD GTE) 11/4/94";
       9: #endif
      10:
      11: /*
      12:  * chmod options mode files
      13:  * where
      14:  *	mode is [ugoa][+-=][rwxXstugo] or an octal number
      15:  *	options are -Rf
      16:  */
      17: #include <stdio.h>
      18: #include <sys/types.h>
      19: #include <sys/file.h>
      20: #include <sys/stat.h>
      21: #include <sys/dir.h>
      22:
      23: static  char    *fchdirmsg = "Can't fchdir() back to starting directory";
      24: char    *modestring, *ms;
      25: int um;
      26: int status;
      27: int fflag;
      28: int rflag;
      29:
      30: main(argc, argv)
      31:     char *argv[];
      32: {
      33:     register char *p, *flags;
      34:     register int i;
      35:     struct stat st;
      36:     int fcurdir;
      37:
      38:     if (argc < 3) {
      39:         fprintf(stderr,
      40:             "Usage: chmod [-Rf] [ugoa][+-=][rwxXstugo] file ...\n");
      41:         exit(-1);
      42:     }
      43:     argv++, --argc;
      44:     while (argc > 0 && argv[0][0] == '-') {
      45:         for (p = &argv[0][1]; *p; p++) switch (*p) {
      46:
      47:         case 'R':
      48:             rflag++;
      49:             break;
      50:
      51:         case 'f':
      52:             fflag++;
      53:             break;
      54:
      55:         default:
      56:             goto done;
      57:         }
      58:         argc--, argv++;
      59:     }
      60: done:
      61:     modestring = argv[0];
      62:     um = umask(0);
      63:     (void) newmode(0);
      64:     if  (rflag)
      65:         {
      66:         fcurdir = open(".", O_RDONLY);
      67:         if  (fcurdir < 0)
      68:             fatal(255, "Can't open .");
      69:         }
      70:
      71:     for (i = 1; i < argc; i++) {
      72:         p = argv[i];
      73:         /* do stat for directory arguments */
      74:         if (lstat(p, &st) < 0) {
      75:             status += Perror(p);
      76:             continue;
      77:         }
      78:         if (rflag && (st.st_mode&S_IFMT) == S_IFDIR) {
      79:             status += chmodr(p, newmode(st.st_mode), fcurdir);
      80:             continue;
      81:         }
      82:         if ((st.st_mode&S_IFMT) == S_IFLNK && stat(p, &st) < 0) {
      83:             status += Perror(p);
      84:             continue;
      85:         }
      86:         if (chmod(p, newmode(st.st_mode)) < 0) {
      87:             status += Perror(p);
      88:             continue;
      89:         }
      90:     }
      91:     close(fcurdir);
      92:     exit(status);
      93: }
      94:
      95: chmodr(dir, mode, savedir)
      96:     char *dir;
      97:     int mode;
      98:     int savedir;
      99: {
     100:     register DIR *dirp;
     101:     register struct direct *dp;
     102:     struct stat st;
     103:     int ecode;
     104:
     105:     /*
     106: 	 * Change what we are given before doing it's contents
     107: 	 */
     108:     if (chmod(dir, newmode(mode)) < 0 && Perror(dir))
     109:         return (1);
     110:     if (chdir(dir) < 0) {
     111:         Perror(dir);
     112:         return (1);
     113:     }
     114:     if ((dirp = opendir(".")) == NULL) {
     115:         Perror(dir);
     116:         return (1);
     117:     }
     118:     dp = readdir(dirp);
     119:     dp = readdir(dirp); /* read "." and ".." */
     120:     ecode = 0;
     121:     for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
     122:         if (lstat(dp->d_name, &st) < 0) {
     123:             ecode = Perror(dp->d_name);
     124:             if (ecode)
     125:                 break;
     126:             continue;
     127:         }
     128:         if ((st.st_mode&S_IFMT) == S_IFDIR) {
     129:             ecode = chmodr(dp->d_name, newmode(st.st_mode), dirfd(dirp));
     130:             if (ecode)
     131:                 break;
     132:             continue;
     133:         }
     134:         if ((st.st_mode&S_IFMT) == S_IFLNK)
     135:             continue;
     136:         if (chmod(dp->d_name, newmode(st.st_mode)) < 0 &&
     137:             (ecode = Perror(dp->d_name)))
     138:             break;
     139:     }
     140:     if  (fchdir(savedir) < 0)
     141:         fatal(255, fchdirmsg);
     142:     closedir(dirp);
     143:     return (ecode);
     144: }
     145:
     146: error(fmt, a)
     147:     char *fmt, *a;
     148: {
     149:
     150:     if (!fflag) {
     151:         fprintf(stderr, "chmod: ");
     152:         fprintf(stderr, fmt, a);
     153:         putc('\n', stderr);
     154:     }
     155:     return (!fflag);
     156: }
     157:
     158: fatal(status, fmt, a)
     159:     int status;
     160:     char *fmt, *a;
     161: {
     162:
     163:     fflag = 0;
     164:     (void) error(fmt, a);
     165:     exit(status);
     166: }
     167:
     168: Perror(s)
     169:     char *s;
     170: {
     171:
     172:     if (!fflag) {
     173:         fprintf(stderr, "chmod: ");
     174:         perror(s);
     175:     }
     176:     return (!fflag);
     177: }
     178:
     179: newmode(nm)
     180:     unsigned nm;
     181: {
     182:     register o, m, b;
     183:     int savem;
     184:
     185:     ms = modestring;
     186:     savem = nm;
     187:     m = abs();
     188:     if (*ms == '\0')
     189:         return (m);
     190:     do {
     191:         m = who();
     192:         while (o = what()) {
     193:             b = where(nm);
     194:             switch (o) {
     195:             case '+':
     196:                 nm |= b & m;
     197:                 break;
     198:             case '-':
     199:                 nm &= ~(b & m);
     200:                 break;
     201:             case '=':
     202:                 nm &= ~m;
     203:                 nm |= b & m;
     204:                 break;
     205:             }
     206:         }
     207:     } while (*ms++ == ',');
     208:     if (*--ms)
     209:         fatal(255, "invalid mode");
     210:     return (nm);
     211: }
     212:
     213: abs()
     214: {
     215:     register c, i;
     216:
     217:     i = 0;
     218:     while ((c = *ms++) >= '0' && c <= '7')
     219:         i = (i << 3) + (c - '0');
     220:     ms--;
     221:     return (i);
     222: }
     223:
     224: #define USER    05700   /* user's bits */
     225: #define GROUP   02070   /* group's bits */
     226: #define OTHER   00007   /* other's bits */
     227: #define ALL 01777   /* all (note absence of setuid, etc) */
     228:
     229: #define READ    00444   /* read permit */
     230: #define WRITE   00222   /* write permit */
     231: #define EXEC    00111   /* exec permit */
     232: #define SETID   06000   /* set[ug]id */
     233: #define STICKY  01000   /* sticky bit */
     234:
     235: who()
     236: {
     237:     register m;
     238:
     239:     m = 0;
     240:     for (;;) switch (*ms++) {
     241:     case 'u':
     242:         m |= USER;
     243:         continue;
     244:     case 'g':
     245:         m |= GROUP;
     246:         continue;
     247:     case 'o':
     248:         m |= OTHER;
     249:         continue;
     250:     case 'a':
     251:         m |= ALL;
     252:         continue;
     253:     default:
     254:         ms--;
     255:         if (m == 0)
     256:             m = ALL & ~um;
     257:         return (m);
     258:     }
     259: }
     260:
     261: what()
     262: {
     263:
     264:     switch (*ms) {
     265:     case '+':
     266:     case '-':
     267:     case '=':
     268:         return (*ms++);
     269:     }
     270:     return (0);
     271: }
     272:
     273: where(om)
     274:     register om;
     275: {
     276:     register m;
     277:
     278:     m = 0;
     279:     switch (*ms) {
     280:     case 'u':
     281:         m = (om & USER) >> 6;
     282:         goto dup;
     283:     case 'g':
     284:         m = (om & GROUP) >> 3;
     285:         goto dup;
     286:     case 'o':
     287:         m = (om & OTHER);
     288:     dup:
     289:         m &= (READ|WRITE|EXEC);
     290:         m |= (m << 3) | (m << 6);
     291:         ++ms;
     292:         return (m);
     293:     }
     294:     for (;;) switch (*ms++) {
     295:     case 'r':
     296:         m |= READ;
     297:         continue;
     298:     case 'w':
     299:         m |= WRITE;
     300:         continue;
     301:     case 'x':
     302:         m |= EXEC;
     303:         continue;
     304:     case 'X':
     305:         if ((om & S_IFDIR) || (om & EXEC))
     306:             m |= EXEC;
     307:         continue;
     308:     case 's':
     309:         m |= SETID;
     310:         continue;
     311:     case 't':
     312:         m |= STICKY;
     313:         continue;
     314:     default:
     315:         ms--;
     316:         return (m);
     317:     }
     318: }

#### Defined functions

Perror defined in line 168; used 8 times

- in line 75, 83-87(2), 108-115(3), 123, 137

abs defined in line 213; used 1 times

- in line 187

chmodr defined in line 95; used 2 times

- in line 79, 129

error defined in line 146; used 1 times

- in line 164

fatal defined in line 158; used 3 times

- in line 68, 141, 209

main defined in line 30; never used
newmode defined in line 179; used 6 times

- in line 63, 79, 86, 108, 129, 136

what defined in line 261; used 1 times

- in line 192

where defined in line 273; used 1 times

- in line 193

who defined in line 235; used 1 times

- in line 191

#### Defined variables

fchdirmsg defined in line 23; used 1 times

- in line 141

fflag defined in line 27; used 6 times

- in line 52, 150-155(2), 163, 172-176(2)

modestring defined in line 24; used 2 times

- in line 61, 185

ms defined in line 24; used 14 times

- in line 185-188(2), 207-208(2), 218-220(2), 240, 254, 264-268(2), 279, 291-294(2), 315

rflag defined in line 28; used 3 times

- in line 48, 64, 78

sccsid defined in line 8; never used
status defined in line 26; used 8 times

- in line 75-92(5), 158-159(2), 165

um defined in line 25; used 2 times

- in line 62, 256

#### Defined macros

ALL defined in line 227; used 2 times

- in line 251-256(2)

EXEC defined in line 231; used 4 times

- in line 289, 302-306(3)

GROUP defined in line 225; used 2 times

- in line 245, 284

OTHER defined in line 226; used 2 times

- in line 248, 287

READ defined in line 229; used 2 times

- in line 289, 296

SETID defined in line 232; used 1 times

- in line 309

STICKY defined in line 233; used 1 times

- in line 312

USER defined in line 224; used 2 times

- in line 242, 281

WRITE defined in line 230; used 2 times

- in line 289, 299

Last modified: 1994-11-05 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 2146 |