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