install correct aliases file
[unix-history] / usr / src / usr.sbin / chown / chown.c
CommitLineData
da158ee3 1/*
7445173f
KB
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
b8c620d6
KB
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.
da158ee3
DF
16 */
17
18#ifndef lint
19char copyright[] =
7445173f 20"@(#) Copyright (c) 1988 Regents of the University of California.\n\
da158ee3 21 All rights reserved.\n";
7445173f 22#endif /* not lint */
da158ee3
DF
23
24#ifndef lint
b8c620d6 25static char sccsid[] = "@(#)chown.c 5.11 (Berkeley) %G%";
7445173f 26#endif /* not lint */
702e3fe5 27
7445173f 28#include <sys/param.h>
69e53de7 29#include <sys/stat.h>
702e3fe5 30#include <sys/dir.h>
7445173f 31#include <pwd.h>
702e3fe5 32#include <grp.h>
7445173f
KB
33#include <stdio.h>
34#include <ctype.h>
69e53de7 35
7445173f 36static int ischown, uid, gid, fflag, rflag, retval;
f9915d58 37static char *gname, *myname;
69e53de7
BJ
38
39main(argc, argv)
7445173f
KB
40 int argc;
41 char **argv;
69e53de7 42{
7445173f
KB
43 extern char *optarg;
44 extern int optind;
45 register char *cp;
46 int ch;
47 char *index(), *rindex();
69e53de7 48
7445173f
KB
49 myname = (cp = rindex(*argv, '/')) ? cp + 1 : *argv;
50 ischown = myname[2] == 'o';
c76e0466 51
7445173f
KB
52 while ((ch = getopt(argc, argv, "Rf")) != EOF)
53 switch((char)ch) {
54 case 'R':
55 rflag++;
56 break;
c76e0466
SL
57 case 'f':
58 fflag++;
59 break;
7445173f
KB
60 case '?':
61 default:
62 usage();
63 }
64 argv += optind;
65 argc -= optind;
c76e0466 66
7445173f
KB
67 if (argc < 2)
68 usage();
c76e0466 69
7445173f
KB
70 if (ischown) {
71 if (cp = index(*argv, '.')) {
72 *cp++ = '\0';
73 setgid(cp);
c76e0466 74 }
7445173f
KB
75 else
76 gid = -1;
77 setuid(*argv);
c76e0466 78 }
7445173f
KB
79 else {
80 uid = -1;
81 setgid(*argv);
69e53de7 82 }
69e53de7 83
7445173f
KB
84 while (*++argv)
85 change(*argv);
86 exit(retval);
69e53de7 87}
702e3fe5 88
7445173f
KB
89static
90setgid(s)
91 register char *s;
702e3fe5 92{
7445173f 93 struct group *gr, *getgrnam();
7445173f
KB
94
95 if (!*s) {
96 gid = -1; /* argument was "uid." */
97 return;
80eff57a 98 }
f9915d58 99 for (gname = s; *s && isdigit(*s); ++s);
7445173f 100 if (!*s)
f9915d58 101 gid = atoi(gname);
7445173f 102 else {
f9915d58 103 if (!(gr = getgrnam(gname))) {
7445173f
KB
104 if (fflag)
105 exit(0);
106 fprintf(stderr, "%s: unknown group id: %s\n",
f9915d58 107 myname, gname);
7445173f 108 exit(-1);
c76e0466 109 }
7445173f
KB
110 gid = gr->gr_gid;
111 }
c76e0466
SL
112}
113
7445173f
KB
114static
115setuid(s)
116 register char *s;
c76e0466 117{
7445173f
KB
118 struct passwd *pwd, *getpwnam();
119 char *beg;
c76e0466 120
7445173f
KB
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;
c76e0466 136 }
c76e0466
SL
137}
138
7445173f
KB
139static
140change(file)
141 char *file;
c76e0466 142{
7445173f
KB
143 register DIR *dirp;
144 register struct direct *dp;
145 struct stat buf;
c76e0466 146
f9915d58 147 if (chown(file, uid, gid)) {
2a151187 148 chownerr(file);
f9915d58
KB
149 return;
150 }
151 if (!rflag)
152 return;
153 if (lstat(file, &buf)) {
7445173f
KB
154 err(file);
155 return;
156 }
f9915d58 157 if ((buf.st_mode & S_IFMT) == S_IFDIR) {
7445173f
KB
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 }
c76e0466
SL
174}
175
2a151187
KB
176static
177chownerr(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
7445173f
KB
207static
208err(s)
c76e0466
SL
209 char *s;
210{
7445173f
KB
211 if (fflag)
212 return;
f9915d58 213 fprintf(stderr, "%s: ", myname);
7445173f
KB
214 perror(s);
215 retval = -1;
216}
c76e0466 217
7445173f
KB
218static
219usage()
220{
221 fprintf(stderr, "usage: %s [-Rf] %s file ...\n", myname,
222 ischown ? "owner[.group]" : "group");
223 exit(-1);
702e3fe5 224}