xref: /csrg-svn/bin/chmod/chmod.c (revision 53782)
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*53782Selan static char sccsid[] = "@(#)chmod.c	5.22 (Berkeley) 06/01/92";
1634043Sbostic #endif /* not lint */
1734043Sbostic 
1816242Slayer #include <sys/types.h>
1916242Slayer #include <sys/stat.h>
2052070Sbostic #include <errno.h>
2139829Sbostic #include <fts.h>
2252070Sbostic #include <unistd.h>
2339829Sbostic #include <stdio.h>
2452070Sbostic #include <stdlib.h>
2542010Sbostic #include <string.h>
2616242Slayer 
2739829Sbostic int retval;
2816242Slayer 
2952070Sbostic void err __P((const char *, ...));
3052070Sbostic void error __P((char *));
3152070Sbostic void usage __P((void));
3252070Sbostic 
3352070Sbostic int
3424503Ssam main(argc, argv)
3534043Sbostic 	int argc;
3652070Sbostic 	char *argv[];
3716242Slayer {
38*53782Selan 	register FTS *ftsp;
3939829Sbostic 	register FTSENT *p;
4039829Sbostic 	register int oct, omode;
4139829Sbostic 	struct stat sb;
4252070Sbostic 	mode_t *set;
43*53782Selan 	int ch, fflag, rflag, hflag, Hflag;
4452070Sbostic 	char *ep, *mode;
45*53782Selan 	int fts_options;
4616242Slayer 
47*53782Selan 	fts_options = FTS_PHYSICAL;
48*53782Selan 	fflag = rflag = hflag = Hflag = 0;
49*53782Selan 	while ((ch = getopt(argc, argv, "HRfhrwx")) != EOF)
5034043Sbostic 		switch((char)ch) {
51*53782Selan 		case 'H':
52*53782Selan 			Hflag = 1;
53*53782Selan 			fts_options |= FTS_COMFOLLOW;
54*53782Selan 			break;
5524503Ssam 		case 'R':
5647072Sbostic 			rflag = 1;
5724503Ssam 			break;
5847072Sbostic 		case 'f':		/* no longer documented */
5947072Sbostic 			fflag = 1;
6024503Ssam 			break;
61*53782Selan 		case 'h':
62*53782Selan 			hflag = 1;
63*53782Selan 			fts_options &= ~FTS_PHYSICAL;
64*53782Selan 			fts_options |= FTS_LOGICAL;
65*53782Selan 			break;
6647072Sbostic 		case 'r':		/* "-[rwx]" are valid file modes */
6739829Sbostic 		case 'w':
6839829Sbostic 		case 'x':
6939829Sbostic 			--optind;
7039829Sbostic 			goto done;
7134043Sbostic 		case '?':
7224503Ssam 		default:
7339829Sbostic 			usage();
7423482Smckusick 		}
7534043Sbostic done:	argv += optind;
7634043Sbostic 	argc -= optind;
7734043Sbostic 
7839829Sbostic 	if (argc < 2)
7939829Sbostic 		usage();
8039829Sbostic 
8139829Sbostic 	mode = *argv;
8239829Sbostic 	if (*mode >= '0' && *mode <= '7') {
8352070Sbostic 		omode = (int)strtol(mode, &ep, 8);
8452070Sbostic 		if (omode < 0 || *ep)
8552070Sbostic 			err("invalid file mode: %s", mode);
8639829Sbostic 		oct = 1;
8739829Sbostic 	} else {
8852070Sbostic 		if (!(set = setmode(mode)))
8952070Sbostic 			err("invalid file mode: %s", mode);
9039829Sbostic 		oct = 0;
9116242Slayer 	}
9234043Sbostic 
9339829Sbostic 	retval = 0;
94*53782Selan 	if (oct)
95*53782Selan 		fts_options |= FTS_NOSTAT;
96*53782Selan 	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
9752070Sbostic 			err("%s", strerror(errno));
98*53782Selan 	while (p = fts_read(ftsp))
99*53782Selan 		switch(p->fts_info) {
100*53782Selan 		case FTS_D:
101*53782Selan 			if (!rflag)
102*53782Selan 				fts_set(ftsp, p, FTS_SKIP);
103*53782Selan 			break;
104*53782Selan 		case FTS_DNR:
105*53782Selan 		case FTS_ERR:
106*53782Selan 		case FTS_NS:
107*53782Selan 			err("%s: %s", p->fts_path, strerror(errno));
108*53782Selan 		default:
109*53782Selan 			if (p->fts_info == FTS_SL &&
110*53782Selan 			    !(hflag ||
111*53782Selan 			    (Hflag && p->fts_level == FTS_ROOTLEVEL)))
112*53782Selan 				continue;
113*53782Selan 			if (chmod(p->fts_accpath, oct ? omode :
114*53782Selan 			    getmode(set, p->fts_statp->st_mode)) &&
115*53782Selan 			    !fflag)
116*53782Selan 				error(p->fts_path);
117*53782Selan 			break;
118*53782Selan 		}
11939829Sbostic 	exit(retval);
12016242Slayer }
12116242Slayer 
12252070Sbostic void
12339829Sbostic error(name)
12439829Sbostic 	char *name;
12516242Slayer {
12652070Sbostic 	(void)fprintf(stderr, "chmod: %s: %s\n", name, strerror(errno));
12739829Sbostic 	retval = 1;
12816242Slayer }
12916242Slayer 
13052070Sbostic void
13139829Sbostic usage()
13216242Slayer {
133*53782Selan 	(void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n");
13439829Sbostic 	exit(1);
13516242Slayer }
13652070Sbostic 
13752070Sbostic #if __STDC__
13852070Sbostic #include <stdarg.h>
13952070Sbostic #else
14052070Sbostic #include <varargs.h>
14152070Sbostic #endif
14252070Sbostic 
14352070Sbostic void
14452070Sbostic #if __STDC__
14552070Sbostic err(const char *fmt, ...)
14652070Sbostic #else
14752070Sbostic err(fmt, va_alist)
14852070Sbostic 	char *fmt;
14952070Sbostic         va_dcl
15052070Sbostic #endif
15152070Sbostic {
15252070Sbostic 	va_list ap;
15352070Sbostic #if __STDC__
15452070Sbostic 	va_start(ap, fmt);
15552070Sbostic #else
15652070Sbostic 	va_start(ap);
15752070Sbostic #endif
15852070Sbostic 	(void)fprintf(stderr, "chmod: ");
15952070Sbostic 	(void)vfprintf(stderr, fmt, ap);
16052070Sbostic 	va_end(ap);
16152070Sbostic 	(void)fprintf(stderr, "\n");
16252070Sbostic 	exit(1);
16352070Sbostic 	/* NOTREACHED */
16452070Sbostic }
165