xref: /csrg-svn/usr.sbin/chown/chown.c (revision 28349)
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";
1124505Ssam #endif
1222488Sdist 
1322488Sdist #ifndef lint
14*28349Smckusick static char sccsid[] = "@(#)chown.c	5.4 (Berkeley) 05/22/86";
1524505Ssam #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>
2824505Ssam #include <strings.h>
29975Sbill 
3024505Ssam struct	passwd *pwd;
3124505Ssam struct	passwd *getpwnam();
3224505Ssam struct	stat stbuf;
33975Sbill int	uid;
34975Sbill int	status;
3524505Ssam int	fflag;
3624505Ssam int	rflag;
37975Sbill 
38975Sbill main(argc, argv)
3924505Ssam 	char *argv[];
40975Sbill {
4118450Smckusick 	register int c, gid;
4224505Ssam 	register char *cp, *group;
4318450Smckusick 	struct group *grp;
44975Sbill 
4524505Ssam 	argc--, argv++;
4624505Ssam 	while (argc > 0 && argv[0][0] == '-') {
4724505Ssam 		for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
4824505Ssam 
4924505Ssam 		case 'f':
5024505Ssam 			fflag++;
5124505Ssam 			break;
5224505Ssam 
5324505Ssam 		case 'R':
5424505Ssam 			rflag++;
5524505Ssam 			break;
5624505Ssam 
5724505Ssam 		default:
5824505Ssam 			fatal(255, "unknown option: %c", *cp);
5924505Ssam 		}
6024505Ssam 		argv++, argc--;
6124505Ssam 	}
6224505Ssam 	if (argc < 2) {
6318474Smckusick 		fprintf(stderr, "usage: chown [-fR] owner[.group] file ...\n");
6418450Smckusick 		exit(-1);
65975Sbill 	}
6627611Sbloom 	gid = -1;
6724505Ssam 	group = index(argv[0], '.');
6824505Ssam 	if (group != NULL) {
6924505Ssam 		*group++ = '\0';
7024505Ssam 		if (!isnumber(group)) {
7124505Ssam 			if ((grp = getgrnam(group)) == NULL)
7224505Ssam 				fatal(255, "unknown group: %s",group);
7324505Ssam 			gid = grp -> gr_gid;
7427611Sbloom 			(void) endgrent();
7527611Sbloom 		} else if (*group != '\0')
7624505Ssam 			gid = atoi(group);
7711442Smckusick 	}
7824505Ssam 	if (!isnumber(argv[0])) {
7924505Ssam 		if ((pwd = getpwnam(argv[0])) == NULL)
8024505Ssam 			fatal(255, "unknown user id: %s",argv[0]);
8118450Smckusick 		uid = pwd->pw_uid;
8224505Ssam 	} else
8324505Ssam 		uid = atoi(argv[0]);
8424505Ssam 	for (c = 1; c < argc; c++) {
8524505Ssam 		/* do stat for directory arguments */
86*28349Smckusick 		if (lstat(argv[c], &stbuf) < 0) {
87*28349Smckusick 			status += Perror(argv[c]);
8824505Ssam 			continue;
8918450Smckusick 		}
9024505Ssam 		if (rflag && stbuf.st_mode&S_IFDIR) {
9127611Sbloom 			status += chownr(argv[c], uid, gid);
9224505Ssam 			continue;
93975Sbill 		}
9424505Ssam 		if (chown(argv[c], uid, gid)) {
95*28349Smckusick 			status += Perror(argv[c]);
9624505Ssam 			continue;
9724505Ssam 		}
98975Sbill 	}
99975Sbill 	exit(status);
100975Sbill }
101975Sbill 
102975Sbill isnumber(s)
10324505Ssam 	char *s;
104975Sbill {
105975Sbill 	register c;
106975Sbill 
107975Sbill 	while(c = *s++)
10824505Ssam 		if (!isdigit(c))
10924505Ssam 			return (0);
11024505Ssam 	return (1);
111975Sbill }
11218450Smckusick 
11327611Sbloom chownr(dir, uid, gid)
11424505Ssam 	char *dir;
11518450Smckusick {
11624505Ssam 	register DIR *dirp;
11724505Ssam 	register struct direct *dp;
11827611Sbloom 	struct stat st;
11924505Ssam 	char savedir[1024];
12027611Sbloom 	int ecode;
12127611Sbloom 	extern char *getwd();
12218450Smckusick 
12327611Sbloom 	if (getwd(savedir) == (char *)0)
12424505Ssam 		fatal(255, "%s", savedir);
12524505Ssam 	/*
12624505Ssam 	 * Change what we are given before doing it's contents.
12724505Ssam 	 */
128*28349Smckusick 	if (chown(dir, uid, gid) < 0 && Perror(dir))
12924505Ssam 		return (1);
130*28349Smckusick 	if (chdir(dir) < 0) {
131*28349Smckusick 		Perror(dir);
132*28349Smckusick 		return (1);
133*28349Smckusick 	}
134*28349Smckusick 	if ((dirp = opendir(".")) == NULL) {
135*28349Smckusick 		Perror(dir);
136*28349Smckusick 		return (1);
137*28349Smckusick 	}
13818450Smckusick 	dp = readdir(dirp);
13918450Smckusick 	dp = readdir(dirp); /* read "." and ".." */
14024505Ssam 	ecode = 0;
14118450Smckusick 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
142*28349Smckusick 		if (lstat(dp->d_name, &st) < 0) {
143*28349Smckusick 			ecode = Perror(dp->d_name);
14424505Ssam 			if (ecode)
14524505Ssam 				break;
14624505Ssam 			continue;
14718450Smckusick 		}
14824505Ssam 		if (st.st_mode&S_IFDIR) {
14927611Sbloom 			ecode = chownr(dp->d_name, uid, gid);
15024505Ssam 			if (ecode)
15124505Ssam 				break;
15224505Ssam 			continue;
15324505Ssam 		}
15424505Ssam 		if (chown(dp->d_name, uid, gid) < 0 &&
155*28349Smckusick 		    (ecode = Perror(dp->d_name)))
15624505Ssam 			break;
15718450Smckusick 	}
15818450Smckusick 	closedir(dirp);
15924505Ssam 	if (chdir(savedir) < 0)
16024505Ssam 		fatal(255, "can't change back to %s", savedir);
16124505Ssam 	return (ecode);
16218450Smckusick }
16324505Ssam 
16424505Ssam error(fmt, a)
16524505Ssam 	char *fmt, *a;
16624505Ssam {
16724505Ssam 
16824505Ssam 	if (!fflag) {
16924505Ssam 		fprintf(stderr, "chown: ");
17024505Ssam 		fprintf(stderr, fmt, a);
17124505Ssam 		putc('\n', stderr);
17224505Ssam 	}
17324505Ssam 	return (!fflag);
17424505Ssam }
17524505Ssam 
17624505Ssam fatal(status, fmt, a)
17724505Ssam 	int status;
17824505Ssam 	char *fmt, *a;
17924505Ssam {
18024505Ssam 
18124505Ssam 	fflag = 0;
18224505Ssam 	(void) error(fmt, a);
18324505Ssam 	exit(status);
18424505Ssam }
18524505Ssam 
18624505Ssam Perror(s)
18724505Ssam 	char *s;
18824505Ssam {
18924505Ssam 
190*28349Smckusick 	if (!fflag) {
191*28349Smckusick 		fprintf(stderr, "chown: ");
192*28349Smckusick 		perror(s);
193*28349Smckusick 	}
194*28349Smckusick 	return (!fflag);
19524505Ssam }
196