xref: /original-bsd/usr.sbin/chown/chown.c (revision 9137f921)
1 /*
2  * Copyright (c) 1980 Regents of the University of California.
3  * All rights reserved.  The Berkeley software License Agreement
4  * specifies the terms and conditions for redistribution.
5  */
6 
7 #ifndef lint
8 char copyright[] =
9 "@(#) Copyright (c) 1980 Regents of the University of California.\n\
10  All rights reserved.\n";
11 #endif
12 
13 #ifndef lint
14 static char sccsid[] = "@(#)chown.c	5.2 (Berkeley) 08/31/85";
15 #endif
16 
17 /*
18  * chown [-fR] uid[.gid] file ...
19  */
20 
21 #include <stdio.h>
22 #include <ctype.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <pwd.h>
26 #include <sys/dir.h>
27 #include <grp.h>
28 #include <strings.h>
29 
30 struct	passwd *pwd;
31 struct	passwd *getpwnam();
32 struct	stat stbuf;
33 int	uid;
34 int	status;
35 int	fflag;
36 int	rflag;
37 
38 main(argc, argv)
39 	char *argv[];
40 {
41 	register int c, gid;
42 	register char *cp, *group;
43 	struct group *grp;
44 
45 	argc--, argv++;
46 	while (argc > 0 && argv[0][0] == '-') {
47 		for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
48 
49 		case 'f':
50 			fflag++;
51 			break;
52 
53 		case 'R':
54 			rflag++;
55 			break;
56 
57 		default:
58 			fatal(255, "unknown option: %c", *cp);
59 		}
60 		argv++, argc--;
61 	}
62 	if (argc < 2) {
63 		fprintf(stderr, "usage: chown [-fR] owner[.group] file ...\n");
64 		exit(-1);
65 	}
66 	group = index(argv[0], '.');
67 	if (group != NULL) {
68 		*group++ = '\0';
69 		if (!isnumber(group)) {
70 			if ((grp = getgrnam(group)) == NULL)
71 				fatal(255, "unknown group: %s",group);
72 			gid = grp -> gr_gid;
73 			endgrent();
74 		} else
75 			gid = atoi(group);
76 	}
77 	if (!isnumber(argv[0])) {
78 		if ((pwd = getpwnam(argv[0])) == NULL)
79 			fatal(255, "unknown user id: %s",argv[0]);
80 		uid = pwd->pw_uid;
81 	} else
82 		uid = atoi(argv[0]);
83 	for (c = 1; c < argc; c++) {
84 		/* do stat for directory arguments */
85 		if (stat(argv[c], &stbuf) < 0) {
86 			status += error("couldn't access %s", argv[c]);
87 			continue;
88 		}
89 		if (group == NULL)
90 			gid = stbuf.st_gid;
91 		if (rflag && stbuf.st_mode&S_IFDIR) {
92 			status += chownr(argv[c], group != NULL, uid, gid);
93 			continue;
94 		}
95 		if (chown(argv[c], uid, gid)) {
96 			status += error("couldn't change %s", argv[c]);
97 			continue;
98 		}
99 	}
100 	exit(status);
101 }
102 
103 isnumber(s)
104 	char *s;
105 {
106 	register c;
107 
108 	while(c = *s++)
109 		if (!isdigit(c))
110 			return (0);
111 	return (1);
112 }
113 
114 chownr(dir, dogrp, uid, ogid)
115 	char *dir;
116 {
117 	register DIR *dirp;
118 	register struct direct *dp;
119 	register struct stat st;
120 	char savedir[1024];
121 	int ecode, gid;
122 
123 	if (getwd(savedir) == 0)
124 		fatal(255, "%s", savedir);
125 	/*
126 	 * Change what we are given before doing it's contents.
127 	 */
128 	if (chown(dir, uid, ogid) < 0 && error("can't change %s", dir))
129 		return (1);
130 	if (chdir(dir) < 0)
131 		return (Perror(dir));
132 	if ((dirp = opendir(".")) == NULL)
133 		return (Perror(dir));
134 	dp = readdir(dirp);
135 	dp = readdir(dirp); /* read "." and ".." */
136 	ecode = 0;
137 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
138 		if (stat(dp->d_name, &st) < 0) {
139 			ecode = error("can't access %s", dp->d_name);
140 			if (ecode)
141 				break;
142 			continue;
143 		}
144 		if (dogrp)
145 			gid = ogid;
146 		else
147 			gid = st.st_gid;
148 		if (st.st_mode&S_IFDIR) {
149 			ecode = chownr(dp->d_name, dogrp, uid, gid);
150 			if (ecode)
151 				break;
152 			continue;
153 		}
154 		if (chown(dp->d_name, uid, gid) < 0 &&
155 		    (ecode = error("can't change %s", dp->d_name)))
156 			break;
157 	}
158 	closedir(dirp);
159 	if (chdir(savedir) < 0)
160 		fatal(255, "can't change back to %s", savedir);
161 	return (ecode);
162 }
163 
164 error(fmt, a)
165 	char *fmt, *a;
166 {
167 
168 	if (!fflag) {
169 		fprintf(stderr, "chown: ");
170 		fprintf(stderr, fmt, a);
171 		putc('\n', stderr);
172 	}
173 	return (!fflag);
174 }
175 
176 fatal(status, fmt, a)
177 	int status;
178 	char *fmt, *a;
179 {
180 
181 	fflag = 0;
182 	(void) error(fmt, a);
183 	exit(status);
184 }
185 
186 Perror(s)
187 	char *s;
188 {
189 
190 	fprintf(stderr, "chown: ");
191 	perror(s);
192 	return (1);
193 }
194