ascii-chat 0.8.38
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
common.c File Reference

Common utilities and helpers for option parsing. More...

Go to the source code of this file.

Data Structures

struct  mode_metadata_t
 Mode metadata for usage display. More...
 

Functions

const char * find_similar_option (const char *unknown_opt, const struct option *options)
 
const char * format_available_modes (option_mode_bitmask_t mode_bitmask)
 
const char * find_similar_option_with_mode (const char *unknown_opt, const options_config_t *config, option_mode_bitmask_t current_mode_bitmask)
 
int strtoint_safe (const char *str)
 
char * get_required_argument (const char *opt_value, char *buffer, size_t buffer_size, const char *option_name, asciichat_mode_t mode)
 
char * validate_required_argument (const char *optarg, char *argbuf, size_t argbuf_size, const char *option_name, asciichat_mode_t mode)
 
bool validate_positive_int_opt (const char *value_str, int *out_value, const char *param_name)
 
bool validate_port_opt (const char *value_str, uint16_t *out_port)
 
bool validate_fps_opt (const char *value_str, int *out_fps)
 
bool validate_webcam_index (const char *value_str, unsigned short int *out_index)
 
asciichat_error_t detect_default_ssh_key (char *key_path, size_t path_size)
 
char * strip_equals_prefix (const char *opt_value, char *buffer, size_t buffer_size)
 
char * read_password_from_stdin (const char *prompt)
 
asciichat_error_t parse_color_mode_option (const char *value_str, options_t *opts)
 
asciichat_error_t parse_render_mode_option (const char *value_str, options_t *opts)
 
asciichat_error_t parse_palette_option (const char *value_str, options_t *opts)
 
asciichat_error_t parse_palette_chars_option (const char *value_str, options_t *opts)
 
asciichat_error_t parse_width_option (const char *value_str, options_t *opts)
 
asciichat_error_t parse_height_option (const char *value_str, options_t *opts)
 
asciichat_error_t parse_webcam_index_option (const char *value_str, options_t *opts)
 
asciichat_error_t parse_snapshot_delay_option (const char *value_str, options_t *opts)
 
asciichat_error_t parse_log_level_option (const char *value_str, options_t *opts)
 
const char * options_get_type_placeholder (option_type_t type)
 
int options_format_default_value (option_type_t type, const void *default_value, char *buf, size_t bufsize)
 
void update_dimensions_for_full_height (options_t *opts)
 
void update_dimensions_to_terminal_size (options_t *opts)
 
void usage (FILE *desc, asciichat_mode_t mode)
 
asciichat_error_t validate_options_and_report (const void *config, const void *opts)
 
void print_project_links (FILE *desc)
 

Variables

ASCIICHAT_API bool auto_width = true
 
ASCIICHAT_API bool auto_height = true
 
bool port_explicitly_set_via_flag = false
 
const float weight_red = 0.2989f
 
const float weight_green = 0.5866f
 
const float weight_blue = 0.1145f
 
unsigned short int RED [256]
 
unsigned short int GREEN [256]
 
unsigned short int BLUE [256]
 
unsigned short int GRAY [256]
 

Detailed Description

Common utilities and helpers for option parsing.

Shared helper functions, validators, and global variables used by all option parsing modules (client.c, server.c, mirror.c).

Definition in file options/common.c.

Function Documentation

◆ detect_default_ssh_key()

asciichat_error_t detect_default_ssh_key ( char *  key_path,
size_t  path_size 
)

Definition at line 262 of file options/common.c.

262 {
263 // Use expand_path utility to resolve ~/.ssh/id_ed25519
264 char *full_path = expand_path("~/.ssh/id_ed25519");
265 if (!full_path) {
266 return SET_ERRNO(ERROR_CONFIG, "Could not expand SSH key path");
267 }
268
269 // Check if the Ed25519 private key file exists
270 struct stat st;
271 bool found = (stat(full_path, &st) == 0 && S_ISREG(st.st_mode));
272
273 if (found) {
274 SAFE_SNPRINTF(key_path, path_size, "%s", full_path);
275 log_debug("Found default SSH key: %s", full_path);
276 SAFE_FREE(full_path);
277 return ASCIICHAT_OK;
278 }
279
280 log_error("No Ed25519 SSH key found at %s", full_path);
281 SAFE_FREE(full_path);
282 return SET_ERRNO(
283 ERROR_CRYPTO_KEY,
284 "Only Ed25519 keys are supported (modern, secure, fast). Generate a new key with: ssh-keygen -t ed25519");
285}
char * expand_path(const char *path)
Definition path.c:471

