Wednesday, April 23, 2008

fpath

Being bored as I often am, I wrote this small C program. It functions almost identically to the Perl findpath script I wrote before, but is much lighter:

fpath.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>


typedef struct {
int splitlen;
char ** split;
char * merged;
} splitstore;
splitstore * splitchr(const char split, const char * str);
void splitstore_delete(splitstore * del);
splitstore * splitstr(const char * split, const char * str);
int execpermissions(uid_t uid, gid_t gid, const struct stat * info) {
return S_IXOTH & info->st_mode || (info->st_gid == gid && S_IXGRP & info->st_mode) || (info->st_uid == uid && S_IXUSR & info->st_mode);
}

int main(int argc, char ** argv) {
const char * path = getenv("PATH");
char * current;
DIR * dirinfo;
char * term = NULL;
struct dirent * file;
struct stat info;
int i;
const char help[1024];
sprintf(help, "Usage: %s exname\n", argv[0]);
if(argc < 2) {
fputs(help, stderr);
return 2;
}
term = argv[1];

uid_t uid = getuid();
gid_t gid = getegid();
splitstore * splitpath = splitchr(':', path);
if(!splitpath)
return 1;
for(i = 0; i < splitpath->splitlen; i++) {
current = splitpath->split[i];
if(!stat(current, &info)) {
if(S_ISDIR(info.st_mode)) {
chdir(current);
dirinfo = opendir(current);
while((file = readdir(dirinfo)) != NULL) {
if(!stat(file->d_name, &info) && S_ISREG(info.st_mode) && execpermissions(uid, gid, &info) && strstr(file->d_name, term))
printf("%s/%s\n", current, file->d_name);
}
closedir(dirinfo);
}
else {
fprintf(stderr, "Not a directory: %s\n", current);
}
}
else
fprintf(stderr, "Unable to stat: %s\n", current);
}
splitstore_delete(splitpath);
return 0;
}

splitstore * splitchr(const char split, const char * str) {
if(!str)
return NULL;
splitstore * ret = (splitstore *) malloc(sizeof(splitstore));
if(!ret)
return NULL;
ret->splitlen = 0;
int len = strlen(str);
char * c = NULL, * start;
ret->merged = (char *) malloc(len + 1);
strcpy(ret->merged, str);
ret->split = NULL;
if(!ret->merged) {
free(ret);
return NULL;
}
ret->split = (char **) malloc(sizeof(char *));
ret->split[ret->splitlen++] = ret->merged;
if(!ret->split) {
free(ret->merged);
free(ret);
return NULL;
}
start = ret->merged;
while((c = strchr(start, split)) != NULL) {
*c = '\0';
ret->split = (char **) realloc(ret->split, sizeof(char *) * (ret->splitlen + 1));
if(!ret->split) {
free(ret->merged);
free(ret);
return NULL;
}
ret->split[ret->splitlen++] = ++c;
start = c;
}
return ret;
}
splitstore * splitstr(const char * split, const char * str) {
if(!str)
return NULL;
splitstore * ret = (splitstore *) malloc(sizeof(splitstore));
if(!ret)
return NULL;
ret->splitlen = 0;
int len = strlen(str);
int slen = strlen(split);
char * c = NULL, * start;
ret->merged = (char *) malloc(len + 1);
strcpy(ret->merged, str);
ret->split = NULL;
if(!ret->merged) {
free(ret);
return NULL;
}
ret->split = (char **) malloc(sizeof(char *));
ret->split[ret->splitlen++] = ret->merged;
if(!ret->split) {
free(ret->merged);
free(ret);
return NULL;
}
start = ret->merged;
while((c = strstr(start, split)) != NULL) {
*c = '\0';
ret->split = (char **) realloc(ret->split, sizeof(char *) * (ret->splitlen + 1));
if(!ret->split) {
free(ret->merged);
free(ret);
return NULL;
}
c += slen;
ret->split[ret->splitlen++] = c;
start = c;
}
return ret;
}
void splitstore_delete(splitstore * del) {
if(del) {
if(del->split)
free(del->split);
if(del->merged)
free(del->merged);
free(del);
}
}

No comments: