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
abs defined in line 213; used 1 times
chmodr defined in line 95; used 2 times
error defined in line 146; used 1 times
fatal defined in line 158; used 3 times
main defined in line 30; never used
newmode defined in line 179; used 6 times
what defined in line 261; used 1 times
where defined in line 273; used 1 times
who defined in line 235; used 1 times

Defined variables

fchdirmsg defined in line 23; used 1 times
fflag defined in line 27; used 6 times
modestring defined in line 24; used 2 times
ms defined in line 24; used 14 times
rflag defined in line 28; used 3 times
sccsid defined in line 8; never used
status defined in line 26; used 8 times
um defined in line 25; used 2 times

Defined macros

ALL defined in line 227; used 2 times
EXEC defined in line 231; used 4 times
GROUP defined in line 225; used 2 times
OTHER defined in line 226; used 2 times
READ defined in line 229; used 2 times
SETID defined in line 232; used 1 times
STICKY defined in line 233; used 1 times
USER defined in line 224; used 2 times
WRITE defined in line 230; used 2 times
Last modified: 1994-11-05
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4761
Valid CSS Valid XHTML 1.0 Strict