References expand_path().

◆ find_similar_option()

const char * find_similar_option ( const char *  unknown_opt,
const struct option *  options 
)

Definition at line 38 of file options/common.c.

38 {
39 if (!unknown_opt || !options) {
40 return NULL;
41 }
42
43 const char *best_match = NULL;
44 size_t best_distance = SIZE_MAX;
45
46 for (int i = 0; options[i].name != NULL; i++) {
47 size_t dist = levenshtein(unknown_opt, options[i].name);
48 if (dist < best_distance) {
49 best_distance = dist;
50 best_match = options[i].name;
51 }
52 }
53
54 // Only suggest if the distance is within our threshold
55 if (best_distance <= LEVENSHTEIN_SUGGESTION_THRESHOLD) {
56 return best_match;
57 }
58
59 return NULL;
60}
size_t levenshtein(const char *a, const char *b)
Definition levenshtein.c:74

References levenshtein().

◆ find_similar_option_with_mode()

const char * find_similar_option_with_mode ( const char *  unknown_opt,
const options_config_t *  config,
option_mode_bitmask_t  current_mode_bitmask 
)

Definition at line 108 of file options/common.c.

109 {
110 if (!unknown_opt || !config) {
111 return NULL;
112 }
113
114 // Extract the option name without dashes
115 const char *opt_name = unknown_opt;
116 if (strncmp(opt_name, "--", 2) == 0) {
117 opt_name += 2;
118 } else if (strncmp(opt_name, "-", 1) == 0) {
119 opt_name += 1;
120 } else {
121 return NULL; // Not an option format
122 }
123
124 const option_descriptor_t *best_match = NULL;
125 size_t best_distance = SIZE_MAX;
126
127 // Search through all descriptors
128 for (size_t i = 0; i < config->num_descriptors; i++) {
129 const option_descriptor_t *desc = &config->descriptors[i];
130 if (!desc->long_name)
131 continue;
132
133 // Calculate distance to the long name
134 size_t dist = levenshtein(opt_name, desc->long_name);
135 if (dist < best_distance) {
136 best_distance = dist;
137 best_match = desc;
138 }
139 }
140
141 // Only suggest if the distance is within our threshold
142 if (best_distance > LEVENSHTEIN_SUGGESTION_THRESHOLD || !best_match) {
143 return NULL;
144 }
145
146 // Check if the option is not available in current mode
147 bool available_in_current_mode = (best_match->mode_bitmask & current_mode_bitmask) != 0;
148
149 static char suggestion[256];
150 if (available_in_current_mode) {
151 // Option exists but user typed it wrong - just suggest the correct spelling
152 safe_snprintf(suggestion, sizeof(suggestion), "Did you mean '--%s'?", best_match->long_name);
153 } else {
154 // Option exists but in a different mode - show all available modes
155 const char *modes_str = format_available_modes(best_match->mode_bitmask);
156 safe_snprintf(suggestion, sizeof(suggestion), "Did you mean '--%s' (available in modes: %s)?",
157 best_match->long_name, modes_str);
158 }
159
160 return suggestion;
161}
const char * format_available_modes(option_mode_bitmask_t mode_bitmask)
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Safe formatted string printing to buffer.
Definition system.c:456

References format_available_modes(), levenshtein(), and safe_snprintf().

◆ format_available_modes()

const char * format_available_modes ( option_mode_bitmask_t  mode_bitmask)

Definition at line 64 of file options/common.c.

