1*18473Smckusick static char *sccsid = "@(#)chmod.c 4.5 03/20/85"; 216242Slayer 316242Slayer /* 416242Slayer * chmod options mode files 516242Slayer * where 6*18473Smckusick * mode is [ugoa][+-=][rwxXstugo] 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; 28*18473Smckusick int rflag, debug; 2916242Slayer 3016242Slayer main(argc,argv) 3116242Slayer char **argv; 3216242Slayer { 3316242Slayer register i; 3416270Slayer register char *p, *flags; 3516242Slayer struct stat st; 3616242Slayer 37*18473Smckusick usage: 3816242Slayer if (argc < 3) { 3916242Slayer fprintf(stderr 40*18473Smckusick ,"Usage: chmod [-R] [ugoa][+-=][rwxXstugo] file ...\n"); 4116242Slayer exit(-1); 4216242Slayer } 4316270Slayer 4416242Slayer argv++, --argc; 4516270Slayer if (*argv[0] == '-') { 4616270Slayer for (flags = argv[0]; *flags; ++flags) 4716270Slayer switch (*flags) { 4816270Slayer case '-': break; 4916270Slayer case 'R': rflag++; break; 50*18473Smckusick default: argc = 0; goto usage; 5116270Slayer } 5216270Slayer argv++, argc--; 5316242Slayer } 5416270Slayer 5516242Slayer modestring = argv[0]; 5616242Slayer 5716242Slayer um = umask(0); 5816242Slayer (void) newmode(0); 5916242Slayer for (i = 1; i < argc; i++) { 6016242Slayer p = argv[i]; 6116594Sralph if (stat(p, &st) < 0) { 6216242Slayer fprintf(stderr, "chmod: can't access %s\n", p); 6316242Slayer ++status; 6416242Slayer continue; 6516242Slayer } 6616242Slayer if (rflag && st.st_mode & S_IFDIR) { 6716242Slayer status += chmodr(p, newmode(st.st_mode)); 6816242Slayer } else if (chmod(p, newmode(st.st_mode)) < 0) { 6916242Slayer fprintf(stderr, "chmod: can't change %s\n", p); 7016242Slayer ++status; 7116242Slayer continue; 7216242Slayer } 7316242Slayer } 7416242Slayer exit(status); 7516242Slayer } 7616242Slayer 7716242Slayer chmodr(dir, mode) 7816242Slayer char *dir; 7916242Slayer { 8016242Slayer register DIR *dirp; 8116242Slayer register struct direct *dp; 8216242Slayer register struct stat st; 8316242Slayer char savedir[1024]; 8416242Slayer 8516242Slayer if (getwd(savedir) == 0) { 8616242Slayer fprintf(stderr, "chmod: %s\n", savedir); 8716242Slayer exit(255); 8816242Slayer } 8916242Slayer 9016242Slayer /* 9116242Slayer ** chmod what we are given before doing it's contents 9216242Slayer */ 9316242Slayer chmod(dir, newmode(mode)); 9416242Slayer 9516242Slayer chdir(dir); 9616242Slayer if ((dirp = opendir(".")) == NULL) { 9716242Slayer perror(dir); 9816242Slayer return(1); 9916242Slayer } 10016242Slayer dp = readdir(dirp); 10116242Slayer dp = readdir(dirp); /* read "." and ".." */ 10216242Slayer for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { 103*18473Smckusick if (stat(dp->d_name, &st) < 0) { 104*18473Smckusick fprintf(stderr, "chmod: can't access %s\n", dp->d_name); 105*18473Smckusick return(1); 106*18473Smckusick } 10716242Slayer chmod(dp->d_name, newmode(st.st_mode)); 10816242Slayer if (st.st_mode & S_IFDIR) 10916242Slayer chmodr(dp->d_name, mode); 11016242Slayer } 11116242Slayer closedir(dirp); 11216242Slayer chdir(savedir); 11316242Slayer return(0); 11416242Slayer } 11516242Slayer 11616242Slayer newmode(nm) 11716242Slayer unsigned nm; 11816242Slayer { 11916242Slayer register o, m, b; 12016242Slayer int savem; 12116242Slayer 12216242Slayer ms = modestring; 12316242Slayer savem = nm; 12416242Slayer m = abs(); 125*18473Smckusick if (!*ms) 126*18473Smckusick return(m); 12716242Slayer do { 12816242Slayer m = who(); 12916242Slayer while (o = what()) { 13016242Slayer b = where(nm); 13116242Slayer switch (o) { 13216242Slayer case '+': 13316242Slayer nm |= b & m; 13416242Slayer break; 13516242Slayer case '-': 13616242Slayer nm &= ~(b & m); 13716242Slayer break; 13816242Slayer case '=': 13916242Slayer nm &= ~m; 14016242Slayer nm |= b & m; 14116242Slayer break; 14216242Slayer } 14316242Slayer } 14416242Slayer } while (*ms++ == ','); 14516242Slayer if (*--ms) { 14616242Slayer fprintf(stderr, "chmod: invalid mode\n"); 14716242Slayer exit(255); 14816242Slayer } 14916242Slayer return(nm); 15016242Slayer } 15116242Slayer 15216242Slayer abs() 15316242Slayer { 15416242Slayer register c, i; 15516242Slayer 15616242Slayer i = 0; 15716242Slayer while ((c = *ms++) >= '0' && c <= '7') 15816242Slayer i = (i << 3) + (c - '0'); 15916242Slayer ms--; 16016242Slayer return(i); 16116242Slayer } 16216242Slayer 16316242Slayer who() 16416242Slayer { 16516242Slayer register m; 16616242Slayer 16716242Slayer m = 0; 16816242Slayer for (;;) switch (*ms++) { 16916242Slayer case 'u': 17016242Slayer m |= USER; 17116242Slayer continue; 17216242Slayer case 'g': 17316242Slayer m |= GROUP; 17416242Slayer continue; 17516242Slayer case 'o': 17616242Slayer m |= OTHER; 17716242Slayer continue; 17816242Slayer case 'a': 17916242Slayer m |= ALL; 18016242Slayer continue; 18116242Slayer default: 18216242Slayer ms--; 18316242Slayer if (m == 0) 18416242Slayer m = ALL & ~um; 18516242Slayer return m; 18616242Slayer } 18716242Slayer } 18816242Slayer 18916242Slayer what() 19016242Slayer { 19116242Slayer 19216242Slayer switch (*ms) { 19316242Slayer case '+': 19416242Slayer case '-': 19516242Slayer case '=': 19616242Slayer return *ms++; 19716242Slayer } 19816242Slayer return(0); 19916242Slayer } 20016242Slayer 20116242Slayer where(om) 20216242Slayer register om; 20316242Slayer { 20416242Slayer register m; 20516242Slayer 20616242Slayer m = 0; 20716242Slayer switch (*ms) { 20816242Slayer case 'u': 20916242Slayer m = (om & USER) >> 6; 21016242Slayer goto dup; 21116242Slayer case 'g': 21216242Slayer m = (om & GROUP) >> 3; 21316242Slayer goto dup; 21416242Slayer case 'o': 21516242Slayer m = (om & OTHER); 21616242Slayer dup: 21716242Slayer m &= (READ|WRITE|EXEC); 21816242Slayer m |= (m << 3) | (m << 6); 21916242Slayer ++ms; 22016242Slayer return m; 22116242Slayer } 22216242Slayer for (;;) switch (*ms++) { 22316242Slayer case 'r': 22416242Slayer m |= READ; 22516242Slayer continue; 22616242Slayer case 'w': 22716242Slayer m |= WRITE; 22816242Slayer continue; 22916242Slayer case 'x': 23016242Slayer m |= EXEC; 23116242Slayer continue; 23216594Sralph case 'X': 233*18473Smckusick if ((om & S_IFDIR) || (om & EXEC)) 234*18473Smckusick m |= EXEC; 23516594Sralph continue; 23616242Slayer case 's': 23716242Slayer m |= SETID; 23816242Slayer continue; 23916242Slayer case 't': 24016242Slayer m |= STICKY; 24116242Slayer continue; 24216242Slayer default: 24316242Slayer ms--; 24416242Slayer return m; 24516242Slayer } 24616242Slayer } 247