progress
This commit is contained in:
parent
58237b1ec4
commit
e9cdb49877
212
src/main.c
212
src/main.c
@ -203,7 +203,7 @@ int read_safe_integer() {
|
||||
// Speicher freigeben und mit 0 überschreiben (Prävention von use-after-free-Schwachstelle)
|
||||
void cleanup_memory() {
|
||||
if (all_entries != NULL) {
|
||||
printf("%lu Bytes Speicher werden freigegeben\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||
printf("\nDEBUG: %lu Bytes Speicher werden freigegeben\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||
free(all_entries);
|
||||
all_entries = NULL;
|
||||
}
|
||||
@ -225,7 +225,7 @@ void mem_expand_dynamically() {
|
||||
int old_max = max_entries;
|
||||
max_entries = max_entries * GROWTH_FACTOR;
|
||||
|
||||
printf("Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR);
|
||||
printf("DEBUG: Dynamische Speichererweiterung von %d auf %d Einträge um Faktor %f\n", old_max, max_entries, GROWTH_FACTOR);
|
||||
|
||||
struct log_entry *new_ptr = realloc(all_entries, max_entries * sizeof(struct log_entry));
|
||||
|
||||
@ -236,7 +236,7 @@ void mem_expand_dynamically() {
|
||||
}
|
||||
|
||||
all_entries = new_ptr;
|
||||
printf("Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||
printf("DEBUG: Speicher erfolgreich erweitert auf %lu Bytes\n", (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||
}
|
||||
}
|
||||
|
||||
@ -250,7 +250,7 @@ void allocate_initial_memory() {
|
||||
exit(1); // cleanup_and_exit() nicht nötig, da der Speicherbereich nicht beschrieben wurde - use-after-free unproblematisch
|
||||
}
|
||||
|
||||
printf("Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||
printf("DEBUG: Speicher erfolgreich alloziert für %d Log-Einträge (%lu Bytes)\n", max_entries, (unsigned long)(max_entries * sizeof(struct log_entry)));
|
||||
}
|
||||
|
||||
void get_current_timestamp(char* buffer, int buffer_size) {
|
||||
@ -540,7 +540,7 @@ void load_regular_file(char* filename) {
|
||||
printf("ERROR: Kann Datei '%s' nicht öffnen!\n", filename);
|
||||
return;
|
||||
}
|
||||
printf("Lade Datei: %s\n", filename);
|
||||
printf("INFO: Lade Datei: %s\n", filename);
|
||||
char line[MAX_LINE_LENGTH_BUF];
|
||||
int loaded_from_this_file = 0;
|
||||
while (fgets(line, sizeof(line), file) != NULL) {
|
||||
@ -558,8 +558,8 @@ void load_log_file(char* path) {
|
||||
total_entries = 0;
|
||||
|
||||
if (is_directory(path)) {
|
||||
printf("Verzeichnis erkannt: %s\n", path);
|
||||
printf("Suche nach .log Dateien...\n");
|
||||
printf("DEBUG: Verzeichnis erkannt: %s\n", path);
|
||||
printf("DEBUG: Suche nach .log Dateien...\n");
|
||||
|
||||
DIR* dir = opendir(path);
|
||||
if (dir == NULL) {
|
||||
@ -585,17 +585,17 @@ void load_log_file(char* path) {
|
||||
files_found++;
|
||||
} else if (strstr(filename, ".gz") != NULL) {
|
||||
printf("INFO: .gz Datei '%s' übersprungen (nicht unterstützt in dieser Version)\n", filename);
|
||||
printf(" Tipp: Dekomprimieren Sie mit 'gunzip %s'\n", filename);
|
||||
printf(" Tipp: Dekomprimieren Sie mit 'gunzip %s'\n", filename);
|
||||
}
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
if (files_found == 0) {
|
||||
printf("Keine .log Dateien im Verzeichnis gefunden.\n");
|
||||
printf("Tipp: Für .gz Dateien verwenden Sie 'gunzip *.gz' zum Dekomprimieren\n");
|
||||
printf("WARNING: Keine .log Dateien im Verzeichnis gefunden.\n");
|
||||
printf(" Tipp: Für .gz Dateien verwenden Sie 'gunzip *.gz' zum Dekomprimieren\n");
|
||||
} else {
|
||||
printf("Insgesamt %d .log Dateien verarbeitet.\n", files_found);
|
||||
printf("INFO: Insgesamt %d .log Dateien verarbeitet.\n", files_found);
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -603,17 +603,17 @@ void load_log_file(char* path) {
|
||||
|
||||
if (strstr(path, ".gz") != NULL) {
|
||||
printf("FEHLER: .gz Dateien werden in dieser Version nicht unterstützt!\n");
|
||||
printf("Lösung: Dekomprimieren Sie die Datei zuerst:\n");
|
||||
printf(" gunzip %s\n", path);
|
||||
printf(" Dann: %s %.*s\n", "PROGRAMM", (int)(strlen(path)-3), path);
|
||||
printf(" Lösung: Dekomprimieren Sie die Datei zuerst:\n");
|
||||
printf(" gunzip %s\n", path);
|
||||
printf(" Dann: %s %.*s\n", "PROGRAMM", (int)(strlen(path)-3), path);
|
||||
return;
|
||||
} else {
|
||||
load_regular_file(path);
|
||||
}
|
||||
}
|
||||
|
||||
printf("Erfolgreich %d Einträge insgesamt geladen.\n", total_entries);
|
||||
printf("Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries);
|
||||
printf("INFO: Erfolgreich %d Einträge insgesamt geladen.\n", total_entries);
|
||||
printf("DEBUG: Aktueller Speicherverbrauch: %lu Bytes für %d Einträge\n", (unsigned long)(max_entries * sizeof(struct log_entry)), max_entries);
|
||||
}
|
||||
|
||||
// Funktion zum suchen eines Suchbegriffs innerhalb eines Strings (lowercase)
|
||||
@ -981,19 +981,23 @@ void format_iso8601_time(struct simple_time time, char* buffer, int buffer_size)
|
||||
}
|
||||
|
||||
//Export in Timesketch-kompatiblem Format
|
||||
void export_filtered_entries() {
|
||||
printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
|
||||
void export_filtered_entries(char *filepath) {
|
||||
//90 chars + delimiter
|
||||
char filename[91];
|
||||
if (scanf("%90s", filename) != 1) {
|
||||
printf("FEHLER: Ungültiger Dateiname!\n");
|
||||
clear_input_buffer();
|
||||
return;
|
||||
if (filepath == NULL) {
|
||||
printf("Dateiname für Timesketch-Export eingeben (ohne .csv): ");
|
||||
if (scanf("%90s", filename) != 1) {
|
||||
printf("FEHLER: Ungültiger Dateiname!\n");
|
||||
clear_input_buffer();
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
strncpy(filename, filepath, sizeof(filename) - 1);
|
||||
filename[sizeof(filename) - 1] = '\0';
|
||||
}
|
||||
clear_input_buffer();
|
||||
// Dateiendung
|
||||
strcat(filename, ".csv");
|
||||
|
||||
printf("\nINFO: Schreibe Datei %s...\n", filename);
|
||||
FILE* file = fopen(filename, "w");
|
||||
if (file == NULL) {
|
||||
printf("ERROR: Kann Datei '%s' nicht erstellen!\n", filename);
|
||||
@ -1028,7 +1032,7 @@ void export_filtered_entries() {
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
printf("%d Logeinträge erfolgreich als Timesketch-kompatible CSV-Datei nach '%s' exportiert.\n", exported_count, filename);
|
||||
printf("INFO: %d Logeinträge erfolgreich als Timesketch-kompatible CSV-Datei nach '%s' exportiert.\n", exported_count, filename);
|
||||
}
|
||||
|
||||
struct ip_stat {
|
||||
@ -2150,7 +2154,7 @@ void menu_show_entries() {
|
||||
supress_preview = 1;
|
||||
show_filtered_entries(0);
|
||||
} else if (choice == 2) {
|
||||
export_filtered_entries();
|
||||
export_filtered_entries(0);
|
||||
} else if (choice == 3) {
|
||||
show_top_x_ips();
|
||||
} else if (choice == 4) {
|
||||
@ -2165,66 +2169,118 @@ void menu_show_entries() {
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc != 2) {
|
||||
printf("Verwendung: %s <nginx-log-datei-oder-verzeichnis>\n", argv[0]);
|
||||
printf("Unterstützte Formate: .log Dateien, sowie für rotierte Logs: .log.1 etc.\n");
|
||||
printf("Beispiele:\n");
|
||||
printf(" %s /var/log/nginx/access.log (einzelne .log Datei)\n", argv[0]);
|
||||
printf(" %s /var/log/nginx/ (Verzeichnis mit .log Dateien)\n", argv[0]);
|
||||
printf("\nRotierte nginx-Logs (.gz-Archive) müssen manuell dekomprimiert werden:\n");
|
||||
printf(" 1. Dekomprimieren: gunzip /var/log/nginx/*.gz\n");
|
||||
printf(" 2. Dann ausführen: %s /var/log/nginx/\n", argv[0]);
|
||||
return 1;
|
||||
} else if (argc == 3) {
|
||||
|
||||
}
|
||||
|
||||
void print_help(char* binary) {
|
||||
printf("\nNGINX EXAMINATOR\n");
|
||||
|
||||
allocate_initial_memory();
|
||||
load_log_file(argv[1]);
|
||||
|
||||
if (total_entries == 0) {
|
||||
printf("Keine gültigen Log-Einträge gefunden. Überprüfen Sie den Pfad und die Dateiformate.\n");
|
||||
cleanup_memory();
|
||||
printf("Verwendung:\n");
|
||||
printf(" %s <LOGDATEI|VERZEICHNIS> -i Interaktiver Modus (Filter/Analyse/Export)\n", binary);
|
||||
printf(" %s <LOGDATEI|VERZEICHNIS> -e <DATEINAME(optional)> Export generieren\n", binary);
|
||||
printf(" %s -h Diese Hilfe anzeigen\n", binary);
|
||||
|
||||
printf("\nArgumente:\n");
|
||||
printf(" <LOGDATEI|VERZEICHNIS> Pfad zu einer einzelnen *.log Datei ODER zu einem Ordner,\n");
|
||||
printf(" der eine oder mehrere *.log / *.log.N Dateien enthält.\n");
|
||||
|
||||
printf("\nFlags:\n");
|
||||
printf(" -i Startet interaktiven Modus mit Filtern (Status, Methode, IP, Zeitraum,\n");
|
||||
printf(" User-Agent, URL-Teilstring), Vorschau, Statistiken und CSV-Export (Timesketch).\n");
|
||||
printf(" -e Generiert Timesketch-kompatible CSV-Datei, nimmt optional Dateinamen entgegen.\n");
|
||||
printf(" -h Zeigt diese Hilfe an.\n");
|
||||
|
||||
printf("\nUnterstützte Eingaben:\n");
|
||||
printf(" - Normale NGINX-Access-Logs: *.log\n");
|
||||
printf(" - Rotierte Logs: *.log.1, *.log.2, ... (rein textbasiert)\n");
|
||||
printf(" - GZIP-Archive (*.gz) werden NICHT direkt unterstützt.\n");
|
||||
printf(" Tipp: Dekomprimieren Sie vorher, z.B.:\n");
|
||||
printf(" gunzip /var/log/nginx/*.gz\n");
|
||||
printf(" %s /var/log/nginx/ -i\n", binary);
|
||||
|
||||
printf("\nErwartetes NGINX-Logformat (default `log_format main`):\n");
|
||||
printf(" log_format main '$remote_addr - $remote_user [$time_local] \"$request\" '\n");
|
||||
printf(" '$status $body_bytes_sent \"$http_referer\" '\n");
|
||||
printf(" '\"$http_user_agent\" \"$http_x_forwarded_for\"';\n");
|
||||
|
||||
printf("\nBeispielzeile (eine Zeile pro Request):\n");
|
||||
printf(" 0.0.0.0 - - [31/Aug/2025:00:11:42 +0000] \"GET /.git/config HTTP/1.1\" 400 255 \"-\" \"Mozilla/5.0\" \"-\"\n");
|
||||
|
||||
printf("\nBeispiele:\n");
|
||||
printf(" - Einzeldatei analysieren:\n");
|
||||
printf(" %s /var/log/nginx/access.log -i\n", binary);
|
||||
printf(" - Verzeichnis mit mehreren .log / .log.N Dateien:\n");
|
||||
printf(" %s /var/log/nginx/ -i\n", binary);
|
||||
|
||||
printf("\nCSV-Export (Timesketch-kompatibel):\n");
|
||||
printf(" Spalten: datetime, timestamp_desc, ip_address, method, url_path, status_code,\n");
|
||||
printf(" bytes_sent, user_agent, source_file, parsing_timestamp\n");
|
||||
|
||||
printf("\nHinweise & Einschränkungen:\n");
|
||||
printf(" - Parser erwartet das obige Standardformat. Abweichungen können zum Abbruch führen.\n");
|
||||
printf(" - Zeitzone aus dem Log wird gelesen, aber intern als einfache Felder verarbeitet.\n");
|
||||
printf(" - ATYPICAL-Methode: für fehlerhafte/binäre Requests innerhalb der \"request\"-Spalte.\n");
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
if (argc <= 3) {
|
||||
print_help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int choice = 0;
|
||||
int stats_show = 0;
|
||||
while (choice != 4 && choice != -4) {
|
||||
show_status();
|
||||
if (stats_show == 1) {
|
||||
show_stats();
|
||||
int stats_show = 0;
|
||||
|
||||
printf("\nNGINX EXAMINATOR\n");
|
||||
|
||||
allocate_initial_memory();
|
||||
|
||||
if (strcmp(argv[2], "-i") == 0) {
|
||||
load_log_file(argv[1]);
|
||||
|
||||
if (total_entries == 0) {
|
||||
printf("Keine gültigen Log-Einträge gefunden. Überprüfen Sie den Pfad und die Dateiformate.\n");
|
||||
cleanup_memory();
|
||||
return 1;
|
||||
}
|
||||
show_main_menu();
|
||||
|
||||
choice = read_menu_input();
|
||||
choice = handle_menu_shortcuts(choice);
|
||||
|
||||
if (choice == -1) {
|
||||
printf("FEHLER: Bitte geben Sie eine gültige Zahl oder Navigation ein (1-4, b, m, q)!\n");
|
||||
continue;
|
||||
int choice = 0;
|
||||
int stats_show = 0;
|
||||
while (choice != 4 && choice != -4) {
|
||||
show_status();
|
||||
if (stats_show == 1) {
|
||||
show_stats();
|
||||
stats_show = 0;
|
||||
}
|
||||
show_main_menu();
|
||||
|
||||
choice = read_menu_input();
|
||||
choice = handle_menu_shortcuts(choice);
|
||||
|
||||
if (choice == -1) {
|
||||
printf("FEHLER: Bitte geben Sie eine gültige Zahl oder Navigation ein (1-4, b, m, q)!\n");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (choice == 1) {
|
||||
menu_filter_management();
|
||||
} else if (choice == 2) {
|
||||
menu_show_entries();
|
||||
} else if (choice == 3) {
|
||||
stats_show = 1;
|
||||
} else if (choice == 4) {
|
||||
printf("Programmende\n");
|
||||
break;
|
||||
} else if (choice == -4) {
|
||||
break;
|
||||
} else {
|
||||
printf("FEHLER: Ungültige Auswahl! Bitte wählen Sie 1-4 oder b/m/q.\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (choice == 1) {
|
||||
menu_filter_management();
|
||||
} else if (choice == 2) {
|
||||
menu_show_entries();
|
||||
} else if (choice == 3) {
|
||||
stats_show =1;
|
||||
} else if (choice == 4) {
|
||||
printf("Programmende\n");
|
||||
break;
|
||||
} else if (choice == -4) {
|
||||
break;
|
||||
} else if (strcmp(argv[2], "-e") == 0){
|
||||
load_log_file(argv[1]);
|
||||
if (argc == 4) {
|
||||
export_filtered_entries(argv[3]);
|
||||
} else {
|
||||
printf("FEHLER: Ungültige Auswahl! Bitte wählen Sie 1-4 oder b/m/q.\n");
|
||||
export_filtered_entries(NULL);
|
||||
}
|
||||
} else if (strcmp(argv[2], "-h") == 0){
|
||||
print_help(argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
cleanup_memory();
|
||||
return 0;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user