1*16594Sralph static char *sccsid = "@(#)chmod.c 4.4 06/18/84"; 216242Slayer 316242Slayer /* 416242Slayer * chmod options mode files 516242Slayer * where 616242Slayer * mode is [ugoa][+-=][rwxstugo] or a octal number 716242Slayer * options are -R 816242Slayer */ 916242Slayer #include <stdio.h> 1016242Slayer #include <sys/types.h> 1116242Slayer #include <sys/stat.h> 1216242Slayer #include <sys/dir.h> 1316242Slayer 1416242Slayer #define USER 05700 /* user's bits */ 1516242Slayer #define GROUP 02070 /* group's bits */ 1616242Slayer #define OTHER 00007 /* other's bits */ 1716242Slayer #define ALL 01777 /* all (note absence of setuid, etc) */ 1816242Slayer 1916242Slayer #define READ 00444 /* read permit */ 2016242Slayer #define WRITE 00222 /* write permit */ 2116242Slayer #define EXEC 00111 /* exec permit */ 2216242Slayer #define SETID 06000 /* set[ug]id */ 2316242Slayer #define STICKY 01000 /* sticky bit */ 2416242Slayer 2516242Slayer char *modestring, *ms; 2616242Slayer int um; 2716242Slayer int status; 2816270Slayer int rflag, debug, Xflag; 2916242Slayer 3016242Slayer main(argc,argv) 3116242Slayer char **argv; 3216242Slayer { 3316242Slayer register i; 3416270Slayer register char *p, *flags; 3516242Slayer struct stat st; 3616242Slayer 3716242Slayer if (argc < 3) { 3816242Slayer fprintf(stderr 3916270Slayer ,"Usage: chmod [-RX] [ugoa][+-=][rwxstugo] file ...\n"); 4016242Slayer exit(-1); 4116242Slayer } 4216270Slayer 4316242Slayer argv++, --argc; 4416270Slayer if (*argv[0] == '-') { 4516270Slayer for (flags = argv[0]; *flags; ++flags) 4616270Slayer switch (*flags) { 4716270Slayer case '-': break; 4816270Slayer case 'R': rflag++; break; 4916270Slayer case 'X': Xflag++; break; 5016270Slayer } 5116270Slayer argv++, argc--; 5216242Slayer } 5316270Slayer 5416242Slayer modestring = argv[0]; 5516242Slayer 5616242Slayer um = umask(0); 5716242Slayer (void) newmode(0); 5816242Slayer for (i = 1; i < argc; i++) { 5916242Slayer p = argv[i]; 60*16594Sralph if (stat(p, &st) < 0) { 6116242Slayer fprintf(stderr, "chmod: can't access %s\n", p); 6216242Slayer ++status; 6316242Slayer continue; 6416242Slayer } 6516242Slayer if (rflag && st.st_mode & S_IFDIR) { 6616242Slayer status += chmodr(p, newmode(st.st_mode)); 6716242Slayer } else if (chmod(p, newmode(st.st_mode)) < 0) { 6816242Slayer fprintf(stderr, "chmod: can't change %s\n", p); 6916242Slayer ++status; 7016242Slayer continue; 7116242Slayer } 7216242Slayer } 7316242Slayer exit(status); 7416242Slayer } 7516242Slayer 7616242Slayer chmodr(dir, mode) 7716242Slayer char *dir; 7816242Slayer { 7916242Slayer #define CHECK(name,sbuf)\ 80*16594Sralph if (stat(name, sbuf) < 0) {\ 8116242Slayer fprintf(stderr, "chmod: can't access %s\n", dp->d_name);\ 8216242Slayer return(1);\ 8316242Slayer } 8416242Slayer 8516242Slayer register DIR *dirp; 8616242Slayer register struct direct *dp; 8716242Slayer register struct stat st; 8816242Slayer char savedir[1024]; 8916242Slayer 9016242Slayer if (getwd(savedir) == 0) { 9116242Slayer fprintf(stderr, "chmod: %s\n", savedir); 9216242Slayer exit(255); 9316242Slayer } 9416242Slayer 9516242Slayer /* 9616242Slayer ** chmod what we are given before doing it's contents 9716242Slayer */ 9816242Slayer chmod(dir, newmode(mode)); 9916242Slayer 10016242Slayer chdir(dir); 10116242Slayer if ((dirp = opendir(".")) == NULL) { 10216242Slayer perror(dir); 10316242Slayer return(1); 10416242Slayer } 10516242Slayer dp = readdir(dirp); 10616242Slayer dp = readdir(dirp); /* read "." and ".." */ 10716242Slayer for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { 10816242Slayer CHECK(dp->d_name, &st); 10916242Slayer chmod(dp->d_name, newmode(st.st_mode)); 11016242Slayer if (st.st_mode & S_IFDIR) 11116242Slayer chmodr(dp->d_name, mode); 11216242Slayer } 11316242Slayer closedir(dirp); 11416242Slayer chdir(savedir); 11516242Slayer return(0); 11616242Slayer } 11716242Slayer 11816242Slayer newmode(nm) 11916242Slayer unsigned nm; 12016242Slayer { 12116242Slayer register o, m, b; 12216242Slayer int savem; 12316242Slayer 12416242Slayer ms = modestring; 12516242Slayer savem = nm; 12616242Slayer m = abs(); 12716242Slayer if (!*ms) { 12816242Slayer nm = m; 12916242Slayer goto ret; 13016242Slayer } 13116242Slayer do { 13216242Slayer m = who(); 13316242Slayer while (o = what()) { 13416242Slayer b = where(nm); 13516242Slayer switch (o) { 13616242Slayer case '+': 13716242Slayer nm |= b & m; 13816242Slayer break; 13916242Slayer case '-': 14016242Slayer nm &= ~(b & m); 14116242Slayer break; 14216242Slayer case '=': 14316242Slayer nm &= ~m; 14416242Slayer nm |= b & m; 14516242Slayer break; 14616242Slayer } 14716242Slayer } 14816242Slayer } while (*ms++ == ','); 14916242Slayer if (*--ms) { 15016242Slayer fprintf(stderr, "chmod: invalid mode\n"); 15116242Slayer exit(255); 15216242Slayer } 15316242Slayer ret: 15416270Slayer if (Xflag && ((savem & S_IFDIR) || (savem & S_IEXEC))) 15516270Slayer nm = nm | ((nm & 0444) >> 2); 15616242Slayer return(nm); 15716242Slayer } 15816242Slayer 15916242Slayer abs() 16016242Slayer { 16116242Slayer register c, i; 16216242Slayer 16316242Slayer i = 0; 16416242Slayer while ((c = *ms++) >= '0' && c <= '7') 16516242Slayer i = (i << 3) + (c - '0'); 16616242Slayer ms--; 16716242Slayer return(i); 16816242Slayer } 16916242Slayer 17016242Slayer who() 17116242Slayer { 17216242Slayer register m; 17316242Slayer 17416242Slayer m = 0; 17516242Slayer for (;;) switch (*ms++) { 17616242Slayer case 'u': 17716242Slayer m |= USER; 17816242Slayer continue; 17916242Slayer case 'g': 18016242Slayer m |= GROUP; 18116242Slayer continue; 18216242Slayer case 'o': 18316242Slayer m |= OTHER; 18416242Slayer continue; 18516242Slayer case 'a': 18616242Slayer m |= ALL; 18716242Slayer continue; 18816242Slayer default: 18916242Slayer ms--; 19016242Slayer if (m == 0) 19116242Slayer m = ALL & ~um; 19216242Slayer return m; 19316242Slayer } 19416242Slayer } 19516242Slayer 19616242Slayer what() 19716242Slayer { 19816242Slayer 19916242Slayer switch (*ms) { 20016242Slayer case '+': 20116242Slayer case '-': 20216242Slayer case '=': 20316242Slayer return *ms++; 20416242Slayer } 20516242Slayer return(0); 20616242Slayer } 20716242Slayer 20816242Slayer where(om) 20916242Slayer register om; 21016242Slayer { 21116242Slayer register m; 21216242Slayer 21316242Slayer m = 0; 21416242Slayer switch (*ms) { 21516242Slayer case 'u': 21616242Slayer m = (om & USER) >> 6; 21716242Slayer goto dup; 21816242Slayer case 'g': 21916242Slayer m = (om & GROUP) >> 3; 22016242Slayer goto dup; 22116242Slayer case 'o': 22216242Slayer m = (om & OTHER); 22316242Slayer dup: 22416242Slayer m &= (READ|WRITE|EXEC); 22516242Slayer m |= (m << 3) | (m << 6); 22616242Slayer ++ms; 22716242Slayer return m; 22816242Slayer } 22916242Slayer for (;;) switch (*ms++) { 23016242Slayer case 'r': 23116242Slayer m |= READ; 23216242Slayer continue; 23316242Slayer case 'w': 23416242Slayer m |= WRITE; 23516242Slayer continue; 23616242Slayer case 'x': 23716242Slayer m |= EXEC; 23816242Slayer continue; 239*16594Sralph case 'X': 240*16594Sralph Xflag++; 241*16594Sralph continue; 24216242Slayer case 's': 24316242Slayer m |= SETID; 24416242Slayer continue; 24516242Slayer case 't': 24616242Slayer m |= STICKY; 24716242Slayer continue; 24816242Slayer default: 24916242Slayer ms--; 25016242Slayer return m; 25116242Slayer } 25216242Slayer } 253