xref: /csrg-svn/bin/chmod/chmod.c (revision 65163)
119840Sdist /*
263597Sbostic  * Copyright (c) 1989, 1993
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[] =
1063597Sbostic "@(#) Copyright (c) 1989, 1993\n\
1163597Sbostic 	The Regents of the University of California.  All rights reserved.\n";
1234043Sbostic #endif /* not lint */
1319840Sdist 
1434043Sbostic #ifndef lint
15*65163Sbostic static char sccsid[] = "@(#)chmod.c	8.2 (Berkeley) 12/16/93";
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;
4653782Selan 	while ((ch = getopt(argc, argv, "HRfhrwx")) != EOF)
4734043Sbostic 		switch((char)ch) {
4853782Selan 		case 'H':
4953782Selan 			Hflag = 1;
5053782Selan 			fts_options |= FTS_COMFOLLOW;
5153782Selan 			break;
5224503Ssam 		case 'R':
5347072Sbostic 			rflag = 1;
5424503Ssam 			break;
5547072Sbostic 		case 'f':		/* 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;
63*65163Sbostic 		/*
64*65163Sbostic 		 * "-[rwx]" are valid mode commands.  If they are the entire
65*65163Sbostic 		 * argument, getopt has moved past them, so decrement optind.
66*65163Sbostic 		 * Regardless, we're done argument processing.
67*65163Sbostic 		 */
68*65163Sbostic 		case 'r':
69*65163Sbostic 			if (!strcmp(argv[optind - 1], "-r"))
70*65163Sbostic 				--optind;
71*65163Sbostic 			goto done;
7239829Sbostic 		case 'w':
73*65163Sbostic 			if (!strcmp(argv[optind - 1], "-w"))
74*65163Sbostic 				--optind;
75*65163Sbostic 			goto done;
7639829Sbostic 		case 'x':
77*65163Sbostic 			if (!strcmp(argv[optind - 1], "-x"))
78*65163Sbostic 				--optind;
7939829Sbostic 			goto done;
8034043Sbostic 		case '?':
8124503Ssam 		default:
8239829Sbostic 			usage();
8323482Smckusick 		}
8434043Sbostic done:	argv += optind;
8534043Sbostic 	argc -= optind;
8634043Sbostic 
8739829Sbostic 	if (argc < 2)
8839829Sbostic 		usage();
8939829Sbostic 
9039829Sbostic 	mode = *argv;
9139829Sbostic 	if (*mode >= '0' && *mode <= '7') {
9252070Sbostic 		omode = (int)strtol(mode, &ep, 8);
9352070Sbostic 		if (omode < 0 || *ep)
9458142Sbostic 			errx(1, "invalid file mode: %s", mode);
9539829Sbostic 		oct = 1;
9639829Sbostic 	} else {
9758142Sbostic 		if ((set = setmode(mode)) == NULL)
9858142Sbostic 			errx(1, "invalid file mode: %s", mode);
9939829Sbostic 		oct = 0;
10016242Slayer 	}
10134043Sbostic 
10239829Sbostic 	retval = 0;
10353782Selan 	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
10463596Sbostic 		err(1, "");
10553782Selan 	while (p = fts_read(ftsp))
10653782Selan 		switch(p->fts_info) {
10753782Selan 		case FTS_D:
10853782Selan 			if (!rflag)
10953782Selan 				fts_set(ftsp, p, FTS_SKIP);
11063596Sbostic 		case FTS_SL:
11163596Sbostic 		case FTS_SLNONE:
11253782Selan 			break;
11353782Selan 		case FTS_DNR:
11453782Selan 		case FTS_ERR:
11553782Selan 		case FTS_NS:
11658142Sbostic 			err(1, "%s", p->fts_path);
11753782Selan 		default:
11863596Sbostic 			if (p->fts_info == FTS_SL && !(hflag ||
11953782Selan 			    (Hflag && p->fts_level == FTS_ROOTLEVEL)))
12053782Selan 				continue;
12153782Selan 			if (chmod(p->fts_accpath, oct ? omode :
12258142Sbostic 			    getmode(set, p->fts_statp->st_mode)) && !fflag) {
12358142Sbostic 				warn(p->fts_path);
12458142Sbostic 				retval = 1;
12558142Sbostic 			}
12653782Selan 			break;
12753782Selan 		}
12839829Sbostic 	exit(retval);
12916242Slayer }
13016242Slayer 
13152070Sbostic void
13239829Sbostic usage()
13316242Slayer {
13453782Selan 	(void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n");
13539829Sbostic 	exit(1);
13616242Slayer }
137