xref: /csrg-svn/bin/chmod/chmod.c (revision 63596)
119840Sdist /*
239829Sbostic  * Copyright (c) 1989 The Regents of the University of California.
339829Sbostic  * All rights reserved.
439829Sbostic  *
542527Sbostic  * %sccs.include.redist.c%
619840Sdist  */
716242Slayer 
819840Sdist #ifndef lint
934043Sbostic char copyright[] =
1039829Sbostic "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
1134043Sbostic  All rights reserved.\n";
1234043Sbostic #endif /* not lint */
1319840Sdist 
1434043Sbostic #ifndef lint
15*63596Sbostic static char sccsid[] = "@(#)chmod.c	5.24 (Berkeley) 06/27/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;
6347072Sbostic 		case 'r':		/* "-[rwx]" are valid file modes */
6439829Sbostic 		case 'w':
6539829Sbostic 		case 'x':
6639829Sbostic 			--optind;
6739829Sbostic 			goto done;
6834043Sbostic 		case '?':
6924503Ssam 		default:
7039829Sbostic 			usage();
7123482Smckusick 		}
7234043Sbostic done:	argv += optind;
7334043Sbostic 	argc -= optind;
7434043Sbostic 
7539829Sbostic 	if (argc < 2)
7639829Sbostic 		usage();
7739829Sbostic 
7839829Sbostic 	mode = *argv;
7939829Sbostic 	if (*mode >= '0' && *mode <= '7') {
8052070Sbostic 		omode = (int)strtol(mode, &ep, 8);
8152070Sbostic 		if (omode < 0 || *ep)
8258142Sbostic 			errx(1, "invalid file mode: %s", mode);
8339829Sbostic 		oct = 1;
8439829Sbostic 	} else {
8558142Sbostic 		if ((set = setmode(mode)) == NULL)
8658142Sbostic 			errx(1, "invalid file mode: %s", mode);
8739829Sbostic 		oct = 0;
8816242Slayer 	}
8934043Sbostic 
9039829Sbostic 	retval = 0;
9153782Selan 	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
92*63596Sbostic 		err(1, "");
9353782Selan 	while (p = fts_read(ftsp))
9453782Selan 		switch(p->fts_info) {
9553782Selan 		case FTS_D:
9653782Selan 			if (!rflag)
9753782Selan 				fts_set(ftsp, p, FTS_SKIP);
98*63596Sbostic 		case FTS_SL:
99*63596Sbostic 		case FTS_SLNONE:
10053782Selan 			break;
10153782Selan 		case FTS_DNR:
10253782Selan 		case FTS_ERR:
10353782Selan 		case FTS_NS:
10458142Sbostic 			err(1, "%s", p->fts_path);
10553782Selan 		default:
106*63596Sbostic 			if (p->fts_info == FTS_SL && !(hflag ||
10753782Selan 			    (Hflag && p->fts_level == FTS_ROOTLEVEL)))
10853782Selan 				continue;
10953782Selan 			if (chmod(p->fts_accpath, oct ? omode :
11058142Sbostic 			    getmode(set, p->fts_statp->st_mode)) && !fflag) {
11158142Sbostic 				warn(p->fts_path);
11258142Sbostic 				retval = 1;
11358142Sbostic 			}
11453782Selan 			break;
11553782Selan 		}
11639829Sbostic 	exit(retval);
11716242Slayer }
11816242Slayer 
11952070Sbostic void
12039829Sbostic usage()
12116242Slayer {
12253782Selan 	(void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n");
12339829Sbostic 	exit(1);
12416242Slayer }
125