281int main(
int argc,
char *argv[]) {
286 if (argc < 1 || argv == NULL || argv[0] == NULL) {
287 fprintf(stderr,
"Error: Invalid argument vector\n");
295 for (
int i = 1; i < argc; i++) {
296 if (strcmp(argv[i],
"--color") == 0 || strcmp(argv[i],
"--color=true") == 0) {
300 }
else if (strcmp(argv[i],
"--color=false") == 0) {
304 }
else if (strncmp(argv[i],
"--color=", 8) == 0) {
315 for (
int i = 1; i < argc - 1; i++) {
316 if (strcmp(argv[i],
"--grep") == 0) {
317 const char *pattern = argv[i + 1];
318 asciichat_error_t filter_result =
grep_init(pattern);
319 if (filter_result != ASCIICHAT_OK) {
321 "ERROR: Invalid --grep pattern or invalid flags: \"%s\" - use /pattern/flags format (e.g., "
322 "\"/query/ig\" or \"/literal/F\")\n",
334 caps = apply_color_mode_override(caps);
337#if ASCII_CHAT_GIT_IS_DIRTY
338 if (strcmp(ASCII_CHAT_BUILD_TYPE,
"Release") == 0) {
339 fprintf(stderr,
"⚠️ WARNING: This Release build was compiled from a dirty git working tree!\n");
340 fprintf(stderr,
" Git commit: %s (dirty)\n", ASCII_CHAT_GIT_COMMIT_HASH);
341 fprintf(stderr,
" Build date: %s\n", ASCII_CHAT_BUILD_DATE);
342 fprintf(stderr,
" For reproducible builds, commit or stash changes before building.\n\n");
351 const char *colorscheme_name =
"pastel";
352 for (
int i = 1; i < argc - 1; i++) {
353 if (strcmp(argv[i],
"--color-scheme") == 0) {
354 colorscheme_name = argv[i + 1];
360 color_scheme_t scheme;
375 int mode_position = -1;
376 for (
int i = 1; i < argc; i++) {
377 if (argv[i][0] !=
'-') {
385 const char *arg = argv[i];
386 const char *opt_name = arg;
388 opt_name = arg + (arg[1] ==
'-' ? 2 : 1);
392 if (strchr(opt_name,
'=')) {
397 if (strcmp(arg,
"--log-file") == 0 || strcmp(arg,
"-L") == 0 || strcmp(arg,
"--log-level") == 0 ||
398 strcmp(arg,
"--config") == 0 || strcmp(arg,
"--color-scheme") == 0 || strcmp(arg,
"--log-template") == 0) {
407 bool is_client_like_mode =
false;
408 if (mode_position > 0) {
409 const char *first_arg = argv[mode_position];
410 if (strcmp(first_arg,
"client") == 0 || strcmp(first_arg,
"mirror") == 0 || strcmp(first_arg,
"discovery") == 0) {
411 is_client_like_mode =
true;
417 const char *log_file =
"ascii-chat.log";
418 int max_search = (mode_position > 0) ? mode_position : argc;
419 for (
int i = 1; i < max_search - 1; i++) {
420 if ((strcmp(argv[i],
"--log-file") == 0 || strcmp(argv[i],
"-L") == 0)) {
421 log_file = argv[i + 1];
429 bool early_json_format =
false;
430 if (mode_position > 0) {
431 for (
int i = 1; i < mode_position; i++) {
432 if (strcmp(argv[i],
"--json") == 0) {
433 early_json_format =
true;
439 for (
int i = 1; i < argc; i++) {
440 if (strcmp(argv[i],
"--json") == 0) {
441 early_json_format =
true;
450 const char *early_log_template = NULL;
451 bool early_log_template_console_only =
false;
452 for (
int i = 1; i < max_search - 1; i++) {
453 if (strcmp(argv[i],
"--log-template") == 0) {
454 early_log_template = argv[i + 1];
458 for (
int i = 1; i < max_search; i++) {
459 if (strcmp(argv[i],
"--log-format-console-only") == 0) {
460 early_log_template_console_only =
true;
469 const char *early_log_file = early_json_format ? NULL : log_file;
471 if (init_result != ASCIICHAT_OK) {
488 for (
int i = 1; i < argc; i++) {
489 if (strcmp(argv[i],
"--backtrace") == 0) {
490 log_info(
"=== Backtrace at startup ===");
492 log_info(
"=== End Backtrace ===");
500 asciichat_error_t options_result =
options_init(argc, argv);
501 if (options_result != ASCIICHAT_OK) {
502 asciichat_error_context_t error_ctx;
503 if (HAS_ERRNO(&error_ctx)) {
504 fprintf(stderr,
"Error: %s\n", error_ctx.context_message);
506 fprintf(stderr,
"Error: Failed to initialize options\n");
508 (void)fflush(stderr);
514 exit(options_result);
520 fprintf(stderr,
"Error: Options not initialized\n");
526 bool use_json_logging = GET_OPTION(json);
530 bool user_specified_log_file =
false;
531 for (
int i = 1; i < argc - 1; i++) {
532 if (strcmp(argv[i],
"--log-file") == 0 || strcmp(argv[i],
"-L") == 0) {
533 user_specified_log_file =
true;
538 const char *final_log_file = opts->log_file;
539 char json_filename_buf[256];
541 if (use_json_logging) {
543 if (user_specified_log_file) {
545 SAFE_STRNCPY(json_filename_buf, final_log_file,
sizeof(json_filename_buf) - 1);
549 size_t len = strlen(final_log_file);
550 if (len > 4 && strcmp(&final_log_file[len - 4],
".log") == 0) {
552 SAFE_STRNCPY(json_filename_buf, final_log_file,
sizeof(json_filename_buf) - 1);
554 strcpy(&json_filename_buf[len - 4],
".json");
557 SAFE_STRNCPY(json_filename_buf, final_log_file,
sizeof(json_filename_buf) - 1);
558 strncat(json_filename_buf,
".json",
sizeof(json_filename_buf) - strlen(json_filename_buf) - 1);
561 final_log_file = json_filename_buf;
564 log_init(NULL, GET_OPTION(log_level),
false,
false);
567 log_init(final_log_file, GET_OPTION(log_level),
false,
false);
571 const char *final_format = early_log_template ? early_log_template : GET_OPTION(log_template);
572 bool final_format_console_only =
573 early_log_template ? early_log_template_console_only : GET_OPTION(log_format_console_only);
574 if (final_format && final_format[0] !=
'\0') {
575 asciichat_error_t fmt_result =
log_set_format(final_format, final_format_console_only);
576 if (fmt_result != ASCIICHAT_OK) {
577 log_error(
"Failed to apply custom log format");
582 if (use_json_logging) {
584 int json_fd =
platform_open(final_log_file, O_CREAT | O_RDWR | O_TRUNC, FILE_PERM_PRIVATE);
589 SET_ERRNO(ERROR_CONFIG,
"Failed to open JSON output file: %s", final_log_file);
601 if (GET_OPTION(quiet) ||
607 const char *custom_chars = opts && opts->palette_custom_set ? opts->palette_custom : NULL;
609 FATAL(ERROR_CONFIG,
"Failed to apply palette configuration");
613#if defined(DEBUG_MEMORY) && !defined(USE_MIMALLOC_DEBUG) && !defined(NDEBUG)
614 debug_memory_set_quiet_mode(GET_OPTION(quiet));
623 print_usage(opts->detected_mode);
641 log_dev(
"Logging initialized to %s", final_log_file);
651 log_debug(
"Initializing lock debug system...");
653 if (lock_debug_result != 0) {
654 LOG_ERRNO_IF_SET(
"Lock debug system initialization failed");
655 FATAL(ERROR_PLATFORM_INIT,
"Lock debug system initialization failed");
657 log_debug(
"Lock debug system initialized successfully");
661 LOG_ERRNO_IF_SET(
"Lock debug thread startup failed");
662 FATAL(ERROR_THREAD,
"Lock debug thread startup failed");
664 log_debug(
"Lock debug thread started");
668 platform_signal(SIGUSR1, common_handle_sigusr1);
673 if (opts->fps < 1 || opts->fps > 144) {
674 log_warn(
"FPS value %d out of range (1-144), using default", opts->fps);
676 log_debug(
"FPS set from command line: %d", opts->fps);
681 if (!GET_OPTION(no_check_update)) {
682 update_check_result_t update_result;
684 if (update_err == ASCIICHAT_OK && update_result.update_available) {
685 char notification[1024];
687 log_info(
"%s", notification);
701 platform_signal(SIGUSR1, common_handle_sigusr1);
708 fprintf(stderr,
"Error: Mode not found for detected_mode=%d\n", opts->detected_mode);
716 if (exit_code == ERROR_USAGE) {
int client_main(void)
Client mode entry point for unified binary.
ascii-chat Client Mode Entry Point Header
ascii-chat Discovery Mode Entry Point Header
int main(int argc, char *argv[])
ascii-chat Mirror Mode Interface
int server_main(void)
Server mode entry point for unified binary.
ascii-chat Server Mode Entry Point Header