xref: /original-bsd/bin/chmod/chmod.c (revision b485b642)
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.8 (Berkeley) 01/01/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 int retval;
35 
36 main(argc, argv)
37 	int argc;
38 	char **argv;
39 {
40 	extern int errno, optind;
41 	register FTS *fts;
42 	register FTSENT *p;
43 	register int oct, omode;
44 	register char *mode;
45 	struct stat sb;
46 	int ch, fflag, rflag;
47 	mode_t setmode();
48 
49 	fflag = rflag = 0;
50 	while ((ch = getopt(argc, argv, "Rfrwx")) != EOF)
51 		switch((char)ch) {
52 		case 'R':
53 			rflag++;
54 			break;
55 		case 'f':
56 			fflag++;
57 			break;
58 		/* "-[rwx]" are valid file modes */
59 		case 'r':
60 		case 'w':
61 		case 'x':
62 			--optind;
63 			goto done;
64 		case '?':
65 		default:
66 			usage();
67 		}
68 done:	argv += optind;
69 	argc -= optind;
70 
71 	if (argc < 2)
72 		usage();
73 
74 	mode = *argv;
75 	if (*mode >= '0' && *mode <= '7') {
76 		omode = (int)strtol(mode, (char **)NULL, 8);
77 		oct = 1;
78 	} else {
79 		if (setmode(mode, 0, 0) == (mode_t)-1) {
80 			(void)fprintf(stderr, "chmod: invalid file mode.\n");
81 			exit(1);
82 		}
83 		oct = 0;
84 	}
85 
86 	retval = 0;
87 	if (rflag) {
88 		if (!(fts = ftsopen(++argv,
89 		    (oct ? FTS_NOSTAT : 0)|FTS_MULTIPLE|FTS_PHYSICAL, 0))) {
90 			(void)fprintf(stderr, "chmod: %s.\n", strerror(errno));
91 			exit(1);
92 		}
93 		while (p = ftsread(fts)) {
94 			if (p->info == FTS_D)
95 				continue;
96 			if (p->info == FTS_ERR) {
97 				if (!fflag)
98 					error(p->path);
99 				continue;
100 			}
101 			if (chmod(p->accpath, oct ? omode :
102 			    (int)setmode(mode, p->statb.st_mode, 0)) && !fflag)
103 				error(p->path);
104 		}
105 		exit(retval);
106 	}
107 	if (oct) {
108 		while (*++argv)
109 			if (chmod(*argv, omode) && !fflag)
110 				error(*argv);
111 	} else
112 		while (*++argv)
113 			if ((lstat(*argv, &sb) || chmod(*argv,
114 			    (int)setmode(mode, sb.st_mode, 0))) && !fflag)
115 				error(*argv);
116 	exit(retval);
117 }
118 
119 error(name)
120 	char *name;
121 {
122 	(void)fprintf(stderr, "chmod: %s: %s.\n", name, strerror(errno));
123 	retval = 1;
124 }
125 
126 usage()
127 {
128 	(void)fprintf(stderr, "chmod: chmod [-fR] mode file ...\n");
129 	exit(1);
130 }
131