64 {
65 static char buffer[256];
66 buffer[0] = '\0';
67
68 bool first = true;
69
70 // Check if it's a global/binary option
71 if (mode_bitmask & OPTION_MODE_BINARY) {
72 SAFE_SNPRINTF(buffer, sizeof(buffer), "global options");
73 return buffer;
74 }
75
76 // Build comma-separated list of modes (ordered: default, client, server, mirror, discovery-service)
77 if (mode_bitmask & OPTION_MODE_DISCOVERY) {
78 safe_snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%sdefault", first ? "" : ", ");
79 first = false;
80 }
81 if (mode_bitmask & OPTION_MODE_CLIENT) {
82 safe_snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%sclient", first ? "" : ", ");
83 first = false;
84 }
85 if (mode_bitmask & OPTION_MODE_SERVER) {
86 safe_snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%sserver", first ? "" : ", ");
87 first = false;
88 }
89 if (mode_bitmask & OPTION_MODE_MIRROR) {
90 safe_snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%smirror", first ? "" : ", ");
91 first = false;
92 }
93 if (mode_bitmask & OPTION_MODE_DISCOVERY_SVC) {
94 safe_snprintf(buffer + strlen(buffer), sizeof(buffer) - strlen(buffer), "%sdiscovery-service", first ? "" : ", ");
95 first = false;
96 }
97
98 // Fallback if no modes matched
99 if (buffer[0] == '\0') {
100 SAFE_SNPRINTF(buffer, sizeof(buffer), "unknown mode");
101 }
102
103 return buffer;
104}

References safe_snprintf().

Referenced by find_similar_option_with_mode().

◆ get_required_argument()

char * get_required_argument ( const char *  opt_value,
char *  buffer,
size_t  buffer_size,
const char *  option_name,
asciichat_mode_t  mode 
)

Definition at line 312 of file options/common.c.

313 {
314 // Check if opt_value is NULL or empty
315 if (!opt_value || strlen(opt_value) == 0) {
316 goto error;
317 }
318
319 // Check if getopt_long returned the option name itself as the argument
320 // This happens when a long option requiring an argument is at the end of argv
321 if (opt_value && option_name && strcmp(opt_value, option_name) == 0) {
322 goto error;
323 }
324
325 // Process the argument normally
326 char *value_str = strip_equals_prefix(opt_value, buffer, buffer_size);
327 if (!value_str) {
328 goto error;
329 }
330
331 return value_str;
332
333error:
334 (void)0;
335 const char *mode_name = (mode == MODE_SERVER ? "server" : (mode == MODE_MIRROR ? "mirror" : "client"));
336 log_error("%s: option '--%s' requires an argument", mode_name, option_name);
337 return NULL; // Signal error to caller
338}
int buffer_size
Size of circular buffer.
Definition grep.c:84
char * strip_equals_prefix(const char *opt_value, char *buffer, size_t buffer_size)

References buffer_size, and strip_equals_prefix().

Referenced by validate_required_argument().

◆ options_format_default_value()

int options_format_default_value ( option_type_t  type,
const void *  default_value,
char *  buf,
size_t  bufsize 
)

Definition at line 576 of file options/common.c.

576 {
577 if (!default_value || !buf || bufsize == 0) {
578 return 0;
579 }
580
581 switch (type) {
582 case OPTION_TYPE_BOOL:
583 return safe_snprintf(buf, bufsize, "%s", *(const bool *)default_value ? "true" : "false");
584 case OPTION_TYPE_INT: {
585 int int_val = 0;
586 memcpy(&int_val, default_value, sizeof(int));
587 return safe_snprintf(buf, bufsize, "%d", int_val);
588 }
589 case OPTION_TYPE_STRING:
590 return safe_snprintf(buf, bufsize, "%s", *(const char *const *)default_value);
591 case OPTION_TYPE_DOUBLE: {
592 double double_val = 0.0;
593 memcpy(&double_val, default_value, sizeof(double));
594 return safe_snprintf(buf, bufsize, "%.2f", double_val);
595 }
596 default:
597 // OPTION_TYPE_CALLBACK and OPTION_TYPE_ACTION don't have defaults to display
598 return 0;
599 }
600}

References safe_snprintf().

Referenced by format_option_default_value_str(), and manpage_content_generate_options().

◆ options_get_type_placeholder()

const char * options_get_type_placeholder ( option_type_t  type)

Definition at line 558 of file options/common.c.

