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

Defined functions

Perror defined in line 158; used 8 times
abs defined in line 203; used 1 times
chmodr defined in line 84; used 2 times
error defined in line 136; used 1 times
fatal defined in line 148; used 3 times
main defined in line 28; never used
newmode defined in line 169; used 6 times
what defined in line 251; used 1 times
where defined in line 263; used 1 times
who defined in line 225; used 1 times

Defined variables

fflag defined in line 25; used 6 times
modestring defined in line 22; used 2 times
ms defined in line 22; used 14 times
rflag defined in line 26; used 2 times
sccsid defined in line 8; never used
status defined in line 24; used 8 times
um defined in line 23; used 2 times

Defined macros

ALL defined in line 217; used 2 times
EXEC defined in line 221; used 4 times
GROUP defined in line 215; used 2 times
OTHER defined in line 216; used 2 times
READ defined in line 219; used 2 times
SETID defined in line 222; used 1 times
STICKY defined in line 223; used 1 times
USER defined in line 214; used 2 times
WRITE defined in line 220; used 2 times
Last modified: 1986-05-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1538
Valid CSS Valid XHTML 1.0 Strict