X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/bcf1365c246c5582498da14e04ab93dabda91f98..647d0ea2dedf292593f7d95d287d445c297ccca2:/usr/src/bin/chmod/chmod.c diff --git a/usr/src/bin/chmod/chmod.c b/usr/src/bin/chmod/chmod.c index 5866a7985b..99e08bbef7 100644 --- a/usr/src/bin/chmod/chmod.c +++ b/usr/src/bin/chmod/chmod.c @@ -1,254 +1,151 @@ /* - * Copyright (c) 1980 Regents of the University of California. - * All rights reserved. The Berkeley software License Agreement - * specifies the terms and conditions for redistribution. + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #ifndef lint -static char sccsid[] = "@(#)chmod.c 5.1 (Berkeley) %G%"; -#endif not lint +char copyright[] = +"@(#) Copyright (c) 1989 The Regents of the University of California.\n\ + All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +static char sccsid[] = "@(#)chmod.c 5.19 (Berkeley) 3/12/91"; +#endif /* not lint */ -/* - * chmod options mode files - * where - * mode is [ugoa][+-=][rwxXstugo] or a octal number - * options are -R - */ -#include #include #include -#include - -#define USER 05700 /* user's bits */ -#define GROUP 02070 /* group's bits */ -#define OTHER 00007 /* other's bits */ -#define ALL 01777 /* all (note absence of setuid, etc) */ - -#define READ 00444 /* read permit */ -#define WRITE 00222 /* write permit */ -#define EXEC 00111 /* exec permit */ -#define SETID 06000 /* set[ug]id */ -#define STICKY 01000 /* sticky bit */ +#include +#include +#include -char *modestring, *ms; -int um; -int status; -int rflag, debug; +extern int errno; +int retval; -main(argc,argv) -char **argv; +main(argc, argv) + int argc; + char **argv; { - register i; - register char *p, *flags; - struct stat st; - -usage: - if (argc < 3) { - fprintf(stderr - ,"Usage: chmod [-R] [ugoa][+-=][rwxXstugo] file ...\n"); - exit(-1); - } - - argv++, --argc; - if (*argv[0] == '-') { - for (flags = argv[0]; *flags; ++flags) - switch (*flags) { - case '-': break; - case 'R': rflag++; break; - default: argc = 0; goto usage; - } - argv++, argc--; - } - - modestring = argv[0]; - - um = umask(0); - (void) newmode(0); - for (i = 1; i < argc; i++) { - p = argv[i]; - if (stat(p, &st) < 0) { - fprintf(stderr, "chmod: can't access %s\n", p); - ++status; - continue; + extern int optind; + register FTS *fts; + register FTSENT *p; + register int oct, omode; + register char *mode; + mode_t *set, *setmode(); + struct stat sb; + int ch, fflag, rflag; + + fflag = rflag = 0; + while ((ch = getopt(argc, argv, "Rfrwx")) != EOF) + switch((char)ch) { + case 'R': + rflag = 1; + break; + case 'f': /* no longer documented */ + fflag = 1; + break; + case 'r': /* "-[rwx]" are valid file modes */ + case 'w': + case 'x': + --optind; + goto done; + case '?': + default: + usage(); } - if (rflag && st.st_mode & S_IFDIR) { - status += chmodr(p, newmode(st.st_mode)); - } else if (chmod(p, newmode(st.st_mode)) < 0) { - fprintf(stderr, "chmod: can't change %s\n", p); - ++status; - continue; +done: argv += optind; + argc -= optind; + + if (argc < 2) + usage(); + + mode = *argv; + if (*mode >= '0' && *mode <= '7') { + omode = (int)strtol(mode, (char **)NULL, 8); + oct = 1; + } else { + if (!(set = setmode(mode))) { + (void)fprintf(stderr, "chmod: invalid file mode.\n"); + exit(1); } - } - exit(status); -} - -chmodr(dir, mode) - char *dir; -{ - register DIR *dirp; - register struct direct *dp; - register struct stat st; - char savedir[1024]; - - if (getwd(savedir) == 0) { - fprintf(stderr, "chmod: %s\n", savedir); - exit(255); + oct = 0; } - /* - ** chmod what we are given before doing it's contents - */ - chmod(dir, newmode(mode)); - - chdir(dir); - if ((dirp = opendir(".")) == NULL) { - perror(dir); - return(1); - } - dp = readdir(dirp); - dp = readdir(dirp); /* read "." and ".." */ - for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) { - if (stat(dp->d_name, &st) < 0) { - fprintf(stderr, "chmod: can't access %s\n", dp->d_name); - return(1); + retval = 0; + if (rflag) { + if (!(fts = fts_open(++argv, + oct ? FTS_NOSTAT|FTS_PHYSICAL : FTS_PHYSICAL, 0))) { + (void)fprintf(stderr, "chmod: %s.\n", strerror(errno)); + exit(1); } - chmod(dp->d_name, newmode(st.st_mode)); - if (st.st_mode & S_IFDIR) - chmodr(dp->d_name, mode); - } - closedir(dirp); - chdir(savedir); - return(0); -} - -newmode(nm) -unsigned nm; -{ - register o, m, b; - int savem; - - ms = modestring; - savem = nm; - m = abs(); - if (!*ms) - return(m); - do { - m = who(); - while (o = what()) { - b = where(nm); - switch (o) { - case '+': - nm |= b & m; - break; - case '-': - nm &= ~(b & m); + while (p = fts_read(fts)) + switch(p->fts_info) { + case FTS_D: break; - case '=': - nm &= ~m; - nm |= b & m; + case FTS_DNR: + case FTS_ERR: + case FTS_NS: + (void)fprintf(stderr, "chmod: %s: %s.\n", + p->fts_path, strerror(errno)); + exit(1); + default: + if (chmod(p->fts_accpath, oct ? omode : + getmode(set, p->fts_statb.st_mode)) && + !fflag) + error(p->fts_path); break; } - } - } while (*ms++ == ','); - if (*--ms) { - fprintf(stderr, "chmod: invalid mode\n"); - exit(255); + exit(retval); } - return(nm); + if (oct) { + while (*++argv) + if (chmod(*argv, omode) && !fflag) + error(*argv); + } else + while (*++argv) + if ((lstat(*argv, &sb) || + chmod(*argv, getmode(set, sb.st_mode))) && !fflag) + error(*argv); + exit(retval); } -abs() +error(name) + char *name; { - register c, i; - - i = 0; - while ((c = *ms++) >= '0' && c <= '7') - i = (i << 3) + (c - '0'); - ms--; - return(i); + (void)fprintf(stderr, "chmod: %s: %s.\n", name, strerror(errno)); + retval = 1; } -who() +usage() { - register m; - - m = 0; - for (;;) switch (*ms++) { - case 'u': - m |= USER; - continue; - case 'g': - m |= GROUP; - continue; - case 'o': - m |= OTHER; - continue; - case 'a': - m |= ALL; - continue; - default: - ms--; - if (m == 0) - m = ALL & ~um; - return m; - } -} - -what() -{ - - switch (*ms) { - case '+': - case '-': - case '=': - return *ms++; - } - return(0); -} - -where(om) -register om; -{ - register m; - - m = 0; - switch (*ms) { - case 'u': - m = (om & USER) >> 6; - goto dup; - case 'g': - m = (om & GROUP) >> 3; - goto dup; - case 'o': - m = (om & OTHER); - dup: - m &= (READ|WRITE|EXEC); - m |= (m << 3) | (m << 6); - ++ms; - return m; - } - for (;;) switch (*ms++) { - case 'r': - m |= READ; - continue; - case 'w': - m |= WRITE; - continue; - case 'x': - m |= EXEC; - continue; - case 'X': - if ((om & S_IFDIR) || (om & EXEC)) - m |= EXEC; - continue; - case 's': - m |= SETID; - continue; - case 't': - m |= STICKY; - continue; - default: - ms--; - return m; - } + (void)fprintf(stderr, "chmod: chmod [-R] mode file ...\n"); + exit(1); }