558 {
559 switch (type) {
560 case OPTION_TYPE_INT:
561 return "INTEGER";
562 case OPTION_TYPE_DOUBLE:
563 return "NUMBER";
564 case OPTION_TYPE_STRING:
565 return "STRING";
566 case OPTION_TYPE_CALLBACK:
567 return "VALUE";
568 case OPTION_TYPE_BOOL:
569 return "[BOOLEAN]";
570 case OPTION_TYPE_ACTION:
571 default:
572 return "";
573 }
574}

Referenced by get_option_help_placeholder_str(), and manpage_content_generate_options().

◆ parse_color_mode_option()

asciichat_error_t parse_color_mode_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 385 of file options/common.c.

385 {
386 if (!value_str || !opts) {
387 return ERROR_INVALID_PARAM;
388 }
389
390 if (strcmp(value_str, "auto") == 0 || strcmp(value_str, "a") == 0) {
391 opts->color_mode = COLOR_MODE_AUTO;
392 } else if (strcmp(value_str, "none") == 0 || strcmp(value_str, "mono") == 0) {
393 opts->color_mode = COLOR_MODE_NONE;
394 } else if (strcmp(value_str, "16") == 0 || strcmp(value_str, "16color") == 0 || strcmp(value_str, "ansi") == 0) {
395 opts->color_mode = COLOR_MODE_16_COLOR;
396 } else if (strcmp(value_str, "256") == 0 || strcmp(value_str, "256color") == 0) {
397 opts->color_mode = COLOR_MODE_256_COLOR;
398 } else if (strcmp(value_str, "truecolor") == 0 || strcmp(value_str, "24bit") == 0 || strcmp(value_str, "tc") == 0 ||
399 strcmp(value_str, "rgb") == 0 || strcmp(value_str, "true") == 0) {
400 opts->color_mode = COLOR_MODE_TRUECOLOR;
401 } else {
402 log_error("Invalid color mode '%s'. Valid modes: auto, none, 16, 256, truecolor", value_str);
403 return ERROR_INVALID_PARAM;
404 }
405
406 return ASCIICHAT_OK;
407}

◆ parse_height_option()

asciichat_error_t parse_height_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 488 of file options/common.c.

488 {
489 if (!opts) {
490 return ERROR_INVALID_PARAM;
491 }
492
493 int height_val;
494 if (!validate_positive_int_opt(value_str, &height_val, "height")) {
495 return ERROR_INVALID_PARAM;
496 }
497
498 opts->height = height_val;
499 opts->auto_height = false;
500
501 return ASCIICHAT_OK;
502}
bool validate_positive_int_opt(const char *value_str, int *out_value, const char *param_name)

References validate_positive_int_opt().

◆ parse_log_level_option()

asciichat_error_t parse_log_level_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 536 of file options/common.c.

536 {
537 if (!opts) {
538 return ERROR_INVALID_PARAM;
539 }
540
541 char error_msg[BUFFER_SIZE_SMALL];
542 int log_level = validate_opt_log_level(value_str, error_msg, sizeof(error_msg));
543
544 if (log_level == -1) {
545 log_error("%s", error_msg);
546 return ERROR_INVALID_PARAM;
547 }
548
549 opts->log_level = (log_level_t)log_level;
550
551 return ASCIICHAT_OK;
552}
int validate_opt_log_level(const char *value_str, char *error_msg, size_t error_msg_size)
Definition validation.c:235

References validate_opt_log_level().

◆ parse_palette_chars_option()

asciichat_error_t parse_palette_chars_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 453 of file options/common.c.

453 {
454 if (!value_str || !opts) {
455 return ERROR_INVALID_PARAM;
456 }
457
458 if (strlen(value_str) >= sizeof(opts->palette_custom)) {
459 log_error("Invalid palette-chars: too long (%zu chars, max %zu)", strlen(value_str),
460 sizeof(opts->palette_custom) - 1);
461 return ERROR_INVALID_PARAM;
462 }
463
464 SAFE_STRNCPY(opts->palette_custom, value_str, sizeof(opts->palette_custom));
465 opts->palette_custom[sizeof(opts->palette_custom) - 1] = '\0';
466 opts->palette_custom_set = true;
467 opts->palette_type = PALETTE_CUSTOM;
468
469 return ASCIICHAT_OK;
470}

◆ parse_palette_option()

asciichat_error_t parse_palette_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 428 of file options/common.c.

