give: change owner/group of files

sources-request at panda.UUCP sources-request at panda.UUCP
Fri Nov 15 11:59:45 AEST 1985


Mod.sources:  Volume 3, Issue 44
Submitted by: philabs!mcnc!ikonas!!roger


[ moderators note:   This program ONLY works properly on System III/V
  where chown(3) allows you to give away ownership of a file.  It might
  be useful to superusers on V7/BSD type systems, perhaps?
]

	Wednesday, 13 November 1985, 5:32 p.m.

	Enclosed find the manual page and C source for a program
	to change owner and group id's for one or more files. If
	a named file is a directory, the entire tree beginning
	with (and including) that directory is descended and changed.

	Roger L. Cordes, Jr.
	William G. Daniel & Associates
	...!mcnc!ikonas!dedalus!roger

#!/bin/sh
#	This is a shar archive: extract with sh, not csh.
#	This archive contains:
#		give.1
#		give.c
echo x - give.1
cat > give.1 << '!Funky!Stuff!'
.TH GIVE sd
.SH NAME
give \- change owner and group information for one or more files
.SH SYNOPSIS
.B give
.I file...
.B to
.I user
[\c
.I group\c
]
.SH DESCRIPTION
.B Give
will change ownership and group information for the files specified.
If any of the files is a directory,
.B give
will descend and change the entire directory tree, including the named
directory.
.sp
AS might be expected,
.B give
will only work for the current owner of the named files or root.
.SH DIAGNOSTICS
.B Give
will exit with a descriptive error message if any of the
following occur:
.br
.in +0.5i
access to /etc/passwd (and /etc/group, if applicable) is denied
.br
the named user (group) does not occur in the file
.br
files specified cannot be accessed or modified
.in -0.5i
.SH FILES
/etc/passwd \- user list
.br
/etc/group \- group list
.br
!Funky!Stuff!
echo x - give.c
cat > give.c << '!Funky!Stuff!'
#

/****
 ****	Wednesday, 13 November 1985, 1:29 p.m.
 ****	give: change owner and group for one or more files as indicated:
 ****		usage:
 ****			give file... to user [group]
 ****		- may be used succesfully only by current owner or root
 ****		- if file is a directory, descend and change the entire tree
 ****		  beginning with (including) the named directory
 ****		compile:
 ****			cc -O -o give give.c
 ****/

main(argc,argv)
int	argc;
char	*argv[];
{
	int	i, to, uid = -1, gid = -1;
/*
 *	find end of filename list in argv[] and verify command-line syntax:
 *	must say at least: "give SOMETHING to SOMEBODY"
 */
	for ( i=0; i<argc; i++ )
		if ( !strcmp(argv[i],"to") )
		{
			to = i;
			break;
		}
	if ( (argc<4) || (to<2) || (to==(argc-1)) || (argc<4) )
		exit(printf("usage: %s File... to User [Group]\n",argv[0]));

/*
 *	get target integer user id
 */
	if ( (uid=getuser(argv[to+1])) < 0 )
		exit(printf("unknown user: `%s'...\n",argv[to+1]));

/*
 *	get target integer group id (if applicable)
 */
	if ( (to<(argc-2)) && ((gid=getgroup(argv[to+2]))<0) )
		exit(printf("unknown group: `%s'...\n",argv[to+2]));

	give(&argv[1],(to-1),uid,gid,0);
}

#include <stdio.h>

/*
 *	getuser: get integer user id: returns -1 if unknown
 */

#define	is_digit(C)	( ((C)>='0') && ((C)<='9') )
char	line[256], *c = (char *)0, *strchr();

getuser(name)
char	*name;
{
	FILE	*file;
	int	uid = -1, i, len, strlen(), intname = 1;

	len = strlen(name);

	for ( i=0; i<len; i++ )
		if ( !is_digit(name[i]) )
			intname = 0;

	if ( !(file=fopen("/etc/passwd","r")) )
		exit(printf("cannot read user name list...\n"));

	while ( fgets(line,128,file) )
		if ( intname || !strncmp(line,name,len) )
		{
			c = line;
			for ( i=0; i<2; i++ )
				if ( !(c=strchr((c+1),':')) )
					if ( intname )
						break;
					else
						goto out;
			if ( !intname || !strncmp((c+1),name,len) )
			{
				sscanf((c+1),"%d",&uid);
				break;
			}
		}
out:
	fclose(file);
	return(uid);
}

/*
 *	getgroup: get integer group id: returns -1 on error
 */

