xref: /original-bsd/bin/chmod/chmod.c (revision 188f7363)
1 /*
2  * Copyright (c) 1989 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms are permitted
6  * provided that the above copyright notice and this paragraph are
7  * duplicated in all such forms and that any documentation,
8  * advertising materials, and other materials related to such
9  * distribution and use acknowledge that the software was developed
10  * by the University of California, Berkeley.  The name of the
11  * University may not be used to endorse or promote products derived
12  * from this software without specific prior written permission.
13  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14  * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
16  */
17 
18 #ifndef lint
19 char copyright[] =
20 "@(#) Copyright (c) 1989 The Regents of the University of California.\n\
21  All rights reserved.\n";
22 #endif /* not lint */
23 
24 #ifndef lint
25 static char sccsid[] = "@(#)chmod.c	5.11 (Berkeley) 04/28/90";
26 #endif /* not lint */
27 
28 #include <sys/types.h>
29 #include <sys/stat.h>
30 #include <fts.h>
31 #include <stdio.h>
32 #include <strings.h>
33 
34 extern int errno;
35 int retval;
36 
37 main(argc, argv)
38 	int argc;
39 	char **argv;
40 {
41 	extern int optind;
42 	register FTS *fts;
43 	register FTSENT *p;
44 	register int oct, omode;
45 	register char *mode;
46 	mode_t *set, *setmode();
47 	struct stat sb;
48 	int ch, fflag, rflag;
49 
50 	fflag = rflag = 0;
51 	while ((ch = getopt(argc, argv, "Rfrwx")) != EOF)
52 		switch((char)ch) {
53 		case 'R':
54 			rflag++;
55 			break;
56 		case 'f':
57 			fflag++;
58 			break;
59 		/* "-[rwx]" are valid file modes */
60 		case 'r':
61 		case 'w':
62 		case 'x':
63 			--optind;
64 			goto done;
65 		case '?':
66 		default:
67 			usage();
68 		}
69 done:	argv += optind;
70 	argc -= optind;
71 
72 	if (argc < 2)
73 		usage();
74 
75 	mode = *argv;
76 	if (*mode >= '0' && *mode <= '7') {
77 		omode = (int)strtol(mode, (char **)NULL, 8);
78 		oct = 1;
79 	} else {
80 		if (!(set = setmode(mode))) {
81 			(void)fprintf(stderr, "chmod: invalid file mode.\n");
82 			exit(1);
83 		}
84 		oct = 0;
85 	}
86 
87 	retval = 0;
88 	if (rflag) {
89 		if (!(fts = ftsopen(++argv,
90 		    (oct ? FTS_NOSTAT : 0)|FTS_MULTIPLE|FTS_PHYSICAL, 0))) {
91 			(void)fprintf(stderr, "chmod: %s.\n", strerror(errno));
92 			exit(1);
93 		}
94 		while (p = ftsread(fts)) {
95 			if (p->info == FTS_D)
96 				continue;
97 			if (p->info == FTS_ERR) {
98 				if (!fflag)
99 					error(p->path);
100 				continue;
101 			}
102 			if (chmod(p->accpath, oct ?
103 			    omode : getmode(set, p->statb.st_mode)) && !fflag)
104 				error(p->path);
105 		}
106 		exit(retval);
107 	}
108 	if (oct) {
109 		while (*++argv)
110 			if (chmod(*argv, omode) && !fflag)
111 				error(*argv);
112 	} else
113 		while (*++argv)
114 			if ((lstat(*argv, &sb) ||
115 			    chmod(*argv, getmode(set, sb.st_mode))) && !fflag)
116 				error(*argv);
117 	exit(retval);
118 }
119 
120 error(name)
121 	char *name;
122 {
123 	(void)fprintf(stderr, "chmod: %s: %s.\n", name, strerror(errno));
124 	retval = 1;
125 }
126 
127 usage()
128 {
129 	(void)fprintf(stderr, "chmod: chmod [-fR] mode file ...\n");
130 	exit(1);
131 }
132