xref: /csrg-svn/usr.sbin/chown/chown.c (revision 45426)
122488Sdist /*
234039Sbostic  * Copyright (c) 1988 Regents of the University of California.
334039Sbostic  * All rights reserved.
434039Sbostic  *
542792Sbostic  * %sccs.include.redist.c%
622488Sdist  */
718450Smckusick 
822488Sdist #ifndef lint
922488Sdist char copyright[] =
1034039Sbostic "@(#) Copyright (c) 1988 Regents of the University of California.\n\
1122488Sdist  All rights reserved.\n";
1234039Sbostic #endif /* not lint */
1322488Sdist 
1422488Sdist #ifndef lint
15*45426Sbostic static char sccsid[] = "@(#)chown.c	5.16 (Berkeley) 10/26/90";
1634039Sbostic #endif /* not lint */
1722488Sdist 
1834039Sbostic #include <sys/param.h>
19975Sbill #include <sys/stat.h>
2038427Sbostic #include <sys/errno.h>
2138427Sbostic #include <dirent.h>
22*45426Sbostic #include <fts.h>
23975Sbill #include <pwd.h>
2418450Smckusick #include <grp.h>
2534039Sbostic #include <stdio.h>
2634039Sbostic #include <ctype.h>
27*45426Sbostic #include <string.h>
28975Sbill 
2941090Smarc int ischown, uid, gid, fflag, rflag, retval;
3041090Smarc char *gname, *myname;
31975Sbill 
32975Sbill main(argc, argv)
3334039Sbostic 	int argc;
3434039Sbostic 	char **argv;
35975Sbill {
3634039Sbostic 	extern int optind;
37*45426Sbostic 	register FTS *fts;
38*45426Sbostic 	register FTSENT *p;
3934039Sbostic 	register char *cp;
4034039Sbostic 	int ch;
41975Sbill 
4234039Sbostic 	myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv;
4334039Sbostic 	ischown = myname[2] == 'o';
4424505Ssam 
4534039Sbostic 	while ((ch = getopt(argc, argv, "Rf")) != EOF)
4634039Sbostic 		switch((char)ch) {
4734039Sbostic 		case 'R':
48*45426Sbostic 			rflag = 1;
4934039Sbostic 			break;
5024505Ssam 		case 'f':
51*45426Sbostic 			fflag = 1;
5224505Ssam 			break;
5334039Sbostic 		case '?':
5434039Sbostic 		default:
5534039Sbostic 			usage();
5634039Sbostic 		}
5734039Sbostic 	argv += optind;
5834039Sbostic 	argc -= optind;
5924505Ssam 
6034039Sbostic 	if (argc < 2)
6134039Sbostic 		usage();
6224505Ssam 
63*45426Sbostic 	uid = gid = -1;
6434039Sbostic 	if (ischown) {
65*45426Sbostic #ifdef SUPPORT_DOT
6634039Sbostic 		if (cp = index(*argv, '.')) {
6734039Sbostic 			*cp++ = '\0';
6834039Sbostic 			setgid(cp);
69*45426Sbostic 		} else
70*45426Sbostic #endif
71*45426Sbostic 		if (cp = index(*argv, ':')) {
72*45426Sbostic 			*cp++ = '\0';
73*45426Sbostic 			setgid(cp);
74*45426Sbostic 		}
7534039Sbostic 		setuid(*argv);
7624505Ssam 	}
77*45426Sbostic 	else
7834039Sbostic 		setgid(*argv);
7934039Sbostic 
80*45426Sbostic 	if (rflag) {
81*45426Sbostic 		if (!(fts = ftsopen(++argv, FTS_NOSTAT|FTS_PHYSICAL, 0))) {
82*45426Sbostic 			(void)fprintf(stderr,
83*45426Sbostic 			    "%s: %s.\n", myname, strerror(errno));
84*45426Sbostic 			exit(1);
8536959Sbostic 		}
86*45426Sbostic 		while (p = ftsread(fts)) {
87*45426Sbostic 			if (p->fts_info == FTS_D)
88*45426Sbostic 				continue;
89*45426Sbostic 			if (p->fts_info == FTS_ERR) {
90*45426Sbostic 				error(p->fts_path);
91*45426Sbostic 				continue;
92*45426Sbostic 			}
93*45426Sbostic 			if (chown(p->fts_accpath, uid, gid) && !fflag)
94*45426Sbostic 				chownerr(p->fts_path);
95*45426Sbostic 		}
96*45426Sbostic 		exit(retval);
9736959Sbostic 	}
98*45426Sbostic 	while (*++argv)
99*45426Sbostic 		if (chown(*argv, uid, gid) && !fflag)
100*45426Sbostic 			chownerr(*argv);
10134039Sbostic 	exit(retval);
10234039Sbostic }
10334039Sbostic 
10434039Sbostic setgid(s)
10534039Sbostic 	register char *s;
10634039Sbostic {
10734039Sbostic 	struct group *gr, *getgrnam();
10834039Sbostic 
10934039Sbostic 	if (!*s) {
11034039Sbostic 		gid = -1;			/* argument was "uid." */
11134039Sbostic 		return;
11211442Smckusick 	}
11334056Sbostic 	for (gname = s; *s && isdigit(*s); ++s);
11434039Sbostic 	if (!*s)
11534056Sbostic 		gid = atoi(gname);
11634039Sbostic 	else {
11734056Sbostic 		if (!(gr = getgrnam(gname))) {
11838427Sbostic 			(void)fprintf(stderr, "%s: unknown group id: %s\n",
11934056Sbostic 			    myname, gname);
120*45426Sbostic 			exit(1);
12118450Smckusick 		}
12234039Sbostic 		gid = gr->gr_gid;
123975Sbill 	}
124975Sbill }
125975Sbill 
12634039Sbostic setuid(s)
12734039Sbostic 	register char *s;
128975Sbill {
12934039Sbostic 	struct passwd *pwd, *getpwnam();
13034039Sbostic 	char *beg;
131975Sbill 
13234039Sbostic 	if (!*s) {
13334039Sbostic 		uid = -1;			/* argument was ".gid" */
13434039Sbostic 		return;
13534039Sbostic 	}
13634039Sbostic 	for (beg = s; *s && isdigit(*s); ++s);
13734039Sbostic 	if (!*s)
13834039Sbostic 		uid = atoi(beg);
13934039Sbostic 	else {
14034039Sbostic 		if (!(pwd = getpwnam(beg))) {
14138427Sbostic 			(void)fprintf(stderr,
14238427Sbostic 			    "chown: unknown user id: %s\n", beg);
143*45426Sbostic 			exit(1);
14434039Sbostic 		}
14534039Sbostic 		uid = pwd->pw_uid;
14634039Sbostic 	}
147975Sbill }
14818450Smckusick 
14934069Sbostic chownerr(file)
15034069Sbostic 	char *file;
15134069Sbostic {
15234069Sbostic 	static int euid = -1, ngroups = -1;
15334069Sbostic 
15434069Sbostic 	/* check for chown without being root */
15538427Sbostic 	if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) {
15634069Sbostic 		if (fflag)
15734069Sbostic 			exit(0);
158*45426Sbostic 		error(file);
159*45426Sbostic 		exit(1);
16034069Sbostic 	}
16134069Sbostic 	/* check group membership; kernel just returns EPERM */
16234069Sbostic 	if (gid != -1 && ngroups == -1) {
16334069Sbostic 		int groups[NGROUPS];
16434069Sbostic 
16534069Sbostic 		ngroups = getgroups(NGROUPS, groups);
16634069Sbostic 		while (--ngroups >= 0 && gid != groups[ngroups]);
16734069Sbostic 		if (ngroups < 0) {
16834069Sbostic 			if (fflag)
16934069Sbostic 				exit(0);
17038427Sbostic 			(void)fprintf(stderr,
17134069Sbostic 			    "%s: you are not a member of group %s.\n",
17234069Sbostic 			    myname, gname);
173*45426Sbostic 			exit(1);
17434069Sbostic 		}
17534069Sbostic 	}
176*45426Sbostic 	if (!fflag)
177*45426Sbostic 		error(file);
17834069Sbostic }
17934069Sbostic 
180*45426Sbostic error(name)
181*45426Sbostic 	char *name;
18224505Ssam {
183*45426Sbostic 	(void)fprintf(stderr, "%s: %s: %s\n", myname, name, strerror(errno));
184*45426Sbostic 	retval = 1;
18524505Ssam }
18624505Ssam 
18734039Sbostic usage()
18824505Ssam {
18938427Sbostic 	(void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
190*45426Sbostic 	    ischown ? "[owner][:group]" : "group");
191*45426Sbostic 	exit(1);
19224505Ssam }
193