For educational use I'm trying to implement a simple find program (similar to find(1) with much less functionality).
While implementing the first functionality - "-user " - I got challanged by combining two different functions (once for uid and once for name) with one "control-function?". I guess I'm looking for something similar like overloaded functions in C#, what's the best practice to solve such a problem in C?
I would appreciate a solution approach, which allows my program to process both options while calling it: E.g.:
- "my_find -user vincent"
- "my_find -user 1000"
If you find some coding or style issues within my samples, please point them out, I'm willing to learn! I'm aware of missing out on some clean memory management but will add this later on.
Update I was thinking about a function which is processing the argument as a char array and checks each char for its ASCII code and call the function if no "char" was found. Is something like that "legit"?
#include <dirent.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <pwd.h>
void entries_with_uid(char *init_path, int pattern_uid);
void entries_with_name(char *init_path, char *pattern_name);
int main(int argc, char **argv)
{
/*
char *path = argv[1];
*/
entries_with_name("/home/mario/Documents/codes", "mario");
entries_with_uid("/home/mario/test_project", 1000);
return 0;
}
void entries_with_uid(char *init_path, int pattern_uid)
{
DIR *dir;
struct dirent *entry;
dir = opendir(init_path);
entry = readdir(dir);
if(dir == NULL) return;
if(entry == NULL) return;
do {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
char path[1024];
int len = snprintf(path, sizeof(path)-1, "%s/%s", init_path, entry->d_name);
path[len] = 0;
struct stat sb;
stat(path, &sb);
if(sb.st_uid == pattern_uid) printf("%s\n", path);
if (entry->d_type == DT_DIR) entries_with_uid(path, pattern_uid);
} while (entry = readdir(dir));
closedir(dir);
}
void entries_with_name(char *init_path, char *pattern_name)
{
DIR *dir;
struct dirent *entry;
dir = opendir(init_path);
entry = readdir(dir);
if(dir == NULL) return;
if(entry == NULL) return;
do {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue;
char path[1024];
int len = snprintf(path, sizeof(path)-1, "%s/%s", init_path, entry->d_name);
path[len] = 0;
struct stat sb;
stat(path, &sb);
struct passwd *pwd = getpwuid(sb.st_uid);
if(strcmp(pwd->pw_name, pattern_name) == 0) printf("%s\n", path);
if (entry->d_type == DT_DIR) entries_with_name(path, pattern_name);
} while (entry = readdir(dir));
closedir(dir);
}
Thanks!
Update
I solved the problem meanwhile with a function which is checking for an alphanumeric string within the argument:
int count_alphanumeric(char *string)
{
int alphanumeric_counter = 0;
int i = 0;
while(string[i]!='\0')
{
if (string[i] <= 57 && string[i] >= 48)
{
i++;
continue;
}
else alphanumeric_counter++;
i++;
}
return alphanumeric_counter;
}
Still looking for a more elegant option! ;)
Cheeers!
char*and always cast to it when passing a string (a bit cumbersome, but portable).