about summary refs log tree commit diff stats
path: root/rf.c
diff options
context:
space:
mode:
Diffstat (limited to 'rf.c')
-rw-r--r--rf.c205
1 files changed, 96 insertions, 109 deletions
diff --git a/rf.c b/rf.c
index 6d6c2c1..5d412c3 100644
--- a/rf.c
+++ b/rf.c
@@ -1,6 +1,9 @@
 #define _BSD_SOURCE
 #define _DEFAULT_SOURCE
 
+#define _POSIX_C_SOURCE 200809L
+#define _XOPEN_SOURCE 600
+
 #include <dirent.h>
 #include <errno.h>
 #include <fnmatch.h>
@@ -13,12 +16,17 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-#include "config.h"
+#include "ignore.h"
 
 extern char *__progname;
 
+struct ignores *global_ignores;
+struct ignores *config_ignores;
+struct ignores *local_ignores;
+
 struct switches {
 	int substring;
+	int wholename;
 	int invert;
 	int limit;
 	int count;
@@ -31,7 +39,7 @@ static void usage(char *error) {
 		fprintf(stderr, "Error: %s\n\n", error);
 	}
 
-	fprintf(stderr, "usage: %s [-lsvSU] pattern ...\n", __progname);
+	fprintf(stderr, "usage: %s [-lsvw] pattern ...\n", __progname);
 }
 
 static int is_child(char *dirname) {
@@ -42,19 +50,25 @@ static int is_child(char *dirname) {
 	return 1;
 }
 
-static int not_in_array(char **arr, char *dirname, size_t size) {
-	for (int i = 0; i < size; i++) {
-		if (fnmatch(arr[i], dirname, 0) == 0) {
-			return 0;
+static int excluded(char *name) {
+	for (int i = 0; i < global_ignores->size; i++) {
+		int res = fnmatch(global_ignores->list[i], name, 0);
+
+		if (res == 0) {
+			return 1;
 		}
 	}
 
-	return 1;
-}
+	for (int i = 0; i < config_ignores->size; i++) {
+		int res = fnmatch(config_ignores->list[i], name, 0);
+
+		if (res == 0) {
+			return 1;
+		}
+	}
 
-static int excluded_extension(char *filename) {
-	for (int i = 0; i < ignored_extensions_size; i++) {
-		int res = fnmatch(ignored_extensions[i], filename, 0);
+	for (int i = 0; i < local_ignores->size; i++) {
+		int res = fnmatch(local_ignores->list[i], name, 0);
 
 		if (res == 0) {
 			return 1;
@@ -65,48 +79,9 @@ static int excluded_extension(char *filename) {
 }
 
 static void handle_result(
-	char *path, struct switches *switches, struct dirent *entry) {
-	int i, j, k = 0;
-	char cmd[MAXPATHLEN];
-	char full_path[MAXPATHLEN];
-
-	memset(cmd, '\0', MAXPATHLEN);
-	full_path[0] = '\0';
-
-	strcat(full_path, path);
-	strcat(full_path, "/");
-	strcat(full_path, entry->d_name);
-
+	char *full_path, struct switches *switches, struct dirent *entry) {
 	if (is_child(entry->d_name) != 0) {
-		if (switches->unlink) {
-			int r = unlink(full_path);
-
-			if (r < 0) {
-				perror("unlink");
-			} else {
-				printf("removed '%s'\n", full_path);
-			}
-		} else if (switches->cmd != NULL) {
-			int l = strlen(switches->cmd);
-
-			for (i = 0, j = 0; i < l; i++) {
-				char c = switches->cmd[i];
-
-				if (c == '%' && (i + 1 < l) && switches->cmd[i + 1] == 's') {
-					i++;
-
-					for (k = 0; k < strlen(full_path); k++) {
-						cmd[j++] = full_path[k];
-					}
-				} else {
-					cmd[j++] = c;
-				}
-			}
-
-			system(cmd);
-		} else {
-			printf("%s\n", full_path);
-		}
+		printf("%s\n", full_path);
 	}
 }
 
@@ -116,66 +91,70 @@ static int recurse_find(char **patterns, int *pattern_count, char *dirname,
 	DIR *dir;
 
 	char path[MAXPATHLEN] = {'\0'};
-	int break_early = 0;
 	strcat(path, dirname);
 	dir = opendir(path);
 
-	if (dir != NULL && not_in_array(ignored_dirs, dirname, ignored_dirs_size)) {
+	if (dir != NULL && !excluded(dirname)) {
 		struct dirent *entry;
 
 		while ((entry = readdir(dir)) != NULL) {
-			int matched = switches->invert ? 1 : 0;
+			int matched = 0;
 			int p = 0;
 
-			switch (entry->d_type) {
-			case DT_DIR:
-				if (is_child(entry->d_name) &&
-					not_in_array(
-						ignored_dirs, entry->d_name, ignored_dirs_size)) {
-					char child_path[MAXPATHLEN] = {'\0'};
-					strcat(child_path, path);
-					strcat(child_path, "/");
-					strcat(child_path, entry->d_name);
+			char full_path[MAXPATHLEN] = {'\0'};
+			strcat(full_path, path);
+			strcat(full_path, "/");
+			strcat(full_path, entry->d_name);
+
+			struct stat entry_stat;
+
+			if (stat(full_path, &entry_stat)) {
+				perror("stat");
+				exit(EXIT_FAILURE);
+			}
+
+			if (entry_stat.st_mode & S_IFDIR) {
+				if (is_child(entry->d_name) && !excluded(entry->d_name)) {
 					if (recurse_find(
-							patterns, pattern_count, child_path, switches)) {
-						break_early = 1;
-						break;
+							patterns, pattern_count, full_path, switches)) {
+						closedir(dir);
+						return 1;
 					};
 				}
-
-				break;
-			case DT_REG:
-				if (excluded_extension(entry->d_name)) {
+			} else if (entry_stat.st_mode & S_IFREG) {
+				if (excluded(entry->d_name)) {
 					matched = 0;
-					break;
+					continue;
 				}
 
 				for (; p < *pattern_count; p++) {
 					char *pattern = patterns[p];
 
 					if (switches->substring) {
-						if (strstr(entry->d_name, pattern) != NULL) {
-							matched = switches->invert ? 0 : 1;
+						if (strstr(
+								switches->wholename ? full_path : entry->d_name,
+								pattern) != NULL) {
+							matched = 1;
 						}
 					} else {
-						if (fnmatch(pattern, entry->d_name, 0) == 0) {
-							matched = switches->invert ? 0 : 1;
+						if (fnmatch(pattern,
+								switches->wholename ? full_path : entry->d_name,
+								0) == 0) {
+							matched = 1;
 						}
 					}
 				}
 
-				break;
-			default:
-				break;
-			} /* switch */
-
-			if (break_early) {
-				closedir(dir);
-				return 1;
+				if (switches->invert) {
+					if (matched)
+						matched = 0;
+					else
+						matched = 1;
+				}
 			}
 
 			if (matched) {
-				handle_result(path, switches, entry);
+				handle_result(full_path, switches, entry);
 
 				if (switches->limit > 0 &&
 					++switches->count == switches->limit) {
@@ -193,14 +172,12 @@ static int recurse_find(char **patterns, int *pattern_count, char *dirname,
 
 int main(int argc, char **argv) {
 	struct switches switches = {
-		.substring = 0, .invert = 0, .limit = 0, .unlink = 0, .cmd = NULL};
+		.substring = 0, .invert = 0, .wholename = 0, .limit = 0, .count = 0};
 
-	int count = 0; /* used to count how matches we find */
 	int ch;
-
 	char *remainder;
 
-	while ((ch = getopt(argc, argv, "l:svS:U")) > -1) {
+	while ((ch = getopt(argc, argv, "l:svw")) > -1) {
 		switch (ch) {
 		case 'h':
 			usage(NULL);
@@ -214,14 +191,8 @@ int main(int argc, char **argv) {
 			switches.invert = 1;
 			break;
 
-		case 'S':
-			if (system(NULL) == 0) {
-				fprintf(stderr, "A shell isn't available.");
-				exit(EXIT_FAILURE);
-			}
-
-			switches.cmd = optarg;
-
+		case 'w':
+			switches.wholename = 1;
 			break;
 
 		case 'l':
@@ -236,28 +207,41 @@ int main(int argc, char **argv) {
 			} while (0);
 
 			break;
-
-		case 'U':
-			switches.unlink = 1;
-			break;
 		}
 	}
 
-	/* sanity check opts for conflicts */
-	int printing = switches.invert + switches.limit;
+	char *home = getenv("HOME");
+	char *xdg_config_home = getenv("XDG_CONFIG_HOME");
+	char cwd[MAXPATHLEN];
 
-	if (switches.unlink == 1 && printing > 0) {
-		fprintf(stderr, "Cannot use -U with any of -lsv.\n");
-		exit(EXIT_FAILURE);
-	} else if (switches.cmd != NULL && printing > 0) {
-		fprintf(stderr, "Cannot use -S with any of -lsv.\n");
+	if (getcwd(cwd, MAXPATHLEN) == NULL) {
+		perror("getcwd");
 		exit(EXIT_FAILURE);
 	}
 
+	char global_ignore_path[(strlen(home) + strlen(".rfignore") + 1)];
+	char config_ignore_path[xdg_config_home
+								? (strlen(xdg_config_home) + strlen("ignore") +
+									  3)
+								: (strlen(cwd) + strlen(".rfignore") + 1)];
+	char local_ignore_path[strlen(cwd) + strlen(".rfignore") + 1];
+	sprintf(global_ignore_path, "%s/%s", home, ".rfignore");
+	sprintf(local_ignore_path, "%s/%s", cwd, ".rfignore");
+
+	if (xdg_config_home) {
+		sprintf(config_ignore_path, "%s/rf/%s", xdg_config_home, "ignore");
+	} else {
+		sprintf(config_ignore_path, "%s/.config/rf/%s", home, "ignore");
+	}
+
+	global_ignores = init_ignores(global_ignore_path);
+	config_ignores = init_ignores(config_ignore_path);
+	local_ignores = init_ignores(local_ignore_path);
+
 	if (optind < argc) {
 		int i = 0;
 		int pattern_count = argc - optind;
-		char **patterns = malloc(sizeof(char *) * pattern_count);
+		char **patterns = calloc(sizeof(char *), pattern_count);
 
 		memset(patterns, '\0', optind);
 
@@ -270,6 +254,9 @@ int main(int argc, char **argv) {
 		};
 
 		free(patterns);
+		free_ignores(global_ignores);
+		free_ignores(config_ignores);
+		free_ignores(local_ignores);
 	} else {
 		usage(NULL);
 	}