xref: /original-bsd/usr.sbin/chown/chown.c (revision 7562ff97)
1 /*
2  * Copyright (c) 1988 Regents of the University of California.
3  * All rights reserved.
4  *
5  * %sccs.include.redist.c%
6  */
7 
8 #ifndef lint
9 char copyright[] =
10 "@(#) Copyright (c) 1988 Regents of the University of California.\n\
11  All rights reserved.\n";
12 #endif /* not lint */
13 
14 #ifndef lint
15 static char sccsid[] = "@(#)chown.c	5.15 (Berkeley) 06/01/90";
16 #endif /* not lint */
17 
18 #include <sys/param.h>
19 #include <sys/stat.h>
20 #include <sys/errno.h>
21 #include <dirent.h>
22 #include <pwd.h>
23 #include <grp.h>
24 #include <stdio.h>
25 #include <ctype.h>
26 
27 int ischown, uid, gid, fflag, rflag, retval;
28 char *gname, *myname;
29 
30 main(argc, argv)
31 	int argc;
32 	char **argv;
33 {
34 	extern char *optarg;
35 	extern int optind;
36 	register char *cp;
37 	int ch;
38 	char curpath[MAXPATHLEN], *reset, *index(), *rindex();
39 
40 	myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv;
41 	ischown = myname[2] == 'o';
42 
43 	while ((ch = getopt(argc, argv, "Rf")) != EOF)
44 		switch((char)ch) {
45 		case 'R':
46 			rflag++;
47 			break;
48 		case 'f':
49 			fflag++;
50 			break;
51 		case '?':
52 		default:
53 			usage();
54 		}
55 	argv += optind;
56 	argc -= optind;
57 
58 	if (argc < 2)
59 		usage();
60 
61 	if (ischown) {
62 		if (cp = index(*argv, '.')) {
63 			*cp++ = '\0';
64 			setgid(cp);
65 		}
66 		else
67 			gid = -1;
68 		setuid(*argv);
69 	}
70 	else {
71 		uid = -1;
72 		setgid(*argv);
73 	}
74 
75 	while (*++argv) {
76 		if (reset = index(*argv, '/'))
77 			(void)getwd(curpath);
78 		change(*argv);
79 		if (reset && chdir(curpath)) {
80 			if (fflag)
81 				exit(0);
82 			err(curpath);
83 			exit(-1);
84 		}
85 	}
86 	exit(retval);
87 }
88 
89 setgid(s)
90 	register char *s;
91 {
92 	struct group *gr, *getgrnam();
93 
94 	if (!*s) {
95 		gid = -1;			/* argument was "uid." */
96 		return;
97 	}
98 	for (gname = s; *s && isdigit(*s); ++s);
99 	if (!*s)
100 		gid = atoi(gname);
101 	else {
102 		if (!(gr = getgrnam(gname))) {
103 			if (fflag)
104 				exit(0);
105 			(void)fprintf(stderr, "%s: unknown group id: %s\n",
106 			    myname, gname);
107 			exit(-1);
108 		}
109 		gid = gr->gr_gid;
110 	}
111 }
112 
113 setuid(s)
114 	register char *s;
115 {
116 	struct passwd *pwd, *getpwnam();
117 	char *beg;
118 
119 	if (!*s) {
120 		uid = -1;			/* argument was ".gid" */
121 		return;
122 	}
123 	for (beg = s; *s && isdigit(*s); ++s);
124 	if (!*s)
125 		uid = atoi(beg);
126 	else {
127 		if (!(pwd = getpwnam(beg))) {
128 			if (fflag)
129 				exit(0);
130 			(void)fprintf(stderr,
131 			    "chown: unknown user id: %s\n", beg);
132 			exit(-1);
133 		}
134 		uid = pwd->pw_uid;
135 	}
136 }
137 
138 change(file)
139 	char *file;
140 {
141 	register DIR *dirp;
142 	register struct dirent *dp;
143 	struct stat buf;
144 
145 	if (chown(file, uid, gid)) {
146 		chownerr(file);
147 		return;
148 	}
149 	if (!rflag)
150 		return;
151 	if (lstat(file, &buf)) {
152 		err(file);
153 		return;
154 	}
155 	if ((buf.st_mode & S_IFMT) == S_IFDIR) {
156 		if (chdir(file) < 0 || !(dirp = opendir("."))) {
157 			err(file);
158 			return;
159 		}
160 		for (dp = readdir(dirp); dp; dp = readdir(dirp)) {
161 			if (dp->d_name[0] == '.' && (!dp->d_name[1] ||
162 			    dp->d_name[1] == '.' && !dp->d_name[2]))
163 				continue;
164 			change(dp->d_name);
165 		}
166 		closedir(dirp);
167 		if (chdir("..")) {
168 			err("..");
169 			exit(fflag ? 0 : -1);
170 		}
171 	}
172 }
173 
174 chownerr(file)
175 	char *file;
176 {
177 	extern int errno;
178 	static int euid = -1, ngroups = -1;
179 
180 	/* check for chown without being root */
181 	if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) {
182 		if (fflag)
183 			exit(0);
184 		err(file);
185 		exit(-1);
186 	}
187 	/* check group membership; kernel just returns EPERM */
188 	if (gid != -1 && ngroups == -1) {
189 		int groups[NGROUPS];
190 
191 		ngroups = getgroups(NGROUPS, groups);
192 		while (--ngroups >= 0 && gid != groups[ngroups]);
193 		if (ngroups < 0) {
194 			if (fflag)
195 				exit(0);
196 			(void)fprintf(stderr,
197 			    "%s: you are not a member of group %s.\n",
198 			    myname, gname);
199 			exit(-1);
200 		}
201 	}
202 	err(file);
203 }
204 
205 err(s)
206 	char *s;
207 {
208 	extern int errno;
209 	char *strerror();
210 
211 	if (fflag)
212 		return;
213 	(void)fprintf(stderr, "%s: %s: %s\n", myname, s, strerror(errno));
214 	retval = -1;
215 }
216 
217 usage()
218 {
219 	(void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
220 	    ischown ? "owner[.group]" : "group");
221 	exit(-1);
222 }
223