|
|
1.1 ! root 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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.