xref: /csrg-svn/usr.sbin/chown/chgrp.c (revision 26262)
119840Sdist /*
219840Sdist  * Copyright (c) 1980 Regents of the University of California.
319840Sdist  * All rights reserved.  The Berkeley software License Agreement
419840Sdist  * specifies the terms and conditions for redistribution.
519840Sdist  */
619840Sdist 
76392Sroot #ifndef lint
8*26262Skarels static char sccsid[] = "@(#)chgrp.c	5.4 (Berkeley) 02/20/86";
919840Sdist #endif not lint
106392Sroot 
11974Sbill /*
1218451Smckusick  * chgrp -fR gid file ...
13974Sbill  */
14974Sbill 
15974Sbill #include <stdio.h>
16974Sbill #include <ctype.h>
17974Sbill #include <sys/types.h>
18974Sbill #include <sys/stat.h>
19974Sbill #include <grp.h>
206037Swnj #include <pwd.h>
2118451Smckusick #include <sys/dir.h>
22974Sbill 
236392Sroot struct	group *gr, *getgrnam(), *getgrgid();
246392Sroot struct	passwd *getpwuid(), *pwd;
256392Sroot struct	stat stbuf;
266037Swnj int	gid, uid;
27974Sbill int	status;
2818451Smckusick int	fflag, rflag;
296392Sroot /* VARARGS */
306392Sroot int	fprintf();
31974Sbill 
32974Sbill main(argc, argv)
336392Sroot 	int argc;
346392Sroot 	char *argv[];
35974Sbill {
366037Swnj 	register c, i;
3724504Ssam 	register char *cp;
38974Sbill 
396392Sroot 	argc--, argv++;
4024504Ssam 	while (argc > 0 && argv[0][0] == '-') {
4124504Ssam 		for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
4224504Ssam 
4324504Ssam 		case 'f':
4424504Ssam 			fflag++;
4524504Ssam 			break;
4624504Ssam 
4724504Ssam 		case 'R':
4824504Ssam 			rflag++;
4924504Ssam 			break;
5024504Ssam 
5124504Ssam 		default:
52*26262Skarels 			fatal(255, "unknown option: %c", *cp);
5324504Ssam 			/*NOTREACHED*/
5424504Ssam 		}
5512075Sralph 		argv++, argc--;
5612075Sralph 	}
576392Sroot 	if (argc < 2) {
5818451Smckusick 		fprintf(stderr, "usage: chgrp [-fR] gid file ...\n");
5918451Smckusick 		exit(255);
60974Sbill 	}
616037Swnj 	uid = getuid();
626392Sroot 	if (isnumber(argv[0])) {
6310426Ssam 		gid = atoi(argv[0]);
646392Sroot 		gr = getgrgid(gid);
6524504Ssam 		if (uid && gr == NULL)
6624504Ssam 			fatal(255, "%s: unknown group", argv[0]);
67974Sbill 	} else {
686392Sroot 		gr = getgrnam(argv[0]);
6924504Ssam 		if (gr == NULL)
7024504Ssam 			fatal(255, "%s: unknown group", argv[0]);
71974Sbill 		gid = gr->gr_gid;
72974Sbill 	}
736392Sroot 	pwd = getpwuid(uid);
7424504Ssam 	if (pwd == NULL)
7524504Ssam 		fatal(255, "Who are you?");
766392Sroot 	if (uid && pwd->pw_gid != gid) {
776392Sroot 		for (i=0; gr->gr_mem[i]; i++)
786392Sroot 			if (!(strcmp(pwd->pw_name, gr->gr_mem[i])))
796392Sroot 				goto ok;
8012075Sralph 		if (fflag)
8112075Sralph 			exit(0);
8224504Ssam 		fatal(255, "You are not a member of the %s group", argv[0]);
836037Swnj 	}
846392Sroot ok:
856392Sroot 	for (c = 1; c < argc; c++) {
8624504Ssam 		/* do stat for directory arguments */
8724504Ssam 		if (stat(argv[c], &stbuf)) {
8824504Ssam 			status += error("can't access %s", argv[c]);
896392Sroot 			continue;
906392Sroot 		}
916037Swnj 		if (uid && uid != stbuf.st_uid) {
9224504Ssam 			status += error("You are not the owner of %s", argv[c]);
936392Sroot 			continue;
946392Sroot 		}
9524504Ssam 		if (rflag && stbuf.st_mode & S_IFDIR) {
9618451Smckusick 			status += chownr(argv[c], stbuf.st_uid, gid);
9724504Ssam 			continue;
9824504Ssam 		}
9924504Ssam 		if (chown(argv[c], stbuf.st_uid, gid)) {
10024504Ssam 			status += error("can't change %s", argv[c]);
10124504Ssam 			continue;
10224504Ssam 		}
103974Sbill 	}
104974Sbill 	exit(status);
105974Sbill }
106974Sbill 
107974Sbill isnumber(s)
1086392Sroot 	char *s;
109974Sbill {
1106392Sroot 	register int c;
111974Sbill 
1126392Sroot 	while (c = *s++)
1136392Sroot 		if (!isdigit(c))
1146392Sroot 			return (0);
1156392Sroot 	return (1);
116974Sbill }
11718451Smckusick 
11818451Smckusick chownr(dir, uid, gid)
11924504Ssam 	char *dir;
12018451Smckusick {
12124504Ssam 	register DIR *dirp;
12224504Ssam 	register struct direct *dp;
12324504Ssam 	register struct stat st;
12424504Ssam 	char savedir[1024];
12524504Ssam 	int ecode;
12618451Smckusick 
12724504Ssam 	if (getwd(savedir) == 0)
12824504Ssam 		fatal(255, "%s", savedir);
12924504Ssam 	/*
13025936Skarels 	 * Change what we are given before doing its contents.
13124504Ssam 	 */
13224504Ssam 	if (chown(dir, uid, gid) < 0 && error("can't change %s", dir))
13324504Ssam 		return (1);
13424504Ssam 	if (chdir(dir) < 0)
13524504Ssam 		return (Perror(dir));
13624504Ssam 	if ((dirp = opendir(".")) == NULL)
13724504Ssam 		return (Perror(dir));
13818451Smckusick 	dp = readdir(dirp);
13918451Smckusick 	dp = readdir(dirp); /* read "." and ".." */
14024504Ssam 	ecode = 0;
14118451Smckusick 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
14224504Ssam 		if (stat(dp->d_name, &st) < 0) {
14324504Ssam 			ecode = error("can't access %s", dp->d_name);
14424504Ssam 			if (ecode)
14524504Ssam 				break;
14624504Ssam 			continue;
14718451Smckusick 		}
14825936Skarels 		if (uid && uid != st.st_uid) {
14925936Skarels 			ecode = error("You are not the owner of %s",
15025936Skarels 				dp->d_name);
15125936Skarels 			continue;
15225936Skarels 		}
15324504Ssam 		if (st.st_mode&S_IFDIR) {
15424504Ssam 			ecode = chownr(dp->d_name, st.st_uid, gid);
15524504Ssam 			if (ecode)
15624504Ssam 				break;
15724504Ssam 			continue;
15824504Ssam 		}
15924504Ssam 		if (chown(dp->d_name, st.st_uid, gid) < 0 &&
16024504Ssam 		    (ecode = error("can't change %s", dp->d_name)))
16124504Ssam 			break;
16218451Smckusick 	}
16318451Smckusick 	closedir(dirp);
16424504Ssam 	if (chdir(savedir) < 0)
16524504Ssam 		fatal(255, "can't change back to %s", savedir);
16624504Ssam 	return (ecode);
16718451Smckusick }
16824504Ssam 
16924504Ssam error(fmt, a)
17024504Ssam 	char *fmt, *a;
17124504Ssam {
17224504Ssam 
17324504Ssam 	if (!fflag) {
17424504Ssam 		fprintf(stderr, "chgrp: ");
17524504Ssam 		fprintf(stderr, fmt, a);
17624504Ssam 		putc('\n', stderr);
17724504Ssam 	}
17824504Ssam 	return (!fflag);
17924504Ssam }
18024504Ssam 
18124504Ssam fatal(status, fmt, a)
18224504Ssam 	int status;
18324504Ssam 	char *fmt, *a;
18424504Ssam {
18524504Ssam 
18624504Ssam 	fflag = 0;
18724504Ssam 	(void) error(fmt, a);
18824504Ssam 	exit(status);
18924504Ssam }
19024504Ssam 
19124504Ssam Perror(s)
19224504Ssam 	char *s;
19324504Ssam {
19424504Ssam 
19524504Ssam 	fprintf(stderr, "chgrp: ");
19624504Ssam 	perror(s);
19724504Ssam 	return (1);
19824504Ssam }
199