xref: /csrg-svn/usr.sbin/chown/chown.c (revision 27611)
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*27611Sbloom static char sccsid[] = "@(#)chown.c	5.3 (Berkeley) 04/29/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 	}
66*27611Sbloom 	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;
74*27611Sbloom 			(void) endgrent();
75*27611Sbloom 		} 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 */
8624505Ssam 		if (stat(argv[c], &stbuf) < 0) {
8724505Ssam 			status += error("couldn't access %s", argv[c]);
8824505Ssam 			continue;
8918450Smckusick 		}
9024505Ssam 		if (rflag && stbuf.st_mode&S_IFDIR) {
91*27611Sbloom 			status += chownr(argv[c], uid, gid);
9224505Ssam 			continue;
93975Sbill 		}
9424505Ssam 		if (chown(argv[c], uid, gid)) {
9524505Ssam 			status += error("couldn't change %s", 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 
113*27611Sbloom chownr(dir, uid, gid)
11424505Ssam 	char *dir;
11518450Smckusick {
11624505Ssam 	register DIR *dirp;
11724505Ssam 	register struct direct *dp;
118*27611Sbloom 	struct stat st;
11924505Ssam 	char savedir[1024];
120*27611Sbloom 	int ecode;
121*27611Sbloom 	extern char *getwd();
12218450Smckusick 
123*27611Sbloom 	if (getwd(savedir) == (char *)0)
12424505Ssam 		fatal(255, "%s", savedir);
12524505Ssam 	/*
12624505Ssam 	 * Change what we are given before doing it's contents.
12724505Ssam 	 */
128*27611Sbloom 	if (chown(dir, uid, gid) < 0 && error("can't change %s", dir))
12924505Ssam 		return (1);
13024505Ssam 	if (chdir(dir) < 0)
13124505Ssam 		return (Perror(dir));
13224505Ssam 	if ((dirp = opendir(".")) == NULL)
13324505Ssam 		return (Perror(dir));
13418450Smckusick 	dp = readdir(dirp);
13518450Smckusick 	dp = readdir(dirp); /* read "." and ".." */
13624505Ssam 	ecode = 0;
13718450Smckusick 	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
13824505Ssam 		if (stat(dp->d_name, &st) < 0) {
13924505Ssam 			ecode = error("can't access %s", dp->d_name);
14024505Ssam 			if (ecode)
14124505Ssam 				break;
14224505Ssam 			continue;
14318450Smckusick 		}
14424505Ssam 		if (st.st_mode&S_IFDIR) {
145*27611Sbloom 			ecode = chownr(dp->d_name, uid, gid);
14624505Ssam 			if (ecode)
14724505Ssam 				break;
14824505Ssam 			continue;
14924505Ssam 		}
15024505Ssam 		if (chown(dp->d_name, uid, gid) < 0 &&
15124505Ssam 		    (ecode = error("can't change %s", dp->d_name)))
15224505Ssam 			break;
15318450Smckusick 	}
15418450Smckusick 	closedir(dirp);
15524505Ssam 	if (chdir(savedir) < 0)
15624505Ssam 		fatal(255, "can't change back to %s", savedir);
15724505Ssam 	return (ecode);
15818450Smckusick }
15924505Ssam 
16024505Ssam error(fmt, a)
16124505Ssam 	char *fmt, *a;
16224505Ssam {
16324505Ssam 
16424505Ssam 	if (!fflag) {
16524505Ssam 		fprintf(stderr, "chown: ");
16624505Ssam 		fprintf(stderr, fmt, a);
16724505Ssam 		putc('\n', stderr);
16824505Ssam 	}
16924505Ssam 	return (!fflag);
17024505Ssam }
17124505Ssam 
17224505Ssam fatal(status, fmt, a)
17324505Ssam 	int status;
17424505Ssam 	char *fmt, *a;
17524505Ssam {
17624505Ssam 
17724505Ssam 	fflag = 0;
17824505Ssam 	(void) error(fmt, a);
17924505Ssam 	exit(status);
18024505Ssam }
18124505Ssam 
18224505Ssam Perror(s)
18324505Ssam 	char *s;
18424505Ssam {
18524505Ssam 
18624505Ssam 	fprintf(stderr, "chown: ");
18724505Ssam 	perror(s);
18824505Ssam 	return (1);
18924505Ssam }
190