|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 1980, 1988 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: char copyright[] = ! 9: "@(#) Copyright (c) 1980, 1988 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif /* not lint */ ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)chmod.c 5.7 (Berkeley) 4/21/88"; ! 15: #endif /* not lint */ ! 16: ! 17: /* ! 18: * chmod options mode files ! 19: * where ! 20: * mode is [ugoa][+-=][rwxXstugo] or an octal number ! 21: * options are -Rf ! 22: */ ! 23: #include <stdio.h> ! 24: #include <sys/types.h> ! 25: #include <sys/stat.h> ! 26: #include <sys/dir.h> ! 27: ! 28: static int fflag, rflag, retval, um; ! 29: static char *modestring, *ms; ! 30: ! 31: main(argc, argv) ! 32: int argc; ! 33: char **argv; ! 34: { ! 35: extern char *optarg; ! 36: extern int optind, opterr; ! 37: int ch; ! 38: ! 39: /* ! 40: * since "-[rwx]" etc. are valid file modes, we don't let getopt(3) ! 41: * print error messages, and we mess around with optind as necessary. ! 42: */ ! 43: opterr = 0; ! 44: while ((ch = getopt(argc, argv, "Rf")) != EOF) ! 45: switch((char)ch) { ! 46: case 'R': ! 47: rflag++; ! 48: break; ! 49: case 'f': ! 50: fflag++; ! 51: break; ! 52: case '?': ! 53: default: ! 54: --optind; ! 55: goto done; ! 56: } ! 57: done: argv += optind; ! 58: argc -= optind; ! 59: ! 60: if (argc < 2) { ! 61: fputs("usage: chmod [-Rf] [ugoa][+-=][rwxXstugo] file ...\n", ! 62: stderr); ! 63: exit(-1); ! 64: } ! 65: ! 66: modestring = *argv; ! 67: um = umask(0); ! 68: (void)newmode((u_short)0); ! 69: ! 70: while (*++argv) ! 71: change(*argv); ! 72: exit(retval); ! 73: } ! 74: ! 75: change(file) ! 76: char *file; ! 77: { ! 78: register DIR *dirp; ! 79: register struct direct *dp; ! 80: struct stat buf; ! 81: ! 82: if (lstat(file, &buf) || chmod(file, newmode(buf.st_mode))) { ! 83: err(file); ! 84: return; ! 85: } ! 86: if (rflag && ((buf.st_mode & S_IFMT) == S_IFDIR)) { ! 87: if (chdir(file) < 0 || !(dirp = opendir("."))) { ! 88: err(file); ! 89: return; ! 90: } ! 91: for (dp = readdir(dirp); dp; dp = readdir(dirp)) { ! 92: if (dp->d_name[0] == '.' && (!dp->d_name[1] || ! 93: dp->d_name[1] == '.' && !dp->d_name[2])) ! 94: continue; ! 95: change(dp->d_name); ! 96: } ! 97: closedir(dirp); ! 98: if (chdir("..")) { ! 99: err(".."); ! 100: exit(fflag ? 0 : -1); ! 101: } ! 102: } ! 103: } ! 104: ! 105: err(s) ! 106: char *s; ! 107: { ! 108: if (fflag) ! 109: return; ! 110: fputs("chmod: ", stderr); ! 111: perror(s); ! 112: retval = -1; ! 113: } ! 114: ! 115: newmode(nm) ! 116: u_short nm; ! 117: { ! 118: register int o, m, b; ! 119: ! 120: ms = modestring; ! 121: m = abs(); ! 122: if (*ms == '\0') ! 123: return (m); ! 124: do { ! 125: m = who(); ! 126: while (o = what()) { ! 127: b = where((int)nm); ! 128: switch (o) { ! 129: case '+': ! 130: nm |= b & m; ! 131: break; ! 132: case '-': ! 133: nm &= ~(b & m); ! 134: break; ! 135: case '=': ! 136: nm &= ~m; ! 137: nm |= b & m; ! 138: break; ! 139: } ! 140: } ! 141: } while (*ms++ == ','); ! 142: if (*--ms) { ! 143: fputs("chmod: invalid mode.\n", stderr); ! 144: exit(-1); ! 145: } ! 146: return ((int)nm); ! 147: } ! 148: ! 149: abs() ! 150: { ! 151: register int c, i; ! 152: ! 153: i = 0; ! 154: while ((c = *ms++) >= '0' && c <= '7') ! 155: i = (i << 3) + (c - '0'); ! 156: ms--; ! 157: return (i); ! 158: } ! 159: ! 160: #define USER 05700 /* user's bits */ ! 161: #define GROUP 02070 /* group's bits */ ! 162: #define OTHER 00007 /* other's bits */ ! 163: #define ALL 01777 /* all (note absence of setuid, etc) */ ! 164: ! 165: #define READ 00444 /* read permit */ ! 166: #define WRITE 00222 /* write permit */ ! 167: #define EXEC 00111 /* exec permit */ ! 168: #define SETID 06000 /* set[ug]id */ ! 169: #define STICKY 01000 /* sticky bit */ ! 170: ! 171: who() ! 172: { ! 173: register int m; ! 174: ! 175: m = 0; ! 176: for (;;) switch (*ms++) { ! 177: case 'u': ! 178: m |= USER; ! 179: continue; ! 180: case 'g': ! 181: m |= GROUP; ! 182: continue; ! 183: case 'o': ! 184: m |= OTHER; ! 185: continue; ! 186: case 'a': ! 187: m |= ALL; ! 188: continue; ! 189: default: ! 190: ms--; ! 191: if (m == 0) ! 192: m = ALL & ~um; ! 193: return (m); ! 194: } ! 195: } ! 196: ! 197: what() ! 198: { ! 199: switch (*ms) { ! 200: case '+': ! 201: case '-': ! 202: case '=': ! 203: return (*ms++); ! 204: } ! 205: return (0); ! 206: } ! 207: ! 208: where(om) ! 209: register int om; ! 210: { ! 211: register int m; ! 212: ! 213: m = 0; ! 214: switch (*ms) { ! 215: case 'u': ! 216: m = (om & USER) >> 6; ! 217: goto dup; ! 218: case 'g': ! 219: m = (om & GROUP) >> 3; ! 220: goto dup; ! 221: case 'o': ! 222: m = (om & OTHER); ! 223: dup: ! 224: m &= (READ|WRITE|EXEC); ! 225: m |= (m << 3) | (m << 6); ! 226: ++ms; ! 227: return (m); ! 228: } ! 229: for (;;) switch (*ms++) { ! 230: case 'r': ! 231: m |= READ; ! 232: continue; ! 233: case 'w': ! 234: m |= WRITE; ! 235: continue; ! 236: case 'x': ! 237: m |= EXEC; ! 238: continue; ! 239: case 'X': ! 240: if ((om & S_IFDIR) || (om & EXEC)) ! 241: m |= EXEC; ! 242: continue; ! 243: case 's': ! 244: m |= SETID; ! 245: continue; ! 246: case 't': ! 247: m |= STICKY; ! 248: continue; ! 249: default: ! 250: ms--; ! 251: return (m); ! 252: } ! 253: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.