#include <sys/unix.h>
#include "chown.h"

extern int ERRNO;

main( argc, argv )
int	argc;
char	*argv[];
{
	int	uid, gid, i;

	/* Are there enough arguments?  No! Yes! No! Yes! */
	if( argc < 4 )
	{
		fprintf(stderr,"usage: %s uid gid filenames\n",argv[0]);
		return(-1);
	}

	/* Arguments 1 and 2 *must* be uid and gid */
	uid = atoi( argv[1] );
	gid = atoi( argv[2] );

	/* Go through all arguments listing things other than flags */
	for( i=3; i<argc; i++ )
		dochown( "", argv[i], uid, gid );

	return(0);
}


int dochown( pre, patt, uid, gid )
char	*pre,
	*patt;
int	uid, gid;
{
	struct direct	dirbuf;
	struct stat	statbuf;
	char		whole[256], dname[16];
	char		*orig, *first;
	int		end;
	int		d, f;

	/* Find the leading directry to search */
	orig = patt;
	first = dname;
	while( *orig && (*orig != '/') )
		*first++ = *orig++;
	*first = 0;
	end = (*orig==0) || (*(orig+1)==0);

	if( strlen(pre)==0 )
		if( strlen(dname)==0 )
		{
			dochown( "/", orig+1, uid, gid );
			return(0);
		}
		else
			pre = ".";

	/* Stat the preceeding path */
	if( stat( pre, &statbuf ) || ERRNO )
	{
		fprintf( stderr, "chown: can't stat %s\n", pre );
		return(0);
	}
	if( (statbuf.st_mode & F_MASK) != F_DIR )
	{
		fprintf( stderr, "chown: not a directory\n" );
		return(0);
	}

	/* Open directory and match entries */
	if( d=open(pre,O_RDONLY), ERRNO )
	{
		fprintf(stderr,"chown: couldn't open %s\n",pre);
		return( 0 );
	}
	while( read( d, (char*)&dirbuf, 16 ) == 16 )
	{
		if( dirbuf.d_name[0] == '\0' )
			continue;

		if( (strcmp(dirbuf.d_name,".")==0) || (strcmp(dirbuf.d_name,"..")==0) )
			continue;

		if( match( dirbuf.d_name, dname ) )
		{
			strcpy( whole, pre );
			strcat( whole, "/" );
			strcat( whole, dirbuf.d_name );

			if( stat( whole, &statbuf ) || ERRNO )
			{
				fprintf( stderr, "chown: can't stat %s\n", dname );
				break;
			}

			if( (statbuf.st_mode & F_MASK) != F_DIR )
			{
				if( !end )
				{
					fprintf( stderr, "chown: %s not a directory\n",whole );
					break;
				}
				if( chown(whole,uid,gid), ERRNO )
				{
					fprintf(stderr,"chown: couldn't change %s\n",whole);
					break;
				}
			}
			else
				if( end )
				{
					if( chown(whole,uid,gid), ERRNO )
						fprintf( stderr, "chown: couldn't change %s\n", whole );
					break;
				}
				else
					dochown( whole, orig+1, uid, gid );
		}
	}
	close( d );

	return( 0 );
}



int match( str, patt )
char	*str,
	*patt;
{
	if( *patt == '*' )
	{
		char	*pos = str;
		if( (!*(patt+1)) && *str )
			return( 1 );
		while( *pos )
			if( match(pos,patt+1) )
				return( 1 );
			else
				pos++;
		return( 0 );
	}
	if( (*str==0) && (*patt==0) )
		return( 1 );
	if( ! (*str && *patt) )
		return( 0 );
	if( (*str==*patt) || (*patt=='?') )
		return( match(str+1,patt+1) );
	return( 0 );
}