getgroup(name)
char	*name;
{
	int	i, gid = -1, intname = 1, len;
	FILE	*file;

	len = strlen(name);

	for ( i=0; i<len; i++ )
		if ( !is_digit(name[i]) )
			intname = 0;

	if ( !(file=fopen("/etc/group","r")) )
		return(-1);

	while ( fgets(line,128,file) )
		if ( intname || !strncmp(line,name,len) )
		{
			if ( !(c=strchr(line,':')) )
				goto out;
			if ( !(c=strchr((c+1),':')) )
				goto out;
			if ( intname && strncmp((c+1),name,len) )
				continue;
			sscanf((c+1),"%d",&gid);
		}
out:
	fclose(file);
	return(gid);
}

/*
 *	give: recursively descend a directory structure changing
 *	      owner and group ids.
 */

#include <sys/types.h>
#include <sys/stat.h>

#define	indent()	for ( j=0; j<pass; j++ ) printf("    ")
#define	is_dir()	((st.st_mode&S_IFDIR)==S_IFDIR)

give(names,n,uid,gid,pass)
char	**names;
int	n, uid, gid, pass;
{
	int		i, j, grp, nn = 0, stat();
	struct stat	st;
	char		**next;

	for ( i=0; i<n; i++ )
	{
		if ( stat(names[i],&st) < 0 )
		{
			indent();
			printf("`%s': cannot stat...\n",names[i]);
			continue;
		}

		if ( gid < 0 )
			grp = st.st_gid;
		else
			grp = gid;

		if ( is_dir() )
		{
			indent();
			printf("%s:\n",names[i]);
			if ( chdir(names[i]) < 0 )
			{
				indent();
				printf("cannot cd to `%s'...\n",
					names[i]);
				continue;
			}
			if ( !(nn=getflist(&next)) )
			{
				indent();
				printf("cannot ls `%s'...\n",names[i]);
			}
			else
				give(next,nn,uid,gid,(pass+1));

			if ( chdir("..") < 0 )
			{
				indent();
				printf("cannot cd to `..'...\n");
				exit(3);
			}
		}

		if ( chown(names[i],uid,grp) < 0 )
		{
			indent();
			printf("`%s': cannot change...\n",names[i]);
		}
	}
}

/*
 *	getflist: get names of files in current working directory
 */

#include <sys/dir.h>

char	ln[4096], *strcat();

getflist(names)
char	***names;
{
	int	n = 0;
	struct direct	dir;
	FILE	*file;

	if ( !(file=fopen(".","r")) )
		return(0);

	ln[0] = 0;

	while ( fread(&dir,sizeof(struct direct),1,file) )
		if ( !strcmp(dir.d_name,".") || !strcmp(dir.d_name,"..") )
			continue;
		else if ( dir.d_ino )
		{
			strcat(ln,dir.d_name);
			strcat(ln," ");
		}

	fclose(file);

	n = get_words(ln,names);

	return(n);
}

/*
 *	get_words: split a character string into individual words
 */

#define	is_white(C)	( ((C)==' ') || ((C)=='\t') )

int	get_words(line,wordlist)
char	*line;
char	***wordlist;
{
	int	i, j, k, nwords = 0, len = 0, longest = 0;
	char	*c, **words, *malloc(), was_white = 0, got_a_word = 0;

/*
 *	count words, find longest word
 */
	for ( c=line; *c; c++ )
		if ( is_white(*c) )
		{
			if ( got_a_word && !was_white )
			{
				if ( len > longest )
					longest = len;
				len = 0;
				nwords++;
			}
			was_white = 1;
		}
		else
		{
			was_white = 0;
			got_a_word = 1;
			len++;
		}

	if ( got_a_word && !was_white )
	{
		if ( len > longest )
			longest = len;
		len = 0;
		nwords++;
	}

	if ( !nwords )
		return(0);

/*
 *	allocate the array of individual words
 */
	if ( !(words=(char **)malloc(nwords*sizeof(char *))) )
	{
		printf("cannot create the word list...\n");
		return(0);
	}

	longest++;	/* plus '\0' */

	for ( i=0; i<nwords; i++ )
		if ( (words[i]=malloc(longest*sizeof(char))) == NULL )
		{
			printf("cannot allocate an individual word...\n");
			for ( --i; i>=0; i-- )
				free(words[i]);
			free((char *)words);
			return(0);
		}

/*
 *	load the array of individual words
 */
	got_a_word = was_white = j = k = 0;

	for ( i=0; line[i]!='\0'; i++ )
		if ( !is_white(line[i]) )
		{
			got_a_word = 1;
			words[j][k] = line[i];
			was_white = 0;
			k++;
		}
		else if ( got_a_word && !was_white )
		{
			words[j][k] = '\0';
			was_white = 1;
			k = 0;
			j++;
		}

	if ( got_a_word && !was_white )
		words[j][k] = '\0';
	*wordlist = words;
	return(nwords);
}

!Funky!Stuff!



More information about the Mod.sources mailing list