428 {
429 if (!value_str || !opts) {
430 return ERROR_INVALID_PARAM;
431 }
432
433 if (strcmp(value_str, "standard") == 0) {
434 opts->palette_type = PALETTE_STANDARD;
435 } else if (strcmp(value_str, "blocks") == 0) {
436 opts->palette_type = PALETTE_BLOCKS;
437 } else if (strcmp(value_str, "digital") == 0) {
438 opts->palette_type = PALETTE_DIGITAL;
439 } else if (strcmp(value_str, "minimal") == 0) {
440 opts->palette_type = PALETTE_MINIMAL;
441 } else if (strcmp(value_str, "cool") == 0) {
442 opts->palette_type = PALETTE_COOL;
443 } else if (strcmp(value_str, "custom") == 0) {
444 opts->palette_type = PALETTE_CUSTOM;
445 } else {
446 log_error("Invalid palette '%s'. Valid palettes: standard, blocks, digital, minimal, cool, custom", value_str);
447 return ERROR_INVALID_PARAM;
448 }
449
450 return ASCIICHAT_OK;
451}

◆ parse_render_mode_option()

asciichat_error_t parse_render_mode_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 409 of file options/common.c.

409 {
410 if (!value_str || !opts) {
411 return ERROR_INVALID_PARAM;
412 }
413
414 if (strcmp(value_str, "foreground") == 0 || strcmp(value_str, "fg") == 0) {
415 opts->render_mode = RENDER_MODE_FOREGROUND;
416 } else if (strcmp(value_str, "background") == 0 || strcmp(value_str, "bg") == 0) {
417 opts->render_mode = RENDER_MODE_BACKGROUND;
418 } else if (strcmp(value_str, "half-block") == 0 || strcmp(value_str, "halfblock") == 0) {
419 opts->render_mode = RENDER_MODE_HALF_BLOCK;
420 } else {
421 log_error("Invalid render mode '%s'. Valid modes: foreground, background, half-block", value_str);
422 return ERROR_INVALID_PARAM;
423 }
424
425 return ASCIICHAT_OK;
426}

◆ parse_snapshot_delay_option()

asciichat_error_t parse_snapshot_delay_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 519 of file options/common.c.

519 {
520 if (!value_str || !opts) {
521 return ERROR_INVALID_PARAM;
522 }
523
524 char *endptr;
525 float delay = strtof(value_str, &endptr);
526 if (endptr == value_str || *endptr != '\0' || delay < 0.0f) {
527 log_error("Invalid snapshot delay '%s'. Must be a non-negative number.", value_str);
528 return ERROR_INVALID_PARAM;
529 }
530
531 opts->snapshot_delay = delay;
532
533 return ASCIICHAT_OK;
534}

◆ parse_webcam_index_option()

asciichat_error_t parse_webcam_index_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 504 of file options/common.c.

504 {
505 if (!opts) {
506 return ERROR_INVALID_PARAM;
507 }
508
509 unsigned short int index_val;
510 if (!validate_webcam_index(value_str, &index_val)) {
511 return ERROR_INVALID_PARAM;
512 }
513
514 opts->webcam_index = index_val;
515
516 return ASCIICHAT_OK;
517}
bool validate_webcam_index(const char *value_str, unsigned short int *out_index)

References validate_webcam_index().

◆ parse_width_option()

asciichat_error_t parse_width_option ( const char *  value_str,
options_t *  opts 
)

Definition at line 472 of file options/common.c.

472 {
473 if (!opts) {
474 return ERROR_INVALID_PARAM;
475 }
476
477 int width_val;
478 if (!validate_positive_int_opt(value_str, &width_val, "width")) {
479 return ERROR_INVALID_PARAM;
480 }
481
482 opts->width = width_val;
483 opts->auto_width = false;
484
485 return ASCIICHAT_OK;
486}

References validate_positive_int_opt().

◆ print_project_links()

void print_project_links ( FILE *  desc)

Definition at line 740 of file options/common.c.

740 {
741 if (!desc) {
742 return;
743 }
744
745 (void)fprintf(desc, "🔗 %s\n", colored_string(LOG_COLOR_GREY, "https://ascii-chat.com"));
746 (void)fprintf(desc, "🔗 %s\n", colored_string(LOG_COLOR_GREY, "https://github.com/zfogg/ascii-chat"));
747}
const char * colored_string(log_color_t color, const char *text)

