xref: /csrg-svn/usr.sbin/chown/chown.c (revision 24505)
122488Sdist /*
222488Sdist  * Copyright (c) 1980 Regents of the University of California.
322488Sdist  * All rights reserved.  The Berkeley software License Agreement
422488Sdist  * specifies the terms and conditions for redistribution.
522488Sdist  */
618450Smckusick 
722488Sdist #ifndef lint
822488Sdist char copyright[] =
922488Sdist "@(#) Copyright (c) 1980 Regents of the University of California.\n\
1022488Sdist  All rights reserved.\n";
11*24505Ssam #endif
1222488Sdist 
1322488Sdist #ifndef lint
14*24505Ssam static char sccsid[] = "@(#)chown.c	5.2 (Berkeley) 08/31/85";
15*24505Ssam #endif
1622488Sdist 
17975Sbill /*
1818474Smckusick  * chown [-fR] uid[.gid] file ...
19975Sbill  */
20975Sbill 
21975Sbill #include <stdio.h>
22975Sbill #include <ctype.h>
23975Sbill #include <sys/types.h>
24975Sbill #include <sys/stat.h>
25975Sbill #include <pwd.h>
2618450Smckusick #include <sys/dir.h>
2718450Smckusick #include <grp.h>
28*24505Ssam #include <strings.h>
29975Sbill 
30*24505Ssam struct	passwd *pwd;
31*24505Ssam struct	passwd *getpwnam();
32*24505Ssam struct	stat stbuf;
33975Sbill int	uid;
34975Sbill int	status;
35*24505Ssam int	fflag;
36*24505Ssam int	rflag;
37975Sbill 
38975Sbill main(argc, argv)
39*24505Ssam 	char *argv[];
40975Sbill {
4118450Smckusick 	register int c, gid;
42*24505Ssam 	register char *cp, *group;
4318450Smckusick 	struct group *grp;
44975Sbill 
45*24505Ssam 	argc--, argv++;
46*24505Ssam 	while (argc > 0 && argv[0][0] == '-') {
47*24505Ssam 		for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
48*24505Ssam 
49*24505Ssam 		case 'f':
50*24505Ssam 			fflag++;
51*24505Ssam 			break;
52*24505Ssam 
53*24505Ssam 		case 'R':
54*24505Ssam 			rflag++;
55*24505Ssam 			break;
56*24505Ssam 
57*24505Ssam 		default:
58*24505Ssam 			fatal(255, "unknown option: %c", *cp);
59*24505Ssam 		}
60*24505Ssam 		argv++, argc--;
61*24505Ssam 	}
62*24505Ssam 	if (argc < 2) {
6318474Smckusick 		fprintf(stderr, "usage: chown [-fR] owner[.group] file ...\n");
6418450Smckusick 		exit(-1);
65975Sbill 	}
66*24505Ssam 	group = index(argv[0], '.');
67*24505Ssam 	if (group != NULL) {
68*24505Ssam 		*group++ = '\0';
69*24505Ssam 		if (!isnumber(group)) {
70*24505Ssam 			if ((grp = getgrnam(group)) == NULL)
71*24505Ssam 				fatal(255, "unknown group: %s",group);
72*24505Ssam 			gid = grp -> gr_gid;
73*24505Ssam 			endgrent();
74*24505Ssam 		} else
75*24505Ssam 			gid = atoi(group);
7611442Smckusick 	}
77*24505Ssam 	if (!isnumber(argv[0])) {
78*24505Ssam 		if ((pwd = getpwnam(argv[0])) == NULL)
79*24505Ssam 			fatal(255, "unknown user id: %s",argv[0]);
8018450Smckusick 		uid = pwd->pw_uid;
81*24505Ssam 	} else
82*24505Ssam 		uid = atoi(argv[0]);
83*24505Ssam 	for (c = 1; c < argc; c++) {
84*24505Ssam 		/* do stat for directory arguments */
85*24505Ssam 		if (stat(argv[c], &stbuf) < 0) {
86*24505Ssam 			status += error("couldn't access %s", argv[c]);
87*24505Ssam 			continue;
8818450Smckusick 		}
8918450Smckusick 		if (group == NULL)
9018450Smckusick 			gid = stbuf.st_gid;
91*24505Ssam 		if (rflag && stbuf.st_mode&S_IFDIR) {
92*24505Ssam 			status += chownr(argv[c], group != NULL, uid, gid);
93*24505Ssam 			continue;
94975Sbill 		}
95*24505Ssam 		if (chown(argv[c], uid, gid)) {
96*24505Ssam 			status += error("couldn't change %s", argv[c]);
97*24505Ssam 			continue;
98*24505Ssam 		}
99975Sbill 	}
100975Sbill 	exit(status);
101975Sbill }
102975Sbill 
103975Sbill isnumber(s)
104*24505Ssam 	char *s;
105975Sbill {
106975Sbill 	register c;
107975Sbill 
108975Sbill 	while(c = *s++)
109*24505Ssam 		if (!isdigit(c))
110*24505Ssam 			return (0);
111*24505Ssam 	return (1);
112975Sbill }
11318450Smckusick 
114*24505Ssam chownr(dir, dogrp, uid, ogid)
115*24505Ssam 	char *dir;
11618450Smckusick {
117*24505Ssam 	register DIR *dirp;
118*24505Ssam 	register struct direct *dp;
119*24505Ssam 	register struct stat st;
120*24505Ssam 	char savedir[1024];
121*24505Ssam 	int ecode, gid;
12218450Smckusick 
123*24505Ssam 	if (getwd(savedir) == 0)
124*24505Ssam 		fatal(255, "%s", savedir);
125*24505Ssam 	/*
126*24505Ssam 	 * Change what we are given before doing it's contents.
127*24505Ssam 	 */
128*24505Ssam 	if (chown(dir, uid, ogid) < 0 && error("can't change %s", dir))
129*24505Ssam 		return (1);
130*24505Ssam 	if (chdir(dir) < 0)
131*24505Ssam 		return (Perror(dir));
132*24505Ssam 	if ((dirp = opendir(".")) == NULL)
133*24505Ssam 		return (Perror(dir));
13418450Smckusick 	dp = readdir(dirp);
13518450Smckusick 	dp = readdir(dirp); /* read "." and ".." */
136*24505Ssam 	ecode = 0;
13718450Smckusick 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
138*24505Ssam 		if (stat(dp->d_name, &st) < 0) {
139*24505Ssam 			ecode = error("can't access %s", dp->d_name);
140*24505Ssam 			if (ecode)
141*24505Ssam 				break;
142*24505Ssam 			continue;
14318450Smckusick 		}
14418450Smckusick 		if (dogrp)
145*24505Ssam 			gid = ogid;
14618450Smckusick 		else
14718450Smckusick 			gid = st.st_gid;
148*24505Ssam 		if (st.st_mode&S_IFDIR) {
149*24505Ssam 			ecode = chownr(dp->d_name, dogrp, uid, gid);
150*24505Ssam 			if (ecode)
151*24505Ssam 				break;
152*24505Ssam 			continue;
153*24505Ssam 		}
154*24505Ssam 		if (chown(dp->d_name, uid, gid) < 0 &&
155*24505Ssam 		    (ecode = error("can't change %s", dp->d_name)))
156*24505Ssam 			break;
15718450Smckusick 	}
15818450Smckusick 	closedir(dirp);
159*24505Ssam 	if (chdir(savedir) < 0)
160*24505Ssam 		fatal(255, "can't change back to %s", savedir);
161*24505Ssam 	return (ecode);
16218450Smckusick }
163*24505Ssam 
164*24505Ssam error(fmt, a)
165*24505Ssam 	char *fmt, *a;
166*24505Ssam {
167*24505Ssam 
168*24505Ssam 	if (!fflag) {
169*24505Ssam 		fprintf(stderr, "chown: ");
170*24505Ssam 		fprintf(stderr, fmt, a);
171*24505Ssam 		putc('\n', stderr);
172*24505Ssam 	}
173*24505Ssam 	return (!fflag);
174*24505Ssam }
175*24505Ssam 
176*24505Ssam fatal(status, fmt, a)
177*24505Ssam 	int status;
178*24505Ssam 	char *fmt, *a;
179*24505Ssam {
180*24505Ssam 
181*24505Ssam 	fflag = 0;
182*24505Ssam 	(void) error(fmt, a);
183*24505Ssam 	exit(status);
184*24505Ssam }
185*24505Ssam 
186*24505Ssam Perror(s)
187*24505Ssam 	char *s;
188*24505Ssam {
189*24505Ssam 
190*24505Ssam 	fprintf(stderr, "chown: ");
191*24505Ssam 	perror(s);
192*24505Ssam 	return (1);
193*24505Ssam }
194