Annotation of 43BSD/bin/chmod.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.