xref: /original-bsd/bin/chmod/chmod.c (revision 3705696b)
1 /*
2  * Copyright (c) 1989, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 static char copyright[] =
10 "@(#) Copyright (c) 1989, 1993\n\
11 	The Regents of the University of California.  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)chmod.c	8.1 (Berkeley) 06/27/93";
16 #endif /* not lint */
17 
18 #include <sys/types.h>
19 #include <sys/stat.h>
20 
21 #include <err.h>
22 #include <errno.h>
23 #include <fts.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <unistd.h>
28 
29 void usage __P((void));
30 
31 int
32 main(argc, argv)
33 	int argc;
34 	char *argv[];
35 {
36 	register FTS *ftsp;
37 	register FTSENT *p;
38 	register int oct, omode;
39 	mode_t *set;
40 	int ch, fflag, rflag, hflag, Hflag;
41 	int fts_options, retval;
42 	char *ep, *mode;
43 
44 	fts_options = FTS_PHYSICAL;
45 	fflag = rflag = hflag = Hflag = 0;
46 	while ((ch = getopt(argc, argv, "HRfhrwx")) != EOF)
47 		switch((char)ch) {
48 		case 'H':
49 			Hflag = 1;
50 			fts_options |= FTS_COMFOLLOW;
51 			break;
52 		case 'R':
53 			rflag = 1;
54 			break;
55 		case 'f':		/* no longer documented */
56 			fflag = 1;
57 			break;
58 		case 'h':
59 			hflag = 1;
60 			fts_options &= ~FTS_PHYSICAL;
61 			fts_options |= FTS_LOGICAL;
62 			break;
63 		case 'r':		/* "-[rwx]" are valid file modes */
64 		case 'w':
65 		case 'x':
66 			--optind;
67 			goto done;
68 		case '?':
69 		default:
70 			usage();
71 		}
72 done:	argv += optind;
73 	argc -= optind;
74 
75 	if (argc < 2)
76 		usage();
77 
78 	mode = *argv;
79 	if (*mode >= '0' && *mode <= '7') {
80 		omode = (int)strtol(mode, &ep, 8);
81 		if (omode < 0 || *ep)
82 			errx(1, "invalid file mode: %s", mode);
83 		oct = 1;
84 	} else {
85 		if ((set = setmode(mode)) == NULL)
86 			errx(1, "invalid file mode: %s", mode);
87 		oct = 0;
88 	}
89 
90 	retval = 0;
91 	if ((ftsp = fts_open(++argv, fts_options, 0)) == NULL)
92 		err(1, "");
93 	while (p = fts_read(ftsp))
94 		switch(p->fts_info) {
95 		case FTS_D:
96 			if (!rflag)
97 				fts_set(ftsp, p, FTS_SKIP);
98 		case FTS_SL:
99 		case FTS_SLNONE:
100 			break;
101 		case FTS_DNR:
102 		case FTS_ERR:
103 		case FTS_NS:
104 			err(1, "%s", p->fts_path);
105 		default:
106 			if (p->fts_info == FTS_SL && !(hflag ||
107 			    (Hflag && p->fts_level == FTS_ROOTLEVEL)))
108 				continue;
109 			if (chmod(p->fts_accpath, oct ? omode :
110 			    getmode(set, p->fts_statp->st_mode)) && !fflag) {
111 				warn(p->fts_path);
112 				retval = 1;
113 			}
114 			break;
115 		}
116 	exit(retval);
117 }
118 
119 void
120 usage()
121 {
122 	(void)fprintf(stderr, "usage: chmod [-HRh] mode file ...\n");
123 	exit(1);
124 }
125