xref: /csrg-svn/bin/chmod/chmod.c (revision 52070)
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*52070Sbostic static char sccsid[] = "@(#)chmod.c	5.20 (Berkeley) 12/28/91";
1634043Sbostic #endif /* not lint */
1734043Sbostic 
1816242Slayer #include <sys/types.h>
1916242Slayer #include <sys/stat.h>
20*52070Sbostic #include <errno.h>
2139829Sbostic #include <fts.h>
22*52070Sbostic #include <unistd.h>
2339829Sbostic #include <stdio.h>
24*52070Sbostic #include <stdlib.h>
2542010Sbostic #include <string.h>
2616242Slayer 
2739829Sbostic int retval;
2816242Slayer 
29*52070Sbostic void err __P((const char *, ...));
30*52070Sbostic void error __P((char *));
31*52070Sbostic void usage __P((void));
32*52070Sbostic 
33*52070Sbostic int
3424503Ssam main(argc, argv)
3534043Sbostic 	int argc;
36*52070Sbostic 	char *argv[];
3716242Slayer {
3839829Sbostic 	register FTS *fts;
3939829Sbostic 	register FTSENT *p;
4039829Sbostic 	register int oct, omode;
4139829Sbostic 	struct stat sb;
42*52070Sbostic 	mode_t *set;
4339829Sbostic 	int ch, fflag, rflag;
44*52070Sbostic 	char *ep, *mode;
4516242Slayer 
4639829Sbostic 	fflag = rflag = 0;
4739829Sbostic 	while ((ch = getopt(argc, argv, "Rfrwx")) != EOF)
4834043Sbostic 		switch((char)ch) {
4924503Ssam 		case 'R':
5047072Sbostic 			rflag = 1;
5124503Ssam 			break;
5247072Sbostic 		case 'f':		/* no longer documented */
5347072Sbostic 			fflag = 1;
5424503Ssam 			break;
5547072Sbostic 		case 'r':		/* "-[rwx]" are valid file modes */
5639829Sbostic 		case 'w':
5739829Sbostic 		case 'x':
5839829Sbostic 			--optind;
5939829Sbostic 			goto done;
6034043Sbostic 		case '?':
6124503Ssam 		default:
6239829Sbostic 			usage();
6323482Smckusick 		}
6434043Sbostic done:	argv += optind;
6534043Sbostic 	argc -= optind;
6634043Sbostic 
6739829Sbostic 	if (argc < 2)
6839829Sbostic 		usage();
6939829Sbostic 
7039829Sbostic 	mode = *argv;
7139829Sbostic 	if (*mode >= '0' && *mode <= '7') {
72*52070Sbostic 		omode = (int)strtol(mode, &ep, 8);
73*52070Sbostic 		if (omode < 0 || *ep)
74*52070Sbostic 			err("invalid file mode: %s", mode);
7539829Sbostic 		oct = 1;
7639829Sbostic 	} else {
77*52070Sbostic 		if (!(set = setmode(mode)))
78*52070Sbostic 			err("invalid file mode: %s", mode);
7939829Sbostic 		oct = 0;
8016242Slayer 	}
8134043Sbostic 
8239829Sbostic 	retval = 0;
8339829Sbostic 	if (rflag) {
84*52070Sbostic 		if ((fts = fts_open(++argv,
85*52070Sbostic 		    oct ? FTS_NOSTAT|FTS_PHYSICAL : FTS_PHYSICAL, 0)) == NULL)
86*52070Sbostic 			err("%s", strerror(errno));
8745639Sbostic 		while (p = fts_read(fts))
8845639Sbostic 			switch(p->fts_info) {
8945639Sbostic 			case FTS_D:
9045639Sbostic 				break;
9147235Sbostic 			case FTS_DNR:
9245639Sbostic 			case FTS_ERR:
9347235Sbostic 			case FTS_NS:
94*52070Sbostic 				err("%s: %s", p->fts_path, strerror(errno));
9545639Sbostic 			default:
9645639Sbostic 				if (chmod(p->fts_accpath, oct ? omode :
9745639Sbostic 				    getmode(set, p->fts_statb.st_mode)) &&
9845639Sbostic 				    !fflag)
9942202Sbostic 					error(p->fts_path);
10045639Sbostic 				break;
10116242Slayer 			}
10239829Sbostic 		exit(retval);
10334043Sbostic 	}
10439829Sbostic 	if (oct) {
10539829Sbostic 		while (*++argv)
10639829Sbostic 			if (chmod(*argv, omode) && !fflag)
10739829Sbostic 				error(*argv);
10839829Sbostic 	} else
10939829Sbostic 		while (*++argv)
11040269Sbostic 			if ((lstat(*argv, &sb) ||
11140944Sbostic 			    chmod(*argv, getmode(set, sb.st_mode))) && !fflag)
11239829Sbostic 				error(*argv);
11339829Sbostic 	exit(retval);
11416242Slayer }
11516242Slayer 
116*52070Sbostic void
11739829Sbostic error(name)
11839829Sbostic 	char *name;
11916242Slayer {
120*52070Sbostic 	(void)fprintf(stderr, "chmod: %s: %s\n", name, strerror(errno));
12139829Sbostic 	retval = 1;
12216242Slayer }
12316242Slayer 
124*52070Sbostic void
12539829Sbostic usage()
12616242Slayer {
127*52070Sbostic 	(void)fprintf(stderr, "usage: chmod [-R] mode file ...\n");
12839829Sbostic 	exit(1);
12916242Slayer }
130*52070Sbostic 
131*52070Sbostic #if __STDC__
132*52070Sbostic #include <stdarg.h>
133*52070Sbostic #else
134*52070Sbostic #include <varargs.h>
135*52070Sbostic #endif
136*52070Sbostic 
137*52070Sbostic void
138*52070Sbostic #if __STDC__
139*52070Sbostic err(const char *fmt, ...)
140*52070Sbostic #else
141*52070Sbostic err(fmt, va_alist)
142*52070Sbostic 	char *fmt;
143*52070Sbostic         va_dcl
144*52070Sbostic #endif
145*52070Sbostic {
146*52070Sbostic 	va_list ap;
147*52070Sbostic #if __STDC__
148*52070Sbostic 	va_start(ap, fmt);
149*52070Sbostic #else
150*52070Sbostic 	va_start(ap);
151*52070Sbostic #endif
152*52070Sbostic 	(void)fprintf(stderr, "chmod: ");
153*52070Sbostic 	(void)vfprintf(stderr, fmt, ap);
154*52070Sbostic 	va_end(ap);
155*52070Sbostic 	(void)fprintf(stderr, "\n");
156*52070Sbostic 	exit(1);
157*52070Sbostic 	/* NOTREACHED */
158*52070Sbostic }
159