References colored_string().

Referenced by options_print_help_for_mode().

◆ read_password_from_stdin()

char * read_password_from_stdin ( const char *  prompt)

Definition at line 341 of file options/common.c.

341 {
342 char *password_buf = SAFE_MALLOC(PASSWORD_MAX_LEN, char *);
343 if (!password_buf) {
344 return NULL;
345 }
346
347 if (prompt_password_simple(prompt, password_buf, PASSWORD_MAX_LEN) != 0) {
348 SAFE_FREE(password_buf);
349 return NULL;
350 }
351
352 return password_buf; // Caller must free
353}
int prompt_password_simple(const char *prompt, char *password, size_t max_len)
Definition password.c:70

References prompt_password_simple().

◆ strip_equals_prefix()

char * strip_equals_prefix ( const char *  opt_value,
char *  buffer,
size_t  buffer_size 
)

Definition at line 292 of file options/common.c.

292 {
293 if (!opt_value)
294 return NULL;
295
296 SAFE_SNPRINTF(buffer, buffer_size, "%s", opt_value);
297 char *value_str = buffer;
298 if (value_str[0] == '=') {
299 value_str++; // Skip the equals sign
300 }
301
302 // Return NULL for empty strings (treat as missing argument)
303 if (strlen(value_str) == 0) {
304 return NULL;
305 }
306
307 return value_str;
308}

References buffer_size.

Referenced by get_required_argument().

◆ strtoint_safe()

int strtoint_safe ( const char *  str)

Definition at line 164 of file options/common.c.

164 {
165 if (!str || *str == '\0') {
166 return INT_MIN; // Error: NULL or empty string
167 }
168
169 int32_t result = 0;
170 // Use safe parsing utility with full int32 range validation
171 if (parse_int32(str, &result, INT_MIN, INT_MAX) != ASCIICHAT_OK) {
172 return INT_MIN; // Error: invalid input or out of range
173 }
174
175 return (int)result;
176}
asciichat_error_t parse_int32(const char *str, int32_t *out_value, int32_t min_value, int32_t max_value)
Definition parsing.c:303

References parse_int32().

Referenced by validate_fps_opt(), validate_opt_device_index(), validate_opt_reconnect(), and validate_positive_int_opt().

◆ update_dimensions_for_full_height()

void update_dimensions_for_full_height ( options_t *  opts)

Definition at line 606 of file options/common.c.

606 {
607 if (!opts) {
608 return;
609 }
610
611 unsigned short int term_width, term_height;
612
613 // Note: Logging is not available during options_init, so we can't use log_debug here
614 asciichat_error_t result = get_terminal_size(&term_width, &term_height);
615 if (result == ASCIICHAT_OK) {
616 // If both dimensions are auto, set height to terminal height and let
617 // aspect_ratio calculate width
618 if (opts->auto_height && opts->auto_width) {
619 opts->height = term_height;
620 opts->width = term_width; // Also set width when both are auto
621 }
622 // If only height is auto, use full terminal height
623 else if (opts->auto_height) {
624 opts->height = term_height;
625 }
626 // If only width is auto, use full terminal width
627 else if (opts->auto_width) {
628 opts->width = term_width;
629 }
630 } else {
631 // Terminal size detection failed, but we can still continue with defaults
632 }
633}
asciichat_error_t get_terminal_size(unsigned short int *width, unsigned short int *height)

References get_terminal_size().

Referenced by options_init().

◆ update_dimensions_to_terminal_size()

void update_dimensions_to_terminal_size ( options_t *  opts)

Definition at line 635 of file options/common.c.

