|
|
1.1 root 1: /*
2: * Copyright (c) 1988 Regents of the University of California.
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms are permitted provided
6: * that: (1) source distributions retain this entire copyright notice and
7: * comment, and (2) distributions including binaries display the following
8: * acknowledgement: ``This product includes software developed by the
9: * University of California, Berkeley and its contributors'' in the
10: * documentation or other materials provided with the distribution and in
11: * all advertising materials mentioning features or use of this software.
12: * Neither the name of the University nor the names of its contributors may
13: * be used to endorse or promote products derived from this software without
14: * specific prior written permission.
15: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
16: * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
17: * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
18: */
19:
20: #ifndef lint
21: char copyright[] =
22: "@(#) Copyright (c) 1988 Regents of the University of California.\n\
23: All rights reserved.\n";
24: #endif /* not lint */
25:
26: #ifndef lint
27: static char sccsid[] = "@(#)chown.c 5.15 (Berkeley) 6/1/90";
28: #endif /* not lint */
29:
30: #include <sys/param.h>
31: #include <sys/stat.h>
32: #include <sys/errno.h>
33: #include <dirent.h>
34: #include <pwd.h>
35: #include <grp.h>
36: #include <stdio.h>
37: #include <ctype.h>
38:
39: int ischown, uid, gid, fflag, rflag, retval;
40: char *gname, *myname;
41:
42: main(argc, argv)
43: int argc;
44: char **argv;
45: {
46: extern char *optarg;
47: extern int optind;
48: register char *cp;
49: int ch;
50: char curpath[MAXPATHLEN], *reset, *index(), *rindex();
51:
52: myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv;
53: ischown = myname[2] == 'o';
54:
55: while ((ch = getopt(argc, argv, "Rf")) != EOF)
56: switch((char)ch) {
57: case 'R':
58: rflag++;
59: break;
60: case 'f':
61: fflag++;
62: break;
63: case '?':
64: default:
65: usage();
66: }
67: argv += optind;
68: argc -= optind;
69:
70: if (argc < 2)
71: usage();
72:
73: if (ischown) {
74: if (cp = index(*argv, '.')) {
75: *cp++ = '\0';
76: setgid(cp);
77: }
78: else
79: gid = -1;
80: setuid(*argv);
81: }
82: else {
83: uid = -1;
84: setgid(*argv);
85: }
86:
87: while (*++argv) {
88: if (reset = index(*argv, '/'))
89: (void)getwd(curpath);
90: change(*argv);
91: if (reset && chdir(curpath)) {
92: if (fflag)
93: exit(0);
94: err(curpath);
95: exit(-1);
96: }
97: }
98: exit(retval);
99: }
100:
101: setgid(s)
102: register char *s;
103: {
104: struct group *gr, *getgrnam();
105:
106: if (!*s) {
107: gid = -1; /* argument was "uid." */
108: return;
109: }
110: for (gname = s; *s && isdigit(*s); ++s);
111: if (!*s)
112: gid = atoi(gname);
113: else {
114: if (!(gr = getgrnam(gname))) {
115: if (fflag)
116: exit(0);
117: (void)fprintf(stderr, "%s: unknown group id: %s\n",
118: myname, gname);
119: exit(-1);
120: }
121: gid = gr->gr_gid;
122: }
123: }
124:
125: setuid(s)
126: register char *s;
127: {
128: struct passwd *pwd, *getpwnam();
129: char *beg;
130:
131: if (!*s) {
132: uid = -1; /* argument was ".gid" */
133: return;
134: }
135: for (beg = s; *s && isdigit(*s); ++s);
136: if (!*s)
137: uid = atoi(beg);
138: else {
139: if (!(pwd = getpwnam(beg))) {
140: if (fflag)
141: exit(0);
142: (void)fprintf(stderr,
143: "chown: unknown user id: %s\n", beg);
144: exit(-1);
145: }
146: uid = pwd->pw_uid;
147: }
148: }
149:
150: change(file)
151: char *file;
152: {
153: register DIR *dirp;
154: register struct dirent *dp;
155: struct stat buf;
156:
157: if (chown(file, uid, gid)) {
158: chownerr(file);
159: return;
160: }
161: if (!rflag)
162: return;
163: if (lstat(file, &buf)) {
164: err(file);
165: return;
166: }
167: if ((buf.st_mode & S_IFMT) == S_IFDIR) {
168: if (chdir(file) < 0 || !(dirp = opendir("."))) {
169: err(file);
170: return;
171: }
172: for (dp = readdir(dirp); dp; dp = readdir(dirp)) {
173: if (dp->d_name[0] == '.' && (!dp->d_name[1] ||
174: dp->d_name[1] == '.' && !dp->d_name[2]))
175: continue;
176: change(dp->d_name);
177: }
178: closedir(dirp);
179: if (chdir("..")) {
180: err("..");
181: exit(fflag ? 0 : -1);
182: }
183: }
184: }
185:
186: chownerr(file)
187: char *file;
188: {
189: extern int errno;
190: static int euid = -1, ngroups = -1;
191:
192: /* check for chown without being root */
193: if (errno != EPERM || uid != -1 && euid == -1 && (euid = geteuid())) {
194: if (fflag)
195: exit(0);
196: err(file);
197: exit(-1);
198: }
199: /* check group membership; kernel just returns EPERM */
200: if (gid != -1 && ngroups == -1) {
201: int groups[NGROUPS];
202:
203: ngroups = getgroups(NGROUPS, groups);
204: while (--ngroups >= 0 && gid != groups[ngroups]);
205: if (ngroups < 0) {
206: if (fflag)
207: exit(0);
208: (void)fprintf(stderr,
209: "%s: you are not a member of group %s.\n",
210: myname, gname);
211: exit(-1);
212: }
213: }
214: err(file);
215: }
216:
217: err(s)
218: char *s;
219: {
220: extern int errno;
221: char *strerror();
222:
223: if (fflag)
224: return;
225: (void)fprintf(stderr, "%s: %s: %s\n", myname, s, strerror(errno));
226: retval = -1;
227: }
228:
229: usage()
230: {
231: (void)fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
232: ischown ? "owner[.group]" : "group");
233: exit(-1);
234: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.