Annotation of coherent/d/bin/chmog.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * chmog -- change the mode, owner, and group of files.
                      3:  *
                      4:  * This program was done from the 'chmod', 'chown', and 'chgrp'
                      5:  * As result code may not be optimal, but should be pretty reliable
                      6:  * and be backword compatible (including bugs and bad design as exit(2)).
                      7:  *
                      8:  * chmog should be link to chown, chmod, and chgrp. BTW it saves about
                      9:  * 15K :-).
                     10:  *
                     11:  * 1-31-92 Vlad
                     12:  */
                     13: 
                     14: #include <stdio.h>
                     15: #include <pwd.h>
                     16: #include <grp.h>
                     17: #include <ctype.h>
                     18: #include <sys/stat.h>
                     19: #include <string.h>
                     20: 
                     21: /* Masks by types of permissions */
                     22: #define        AEXEC   (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6))
                     23: #define        AREAD   (S_IREAD|(S_IREAD>>3)|(S_IREAD>>6))
                     24: #define        AWRITE  (S_IWRITE|(S_IWRITE>>3)|(S_IWRITE>>6))
                     25: #define        ASUID   (S_ISUID|S_ISGID)
                     26: #define        ATEXT   S_ISVTX
                     27: 
                     28: /* Masks by types of users */
                     29: #define        AOWN    (S_ISUID|S_ISVTX|S_IREAD|S_IWRITE|S_IEXEC)
                     30: #define        AGRP    (S_ISGID|S_ISVTX|(S_IREAD>>3)|(S_IWRITE>>3)|(S_IEXEC>>3))
                     31: #define        AOTH    (S_ISVTX|(S_IREAD>>6)|(S_IWRITE>>6)|(S_IEXEC>>6))
                     32: #define        AALL    (AOWN|AGRP|AOTH)
                     33: 
                     34: short  int     uid;
                     35: 
                     36: char   *chmod_usage = "chmod mode file ...";
                     37: char   *chown_usage = "chown owner file ...";
                     38: char   *chgrp_usage = "chgrp group file ...";
                     39: char   *chmog_usage = "chmog mod owner group file ...";
                     40: 
                     41: char   stickwarn[] = "\
                     42: chmod: Warning: non-super user may not set sticky bit\n\
                     43: ";
                     44: 
                     45: main(argc, argv)
                     46: int    argc;
                     47: char   *argv[];
                     48: {
                     49:        char    *cmdname;       /* Name of the command */
                     50: 
                     51:        /* Strip the pathname off of the name of the executable */
                     52:        if ((cmdname = strrchr(argv[0], '/')) != (char *) NULL) 
                     53:                cmdname++;
                     54:        else
                     55:                cmdname = argv[0];
                     56: 
                     57:        /* Who am I? */
                     58:        if (!strcmp(cmdname, "chmod"))
                     59:                cmd_chmod(argc, argv, 0);       /* Emulate chmod */
                     60:        else if (!strcmp(cmdname, "chown"))
                     61:                cmd_chown(argc, argv, 0, 0);    /* Emulate chown */
                     62:        else if (!strcmp(cmdname, "chgrp"))
                     63:                cmd_chgrp(argc, argv, 0, 0);    /* Emulate chgrp */
                     64:        else if (!strcmp(cmdname, "chmog"))
                     65:                chmog(argc, argv);              /* Be itself */
                     66:        else    /* If some entysiast will link to a different name....*/
                     67:                usage(chmog_usage);
                     68:        exit(0);
                     69: }
                     70: 
                     71: /*
                     72:  * This is main entry for chmog. Call all functions (*chmod, *chown, *chgrp)
                     73:  * and set the proper shifts of the argv. If correspoding *argv is '-'
                     74:  * it means that this characteristic of file should be unchanged.
                     75:  */
                     76: chmog(argc, argv)
                     77: int    argc;
                     78: char   **argv;
                     79: {
                     80:        if (argc < 5)
                     81:                usage(chmog_usage);
                     82: 
                     83:        /* Change owner */
                     84:        if (strcmp(argv[2], "-")) 
                     85:                cmd_chown(argc, argv, 1, 2);
                     86:        /* Change group */
                     87:        if (strcmp(argv[3], "-")) 
                     88:                cmd_chgrp(argc, argv, 2, 2);
                     89:        /* Change mode. We want to do it at the very and, otherwise
                     90:         * chown or chgrp will remove setuid & setgid bits
                     91:         */
                     92:        if (strcmp(argv[1], "-")) 
                     93:                cmd_chmod(argc, argv, 2);
                     94:        exit(0);
                     95: }
                     96: 
                     97: /*
                     98:  * Change mode of the file.
                     99:  */
                    100: cmd_chmod(argc, argv, shift_file)
                    101: int    argc;
                    102: char   **argv;
                    103: int    shift_file;     /* Shift argv to the file names */
                    104: {
                    105:        register int i;
                    106:        register char *fn;
                    107:        int status = 0;
                    108: 
                    109:        if (argc < 3)
                    110:                usage(chmod_usage);
                    111:        uid = getuid();
                    112:        for (i = 2 + shift_file; i < argc; i++) {
                    113:                fn = argv[i];
                    114:                if (chmod(fn, readmode(argv[1], fn)) < 0) {
                    115:                        perror(fn);
                    116:                        status = 2;
                    117:                }
                    118:        }
                    119:        if (status)
                    120:                exit(status);
                    121: }
                    122: 
                    123: /*
                    124:  * Read in the symbolic mode and
                    125:  * set the variables `who', `op',
                    126:  * and `mode'.
                    127:  * Knows about the old octal modes as well.
                    128:  */
                    129: readmode(s, file)
                    130: register char *s;
                    131: char *file;
                    132: {
                    133:        register int c;
                    134:        register int mode;
                    135:        register int op;
                    136:        register int m1, m2;
                    137:        struct stat sb;
                    138: 
                    139:        mode = 0;
                    140:        if (*s>='0' && *s<='7') {
                    141:                while (*s != '\0') {
                    142:                        if (*s<'0' || *s>'7')
                    143:                                omusage();
                    144:                        mode = (mode<<3) | *s++-'0';
                    145:                }
                    146:                checkmode(mode);
                    147:                return (mode);
                    148:        }
                    149:        sb.st_mode = 0;
                    150:        stat(file, &sb);
                    151:        mode = sb.st_mode;
                    152: newsym:
                    153:        m1 = 0;
                    154:        for (;;) {
                    155:                switch (*s++) {
                    156:                case 'u':
                    157:                        m1 |= AOWN;
                    158:                        continue;
                    159: 
                    160:                case 'g':
                    161:                        m1 |= AGRP;
                    162:                        continue;
                    163: 
                    164:                case 'o':
                    165:                        m1 |= AOTH;
                    166:                        continue;
                    167: 
                    168:                case 'a':
                    169:                        m1 |= AALL;
                    170:                        continue;
                    171: 
                    172:                default:
                    173:                        s--;
                    174:                        break;
                    175:                }
                    176:                break;
                    177:        }
                    178:        if (m1 == 0) {
                    179:                m1 = AALL&~getumask();
                    180:        }
                    181: newop:
                    182:        if ((c = *s++)=='=' || c=='+' || c=='-')
                    183:                op = c;
                    184:        else
                    185:                smusage();
                    186:        m2 = 0;
                    187:        for (;;) {
                    188:                switch (*s++) {
                    189:                case 'r':
                    190:                        m2 |= AREAD;
                    191:                        continue;
                    192: 
                    193:                case 'w':
                    194:                        m2 |= AWRITE;
                    195:                        continue;
                    196: 
                    197:                case 'x':
                    198:                        m2 |= AEXEC;
                    199:                        continue;
                    200: 
                    201:                case 's':
                    202:                        m2 |= ASUID;
                    203:                        continue;
                    204: 
                    205:                case 't':
                    206:                        m2 |= ATEXT;
                    207:                        continue;
                    208: 
                    209:                case 'u':
                    210:                        m2 |= mrepl(mode&AOWN);
                    211:                        continue;
                    212: 
                    213:                case 'g':
                    214:                        m2 |= mrepl((mode&AGRP)<<3);
                    215:                        continue;
                    216: 
                    217:                case 'o':
                    218:                        m2 |= mrepl((mode&AOTH)<<6);
                    219:                        continue;
                    220: 
                    221:                default:
                    222:                        s--;
                    223:                        break;
                    224:                }
                    225:                break;
                    226:        }
                    227:        switch (op) {
                    228:        case '-':
                    229:                mode &= ~(m1&m2);
                    230:                break;
                    231: 
                    232:        case '+':
                    233:                mode |= m1&m2;
                    234:                break;
                    235: 
                    236:        case '=':
                    237:                mode = (mode&~m1) | (m1&m2);
                    238:                break;
                    239:        }
                    240:        if (*s == '\0') {
                    241:                checkmode(mode);
                    242:                return (mode);
                    243:        }
                    244:        if (*s=='+' || *s=='-' || *s=='=')
                    245:                goto newop;
                    246:        if (*s++ == ',')
                    247:                goto newsym;
                    248:        smusage();
                    249: }
                    250: 
                    251: /*
                    252:  * Get the value of the umask setting.
                    253:  */
                    254: getumask()
                    255: {
                    256:        register int omask;
                    257: 
                    258:        omask = umask(0);
                    259:        umask(omask);
                    260:        return (omask);
                    261: }
                    262: 
                    263: /*
                    264:  * Check the mode to see if any problem
                    265:  * bits are on.  For now, this is
                    266:  * S_ISVTX for non-super-users.
                    267:  */
                    268: checkmode(mode)
                    269: register int mode;
                    270: {
                    271:        static int beenhere;
                    272: 
                    273:        if (!beenhere && uid!=0 && mode&S_ISVTX) {
                    274:                fprintf(stderr, stickwarn);
                    275:                beenhere++;
                    276:        }
                    277: }
                    278: 
                    279: /*
                    280:  * Replicate the 3-bits of the mode from
                    281:  * the owner position to all positions.
                    282:  */
                    283: mrepl(m)
                    284: register int m;
                    285: {
                    286:        register int m1;
                    287: 
                    288:        m1 = m&AOWN;
                    289:        m = m1 | (m1>>3) | (m1>>6);
                    290:        if (m1 & S_ISUID)
                    291:                m |= S_ISGID;
                    292:        return (m);
                    293: }
                    294: 
                    295: smusage()
                    296: {
                    297:        fprintf(stderr, "chmod: badly formed symbolic mode\n");
                    298:        exit(1);
                    299: }
                    300: 
                    301: omusage()
                    302: {
                    303:        fprintf(stderr, "chmod: badly formed octal mode\n");
                    304:        exit(1);
                    305: }
                    306: 
                    307: /*
                    308:  * Change owner of the file
                    309:  */
                    310: cmd_chown(argc, argv, shift_cmd, shift_file)
                    311: int    argc;
                    312: char   **argv;
                    313: int    shift_cmd;      /* Shift argv to the owner */
                    314: int    shift_file;     /* Shift argv to the file names */
                    315: {
                    316:        register struct passwd *pwp;
                    317:        register int c;
                    318:        register short owner, group;
                    319:        struct stat sb;
                    320:        register short status = 0;
                    321:        int     i_cmd;
                    322:        int     i_file;
                    323: 
                    324:        if (argc < 3)
                    325:                usage(chown_usage);
                    326:        i_cmd = 1 + shift_cmd;
                    327:        i_file = 2 + shift_file;
                    328: 
                    329:        if ((c = *argv[i_cmd]) >='0' && c <= '9')
                    330:                owner = atoi(argv[i_cmd]);
                    331:        else {
                    332:                if ((pwp = getpwnam(argv[i_cmd])) == NULL)
                    333:                        cherr("%s: bad username `%s'\n", argv[0], argv[i_cmd]);
                    334:                owner = pwp->pw_uid;
                    335:        }
                    336:        for (c = i_file; c < argc; c++) {
                    337:                group = 0;
                    338:                if (stat(argv[c], &sb) >= 0)
                    339:                        group = sb.st_gid;
                    340:                if (chown(argv[c], owner, group) < 0) {
                    341:                        perror(argv[c]);
                    342:                        status = 2;
                    343:                }
                    344:        }
                    345:        if (status)
                    346:                exit (status);
                    347: }
                    348: 
                    349: /*
                    350:  * Change the group owner of specified files.
                    351:  */
                    352: cmd_chgrp(argc, argv,  shift_cmd, shift_file)
                    353: int    argc;
                    354: char   **argv;
                    355: int    shift_cmd;      /* Shift argv to the group */
                    356: int    shift_file;     /* Shift argv to the file names */
                    357: {
                    358:        register struct group *grp;
                    359:        register int c;
                    360:        register short owner, group;
                    361:        struct stat sb;
                    362:        register short status = 0;
                    363:        int     i_cmd;
                    364:        int     i_file;
                    365: 
                    366:        /* Only superuser can invoke chgrp under COHERENT. Vlad */
                    367:        if (geteuid())
                    368:                cherr("%s: only superuser can changed group name.\n", argv[0]);
                    369: 
                    370:        if (argc < 3)
                    371:                usage(chgrp_usage);
                    372:        
                    373:        i_cmd = 1 + shift_cmd;
                    374:        i_file = 2 + shift_file;
                    375: 
                    376:        /* You can specify group by numeric id or by name. Vlad */
                    377:        if (isdigit((int) *argv[i_cmd])) {
                    378:                if ((grp = getgrgid(atoi(argv[i_cmd]))) == NULL)
                    379:                        cherr("%s: bad numeric group id `%s'\n",
                    380:                                argv[0], argv[i_cmd]);
                    381:        } else
                    382:                if ((grp = getgrnam(argv[i_cmd])) == NULL)
                    383:                        cherr("%s: bad group name `%s'\n", argv[0],argv[i_cmd]);
                    384: 
                    385:        group = grp->gr_gid;
                    386: 
                    387:        for (c = i_file; c < argc; c++) {
                    388:                owner = 0;
                    389:                if (stat(argv[c], &sb) >= 0)
                    390:                        owner = sb.st_uid;
                    391:                if (chown(argv[c], owner, group) < 0) {
                    392:                        perror(argv[c]);
                    393:                        status = 2;
                    394:                }
                    395:        }
                    396:        if (status)
                    397:                exit (status);
                    398: }
                    399: 
                    400: usage(msg)
                    401: char   *msg;
                    402: {
                    403:        fprintf(stderr, "Usage: %s\n", msg);
                    404:        exit(1);
                    405: }
                    406: 
                    407: /* VARARGS */
                    408: cherr(x)
                    409: {
                    410:        fprintf(stderr, "%r", &x);
                    411:        exit(2);
                    412: }

unix.superglobalmegacorp.com

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