xref: /original-bsd/usr.sbin/chown/chgrp.c (revision 1a56dd2c)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 static char sccsid[] = "@(#)chgrp.c	5.9 (Berkeley) 12/21/87";
9 #endif not lint
10 
11 /*
12  * chgrp -fR gid file ...
13  */
14 
15 #include <stdio.h>
16 #include <ctype.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <grp.h>
20 #include <pwd.h>
21 #include <sys/dir.h>
22 
23 struct	group *gr, *getgrnam(), *getgrgid();
24 struct	passwd *getpwuid(), *pwd;
25 struct	stat stbuf;
26 int	gid, uid;
27 int	status;
28 int	fflag, rflag;
29 /* VARARGS */
30 int	fprintf();
31 
32 main(argc, argv)
33 	int argc;
34 	char *argv[];
35 {
36 	register c, i;
37 	register char *cp;
38 
39 	argc--, argv++;
40 	while (argc > 0 && argv[0][0] == '-') {
41 		for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
42 
43 		case 'f':
44 			fflag++;
45 			break;
46 
47 		case 'R':
48 			rflag++;
49 			break;
50 
51 		default:
52 			fatal(255, "unknown option: %c", *cp);
53 			/*NOTREACHED*/
54 		}
55 		argv++, argc--;
56 	}
57 	if (argc < 2) {
58 		fprintf(stderr, "usage: chgrp [-fR] gid file ...\n");
59 		exit(255);
60 	}
61 	uid = getuid();
62 	if (isnumber(argv[0])) {
63 		gid = atoi(argv[0]);
64 		gr = getgrgid(gid);
65 		if (uid && gr == NULL)
66 			fatal(255, "%s: unknown group", argv[0]);
67 	} else {
68 		gr = getgrnam(argv[0]);
69 		if (gr == NULL)
70 			fatal(255, "%s: unknown group", argv[0]);
71 		gid = gr->gr_gid;
72 	}
73 	pwd = getpwuid(uid);
74 	if (pwd == NULL)
75 		fatal(255, "Who are you?");
76 	if (uid && pwd->pw_gid != gid) {
77 		for (i=0; gr->gr_mem[i]; i++)
78 			if (!(strcmp(pwd->pw_name, gr->gr_mem[i])))
79 				goto ok;
80 		if (fflag)
81 			exit(0);
82 		fatal(255, "You are not a member of the %s group", argv[0]);
83 	}
84 ok:
85 	for (c = 1; c < argc; c++) {
86 		/* do stat for directory arguments */
87 		if (lstat(argv[c], &stbuf)) {
88 			status += Perror(argv[c]);
89 			continue;
90 		}
91 		if (uid && uid != stbuf.st_uid) {
92 			status += error("You are not the owner of %s", argv[c]);
93 			continue;
94 		}
95 		if (rflag && ((stbuf.st_mode & S_IFMT) == S_IFDIR)) {
96 			status += chownr(argv[c]);
97 			continue;
98 		}
99 		if (chown(argv[c], -1, gid)) {
100 			status += Perror(argv[c]);
101 			continue;
102 		}
103 	}
104 	exit(status);
105 }
106 
107 isnumber(s)
108 	char *s;
109 {
110 	register int c;
111 
112 	while (c = *s++)
113 		if (!isdigit(c))
114 			return (0);
115 	return (1);
116 }
117 
118 chownr(dir)
119 	char *dir;
120 {
121 	register DIR *dirp;
122 	register struct direct *dp;
123 	struct stat st;
124 	char savedir[1024];
125 	int ecode;
126 
127 	if (getwd(savedir) == 0)
128 		fatal(255, "%s", savedir);
129 	/*
130 	 * Change what we are given before doing its contents.
131 	 */
132 	if (chown(dir, -1, gid) < 0 && Perror(dir))
133 		return (1);
134 	if (chdir(dir) < 0) {
135 		Perror(dir);
136 		return (1);
137 	}
138 	if ((dirp = opendir(".")) == NULL) {
139 		Perror(dir);
140 		return (1);
141 	}
142 	dp = readdir(dirp);
143 	dp = readdir(dirp); /* read "." and ".." */
144 	ecode = 0;
145 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
146 		if (lstat(dp->d_name, &st) < 0) {
147 			ecode = Perror(dp->d_name);
148 			if (ecode)
149 				break;
150 			continue;
151 		}
152 		if (uid && uid != st.st_uid) {
153 			ecode = error("You are not the owner of %s",
154 				dp->d_name);
155 			continue;
156 		}
157 		if ((st.st_mode & S_IFMT) == S_IFDIR) {
158 			ecode = chownr(dp->d_name);
159 			if (ecode)
160 				break;
161 			continue;
162 		}
163 		if (chown(dp->d_name, -1, gid) < 0 &&
164 		    (ecode = Perror(dp->d_name)))
165 			break;
166 	}
167 	closedir(dirp);
168 	if (chdir(savedir) < 0)
169 		fatal(255, "can't change back to %s", savedir);
170 	return (ecode);
171 }
172 
173 error(fmt, a)
174 	char *fmt, *a;
175 {
176 
177 	if (!fflag) {
178 		fprintf(stderr, "chgrp: ");
179 		fprintf(stderr, fmt, a);
180 		putc('\n', stderr);
181 	}
182 	return (!fflag);
183 }
184 
185 fatal(status, fmt, a)
186 	int status;
187 	char *fmt, *a;
188 {
189 
190 	fflag = 0;
191 	(void) error(fmt, a);
192 	exit(status);
193 }
194 
195 Perror(s)
196 	char *s;
197 {
198 
199 	if (!fflag) {
200 		fprintf(stderr, "chgrp: ");
201 		perror(s);
202 	}
203 	return (!fflag);
204 }
205