hfc

Hosts file client
git clone git://git.marlonivo.com/hfc
Log | Files | Refs | LICENSE

commit a8d1bfe49705835d7d2308323dc1a388c5af5f03
parent 549ae017c6bf549bd9944a4289f4679f5f1e9f6c
Author: Marlon Ivo <email@marlonivo.xyz>
Date:   Sun, 24 Aug 2025 05:30:28 +0000

its too early, brain not working

Diffstat:
MMakefile | 4++--
Mconfig.c | 41++++++++++++++++++++++++++++++++---------
Aconfig.o | 0
Mget.c | 2+-
Aget.o | 0
Ahfc | 0
Mhfc.c | 160+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------
Ahfc.o | 0
Aupdate.o | 0
9 files changed, 156 insertions(+), 51 deletions(-)

diff --git a/Makefile b/Makefile @@ -16,10 +16,10 @@ TARGET = hfc all: prepare $(TARGET) prepare: mkdir -p $(HOME)/.config/hfc - mkdir -p $(HOME)/.local/state + mkdir -p $(HOME)/.local/state/hfc touch $(HOME)/.config/hfc/urls touch $(HOME)/.config/hfc/conf - touch $(HOME)/.local/state/counts + touch $(HOME)/.local/state/hfc/counts $(TARGET): $(OBJS) $(CC) $(OBJS) -o $(TARGET) $(LDFLAGS) diff --git a/config.c b/config.c @@ -7,6 +7,9 @@ #include <ctype.h> #include <ncurses.h> #include <unistd.h> +#include <pwd.h> + +#include <sys/types.h> #include "config.h" /* functions */ @@ -329,21 +332,41 @@ remove_color(ColorSetting *setting, short pair_id) /* 10.00 */ const char * get_config_path(const char *filename, char *buffer, size_t size) { - const char *home; + const char *home = NULL; + + if (geteuid() == 0) { + const char *sudo_user = getenv("SUDO_USER"); + if (sudo_user && strlen(sudo_user) > 0) { + struct passwd *pw = getpwnam(sudo_user); + if (pw && pw->pw_dir) { + home = pw->pw_dir; + } + } + } - home = getenv("HOME"); - if (!home) + if (!home || strlen(home) == 0) { + home = getenv("HOME"); + } + + if (!home || strlen(home) == 0) { + fprintf(stderr, "[FATAL] Kein HOME-Verzeichnis gefunden!\n"); return NULL; + } + + const char *xdg_config_home = getenv("XDG_CONFIG_HOME"); + const char *xdg_state_home = getenv("XDG_STATE_HOME"); if (strcmp(filename, "counts") == 0) { - snprintf(buffer, size, "%s/.local/state/hfc/%s", home,filename); + if (xdg_state_home && strlen(xdg_state_home) > 0) { + snprintf(buffer, size, "%s/hfc/%s", xdg_state_home, filename); + } else { + snprintf(buffer, size, "%s/.local/state/hfc/%s", home, filename); + } } else { - const char *config_home = getenv("XDG_CONFIG_HOME"); - - if (!config_home || strlen(config_home) == 0) { - snprintf(buffer, size, "%s/.config/hfc/%s", home, filename); + if (xdg_config_home && strlen(xdg_config_home) > 0) { + snprintf(buffer, size, "%s/hfc/%s", xdg_config_home, filename); } else { - snprintf(buffer, size, "%s/hfc/%s", config_home, filename); + snprintf(buffer, size, "%s/.config/hfc/%s", home, filename); } } diff --git a/config.o b/config.o Binary files differ. diff --git a/get.c b/get.c @@ -78,7 +78,7 @@ download_url(const char *url, char *error_msg, size_t err_size) return chunk.memory; } -/* 02.01 */ long +long get_remote_content_length(const char *url) { CURL *curl; diff --git a/get.o b/get.o Binary files differ. diff --git a/hfc b/hfc Binary files differ. diff --git a/hfc.c b/hfc.c @@ -67,16 +67,17 @@ /* 33.00 */ int main(int argc, char *argv[]); /* variables */ -int domain_count = 0; -int footer_busy = 0; -int in_help_mode = 0; -int highlight = 0; -int updates_count = 0; -int entry_count = 0; -int keybinding_count = 0; -int is_checking = 1; -volatile int update_progress = -1; -int selected[MAX_ENTRIES] = {0}; +int domain_count = 0; +int footer_busy = 0; +int in_help_mode = 0; +int highlight = 0; +int updates_count = 0; +int entry_count = 0; +int keybinding_count = 0; +int is_checking = 1; +volatile int update_progress = -1; +int is_updating[MAX_ENTRIES] = {0}; +int selected[MAX_ENTRIES] = {0}; int update_pipe[2]; int updates_counts[MAX_ENTRIES]; int domains_counts[MAX_ENTRIES]; @@ -552,6 +553,59 @@ load_counts(void) } } +static void +background_count_entry(int index) +{ + is_updating[index] = 1; + + pid_t pid = fork(); + if (pid == 0) { + setsid(); + signal(SIGHUP, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + + fclose(stdin); + fclose(stdout); + fclose(stderr); + + create_fetch_lock(index); + + long new_size = get_remote_content_length(entries[index]); + if (new_size <= 0) { + remove_index_from_lock(index); + _exit(1); + } + + if (new_size == remote_sizes[index]) { + domains_counts[index] = updates_counts[index]; + updates_counts[index] = domains_counts[index]; + } else { + char error_msg[CURL_ERROR_SIZE] = {0}; + char *content = download_url(entries[index], error_msg, sizeof(error_msg)); + if (!content) { + remove_index_from_lock(index); + _exit(1); + } + + int count = count_hosts_in_content(content); + domains_counts[index] = count; + updates_counts[index] = count; + free(content); + } + + remote_sizes[index] = new_size; + save_count_for_index(index); + + remove_index_from_lock(index); + + if (update_pipe[1] != -1) { + write(update_pipe[1], &index, sizeof(int)); + } + + _exit(0); + } +} + /* 12.00 */ static void update_all_sources(void) { @@ -567,29 +621,36 @@ update_all_sources(void) return; } - /* skips personal lists */ for (i = 0; i < entry_count; i++) { - if (!is_local_entry(entries[i])) { + if (!is_local_entry(entries[i]) && updates_counts[i] != -1) total++; - } } + int old_highlight = highlight; + for (i = 0; i < entry_count; i++) { if (is_local_entry(entries[i])) continue; if (domains_counts[i] == -1 || updates_counts[i] == -1) - continue; /* skip lists in fetch.lock */ + continue; current++; update_progress = i; + + display_entries(highlight); print_footer("(%d/%d) loading %s", current, total, entries[i]); - update_domain_count(i); + refresh(); + + background_count_entry(i); } update_progress = -1; + highlight = old_highlight; + save_counts(); display_entries(highlight); + refresh(); } /* 13.00 */ static void @@ -608,22 +669,29 @@ update_selected_sources(void) total++; } + int old_highlight = highlight; + for (i = 0; i < entry_count; i++) { if (!selected[i] || is_local_entry(entries[i])) continue; current++; update_progress = i; - print_footer("(%d/%d) updating %s", current, total, entries[i]); - update_domain_count(i); + + display_entries(highlight); + print_footer("(%d/%d) loading %s", current, total, entries[i]); + refresh(); + + background_count_entry(i); } update_progress = -1; - save_counts(); + highlight = old_highlight; + display_entries(highlight); + refresh(); } - /* 14.00 */ static void update_domain_count(int index) { @@ -645,7 +713,9 @@ update_domain_count(int index) if (!content) return; - updates_counts[index] = count_hosts_in_content(content); + int count = count_hosts_in_content(content); + updates_counts[index] = count; + domains_counts[index] = count; remote_sizes[index] = new_size; free(content); @@ -755,13 +825,13 @@ display_entries(int highlight) if (selected_count > 0) { mvprintw(0, right_col, "*%d | %d/%d", - selected_count, + selected_count, (entry_count == 0) ? 0 : highlight + 1, - entry_count); + entry_count); } else { mvprintw(0, right_col, " | %d/%d", - (entry_count == 0) ? 0 : highlight + 1, - entry_count); + (entry_count == 0) ? 0 : highlight + 1, + entry_count); } if (fg_code != -1) @@ -769,7 +839,7 @@ display_entries(int highlight) else attroff(COLOR_PAIR(0)); - /* line unter dem header */ + /* line below header */ short line_code = get_color_code(config.header.bg); if (line_code != -1) { init_pair(10, line_code, -1); @@ -838,8 +908,8 @@ display_entries(int highlight) short bg_code = get_color_code(config.entry_default.bg); if (fg_code != -1 || bg_code != -1) { init_pair(20, - (fg_code != -1 ? fg_code : -1), - (bg_code != -1 ? bg_code : -1)); + (fg_code != -1 ? fg_code : -1), + (bg_code != -1 ? bg_code : -1)); attron(COLOR_PAIR(20) | (config.entry_default.bold ? A_BOLD : 0)); } } @@ -849,7 +919,14 @@ display_entries(int highlight) mvprintw(y, 2, "%-*d", id_width, i + 1); mvprintw(y, indent, "%.*s", max_url_width, text + line * max_url_width); - if (domains_counts[i] == -1 || updates_counts[i] == -1) { + if (is_updating[i]) { + if (domains_counts[i] > 0) { + snprintf(buf, sizeof(buf), "(%d/...)", domains_counts[i]); + } else { + snprintf(buf, sizeof(buf), "(...)"); + } + mvprintw(y, local_source_start, "%s", buf); + } else if (domains_counts[i] == -1 || updates_counts[i] == -1) { mvprintw(y, local_source_start, "(...)"); } else if (is_local_entry(entries[i])) { snprintf(buf, sizeof(buf), "(%d)", domains_counts[i]); @@ -1654,9 +1731,9 @@ rename_entry(int index) return; snprintf(old_header, sizeof(old_header), - "# %d. %s", index + 1, entries[index]); + "# %d. %s", index + 1, entries[index]); snprintf(new_header, sizeof(new_header), - "# %d. %.220s", index + 1, input); + "# %d. %.220s", index + 1, input); in = fopen(hosts_path, "r"); out = fopen("/tmp/hosts_rename_temp", "w"); @@ -1719,24 +1796,19 @@ main(int argc, char *argv[]) int ch; const char *editor = getenv("EDITOR"); - /* load config file */ load_config(); - /* resolve default config paths via XDG */ get_config_path("counts", counts_path, sizeof(counts_path)); get_config_path("urls", urls_path, sizeof(urls_path)); get_config_path("fetch.lock", fetch_lock_path, sizeof(fetch_lock_path)); - /* initialize locale and curl */ setlocale(LC_ALL, ""); curl_global_init(CURL_GLOBAL_DEFAULT); update_progress = -1; - /* load saved state */ load_entries(); load_counts(); - /* check for ongoing background fetches */ if (pipe(update_pipe) < 0) { perror("pipe"); } else { @@ -1965,13 +2037,18 @@ main(int argc, char *argv[]) load_counts(); display_entries(highlight); } - /* check update_pipe to refresh UI */ + /* check background_fetch_entry to refresh UI */ int idx; while (read(update_pipe[0], &idx, sizeof(int)) > 0) { if (idx >= 0 && idx < entry_count) { + // Nur zurücksetzen, wenn es ein Count-Vorgang war: + if (is_updating[idx]) { + is_updating[idx] = 0; + } display_entries(highlight); } } + /* handle user input */ ch = getch(); @@ -2138,19 +2215,24 @@ main(int argc, char *argv[]) } if (!has_network_connection()) { print_footer("Error: No network connection."); - napms(2000); display_entries(highlight); continue; } if (any) { - print_footer("Updating selected entries..."); update_selected_sources(); } else { + if (is_local_entry(entries[highlight])) { + display_entries(highlight); + continue; + } + print_footer("Checking for updates..."); + refresh(); + napms(100); long before = remote_sizes[highlight]; long after = get_remote_content_length(entries[highlight]); if (after > 0 && after != before) { print_footer("Updating %s...", entries[highlight]); - update_domain_count(highlight); + background_count_entry(highlight); domains_counts[highlight] = count_hosts_in_section(highlight); updates_counts[highlight] = domains_counts[highlight]; save_counts(); diff --git a/hfc.o b/hfc.o Binary files differ. diff --git a/update.o b/update.o Binary files differ.