|
|
1.1 ! root 1: /* ! 2: * Chmod -- change the mode of ! 3: * files (both symbolic and octal) ! 4: * I really don't like the syntax though. ! 5: */ ! 6: ! 7: #include <stdio.h> ! 8: #include <sys/stat.h> ! 9: ! 10: /* Masks by types of permissions */ ! 11: #define AEXEC (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6)) ! 12: #define AREAD (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6)) ! 13: #define AWRITE (S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6)) ! 14: #define ASUID (S_ISUID|S_ISGID) ! 15: #define ATEXT S_ISVTX ! 16: ! 17: /* Masks by types of users */ ! 18: #define AOWN (S_ISUID|S_ISVTX|S_IREAD|S_IWRITE|S_IEXEC) ! 19: #define AGRP (S_ISGID|S_ISVTX|(S_IREAD>>3)|(S_IWRITE>>3)|(S_IEXEC>>3)) ! 20: #define AOTH (S_ISVTX|(S_IREAD>>6)|(S_IWRITE>>6)|(S_IEXEC>>6)) ! 21: #define AALL (AOWN|AGRP|AOTH) ! 22: ! 23: short int uid; ! 24: ! 25: char stickwarn[] = "\ ! 26: chmod: Warning: non-super user may not set sticky bit\n\ ! 27: "; ! 28: ! 29: main(argc, argv) ! 30: char *argv[]; ! 31: { ! 32: register int i; ! 33: register char *fn; ! 34: int status = 0; ! 35: ! 36: if (argc < 3) ! 37: usage(); ! 38: uid = getuid(); ! 39: for (i=2; i<argc; i++) { ! 40: fn = argv[i]; ! 41: if (chmod(fn, readmode(argv[1], fn)) < 0) { ! 42: perror(fn); ! 43: status = 2; ! 44: } ! 45: } ! 46: exit (status); ! 47: } ! 48: ! 49: /* ! 50: * Read in the symbolic mode and ! 51: * set the variables `who', `op', ! 52: * and `mode'. ! 53: * Knows about the old octal modes as well. ! 54: */ ! 55: readmode(s, file) ! 56: register char *s; ! 57: char *file; ! 58: { ! 59: register int c; ! 60: register int mode; ! 61: register int op; ! 62: register int m1, m2; ! 63: struct stat sb; ! 64: ! 65: mode = 0; ! 66: if (*s>='0' && *s<='7') { ! 67: while (*s != '\0') { ! 68: if (*s<'0' || *s>'7') ! 69: omusage(); ! 70: mode = (mode<<3) | *s++-'0'; ! 71: } ! 72: checkmode(mode); ! 73: return (mode); ! 74: } ! 75: sb.st_mode = 0; ! 76: stat(file, &sb); ! 77: mode = sb.st_mode; ! 78: newsym: ! 79: m1 = 0; ! 80: for (;;) { ! 81: switch (*s++) { ! 82: case 'u': ! 83: m1 |= AOWN; ! 84: continue; ! 85: ! 86: case 'g': ! 87: m1 |= AGRP; ! 88: continue; ! 89: ! 90: case 'o': ! 91: m1 |= AOTH; ! 92: continue; ! 93: ! 94: case 'a': ! 95: m1 |= AALL; ! 96: continue; ! 97: ! 98: default: ! 99: s--; ! 100: break; ! 101: } ! 102: break; ! 103: } ! 104: if (m1 == 0) { ! 105: m1 = AALL&~getumask(); ! 106: } ! 107: newop: ! 108: if ((c = *s++)=='=' || c=='+' || c=='-') ! 109: op = c; ! 110: else ! 111: smusage(); ! 112: m2 = 0; ! 113: for (;;) { ! 114: switch (*s++) { ! 115: case 'r': ! 116: m2 |= AREAD; ! 117: continue; ! 118: ! 119: case 'w': ! 120: m2 |= AWRITE; ! 121: continue; ! 122: ! 123: case 'x': ! 124: m2 |= AEXEC; ! 125: continue; ! 126: ! 127: case 's': ! 128: m2 |= ASUID; ! 129: continue; ! 130: ! 131: case 't': ! 132: m2 |= ATEXT; ! 133: continue; ! 134: ! 135: case 'u': ! 136: m2 |= mrepl(mode&AOWN); ! 137: continue; ! 138: ! 139: case 'g': ! 140: m2 |= mrepl((mode&AGRP)<<3); ! 141: continue; ! 142: ! 143: case 'o': ! 144: m2 |= mrepl((mode&AOTH)<<6); ! 145: continue; ! 146: ! 147: default: ! 148: s--; ! 149: break; ! 150: } ! 151: break; ! 152: } ! 153: switch (op) { ! 154: case '-': ! 155: mode &= ~(m1&m2); ! 156: break; ! 157: ! 158: case '+': ! 159: mode |= m1&m2; ! 160: break; ! 161: ! 162: case '=': ! 163: mode = (mode&~m1) | (m1&m2); ! 164: break; ! 165: } ! 166: if (*s == '\0') { ! 167: checkmode(mode); ! 168: return (mode); ! 169: } ! 170: if (*s=='+' || *s=='-' || *s=='=') ! 171: goto newop; ! 172: if (*s++ == ',') ! 173: goto newsym; ! 174: smusage(); ! 175: } ! 176: ! 177: /* ! 178: * Get the value of the umask setting. ! 179: */ ! 180: getumask() ! 181: { ! 182: register int omask; ! 183: ! 184: omask = umask(0); ! 185: umask(omask); ! 186: return (omask); ! 187: } ! 188: ! 189: /* ! 190: * Check the mode to see if any problem ! 191: * bits are on. For now, this is ! 192: * S_ISVTX for non-super-users. ! 193: */ ! 194: checkmode(mode) ! 195: register int mode; ! 196: { ! 197: static int beenhere; ! 198: ! 199: if (!beenhere && uid!=0 && mode&S_ISVTX) { ! 200: fprintf(stderr, stickwarn); ! 201: beenhere++; ! 202: } ! 203: } ! 204: ! 205: /* ! 206: * Replicate the 3-bits of the mode from ! 207: * the owner position to all positions. ! 208: */ ! 209: mrepl(m) ! 210: register int m; ! 211: { ! 212: register int m1; ! 213: ! 214: m1 = m&AOWN; ! 215: m = m1 | (m1>>3) | (m1>>6); ! 216: if (m1 & S_ISUID) ! 217: m |= S_ISGID; ! 218: return (m); ! 219: } ! 220: ! 221: usage() ! 222: { ! 223: fprintf(stderr, "Usage: chmod mode file ...\n"); ! 224: exit(1); ! 225: } ! 226: ! 227: smusage() ! 228: { ! 229: fprintf(stderr, "chmod: badly formed symbolic mode\n"); ! 230: exit(1); ! 231: } ! 232: ! 233: omusage() ! 234: { ! 235: fprintf(stderr, "chmod: badly formed octal mode\n"); ! 236: exit(1); ! 237: } ! 238: ! 239: ! 240:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.