[net.sources] 4.1BSD chgrp, modified to allow users to change group ownership

fred@umcp-cs.UUCP (07/27/83)

This version of chgrp, which is a modified version of Berkeley 4.1 chgrp,
allows non-super-users to change the group ownership of files provided that:

	1) They own the file which they are attempting to change the group
	   ownership of.
    and
	2) They are listed in /etc/group as a member of the group which
	   they wish to own the file.

This solves the problem of needing to get a super-user to chgrp a file after
you created it while you were in the wrong group.

 static char *sccsid = "@(#)chgrp.c	4.1 (U of M modified) 11/24/81";
 /*
  * chgrp gid file ...
  */
 
 #include <stdio.h>
 #include <ctype.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <grp.h>
 
 struct	group	*gr,*getgrnam(), *getgrgid();
 struct	stat	stbuf;
 int	gid;
 int	uid;
 int	status;
 
 main(argc, argv)
 char *argv[];
 {
 	register c;
 
 	if(argc < 3) {
 		printf("usage: chgrp gid file ...\n");
 		exit(4);
 	}
 	if(isnumber(argv[1])) {
 		if((gr=getgrgid(atoi(argv[1]))) == NULL) {
 			printf("unknown group: %s\n",argv[1]);
 			exit(4);
 		}
 	} else {
 		if((gr=getgrnam(argv[1])) == NULL) {
 			printf("unknown group: %s\n",argv[1]);
 			exit(4);
 		}
 	}
 	gid = gr->gr_gid;
 
 	if (uid = getuid()) {
 		char pwbuf[200], *cp, **np;
 
 		if (getpw(uid, pwbuf)) {
 			printf("chgrp: can't locate user name.\n");
 			exit(1);
 			}
 
 		for (cp = pwbuf; *cp && *cp != ':'; cp++);
 		*cp = 0;
 
 		for (np = gr->gr_mem; *np && strcmp(*np, pwbuf); np++);
 		if ((int)*np == 0) {
 			printf("chgrp: You're not a member of ``%s''.\n",
 							gr->gr_name);
 			exit(1);
 			}
 		}
 
 	for(c=2; c<argc; c++) {
 		stat(argv[c], &stbuf);
 		if (uid && uid != stbuf.st_uid) {
 			printf("chgrp: You don't own ``%s''.\n", argv[c]);
 			status = 1;
 			}
 		else
 			if(chown(argv[c], stbuf.st_uid, gid) < 0) {
 				perror(argv[c]);
 				status = 1;
 			}
 	}
 	exit(status);
 }
 
 isnumber(s)
 char *s;
 {
 	register c;
 
 	while(c = *s++)
 		if(!isdigit(c))
 			return(0);
 	return(1);
 }