We are
developers, after all (error handling left to the reader):
#include <string.h>
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <dirent.h>
#define BUFSIZE 0x400
int has_slash(const char * buf, size_t len);
int rd(const char * nam, int check)
{
char buf[BUFSIZE];
DIR * d = opendir(nam);
if (d)
{
struct dirent *entry;
while ((entry = readdir(d)) != NULL)
{
if ( check && entry->d_type == DT_REG )
{
if (strlen(entry->d_name)==2)
{
printf("%s/%s\n", nam, entry->d_name);
}
}
if (entry->d_type == DT_DIR)
{
int check;
int len;
strcpy( buf, nam );
if ( ! has_slash(nam, strlen(nam)))
strcat(buf, "/");
strcat(buf, entry->d_name);
len = strlen(entry->d_name);
check = ! strncmp( &entry->d_name[len-3], "bin", 3);
if ( strcmp(".", entry->d_name) && strcmp("..", entry->d_name))
rd(buf, check);
}
}
}
closedir(d);
return 0;
}
int has_slash(const char * buf, size_t len)
{
if ( len < 1) return 0;
if ( buf[len-1] == '/' ) return 1;
return 0;
}
int is_bin(const char * buf, size_t len)
{
if ( has_slash( buf, len) )
{
len--;
}
if ( len < 3)
return 0;
else if ( len == 3 )
{
if ( ! strncmp(buf, "bin",3))
return 1;
}
else
{
if ( !strncmp(&buf[len-4], "/bin", 4))
return 1;
}
return 0;
}
int main (int argc, char * argv[])
{
char buf[BUFSIZE];
if (argc > 1)
{
strncpy(buf, argv[1], BUFSIZE-1);
buf[BUFSIZE-1] = '\0';
}
else
{
getcwd(buf, sizeof(buf));
}
rd( buf, is_bin(buf, strlen(buf)));
return 0;
}
output example:
$ ./rd /
/sbin/tc
/sbin/ss
/usr/lib/klibc/bin/ls
/usr/lib/klibc/bin/ln
/usr/lib/klibc/bin/dd
/usr/bin/pg
/usr/bin/pr
/usr/bin/m4
/usr/bin/at
/usr/bin/ar
/usr/bin/gs
/usr/bin/lp
/usr/bin/nm
/usr/bin/dc
/usr/bin/7z
/usr/bin/du
/usr/bin/wc
/usr/bin/bc
/usr/bin/tr
/usr/bin/ab
/usr/bin/uz
/usr/bin/od
/usr/bin/ul
/usr/bin/as
/usr/bin/nl
/usr/bin/xz
/usr/bin/id
/bin/ls
/bin/ip
/bin/cp
/bin/su
/bin/ln
/bin/mv
/bin/dd
/bin/ps
/bin/rm
/bin/df