635 {
636 if (!opts) {
637 return;
638 }
639
640 unsigned short int term_width, term_height;
641 // Get current terminal size (get_terminal_size already handles ioctl first, then $COLUMNS/$LINES fallback)
642 asciichat_error_t terminal_result = get_terminal_size(&term_width, &term_height);
643 if (terminal_result == ASCIICHAT_OK) {
644 // Use INFO level so this is visible without -v flag (important for debugging dimension issues)
645 log_dev("Terminal size detected: %ux%u (auto_width=%d, auto_height=%d)", term_width, term_height, opts->auto_width,
646 opts->auto_height);
647 if (opts->auto_width) {
648 opts->width = term_width;
649 log_debug("Auto-width: set width to %u", opts->width);
650 }
651 if (opts->auto_height) {
652 opts->height = term_height;
653 log_debug("Auto-height: set height to %u", opts->height);
654 }
655 log_debug("Final dimensions: %ux%u", opts->width, opts->height);
656 } else {
657 // Terminal detection failed - keep the default values set in options_init()
658 log_warn("TERMINAL_DETECT_FAIL: Could not detect terminal size, using defaults: %ux%u", opts->width, opts->height);
659 }
660}

References get_terminal_size().

Referenced by options_init().

◆ usage()

void usage ( FILE *  desc,
asciichat_mode_t  mode 
)

Definition at line 683 of file options/common.c.

683 {
684 if (!desc) {
685 return;
686 }
687
688 // Find mode metadata
689 const mode_metadata_t *metadata = NULL;
690 for (size_t i = 0; i < sizeof(mode_info) / sizeof(mode_info[0]); i++) {
691 if (mode_info[i].mode == mode) {
692 metadata = &mode_info[i];
693 break;
694 }
695 }
696
697 if (!metadata) {
698 (void)fprintf(desc, "error: Unknown mode\n");
699 return;
700 }
701
702 // Get unified config
703 const options_config_t *config = options_preset_unified(metadata->program_name, metadata->description);
704 if (!config) {
705 (void)fprintf(desc, "Error: Failed to create options config\n");
706 return;
707 }
708
709 options_print_help_for_mode(config, mode, metadata->program_name, metadata->description, desc);
710
712}
void options_config_destroy(options_config_t *config)
Definition builder.c:601
void options_print_help_for_mode(const options_config_t *config, asciichat_mode_t mode, const char *program_name, const char *description, FILE *desc)
Print help for a specific mode or binary level.
Definition help.c:1094
options_config_t * options_preset_unified(const char *program_name, const char *description)
Build unified options config with ALL options (binary + all modes)
Definition presets.c:51
Mode metadata for usage display.
const char * program_name
Program name shown in usage.
const char * description
One-line description of mode.

References mode_metadata_t::description, options_config_destroy(), options_preset_unified(), options_print_help_for_mode(), and mode_metadata_t::program_name.

Referenced by action_help_acds(), action_help_client(), action_help_discovery(), action_help_mirror(), action_help_server(), manpage_content_generate_usage(), manpage_merger_generate_usage(), options_builder_add_usage(), options_config_calculate_max_col_width(), options_init(), and options_print_help_for_mode().

◆ validate_fps_opt()

bool validate_fps_opt ( const char *  value_str,
int *  out_fps 
)

Definition at line 224 of file options/common.c.

224 {
225 if (!value_str || !out_fps) {
226 return false;
227 }
228
229 int fps_val = strtoint_safe(value_str);
230 if (fps_val == INT_MIN || fps_val < 1 || fps_val > 144) {
231 log_error("Invalid FPS value '%s'. FPS must be between 1 and 144.", value_str);
232 return false;
233 }
234
235 *out_fps = fps_val;
236 return true;
237}
int strtoint_safe(const char *str)

References strtoint_safe().

◆ validate_options_and_report()

asciichat_error_t validate_options_and_report ( const void *  config,
const void *  opts 
)

Definition at line 718 of file options/common.c.

718 {
719 if (!config || !opts) {
720 return SET_ERRNO(ERROR_INVALID_PARAM, "Config or options is NULL");
721 }
722
723 char *error_message = NULL;
724 // Cast opaque config pointer to actual type
725 const options_config_t *config_typed = (const options_config_t *)config;
726 asciichat_error_t result = options_config_validate(config_typed, opts, &error_message);
727 if (result != ASCIICHAT_OK) {
728 if (error_message) {
729 log_error("%s", error_message);
730 free(error_message);
731 }
732 }
733 return result;
734}
asciichat_error_t options_config_validate(const options_config_t *config, const void *options_struct, char **error_message)
Definition builder.c:1775

References options_config_validate().

Referenced by options_init().

◆ validate_port_opt()

bool validate_port_opt ( const char *  value_str,
uint16_t *  out_port 
)

