xref: /csrg-svn/bin/chmod/chmod.c (revision 66445)
119840Sdist /*
2*66445Sbostic  * Copyright (c) 1989, 1993, 1994
363597Sbostic  *	The Regents of the University of California.  All rights reserved.
439829Sbostic  *
542527Sbostic  * %sccs.include.redist.c%
619840Sdist  */
716242Slayer 
819840Sdist #ifndef lint
963597Sbostic static char copyright[] =
10*66445Sbostic "@(#) Copyright (c) 1989, 1993, 1994\n\
1163597Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1234043Sbostic #endif /* not lint */
1319840Sdist 
1434043Sbostic #ifndef lint
15*66445Sbostic static char sccsid[] = "@(#)chmod.c	8.3 (Berkeley) 03/25/94";
1634043Sbostic #endif /* not lint */
1734043Sbostic 
1816242Slayer #include <sys/types.h>
1916242Slayer #include <sys/stat.h>
2058142Sbostic 
2158142Sbostic #include <err.h>
2252070Sbostic #include <errno.h>
2339829Sbostic #include <fts.h>
2439829Sbostic #include <stdio.h>
2552070Sbostic #include <stdlib.h>
2642010Sbostic #include <string.h>
2758142Sbostic #include <unistd.h>
2816242Slayer 
2952070Sbostic void usage __P((void));
3052070Sbostic 
3152070Sbostic int
3224503Ssam main(argc, argv)
3334043Sbostic 	int argc;
3452070Sbostic 	char *argv[];
3516242Slayer {
3653782Selan 	register FTS *ftsp;
3739829Sbostic 	register FTSENT *p;
3839829Sbostic 	register int oct, omode;
3952070Sbostic 	mode_t *set;
4053782Selan 	int ch, fflag, rflag, hflag, Hflag;
4158142Sbostic 	int fts_options, retval;
4252070Sbostic 	char *ep, *mode;
4316242Slayer 
4453782Selan 	fts_options = FTS_PHYSICAL;
4553782Selan 	fflag = rflag = hflag = Hflag = 0;
46*66445Sbostic 	while ((ch = getopt(argc, argv, "HRXfghorstuwx")) != EOF)
47*66445Sbostic 		switch (ch) {
4853782Selan 		case 'H':
4953782Selan 			Hflag = 1;
5053782Selan 			fts_options |= FTS_COMFOLLOW;
5153782Selan 			break;
5224503Ssam 		case 'R':
5347072Sbostic 			rflag = 1;
5424503Ssam 			break;
55*66445Sbostic 		case 'f':		/* XXX: no longer documented. */
5647072Sbostic 			fflag = 1;
5724503Ssam 			break;
5853782Selan 		case 'h':
5953782Selan 			hflag = 1;
6053782Selan 			fts_options &= ~FTS_PHYSICAL;
6153782Selan 			fts_options |= FTS_LOGICAL;
6253782Selan 			break;
6365163Sbostic 		/*
64*66445Sbostic 		 * XXX
6565163Sbostic 		 * "-[rwx]" are valid mode commands.  If they are the entire
6665163Sbostic 		 * argument, getopt has moved past them, so decrement optind.
6765163Sbostic 		 * Regardless, we're done argument processing.
6865163Sbostic 		 */
69*66445Sbostic 		case 'g': case 'o': case 'r': case 's':
70*66445Sbostic 		case 't': case 'u': case 'w': case 'X': case 'x':
71*66445Sbostic 			if (argv[optind - 1][0] == '-' &&
72*66445Sbostic 			    argv[optind - 1][1] == ch &&
73*66445Sbostic 			    argv[optind - 1][2] == '\0')
7465163Sbostic 				--optind;
7565163Sbostic 			goto done;
7634043Sbostic 		case '?':
7724503Ssam 		default:
7839829Sbostic 			usage();
7923482Smckusick 		}
8034043Sbostic done:	argv += optind;
8134043Sbostic 	argc -= optind;
8234043Sbostic 
8339829Sbostic 	if (argc < 2)
8439829Sbostic 		usage();
8539829Sbostic 
8639829Sbostic 	mode = *argv;
8739829Sbostic 	if (*mode >= '0' && *mode <= '7') {
8852070Sbostic 		omode = (int)strtol(mode, &ep, 8);
8952070Sbostic 		if (omode < 0 || *ep)
9058142Sbostic 			errx(1, "invalid file mode: %s", mode);
9139829Sbostic 		oct = 1;
9239829Sbostic 	} else {
9358142Sbostic 		if ((set = setmode(mode)) == NULL)
9458142Sbostic 			errx(1, "invalid file mode: %s", mode);
9539829Sbostic 		oct = 0;
9616242Slayer 	}
9734043Sbostic 
9839829Sbostic 	retval = 0;
9953782Selan 	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
10063596Sbostic 		err(1, "");
101*66445Sbostic 	while ((p = fts_read(ftsp)) != NULL)
102*66445Sbostic 		switch (p->fts_info) {
10353782Selan 		case FTS_D:
10453782Selan 			if (!rflag)
10553782Selan 				fts_set(ftsp, p, FTS_SKIP);
10663596Sbostic 		case FTS_SL:
10763596Sbostic 		case FTS_SLNONE:
10853782Selan 			break;
10953782Selan 		case FTS_DNR:
11053782Selan 		case FTS_ERR:
11153782Selan 		case FTS_NS:
11258142Sbostic 			err(1, "%s", p->fts_path);
11353782Selan 		default:
11463596Sbostic 			if (p->fts_info == FTS_SL && !(hflag ||
11553782Selan 			    (Hflag && p->fts_level == FTS_ROOTLEVEL)))
11653782Selan 				continue;
11753782Selan 			if (chmod(p->fts_accpath, oct ? omode :
11858142Sbostic 			    getmode(set, p->fts_statp->st_mode)) && !fflag) {
11958142Sbostic 				warn(p->fts_path);
12058142Sbostic 				retval = 1;
12158142Sbostic 			}
12253782Selan 			break;
12353782Selan 		}
12439829Sbostic 	exit(retval);
12516242Slayer }
12616242Slayer 
12752070Sbostic void
12839829Sbostic usage()
12916242Slayer {
13053782Selan 	(void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n");
13139829Sbostic 	exit(1);
13216242Slayer }
133