#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/param.h>

#define LASTCHR(s) s[strlen(s)-1]

int do_nothing(name)
char *name;
{       return 0; }

int printfile(name)
char *name;
{       printf("%s\n", name);
	return 0;
}

int suidfile(name)
char *name;
{       struct stat stbuf;
	stat(name, &stbuf);
	return (stbuf.st_mode & S_ISUID);
}
	
int mapdir(name, predfn, thenfn, elsefn)
char *name;
int (*predfn)(), (*thenfn)(), (*elsefn)();
{
	DIR *dirp;
	struct dirent *entry;
	struct stat stbuf;
	char olddir[MAXPATHLEN];
	char cname[MAXPATHLEN];

	getwd(olddir);
	strcpy(cname, name);
	if (chdir(name)) {
		printf("Couldn't change to directory %s\n", name);
		return -1;
	}
	if ((dirp = opendir(name)) == NULL){
		printf("Unable tto open DIR %s\n", name);
		chdir(olddir);
		return -1;
	}
	for (entry=readdir(dirp); entry != NULL; entry=readdir(dirp)) {
		if (0 != stat(entry->d_name, &stbuf))
			printf("Can't read file information %s\n", 
				entry->d_name);
		else if (strcmp(entry->d_name, ".") == 0  ||
		    strcmp(entry->d_name, "..") == 0)
			/* don't pursue these entries */ ;
		else if (S_ISLNK(stbuf.st_mode))
			/* don't pursue links */ ;
		else if (S_ISDIR(stbuf.st_mode)) {
			if (LASTCHR(cname) != '/') strcat(cname, "/");
			strcat(cname, entry->d_name);
			mapdir(cname, predfn, thenfn, elsefn);
			strcpy(cname,name);
		} else
			if ((*predfn) (entry->d_name))
				(*thenfn) (entry->d_name);
			else (*elsefn) (entry->d_name);
	}
	closedir(dirp);
	chdir(olddir);
	return 0;
}

char *setupdir(buf, name)
char *name;
char *buf;
{
	char curdir[MAXPATHLEN];

	getwd(curdir);
	if (name[0] == '/')     
		strcpy(buf, name);
	else {  strcpy(buf, curdir);
		if (buf[strlen(buf)-1] != '/') strcat(buf, "/"); /* may be at root */
		strcat(buf, name);
	}
	return buf;
}

int main(argc, argv)
int argc;
char **argv;
{
	char *predfn, *thenfn, *elsefn;
	char name[MAXPATHLEN];

	if (argc < 2) {
		printf("Usage: %s <directory>",argv[0]);
		return -1;
	}
	setupdir(name, argv[1]);
	predfn = (char *) suidfile;
	thenfn = (char *) printfile;
	elsefn = (char *) do_nothing;
	return mapdir(name, predfn, thenfn, elsefn);
}