Definition at line 209 of file options/common.c.

209 {
210 if (!value_str || !out_port) {
211 return false;
212 }
213
214 // Use safe integer parsing with range validation
215 if (parse_port(value_str, out_port) != ASCIICHAT_OK) {
216 log_error("Invalid port value '%s'. Port must be a number between 1 and 65535.", value_str);
217 return false;
218 }
219
220 return true;
221}
asciichat_error_t parse_port(const char *str, uint16_t *out_port)
Definition parsing.c:251

References parse_port().

◆ validate_positive_int_opt()

bool validate_positive_int_opt ( const char *  value_str,
int *  out_value,
const char *  param_name 
)

Definition at line 193 of file options/common.c.

193 {
194 if (!value_str || !out_value) {
195 return false;
196 }
197
198 int val = strtoint_safe(value_str);
199 if (val == INT_MIN || val <= 0) {
200 log_error("Invalid %s value '%s'. %s must be a positive integer.", param_name, value_str, param_name);
201 return false;
202 }
203
204 *out_value = val;
205 return true;
206}

References strtoint_safe().

Referenced by parse_height_option(), and parse_width_option().

◆ validate_required_argument()

char * validate_required_argument ( const char *  optarg,
char *  argbuf,
size_t  argbuf_size,
const char *  option_name,
asciichat_mode_t  mode 
)

Definition at line 183 of file options/common.c.

184 {
185 char *value = get_required_argument(optarg, argbuf, argbuf_size, option_name, mode);
186 if (!value) {
187 (void)option_error_invalid();
188 }
189 return value;
190}
char * get_required_argument(const char *opt_value, char *buffer, size_t buffer_size, const char *option_name, asciichat_mode_t mode)

References get_required_argument().

◆ validate_webcam_index()

bool validate_webcam_index ( const char *  value_str,
unsigned short int *  out_index 
)

Definition at line 240 of file options/common.c.

240 {
241 if (!value_str || !out_index) {
242 return false;
243 }
244
245 char error_msg[BUFFER_SIZE_SMALL];
246 int parsed_index = validate_opt_device_index(value_str, error_msg, sizeof(error_msg));
247 if (parsed_index == INT_MIN) {
248 log_error("Invalid webcam index: %s", error_msg);
249 return false;
250 }
251 // Webcam index doesn't support -1 (default), must be >= 0
252 if (parsed_index < 0) {
253 log_error("Invalid webcam index '%s'. Webcam index must be a non-negative integer.", value_str);
254 return false;
255 }
256
257 *out_index = (unsigned short int)parsed_index;
258 return true;
259}
int validate_opt_device_index(const char *value_str, char *error_msg, size_t error_msg_size)
Definition validation.c:457

References validate_opt_device_index().

Referenced by parse_webcam_index_option().

Variable Documentation

◆ auto_height

ASCIICHAT_API bool auto_height = true

Definition at line 364 of file options/common.c.

Referenced by threaded_send_terminal_size_with_auto_detect().

◆ auto_width

ASCIICHAT_API bool auto_width = true

Definition at line 364 of file options/common.c.

Referenced by threaded_send_terminal_size_with_auto_detect().

◆ BLUE

unsigned short int BLUE[256]

Definition at line 378 of file options/common.c.

Referenced by precalc_rgb_palettes().

◆ GRAY

unsigned short int GRAY[256]

Definition at line 379 of file options/common.c.

Referenced by precalc_rgb_palettes().

◆ GREEN

unsigned short int GREEN[256]

Definition at line 377 of file options/common.c.

Referenced by precalc_rgb_palettes().

◆ port_explicitly_set_via_flag

bool port_explicitly_set_via_flag = false

Definition at line 367 of file options/common.c.

◆ RED

unsigned short int RED[256]

Definition at line 376 of file options/common.c.

Referenced by precalc_rgb_palettes().

◆ weight_blue

const float weight_blue = 0.1145f

Definition at line 372 of file options/common.c.

Referenced by server_main().

◆ weight_green

const float weight_green = 0.5866f

Definition at line 371 of file options/common.c.

Referenced by server_main().

◆ weight_red

const float weight_red = 0.2989f

Definition at line 370 of file options/common.c.

Referenced by server_main().