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

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

int suidfile(name)
char *name;
{
	struct stat stbuf;
	stat(name, &stbuf);
	if (stbuf.st_mode & S_ISUID) printf("%s\n", name);
	return 0;
}

int mapdir(name, filefn)
char *name;
int (*filefn)();
{
	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, filefn);
			strcpy(cname,name);
		} else
			(*filefn) (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] == '/')     /* absolute pathname */
		strcpy(buf, name);
	else {                  /* relative pathname*/
		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 *filefn;
	char name[MAXPATHLEN];

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

