ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
Platform

Data Structures

struct  static_mutex_t
 Static mutex structure for global mutexes requiring static initialization. More...
struct  static_rwlock_t
 Statically initialized mutex wrapper for globals touched during startup. The embedded mutex carries the platform lock and initialized records whether runtime setup has completed; callers use normal mutex operations after initialization. More...
struct  static_cond_t
 Static condition variable structure for global condition variables requiring static initialization. More...
struct  keyboard_line_edit_opts_t
 Options for interactive line editing. More...
struct  platform_mmap
 For platform mmap, this is the live record that ties addr, size, fd together. The owning code creates it, updates it while work is active, and releases its handles and pointed-to storage before freeing the record. More...
struct  platform_process_stats_t
struct  rwlock_t
 Read-write lock type (POSIX: pthread_rwlock_t with debug tracking). More...
struct  platform_signal_handler_t
 Signal handler descriptor for bulk registration. More...
struct  platform_stderr_redirect_handle_t
 Handle for temporary stderr redirection. More...
struct  platform_binary_match_t
 Find which binary(ies) contain a given address. More...

Macros

#define STATIC_MUTEX_INIT   {.mutex.impl = PTHREAD_MUTEX_INITIALIZER, .mutex.name = NULL, .initialized = 1}
#define STATIC_RWLOCK_INIT   {.lock.impl = PTHREAD_RWLOCK_INITIALIZER, .lock.name = NULL, .initialized = 1}
#define STATIC_COND_INIT   {.cond.impl = PTHREAD_COND_INITIALIZER, .cond.name = NULL, .initialized = 1}
#define ASCIICHAT_API   __attribute__((visibility("default")))
 Export symbols on Unix platforms (Linux, macOS).
#define platform_alloca(size)
 Platform-specific stack allocation (POSIX).
#define ntohll(x)
#define INVALID_PIPE_VALUE   (-1)
 Invalid pipe value (POSIX: -1).
#define LOG_RWLOCK_STATE(rwlock)
#define SAFE_IGNORE_PRINTF_RESULT(expr)
#define EINVAL   22
#define ERANGE   34
#define ETIMEDOUT   110
#define EINTR   4
#define EBADF   9
#define EAGAIN   11
#define EWOULDBLOCK   11
#define EPIPE   32
#define ECONNREFUSED   111
#define ENETUNREACH   101
#define EHOSTUNREACH   113
#define ECONNRESET   104
#define ENOTSOCK   88

Typedefs

typedef struct platform_mmap platform_mmap_t
 For platform mmap, this is the live record that ties addr, size, fd together. The owning code creates it, updates it while work is active, and releases its handles and pointed-to storage before freeing the record.
typedef int pipe_t
 Pipe handle type (POSIX: int file descriptor).
typedef struct platform_process platform_process_t
 Opaque process handle.
typedef void(* platform_crash_handler_t) (int signal, void *context)
 Callback function type for crash handlers.
typedef void(* signal_handler_t) (int)

Enumerations

enum  keyboard_key_t {
  KEY_NONE = 0 , KEY_ESCAPE = 27 , KEY_SPACE = 32 , KEY_UP = 0x110000 ,
  KEY_DOWN = 0x110001 , KEY_LEFT = 0x110002 , KEY_RIGHT = 0x110003 , KEY_DELETE = 0x110004 ,
  KEY_HOME = 0x110005 , KEY_END = 0x110006 , KEY_CTRL_DELETE = 0x110007 , KEY_PASTE_BEGIN = 0x110008 ,
  KEY_PASTE_END = 0x110009 , KEY_PASTE = 0x11000a , KEY_MEDIA_SUBMIT = 0x11000b , KEY_F12 = 0x11000c ,
  KEY_PAGEUP = 0x11000d , KEY_PAGEDOWN = 0x11000e , KEY_SHIFT_ENTER = 0x11000f , KEY_SHIFT_ESCAPE = 0x110010 ,
  KEY_MINUS = '-' , KEY_0 = '0' , KEY_1 = '1' , KEY_2 = '2' ,
  KEY_3 = '3' , KEY_C = 'c' , KEY_R = 'r' , KEY_M = 'm' ,
  KEY_F = 'f' , KEY_QUESTION = '?' , KEY_BACKTICK = '`'
}
 Options for interactive line editing. More...
enum  keyboard_line_edit_result_t { LINE_EDIT_CONTINUE , LINE_EDIT_ACCEPTED , LINE_EDIT_CANCELLED , LINE_EDIT_NO_INPUT }
 Result codes for interactive line editing. More...

Functions

int platform_backtrace (void **buffer, int size)
 Get a backtrace of the current call stack.
char ** platform_backtrace_symbols (void *const *buffer, int size, const char *const *owned_dirs)
 Convert backtrace addresses to symbol names.
void platform_backtrace_symbols_destroy (char **strings)
 Free symbol array from platform_backtrace_symbols().
void backtrace_print_simple (int skip_frames)
 Print backtrace of the current call stack.
void platform_clear_error_state (void)
asciichat_error_t keyboard_init (void)
 Initialize keyboard input system.
void keyboard_destroy (void)
 Cleanup keyboard input system and restore terminal.
keyboard_key_t keyboard_read_nonblocking (void)
 Read next keyboard input without blocking.
bool keyboard_input_available (void)
keyboard_key_t keyboard_read_with_timeout (uint32_t timeout_ms)
 Read keyboard input with timeout.
keyboard_line_edit_result_t keyboard_read_line_interactive (keyboard_line_edit_opts_t *opts)
 Process one keystroke for interactive line editing.
keyboard_line_edit_result_t keyboard_apply_key (keyboard_line_edit_opts_t *opts)
void platform_mmap_init (platform_mmap_t *mapping)
 Initialize a platform_mmap_t structure.
asciichat_error_t platform_mmap_open (const char *name, const char *path, size_t size, platform_mmap_t *out)
 Memory-map a file for read/write access.
void platform_mmap_close (platform_mmap_t *mapping)
 Unmap and close a memory-mapped file.
void platform_mmap_sync (platform_mmap_t *mapping, bool async)
 Flush memory-mapped changes to disk.
bool platform_mmap_is_valid (const platform_mmap_t *mapping)
 Check if a mapping is currently valid.
pipe_t platform_pipe_connect (const char *path)
 Connect to an agent via named pipe (Windows) or Unix socket (POSIX).
int platform_pipe_close (pipe_t pipe)
 Close a pipe connection.
ssize_t platform_pipe_read (pipe_t pipe, void *buf, size_t len)
 Read data from a pipe.
ssize_t platform_pipe_write (pipe_t pipe, const void *buf, size_t len)
 Write data to a pipe.
bool platform_pipe_is_valid (pipe_t pipe)
 Check if a pipe handle is valid.
asciichat_error_t platform_process_stats (platform_process_stats_t *out)
asciichat_error_t process_utf8_arguments (int *argc, char ***argv)
pid_t platform_get_pid (void)
 Get the current process ID.
asciichat_error_t platform_process_title_init (int argc, char ***argv)
 Reserve process-title storage before option parsing or environment use.
asciichat_error_t platform_process_title_set (const char *title)
 Update the OS process naming surfaces through one platform API.
asciichat_error_t platform_process_title_set_args (const char *prefix, const char *mode, int argc, char **argv, int mode_arg_index)
 Set "ascii-chat: <mode> mode - <arguments>" with secret values redacted.
void platform_process_title_destroy (void)
 Restore Unix argument storage and release title allocations.
asciichat_error_t platform_process_spawn (platform_process_t **process_out, const char *path, const char *const *argv, int stdin_fd, int stdout_fd, int stderr_fd)
 Spawn a child process.
asciichat_error_t platform_process_wait (platform_process_t *process, int timeout_ms, int *exit_code_out)
 Wait for process to terminate with timeout.
bool platform_process_is_alive (platform_process_t *process)
 Check if process is still running.
asciichat_error_t platform_process_kill (platform_process_t *process)
 Terminate a process.
void platform_process_destroy (platform_process_t *process)
 Free process handle.
 rwlock_t::_Atomic (uint64_t) last_rdlock_time_ns
 Timestamp of last read lock acquisition (nanoseconds).
 rwlock_t::_Atomic (uintptr_t) write_held_by_key
 Registry key of thread holding write lock (0 if not held).
bool debug_sync_is_initialized (void)
int debug_sync_rwlock_rdlock (rwlock_t *rwlock, const char *file_name, int line_number, const char *function_name)
int debug_sync_rwlock_wrlock (rwlock_t *rwlock, const char *file_name, int line_number, const char *function_name)
int debug_sync_rwlock_rdunlock (rwlock_t *rwlock, const char *file_name, int line_number, const char *function_name)
int debug_sync_rwlock_wrunlock (rwlock_t *rwlock, const char *file_name, int line_number, const char *function_name)
int rwlock_init (rwlock_t *lock, const char *name)
 Initialize a read-write lock with a name.
int rwlock_destroy (rwlock_t *lock)
 Destroy a read-write lock.
void rwlock_on_rdlock (rwlock_t *rwlock)
 Hook called when a read lock is successfully acquired.
void rwlock_on_wrlock (rwlock_t *rwlock)
 Hook called when a write lock is successfully acquired.
void rwlock_on_unlock (rwlock_t *rwlock)
 Hook called when an rwlock is unlocked (read or write).
void rwlock_log_state (const rwlock_t *rwlock, const char *file, int line, const char *func)
 Format and log the current state of a read-write lock.
int rwlock_init_impl (rwlock_t *lock)
 Initialize a read-write lock (implementation function).
int rwlock_destroy_impl (rwlock_t *lock)
 Destroy a read-write lock (implementation function).
int rwlock_rdlock_impl (rwlock_t *lock)
 Acquire a read lock (implementation function).
asciichat_error_t rwlock_tryrdlock (rwlock_t *lock, bool *acquired)
int rwlock_wrlock_impl (rwlock_t *lock)
 Acquire a write lock (implementation function).
int rwlock_rdunlock_impl (rwlock_t *lock)
 Release a read lock (implementation function).
int rwlock_wrunlock_impl (rwlock_t *lock)
 Release a write lock (implementation function).
asciichat_error_t platform_install_crash_handler (platform_crash_handler_t handler)
 Install a crash signal handler.
asciichat_error_t platform_uninstall_crash_handler (void)
 Uninstall the crash signal handler.
const char * platform_signal_name (int signal)
 Get human-readable name for signal number.
bool symbol_module_is_project (const char *module_name)
 Check whether a module belongs to ascii-chat.
asciichat_error_t symbol_format_source_path (const char *module_name, const char *source_path, char *output, size_t output_size, bool *external, const char *const *owned_dirs)
 Format a source path for a symbolized frame.
asciichat_error_t symbol_cache_init (void)
 Initialize the symbol cache.
void symbol_cache_destroy (void)
 Clean up the symbol cache and free all resources.
const char * symbol_cache_lookup (void *addr)
 Look up a symbol for a given address.
bool symbol_cache_insert (void *addr, const char *symbol)
 Insert a symbol into the cache.
void symbol_cache_get_stats (uint64_t *hits_out, uint64_t *misses_out, size_t *entries_out)
 Get cache statistics.
void symbol_cache_print_stats (void)
 Print cache statistics to logging system.
char ** symbol_cache_resolve_batch (void *const *buffer, int size, const char *const *owned_dirs)
 Resolve multiple addresses using addr2line and cache results.
void symbol_cache_free_symbols (char **symbols)
 Free symbol array returned by symbol_cache_resolve_batch.
asciichat_error_t platform_init (void)
 Initialize platform-specific subsystems.
void platform_destroy (void)
 Cleanup platform-specific subsystems.
void platform_force_exit (int exit_code)
 Forcefully terminate the process immediately without cleanup.
void platform_sleep_ms (unsigned int ms)
 Sleep for a specified number of milliseconds.
uint64_t platform_get_monotonic_time_us (void)
 Get monotonic time in microseconds.
asciichat_error_t platform_request_timer_precision (int precision)
 Request coarse (reduced resolution) timer precision.
asciichat_error_t platform_restore_timer_resolution (void)
 Restore default timer precision.
asciichat_error_t platform_enable_keepawake (void)
 Enable system sleep prevention (keepawake mode).
void platform_disable_keepawake (void)
 Disable system sleep prevention (allow OS to sleep).
asciichat_error_t platform_localtime (const time_t *timer, struct tm *result)
 Platform-safe localtime wrapper.
asciichat_error_t platform_gtime (const time_t *timer, struct tm *result)
 Platform-safe gmtime wrapper.
const char * platform_get_username (void)
 Get the current username.
signal_handler_t platform_signal (int sig, signal_handler_t handler)
 Set a signal handler.
asciichat_error_t platform_register_signal_handlers (const platform_signal_handler_t *handlers, int count)
 Register multiple signal handlers at once.
const char * platform_getenv (const char *name)
 Get an environment variable value.
int platform_setenv (const char *name, const char *value)
 Set an environment variable.
int platform_unsetenv (const char *name)
 Remove an environment variable.
void platform_raise_fd_limit (unsigned int limit)
 Raise the file descriptor limit for the current process.
platform_stderr_redirect_handle_t platform_stderr_redirect_to_null (void)
 Redirect stderr to /dev/null temporarily.
void platform_stderr_restore (platform_stderr_redirect_handle_t handle)
 Restore stderr from a redirect handle.
platform_stderr_redirect_handle_t platform_stdout_stderr_redirect_to_null (void)
 Redirect both stdout and stderr to /dev/null (restorable).
void platform_stdout_stderr_restore (platform_stderr_redirect_handle_t handle)
 Restore stdout and stderr after platform_stdout_stderr_redirect_to_null().
void platform_stdio_redirect_to_null_permanent (void)
 Permanently redirect stderr and stdout to /dev/null.
int safe_snprintf (char *buffer, size_t buffer_size, const char *format,...)
 Platform-safe snprintf wrapper.
int safe_fprintf (FILE *stream, const char *format,...)
 Platform-safe fprintf wrapper.
int safe_vsnprintf (char *buffer, size_t buffer_size, const char *format, va_list ap)
 Platform-safe vsnprintf wrapper.
asciichat_error_t platform_memcpy (void *dest, size_t dest_size, const void *src, size_t count)
 Platform-safe memcpy wrapper.
asciichat_error_t platform_memset (void *dest, size_t dest_size, int ch, size_t count)
 Platform-safe memset wrapper.
asciichat_error_t platform_memmove (void *dest, size_t dest_size, const void *src, size_t count)
 Platform-safe memmove wrapper.
asciichat_error_t platform_strcpy (char *dest, size_t dest_size, const char *src)
 Platform-safe strcpy wrapper.
int platform_get_last_error (void)
 Get the last system error code.
const char * platform_strerror (int errnum)
 Get human-readable error message for a system error code.
asciichat_error_t platform_resolve_hostname_to_ipv4 (const char *hostname, char *ipv4_out, size_t ipv4_out_size)
 Resolve hostname to IPv4 address.
asciichat_error_t platform_load_system_ca_certs (char **pem_data_out, size_t *pem_size_out)
 Load system CA certificates for TLS/HTTPS.
int platform_execute_subprocess (const char *executable, const char **argv, char *output_buffer, size_t output_size, bool(*cancel)(void *), void *data)
 Execute a subprocess and optionally capture its output.
size_t platform_write_all (int fd, const void *buf, size_t count)
 Write all bytes to a file descriptor, handling partial writes.
ssize_t platform_write (int fd, const void *buf, size_t count)
 Platform-safe write function.
int platform_dup (int fd)
int platform_fileno (FILE *stream)
asciichat_error_t platform_dup2 (int source_fd, int target_fd)
int get_binary_file_address_offsets (const void *addr, platform_binary_match_t *matches, int max_matches)

Variables

pthread_rwlock_t rwlock_t::impl
 Underlying POSIX rwlock.
const char * rwlock_t::name
 Human-readable name for named registry (all builds).
atomic_t rwlock_t::read_lock_count
 Number of threads holding read locks (thread-safe atomic).
int errno

Read-Write Lock Macros

#define rwlock_rdlock(lock)
 Acquire a read lock (with debug tracking in debug builds).
#define rwlock_wrlock(lock)
 Acquire a write lock (with debug tracking in debug builds).
#define rwlock_rdunlock(lock)
 Release a read lock (with debug tracking in debug builds).
#define rwlock_wrunlock(lock)
 Release a write lock (with debug tracking in debug builds).

Detailed Description

This header provides platform initialization functions and static initialization helpers for synchronization primitives that need to work before main().

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
September 2025

This header defines the ASCIICHAT_API macro used to control symbol visibility in shared libraries (DLLs on Windows, .so/.dylib on Unix).

Windows DLL Behavior:

  • When BUILDING_ASCIICHAT_DLL is defined: exports symbols from the DLL
  • When using the DLL: imports symbols from the DLL
  • Without proper export/import, each module gets its own copy of globals

Unix Behavior:

  • No special handling needed (symbols are visible by default)

Usage:

// In header file (extern declaration):
extern ASCIICHAT_API int global_variable;
extern ASCIICHAT_API void my_function(void);
// In source file (definition):
ASCIICHAT_API int global_variable = 42;
ASCIICHAT_API void my_function(void) { ... }
#define ASCIICHAT_API
Export symbols on Unix platforms (Linux, macOS).
Definition api.h:82

CRITICAL: This header must have ZERO dependencies

  • Do not include any other headers
  • Do not reference any types except built-in C types
  • This allows it to be included first in common.h to avoid circular dependencies
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
2025

Platform abstraction for capturing and symbolizing stack traces.

Platform-specific implementations:

  • POSIX (Linux/macOS): Uses libexecinfo backtrace() with fallback to manual frame walking
  • Windows: Uses CaptureStackBackTrace or StackWalk64 API
  • WASM: No-op stubs (web environment doesn't support stack traces)

Thread safety:

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
March 2026

Provides platform-independent error handling functions for:

  • Clearing error state (Windows WSA, system errno)
  • Error string retrieval
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

This header contains PRIVATE implementation helpers and macros used ONLY by the platform abstraction layer implementation files.

IMPORTANT: This header must ONLY be included within lib/platform/ files.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
September 2025

This header provides unified keyboard input operations for interactive controls during media playback and rendering. Supports both POSIX and Windows platforms with consistent key code mappings.

The interface provides:

  • Non-blocking keyboard input detection
  • Unified key code enumeration
  • Platform-specific escape sequence handling
  • Terminal raw mode setup/cleanup
  • UTF-8 character support
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

Provides unified memory allocation abstractions across Windows and POSIX platforms.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

This header provides a unified interface for memory-mapped files across platforms. Memory-mapped files allow treating file contents as memory, enabling efficient shared state and crash-safe logging.

The interface provides:

  • Memory-mapping files for read/write access
  • Automatic file creation and sizing
  • Explicit sync to flush changes to disk
  • Clean unmapping and resource cleanup

Platform implementations:

  • POSIX (Linux/macOS): mmap(), munmap(), msync()
  • Windows: CreateFileMapping(), MapViewOfFile(), FlushViewOfFile()
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
December 2025

Provides unified network header includes across Windows and POSIX platforms.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

This header provides a unified interface for agent communication (SSH agent, GPG agent) that abstracts platform-specific implementations:

  • Windows: Named pipes (HANDLE with ReadFile/WriteFile)
  • POSIX: Unix domain sockets (file descriptor with read/write)

The interface provides:

  • Pipe/agent connection management
  • Binary I/O operations (read/write)
  • Connection lifecycle management
Note
On Windows, uses named pipes (CreateFileA, ReadFile, WriteFile). On POSIX systems, uses Unix domain sockets (socket, connect, read, write).
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
October 2025

Provides platform-independent process types and execution functions for running external programs (like ssh-keygen, gpg) and capturing their output.

Windows does not provide pid_t natively, so we typedef it here.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
December 2025

This header provides a unified read-write lock interface that abstracts platform-specific implementations (Windows SRW Locks vs POSIX pthread read-write locks).

The interface provides:

  • Read-write lock initialization and destruction
  • Shared read lock acquisition (multiple readers allowed)
  • Exclusive write lock acquisition (exclusive access)
  • Lock release operations
  • Debug-enabled macros with lock tracking (in debug builds)
Note
On Windows, uses SRWLOCK for lightweight synchronization. On POSIX systems, uses pthread_rwlock_t.
In debug builds, rwlock_rdlock(), rwlock_wrlock(), rwlock_rdunlock(), and rwlock_wrunlock() macros use lock debugging if enabled. In release builds, they call the implementation directly for zero overhead.
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
September 2025

Provides unified crash handler registration across Windows and POSIX platforms. Enables capturing segmentation faults, access violations, aborts, and bus errors with consistent behavior across platforms.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

Provides unified macros for checking file types and properties across Windows and POSIX platforms. Windows requires special handling since it doesn't provide standard POSIX stat macros.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
January 2026

This header provides a high-performance symbol resolution cache system for converting backtrace addresses to human-readable symbol names. The system caches resolved symbols to avoid expensive addr2line subprocess spawns on every backtrace operation.

CORE FEATURES:

  • Cached symbol resolution using hashtable for O(1) lookups
  • Batch address resolution using addr2line subprocess
  • Automatic caching of resolved symbols for future lookups
  • Comprehensive statistics tracking (hits, misses, entries)
  • Thread-safe operations for concurrent backtrace processing
  • Memory-efficient symbol string storage

PERFORMANCE BENEFITS:

Symbol resolution without caching requires:

  • Fork/exec subprocess for each address (expensive)
  • addr2line parsing and symbol lookup (slow)
  • File I/O for debug information (disk-bound)

With caching:

  • First resolution: Same cost as uncached (cache miss)
  • Subsequent lookups: O(1) hashtable lookup (fast)
  • Batch resolution: Single subprocess for multiple addresses
  • Eliminates redundant addr2line invocations

ARCHITECTURE:

The symbol cache uses a hashtable to store resolved symbols:

  • Key: Memory address (void*)
  • Value: Symbol string (allocated, owned by cache)
  • Lookup: O(1) average case using address as key
  • Insertion: O(1) average case for new symbols

BATCH RESOLUTION:

For efficient backtrace processing:

  • Collect all addresses from backtrace
  • Check cache for each address (fast)
  • Resolve uncached addresses in single addr2line invocation
  • Cache all resolved symbols for future use

STATISTICS TRACKING:

The system tracks:

  • Cache hits: Successful lookups from cache
  • Cache misses: Addresses not in cache (required resolution)
  • Entry count: Number of cached symbols

These statistics enable performance monitoring and cache efficiency analysis.

THREAD SAFETY:

  • All cache operations are thread-safe
  • Concurrent lookups and insertions are supported
  • Statistics are updated atomically
  • Batch resolution is safe for concurrent use
Note
The symbol cache significantly improves backtrace performance by avoiding repeated addr2line subprocess spawns for the same addresses.
Cached symbol strings are owned by the cache and should not be freed by callers. The cache manages memory automatically.
addr2line must be available in PATH for batch resolution to work.
Debug symbols must be available in the executable for resolution.
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
October 2025

This header provides unified system functions including process management, environment variables, TTY operations, and signal handling.

The interface provides:

  • Platform initialization and cleanup
  • Time and sleep functions
  • Process information (PID, username)
  • Signal handling
  • Environment variable operations
  • TTY/terminal operations
  • Stack trace and crash handling
  • Safe string and memory functions
  • Network utilities (DNS resolution, CA certificates)
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
September 2025

This header provides a single point to include windows.h with proper alignment. The pragma pack ensures Windows SDK types get 8-byte alignment as expected, then immediately restores default packing so application structs are unaffected.

Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
September 2025

This header provides POSIX-style errno constant definitions for Windows compatibility. Windows headers do not define these constants by default, so this header fills the gap to enable cross-platform code.

CORE FEATURES:

  • POSIX errno constants (EINVAL, ERANGE, ETIMEDOUT, etc.)
  • Windows errno variable declaration
  • Safe redefinition guards (only defines if not already defined)
  • Header inclusion order safety (must be included before Windows headers)

WINDOWS COMPATIBILITY:

Windows uses WSA errors for socket operations, but many functions also use standard errno. This header ensures standard errno constants are available on Windows for consistent error handling.

DEFINED CONSTANTS:

This header defines the following errno constants:

  • EINVAL: Invalid argument
  • ERANGE: Result out of range
  • ETIMEDOUT: Operation timed out
  • EINTR: Interrupted system call
  • EBADF: Bad file descriptor
  • EAGAIN: Resource temporarily unavailable
  • EWOULDBLOCK: Operation would block (alias for EAGAIN on Windows)
  • EPIPE: Broken pipe
  • ECONNREFUSED: Connection refused
  • ENETUNREACH: Network unreachable
  • EHOSTUNREACH: Host unreachable
  • ECONNRESET: Connection reset by peer
  • ENOTSOCK: Socket operation on non-socket
Note
This header must be included before any Windows headers that might define or use these constants.
All constants are protected with #ifndef guards to prevent redefinition errors.
On POSIX systems, these constants are typically defined in <errno.h>, but this header can still be included safely.
Author
Zachary Fogg me@zf.nosp@m.o.gg
Date
September 2025

Macro Definition Documentation

◆ ASCIICHAT_API

#define ASCIICHAT_API   __attribute__((visibility("default")))

#include <include/ascii-chat/os/api.h>

Export symbols on Unix platforms (Linux, macOS).

Uses GCC/Clang visibility attributes to explicitly export symbols. This is needed when building with -fvisibility=hidden for better performance and smaller symbol tables.

Definition at line 82 of file api.h.

Referenced by platform_process_title_destroy(), platform_process_title_init(), platform_process_title_set(), platform_process_title_set_args(), and process_utf8_arguments().

◆ EAGAIN

◆ EBADF

#define EBADF   9

◆ ECONNREFUSED

#define ECONNREFUSED   111

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 93 of file windows_errno.h.

◆ ECONNRESET

#define ECONNRESET   104

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 105 of file windows_errno.h.

◆ EHOSTUNREACH

#define EHOSTUNREACH   113

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 101 of file windows_errno.h.

◆ EINTR

#define EINTR   4

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 73 of file windows_errno.h.

Referenced by stdout_writer_write().

◆ EINVAL

#define EINVAL   22

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 61 of file windows_errno.h.

◆ ENETUNREACH

#define ENETUNREACH   101

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 97 of file windows_errno.h.

◆ ENOTSOCK

#define ENOTSOCK   88

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 109 of file windows_errno.h.

◆ EPIPE

#define EPIPE   32

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 89 of file windows_errno.h.

◆ ERANGE

#define ERANGE   34

◆ ETIMEDOUT

◆ EWOULDBLOCK

#define EWOULDBLOCK   11

#include <include/ascii-chat/os/windows_errno.h>

Definition at line 85 of file windows_errno.h.

◆ INVALID_PIPE_VALUE

#define INVALID_PIPE_VALUE   (-1)

#include <include/ascii-chat/os/pipe.h>

Invalid pipe value (POSIX: -1).

Definition at line 42 of file pipe.h.

Referenced by ssh_agent_add_key(), ssh_agent_has_key(), ssh_agent_is_available(), and ssh_agent_sign().

◆ LOG_RWLOCK_STATE

#define LOG_RWLOCK_STATE ( rwlock)

#include <include/ascii-chat/os/rwlock.h>

Value:
rwlock_log_state(rwlock, __FILE__, __LINE__, __func__)
void rwlock_log_state(const rwlock_t *rwlock, const char *file, int line, const char *func)
Format and log the current state of a read-write lock.
rwlock_t rwlock
Read-write lock for thread-safe access (uthash requires external locking).
Definition time.c:39

Definition at line 191 of file rwlock.h.

◆ ntohll

#define ntohll ( x)

#include <include/ascii-chat/os/network.h>

Value:
htonll(x)

Definition at line 47 of file os/network.h.

◆ platform_alloca

#define platform_alloca ( size)

#include <include/ascii-chat/os/memory.h>

Value:
alloca(size)

Platform-specific stack allocation (POSIX).

On POSIX, use standard alloca

Definition at line 31 of file os/memory.h.

◆ rwlock_rdlock

#define rwlock_rdlock ( lock)

#include <include/ascii-chat/os/rwlock.h>

Value:
(debug_sync_is_initialized() ? debug_sync_rwlock_rdlock(lock, __FILE__, __LINE__, __func__) \
int rwlock_rdlock_impl(rwlock_t *lock)
Acquire a read lock (implementation function).
bool debug_sync_is_initialized(void)
int debug_sync_rwlock_rdlock(rwlock_t *rwlock, const char *file_name, int line_number, const char *function_name)

Acquire a read lock (with debug tracking in debug builds).

Parameters
lockPointer to read-write lock

Acquires a shared read lock. Multiple threads can hold read locks simultaneously. Blocks if a write lock is held.

Note
In debug builds, this macro includes lock debugging if initialized. In release builds, calls the implementation directly for zero overhead.

Definition at line 299 of file rwlock.h.

299#define rwlock_rdlock(lock) \
300 (debug_sync_is_initialized() ? debug_sync_rwlock_rdlock(lock, __FILE__, __LINE__, __func__) \
301 : rwlock_rdlock_impl(lock))

Referenced by find_client_by_id(), get_utf8_palette_cache(), named_describe(), named_get(), named_get_fd(), named_get_fd_format_spec(), named_get_format_spec(), named_get_packet_type(), named_get_packet_type_format_spec(), named_get_type(), named_print_hash_stats(), named_register(), and stats_logger_thread().

◆ rwlock_rdunlock

#define rwlock_rdunlock ( lock)

#include <include/ascii-chat/os/rwlock.h>

Value:
(debug_sync_is_initialized() ? debug_sync_rwlock_rdunlock(lock, __FILE__, __LINE__, __func__) \
int debug_sync_rwlock_rdunlock(rwlock_t *rwlock, const char *file_name, int line_number, const char *function_name)
int rwlock_rdunlock_impl(rwlock_t *lock)
Release a read lock (implementation function).

Release a read lock (with debug tracking in debug builds).

Parameters
lockPointer to read-write lock

Releases a shared read lock held by the calling thread.

Note
In debug builds, this macro includes lock debugging if initialized. In release builds, calls the implementation directly for zero overhead.

Definition at line 338 of file rwlock.h.

338#define rwlock_rdunlock(lock) \
339 (debug_sync_is_initialized() ? debug_sync_rwlock_rdunlock(lock, __FILE__, __LINE__, __func__) \
340 : rwlock_rdunlock_impl(lock))

Referenced by find_client_by_id(), get_utf8_palette_cache(), named_describe(), named_get(), named_get_fd(), named_get_fd_format_spec(), named_get_format_spec(), named_get_packet_type(), named_get_packet_type_format_spec(), named_get_type(), named_metadata_copy(), named_print_hash_stats(), named_register(), named_registry_for_each(), named_registry_read(), named_registry_try_snapshot(), and stats_logger_thread().

◆ rwlock_wrlock

#define rwlock_wrlock ( lock)

#include <include/ascii-chat/os/rwlock.h>

Value:
(debug_sync_is_initialized() ? debug_sync_rwlock_wrlock(lock, __FILE__, __LINE__, __func__) \
int debug_sync_rwlock_wrlock(rwlock_t *rwlock, const char *file_name, int line_number, const char *function_name)
int rwlock_wrlock_impl(rwlock_t *lock)
Acquire a write lock (implementation function).

Acquire a write lock (with debug tracking in debug builds).

Parameters
lockPointer to read-write lock

Acquires an exclusive write lock. Only one thread can hold a write lock, and it excludes all read locks. Blocks if any locks are held.

Note
In debug builds, this macro includes lock debugging if initialized. In release builds, calls the implementation directly for zero overhead.

Definition at line 319 of file rwlock.h.

319#define rwlock_wrlock(lock) \
320 (debug_sync_is_initialized() ? debug_sync_rwlock_wrlock(lock, __FILE__, __LINE__, __func__) \
321 : rwlock_wrlock_impl(lock))

Referenced by add_transport_client(), get_utf8_palette_cache(), mixer_add_source(), mixer_process(), mixer_process_excluding_source(), mixer_remove_source(), mixer_set_source_active(), named_destroy(), named_register(), named_register_fd(), named_register_fmt(), named_register_packet_type(), named_unregister(), named_update_name(), simd_caches_destroy_all(), timer_start(), timer_stop(), and timer_system_destroy().

◆ rwlock_wrunlock

#define rwlock_wrunlock ( lock)

#include <include/ascii-chat/os/rwlock.h>

Value:
(debug_sync_is_initialized() ? debug_sync_rwlock_wrunlock(lock, __FILE__, __LINE__, __func__) \
int debug_sync_rwlock_wrunlock(rwlock_t *rwlock, const char *file_name, int line_number, const char *function_name)
int rwlock_wrunlock_impl(rwlock_t *lock)
Release a write lock (implementation function).

Release a write lock (with debug tracking in debug builds).

Parameters
lockPointer to read-write lock

Releases an exclusive write lock held by the calling thread.

Note
In debug builds, this macro includes lock debugging if initialized. In release builds, calls the implementation directly for zero overhead.

Definition at line 357 of file rwlock.h.

357#define rwlock_wrunlock(lock) \
358 (debug_sync_is_initialized() ? debug_sync_rwlock_wrunlock(lock, __FILE__, __LINE__, __func__) \
359 : rwlock_wrunlock_impl(lock))

Referenced by add_transport_client(), get_utf8_palette_cache(), mixer_add_source(), mixer_process(), mixer_process_excluding_source(), mixer_remove_source(), mixer_set_source_active(), named_destroy(), named_register(), named_register_fd(), named_register_fmt(), named_register_packet_type(), named_unregister(), named_update_name(), simd_caches_destroy_all(), timer_start(), timer_stop(), and timer_system_destroy().

◆ SAFE_IGNORE_PRINTF_RESULT

#define SAFE_IGNORE_PRINTF_RESULT ( expr)

#include <include/ascii-chat/os/system.h>

Value:
((void)(expr))

Check return value of snprintf/fprintf and cast to void if needed

This macro satisfies clang-tidy cert-err33-c by explicitly handling the return value of printf family functions.

Definition at line 529 of file system.h.

Referenced by format_bytes_pretty(), and format_number_compact().

◆ STATIC_COND_INIT

#define STATIC_COND_INIT   {.cond.impl = PTHREAD_COND_INITIALIZER, .cond.name = NULL, .initialized = 1}

#include <include/ascii-chat/common/sync.h>

Definition at line 117 of file common/sync.h.

◆ STATIC_MUTEX_INIT

#define STATIC_MUTEX_INIT   {.mutex.impl = PTHREAD_MUTEX_INITIALIZER, .mutex.name = NULL, .initialized = 1}

#include <include/ascii-chat/common/sync.h>

Definition at line 115 of file common/sync.h.

◆ STATIC_RWLOCK_INIT

#define STATIC_RWLOCK_INIT   {.lock.impl = PTHREAD_RWLOCK_INITIALIZER, .lock.name = NULL, .initialized = 1}

#include <include/ascii-chat/common/sync.h>

Definition at line 116 of file common/sync.h.

Typedef Documentation

◆ pipe_t

typedef int pipe_t

#include <include/ascii-chat/os/pipe.h>

Pipe handle type (POSIX: int file descriptor).

Definition at line 40 of file pipe.h.

◆ platform_crash_handler_t

typedef void(* platform_crash_handler_t) (int signal, void *context)

#include <include/ascii-chat/os/signal.h>

Callback function type for crash handlers.

Called when a critical signal (segfault, abort, etc.) is caught.

Parameters
signalSignal number (SIGSEGV, SIGABRT, etc.)
contextPlatform-specific context information (can be NULL)
Note
Callback should not perform blocking operations or allocate memory
On some platforms, only limited operations are safe in this callback

Definition at line 38 of file signal.h.

◆ platform_mmap_t

#include <include/ascii-chat/os/mmap.h>

For platform mmap, this is the live record that ties addr, size, fd together. The owning code creates it, updates it while work is active, and releases its handles and pointed-to storage before freeing the record.

Memory-mapped file handle

Contains platform-specific handles and mapping information. Do not access members directly; use the platform_mmap_* functions.

◆ platform_process_t

typedef struct platform_process platform_process_t

#include <include/ascii-chat/os/process.h>

Opaque process handle.

Platform-specific process representation:

  • Windows: PROCESS_INFORMATION-based handle
  • POSIX: PID and status tracking

Definition at line 197 of file process.h.

◆ signal_handler_t

typedef void(* signal_handler_t) (int)

#include <include/ascii-chat/os/system.h>

Definition at line 56 of file system.h.

Enumeration Type Documentation

◆ keyboard_key_t

#include <include/ascii-chat/os/keyboard.h>

Options for interactive line editing.

Unified keyboard key code enumeration

Maps keyboard input to unified key codes. Arrow keys and special keys are abstracted across POSIX (escape sequences) and Windows (extended codes).

Return Value Ranges:

  • KEY_NONE (0): No key available
  • KEY_ESCAPE (27): Escape key
  • KEY_SPACE (32): Space bar
  • Text: Unicode scalar values (1 through 0x10FFFF, excluding surrogates)
  • Special keys: KEY_UP and subsequent codes start at 0x110000
Note
UTF-8 sequences are assembled before returning text keys. Text is returned as Unicode scalar values; paste payloads remain UTF-8 bytes.
Enumerator
KEY_NONE 

No key pressed or no input available.

KEY_ESCAPE 

Escape key (ESC).

KEY_SPACE 

Space bar.

KEY_UP 

Up arrow key.

KEY_DOWN 

Down arrow key.

KEY_LEFT 

Left arrow key.

KEY_RIGHT 

Right arrow key.

KEY_DELETE 

Delete key (forward delete).

KEY_HOME 

Home key (move to start of line).

KEY_END 

End key (move to end of line).

KEY_CTRL_DELETE 

Ctrl+Delete (delete word forward).

KEY_PASTE_BEGIN 
KEY_PASTE_END 
KEY_PASTE 
KEY_MEDIA_SUBMIT 

Nonblocking media prompt submitted.

KEY_F12 

Open the version update checker TUI.

KEY_PAGEUP 
KEY_PAGEDOWN 
KEY_SHIFT_ENTER 

Shift+Enter (insert a newline in multiline prompts).

KEY_SHIFT_ESCAPE 

Shift+Escape (immediate exit).

KEY_MINUS 

'-' key - toggle FPS counter

KEY_0 

'0' key - toggle sync debug screen

KEY_1 

'1' key - toggle matrix rain effect

KEY_2 

'2' key - toggle audio waveform

KEY_3 

'3' key - toggle audio frequency display

KEY_C 

'c' key - cycle color modes

KEY_R 

'r' key - cycle render modes

KEY_M 

'm' key - toggle mute

KEY_F 

'f' key - flip webcam

KEY_QUESTION 

'?' key - show help screen

KEY_BACKTICK 

'`' key - print lock state (debug builds)

Definition at line 53 of file keyboard.h.

53 {
54 KEY_NONE = 0,
55 KEY_ESCAPE = 27,
56 KEY_SPACE = 32,
57 KEY_UP = 0x110000,
58 KEY_DOWN = 0x110001,
59 KEY_LEFT = 0x110002,
60 KEY_RIGHT = 0x110003,
61 KEY_DELETE = 0x110004,
62 KEY_HOME = 0x110005,
63 KEY_END = 0x110006,
64 KEY_CTRL_DELETE = 0x110007,
65 KEY_PASTE_BEGIN = 0x110008,
66 KEY_PASTE_END = 0x110009,
67 KEY_PASTE = 0x11000a,
68 KEY_MEDIA_SUBMIT = 0x11000b,
69 KEY_F12 = 0x11000c,
70 KEY_PAGEUP = 0x11000d,
71 KEY_PAGEDOWN = 0x11000e,
72 KEY_SHIFT_ENTER = 0x11000f,
73 KEY_SHIFT_ESCAPE = 0x110010,
74 KEY_MINUS = '-',
75 KEY_0 = '0',
76 KEY_1 = '1',
77 KEY_2 = '2',
78 KEY_3 = '3',
79 KEY_C = 'c',
80 KEY_R = 'r',
81 KEY_M = 'm',
82 KEY_F = 'f',
83 KEY_QUESTION = '?',
84 KEY_BACKTICK = '`',
keyboard_key_t
Options for interactive line editing.
Definition keyboard.h:53
@ KEY_SPACE
Space bar.
Definition keyboard.h:56
@ KEY_UP
Up arrow key.
Definition keyboard.h:57
@ KEY_M
'm' key - toggle mute
Definition keyboard.h:81
@ KEY_SHIFT_ESCAPE
Shift+Escape (immediate exit).
Definition keyboard.h:73
@ KEY_2
'2' key - toggle audio waveform
Definition keyboard.h:77
@ KEY_BACKTICK
'`' key - print lock state (debug builds)
Definition keyboard.h:84
@ KEY_1
'1' key - toggle matrix rain effect
Definition keyboard.h:76
@ KEY_ESCAPE
Escape key (ESC).
Definition keyboard.h:55
@ KEY_F
'f' key - flip webcam
Definition keyboard.h:82
@ KEY_PAGEDOWN
Definition keyboard.h:71
@ KEY_PAGEUP
Definition keyboard.h:70
@ KEY_MINUS
'-' key - toggle FPS counter
Definition keyboard.h:74
@ KEY_LEFT
Left arrow key.
Definition keyboard.h:59
@ KEY_MEDIA_SUBMIT
Nonblocking media prompt submitted.
Definition keyboard.h:68
@ KEY_RIGHT
Right arrow key.
Definition keyboard.h:60
@ KEY_0
'0' key - toggle sync debug screen
Definition keyboard.h:75
@ KEY_PASTE_BEGIN
Definition keyboard.h:65
@ KEY_F12
Open the version update checker TUI.
Definition keyboard.h:69
@ KEY_NONE
No key pressed or no input available.
Definition keyboard.h:54
@ KEY_C
'c' key - cycle color modes
Definition keyboard.h:79
@ KEY_PASTE
Definition keyboard.h:67
@ KEY_R
'r' key - cycle render modes
Definition keyboard.h:80
@ KEY_END
End key (move to end of line).
Definition keyboard.h:63
@ KEY_DOWN
Down arrow key.
Definition keyboard.h:58
@ KEY_QUESTION
'?' key - show help screen
Definition keyboard.h:83
@ KEY_PASTE_END
Definition keyboard.h:66
@ KEY_HOME
Home key (move to start of line).
Definition keyboard.h:62
@ KEY_SHIFT_ENTER
Shift+Enter (insert a newline in multiline prompts).
Definition keyboard.h:72
@ KEY_DELETE
Delete key (forward delete).
Definition keyboard.h:61
@ KEY_3
'3' key - toggle audio frequency display
Definition keyboard.h:78
@ KEY_CTRL_DELETE
Ctrl+Delete (delete word forward).
Definition keyboard.h:64

◆ keyboard_line_edit_result_t

#include <include/ascii-chat/os/keyboard.h>

Result codes for interactive line editing.

Return values for keyboard_read_line_interactive() indicating the current state of the editing session after processing one keystroke.

Enumerator
LINE_EDIT_CONTINUE 

Keep editing (more input needed).

LINE_EDIT_ACCEPTED 

User pressed Enter (accept input).

LINE_EDIT_CANCELLED 

User pressed Escape/Ctrl+C (cancel input).

LINE_EDIT_NO_INPUT 

No key available (non-blocking mode).

Definition at line 223 of file keyboard.h.

223 {
keyboard_line_edit_result_t
Result codes for interactive line editing.
Definition keyboard.h:223
@ LINE_EDIT_ACCEPTED
User pressed Enter (accept input).
Definition keyboard.h:225
@ LINE_EDIT_CANCELLED
User pressed Escape/Ctrl+C (cancel input).
Definition keyboard.h:226
@ LINE_EDIT_CONTINUE
Keep editing (more input needed).
Definition keyboard.h:224
@ LINE_EDIT_NO_INPUT
No key available (non-blocking mode).
Definition keyboard.h:227

Function Documentation

◆ _Atomic() [1/2]

rwlock_t::_Atomic ( uint64_t )

#include <include/ascii-chat/os/rwlock.h>

Timestamp of last read lock acquisition (nanoseconds).

◆ _Atomic() [2/2]

rwlock_t::_Atomic ( uintptr_t )

#include <include/ascii-chat/os/rwlock.h>

Registry key of thread holding write lock (0 if not held).

◆ backtrace_print_simple()

void backtrace_print_simple ( int skip_frames)

#include <include/ascii-chat/os/backtrace.h>

Print backtrace of the current call stack.

Captures the current call stack and prints it to stderr using platform_backtrace_symbols(). Useful for debugging crashes and errors.

Parameters
skip_framesNumber of frames to skip from the top (0 = include all)

Referenced by main().

◆ debug_sync_is_initialized()

bool debug_sync_is_initialized ( void )

◆ debug_sync_rwlock_rdlock()

int debug_sync_rwlock_rdlock ( rwlock_t * rwlock,
const char * file_name,
int line_number,
const char * function_name )

#include <include/ascii-chat/os/rwlock.h>

References rwlock.

◆ debug_sync_rwlock_rdunlock()

int debug_sync_rwlock_rdunlock ( rwlock_t * rwlock,
const char * file_name,
int line_number,
const char * function_name )

#include <include/ascii-chat/os/rwlock.h>

References rwlock.

◆ debug_sync_rwlock_wrlock()

int debug_sync_rwlock_wrlock ( rwlock_t * rwlock,
const char * file_name,
int line_number,
const char * function_name )

#include <include/ascii-chat/os/rwlock.h>

References rwlock.

◆ debug_sync_rwlock_wrunlock()

int debug_sync_rwlock_wrunlock ( rwlock_t * rwlock,
const char * file_name,
int line_number,
const char * function_name )

#include <include/ascii-chat/os/rwlock.h>

References rwlock.

◆ get_binary_file_address_offsets()

int get_binary_file_address_offsets ( const void * addr,
platform_binary_match_t * matches,
int max_matches )

◆ keyboard_apply_key()

#include <include/ascii-chat/os/keyboard.h>

Apply a decoded key without platform I/O.

◆ keyboard_destroy()

void keyboard_destroy ( void )

#include <include/ascii-chat/os/keyboard.h>

Cleanup keyboard input system and restore terminal.

Restores terminal to original state (canonical mode with echo enabled). Must be called after keyboard_init() to prevent terminal corruption on program exit.

Platform behavior:

  • POSIX: Restores original termios settings via tcsetattr
  • Windows: Restores original console mode
Note
Safe to call multiple times (no-op if not initialized)
Safe to call even if keyboard_init() failed

Referenced by asciichat_shared_destroy(), stats_runtime_start(), stats_runtime_stop(), ui_sync_start(), and ui_sync_stop().

◆ keyboard_init()

asciichat_error_t keyboard_init ( void )

#include <include/ascii-chat/os/keyboard.h>

Initialize keyboard input system.

Returns
ASCIICHAT_OK on success, or error code on failure

Sets up terminal for keyboard input by enabling raw mode (character-by-character input without line buffering or echo). Must be called before keyboard_read_nonblocking() and paired with keyboard_destroy() for proper terminal restoration.

Errors:

Platform behavior:

  • POSIX: Uses tcgetattr/tcsetattr to set raw mode (ICANON/ECHO disabled)
  • POSIX: Sets stdin to non-blocking mode with fcntl(F_SETFL, O_NONBLOCK)
  • Windows: Uses GetStdHandle(STD_INPUT_HANDLE) and SetConsoleMode()
  • Windows: Disables ENABLE_LINE_INPUT and ENABLE_ECHO_INPUT modes

Error handling:

  • Automatically sets asciichat_errno on failure with context
  • Call HAS_ERRNO() to check for error details after failure
Note
Must be paired with keyboard_destroy() before program exit
Calling multiple times is safe (idempotent)
Terminal state is restored by keyboard_destroy()
Safe to call before or after calling keyboard_read_nonblocking()

Referenced by asciichat_shared_init(), stats_runtime_start(), ui_status_display_interactive(), and ui_sync_start().

◆ keyboard_input_available()

bool keyboard_input_available ( void )

#include <include/ascii-chat/os/keyboard.h>

Nonblocking readiness probe. Retains decoded events in order for the next reader.

◆ keyboard_read_line_interactive()

keyboard_line_edit_result_t keyboard_read_line_interactive ( keyboard_line_edit_opts_t * opts)

#include <include/ascii-chat/os/keyboard.h>

Process one keystroke for interactive line editing.

Parameters
optsLine editing options (must not be NULL)
Returns
Result code indicating editing status

Non-blocking line editor that processes one keystroke per call. Supports full text editing with cursor movement, character insertion/deletion, and UTF-8 multi-byte sequences.

Supported editing operations:

  • Backspace (8/127): Delete character before cursor
  • Delete (ESC[3~): Delete character at cursor
  • Left/Right arrows: Move cursor
  • Home/End: Jump to start/end of line
  • Enter: Accept input (return LINE_EDIT_ACCEPTED)
  • Escape/Ctrl+C: Cancel input (return LINE_EDIT_CANCELLED)
  • Printable characters: Insert at cursor position
  • UTF-8 multi-byte: Full support for non-ASCII characters

Display behavior:

  • Editing never renders or reads the terminal. Callers render and validate.
  • echo, mask_char, prefix and validator remain for source compatibility.

Non-blocking design:

  • Returns immediately if no input available (LINE_EDIT_NO_INPUT)
  • Suitable for integration with render loops
  • Call repeatedly in a loop until LINE_EDIT_ACCEPTED or LINE_EDIT_CANCELLED

Errors:

  • Returns LINE_EDIT_NO_INPUT if no pre-read key is supplied
  • Returns LINE_EDIT_NO_INPUT if opts is NULL or buffer is NULL
Note
Supply decoded text/special keys from the shared input decoder
The buffer is modified in-place as user types
len and cursor are updated to reflect current state
Callers serialize access to their editing state
Example
// Interactive grep input
char pattern[256] = {0};
size_t len = 0;
size_t cursor = 0;
.buffer = pattern,
.max_len = sizeof(pattern),
.len = &len,
.cursor = &cursor,
.echo = false, // We render ourselves
.mask_char = 0, // No masking
.prefix = "/", // Show "/" prefix
.validator = validate_pattern // Optional validator
};
while (true) {
switch (result) {
// User pressed Enter - pattern is in buffer
apply_pattern(pattern);
return;
// User pressed Escape - restore previous state
restore_previous();
return;
// Still editing - re-render display
render_input_line(pattern, cursor);
break;
// No input - continue loop
break;
}
}
keyboard_line_edit_result_t keyboard_read_line_interactive(keyboard_line_edit_opts_t *opts)
Process one keystroke for interactive line editing.
keyboard_key_t keyboard_read_nonblocking(void)
Read next keyboard input without blocking.
Options for interactive line editing.
Definition keyboard.h:203
keyboard_key_t key
Required pre-read key; KEY_NONE means no input.
Definition keyboard.h:212

Referenced by log_search_handle_key().

◆ keyboard_read_nonblocking()

keyboard_key_t keyboard_read_nonblocking ( void )

#include <include/ascii-chat/os/keyboard.h>

Read next keyboard input without blocking.

Returns
Keyboard key code (keyboard_key_t) or KEY_NONE if no input

Checks for available keyboard input and returns immediately. Returns KEY_NONE if no input is currently available. This is a non-blocking operation suitable for integration into render loops.

Supported input:

  • Arrow keys: KEY_UP, KEY_DOWN, KEY_LEFT, KEY_RIGHT
  • Special keys: KEY_ESCAPE, KEY_SPACE
  • ASCII characters: Returned as raw character codes (a-z, A-Z, 0-9, etc.)
  • Control keys: Ctrl+C, Ctrl+Z, and other control sequences (codes 1-31)
  • UTF-8: Complete scalars are returned as Unicode code points

Platform behavior:

  • POSIX: Uses select() with zero timeout on stdin for non-blocking check
  • POSIX: Parses ESC escape sequences for arrow keys (ESC [ A/B/C/D)
  • POSIX: 50ms escape-sequence deadline to distinguish ESC from sequences
  • Windows: Reads Unicode console events and normalizes UTF-16 and native keys

Return behavior:

  • Returns immediately with KEY_NONE if no input available (non-blocking)
  • Returns KEY_NONE if keyboard_init() was never called (safe, graceful)
  • Returns ASCII character code unchanged (e.g., 'c'=99, 'm'=109, '5'=53)
  • Arrow key sequences are fully consumed before returning
Note
Safe to call without prior keyboard_init() (returns KEY_NONE)
Thread-safe; uses mutex to check initialization state
Not suitable for high-frequency polling (CPU overhead); use in 60 FPS loops
Assumes terminal is in raw mode (set by keyboard_init())

◆ keyboard_read_with_timeout()

keyboard_key_t keyboard_read_with_timeout ( uint32_t timeout_ms)

#include <include/ascii-chat/os/keyboard.h>

Read keyboard input with timeout.

Parameters
timeout_msTimeout in milliseconds (0 for non-blocking)
Returns
Keyboard key code or KEY_NONE if timeout

Waits up to timeout_ms for keyboard input. Returns immediately if input is available, or after timeout if no input. Use this for event-driven input handling where you want to wait for keypresses.

◆ platform_backtrace()

int platform_backtrace ( void ** buffer,
int size )

#include <include/ascii-chat/os/backtrace.h>

Get a backtrace of the current call stack.

Captures return addresses from the current call stack into a provided buffer. Uses platform-specific mechanisms to walk the stack:

  • POSIX: libexecinfo backtrace() or manual frame pointer walking
  • Windows: CaptureStackBackTrace or StackWalk64
Parameters
bufferArray of void* pointers to store return addresses
sizeMaximum number of frames to capture
Returns
Number of frames captured (0 on error or empty stack)
Note
Return addresses are raw pointers; use platform_backtrace_symbols() to convert to names
This is a low-level function; prefer backtrace_capture() from debug/backtrace.h

◆ platform_backtrace_symbols()

char ** platform_backtrace_symbols ( void *const * buffer,
int size,
const char *const * owned_dirs )

#include <include/ascii-chat/os/backtrace.h>

Convert backtrace addresses to symbol names.

Converts raw return addresses from platform_backtrace() into human-readable symbol information (function names, file paths, line numbers).

Platform-specific resolution strategy:

  • POSIX: Uses addr2line/llvm-symbolizer via symbol_cache_resolve_batch()
  • Windows: Uses DbgHelp (SymFromAddr) with fallback to addr2line cache
Parameters
bufferArray of return addresses from platform_backtrace()
sizeNumber of addresses in buffer
Returns
Null-terminated array of symbol strings, or NULL on error
Note
The returned array must be freed with platform_backtrace_symbols_destroy()
Array is guaranteed to have 'size' valid entries plus a NULL terminator
This is a low-level function; prefer backtrace_symbolize() from debug/backtrace.h

◆ platform_backtrace_symbols_destroy()

void platform_backtrace_symbols_destroy ( char ** strings)

#include <include/ascii-chat/os/backtrace.h>

Free symbol array from platform_backtrace_symbols().

Releases all memory allocated by platform_backtrace_symbols(), including individual symbol strings and the array itself.

Parameters
stringsArray returned by platform_backtrace_symbols(), or NULL
Note
Safe to call with NULL pointer
Must not be called multiple times on same pointer

◆ platform_clear_error_state()

void platform_clear_error_state ( void )

#include <include/ascii-chat/os/errno.h>

Clear all error state on the current platform.

Windows: Clears WSA errors via WSASetLastError(0). POSIX: Clears system errno.

Referenced by errno_clear(), and errno_clear_all().

◆ platform_destroy()

void platform_destroy ( void )

#include <include/ascii-chat/os/system.h>

Cleanup platform-specific subsystems.

Performs cleanup for platform-specific subsystems. Should be called during program shutdown.

Referenced by asciichat_shared_destroy(), and mirror_cleanup().

◆ platform_disable_keepawake()

void platform_disable_keepawake ( void )

#include <include/ascii-chat/os/system.h>

Disable system sleep prevention (allow OS to sleep).

Allows the operating system to enter sleep mode. This reverts the effect of platform_enable_keepawake().

Platform-specific implementations:

  • macOS: Releases the IOKit power assertion
  • Linux: Closes the systemd-inhibit file descriptor
  • Windows: Clears all execution state flags
Note
Safe to call even if keepawake was never enabled
Safe to call multiple times

Referenced by session_server_like_run().

◆ platform_dup()

int platform_dup ( int fd)

#include <include/ascii-chat/os/system.h>

Duplicate a file descriptor, retaining its current destination across stdio redirection.

Referenced by log_io_start(), mcp_stdio_reserve(), render_progress_create(), session_display_create(), ui_controller_title_start(), and ui_sync_start().

◆ platform_dup2()

asciichat_error_t platform_dup2 ( int source_fd,
int target_fd )

#include <include/ascii-chat/os/system.h>

Redirect a descriptor to the same destination as another descriptor.

Referenced by log_io_start(), log_io_stop(), and mcp_stdio_reserve().

◆ platform_enable_keepawake()

asciichat_error_t platform_enable_keepawake ( void )

#include <include/ascii-chat/os/system.h>

Enable system sleep prevention (keepawake mode).

Returns
ASCIICHAT_OK on success, error code on failure

Prevents the operating system from entering sleep mode while the application is running.

Platform-specific implementations:

  • macOS: Uses IOKit power assertions (IOPMAssertionCreateWithName)
  • Linux: Uses systemd-inhibit if available, gracefully degrades if unavailable
  • Windows: Uses SetThreadExecutionState with ES_SYSTEM_REQUIRED and ES_DISPLAY_REQUIRED
Note
Logs warning and returns OK if platform doesn't support keepawake
Safe to call multiple times (checks for already-enabled state)
Call platform_disable_keepawake() to revert

Referenced by session_server_like_run().

◆ platform_execute_subprocess()

int platform_execute_subprocess ( const char * executable,
const char ** argv,
char * output_buffer,
size_t output_size,
bool(* cancel )(void *),
void * data )

#include <include/ascii-chat/os/system.h>

Execute a subprocess and optionally capture its output.

Parameters
executablePath to executable to run (e.g., "gpg", "/usr/bin/yt-dlp")
argvNULL-terminated array of arguments (argv[0] should be executable name or path)
output_bufferOptional buffer to store captured stdout (NULL to skip output capture)
output_sizeSize of output buffer (ignored if output_buffer is NULL)
cancelOptional callback to terminate the child and its descendants
dataContext passed to cancel
Returns
Exit code of the process, or -1 on error or cancellation

Executes a subprocess using platform-specific mechanisms:

  • POSIX: fork() + execvp(), with a pipe when capturing output
  • Windows: CreateProcess() (no output), or piped output capture (with output)

If output_buffer is NULL or output_size is 0, stdout and stderr are inherited from the parent process. Otherwise, stdout is captured into output_buffer.

Usage examples:

// No output capture
const char *argv[] = {"gpg", "--version", NULL};
int exit_code = platform_execute_subprocess("gpg", argv, NULL, 0, NULL, NULL);
// With output capture
char output[1024];
const char *argv[] = {"gpg", "--list-secret-keys", "--with-colons", NULL};
int exit_code = platform_execute_subprocess("gpg", argv, output, sizeof(output), NULL, NULL);
if (exit_code == 0) {
// Parse output (null-terminated)
}
int platform_execute_subprocess(const char *executable, const char **argv, char *output_buffer, size_t output_size, bool(*cancel)(void *), void *data)
Execute a subprocess and optionally capture its output.
Note
When output_buffer is NULL: stdout and stderr inherited, fast fork+exec
When output_buffer is provided: stdout captured, stderr inherited
Output is always null-terminated when captured
Returns -1 if output_buffer is provided but too small for output
More secure than system() as it doesn't invoke a shell

Referenced by gpg_sign_with_key(), update_banner_install_update(), update_check_get_aur_helper(), yt_dlp_extract_with_options(), and yt_dlp_is_available().

◆ platform_fileno()

int platform_fileno ( FILE * stream)

#include <include/ascii-chat/os/system.h>

Get the file descriptor associated with a stream.

Referenced by log_io_start().

◆ platform_force_exit()

void platform_force_exit ( int exit_code)

#include <include/ascii-chat/os/system.h>

Forcefully terminate the process immediately without cleanup.

Parameters
exit_codeExit code to return to the operating system

Forcefully terminates the current process immediately without running atexit handlers or cleanup code. Used when normal exit() won't suffice (e.g., handling second Ctrl+C during shutdown).

Platform-specific implementations:

  • Windows: ExitProcess(exit_code)
  • POSIX: _exit(exit_code)
Note
This function does not return. Process is terminated immediately.
Use this sparingly - prefer normal exit() whenever possible.

Referenced by session_handle_keyboard_input().

◆ platform_get_last_error()

int platform_get_last_error ( void )

#include <include/ascii-chat/os/system.h>

Get the last system error code.

Returns the last error code from the operating system. On Windows: Returns GetLastError() On POSIX: Returns errno

Returns
System error code (Windows DWORD cast to int, or errno on POSIX)

◆ platform_get_monotonic_time_us()

uint64_t platform_get_monotonic_time_us ( void )

#include <include/ascii-chat/os/system.h>

Get monotonic time in microseconds.

Returns
Current monotonic time in microseconds

Returns a monotonically increasing time value in microseconds. Useful for measuring elapsed time without being affected by system clock changes. Thread-safe and lock-free.

Platform-specific implementations:

  • Unix/POSIX: Uses CLOCK_MONOTONIC via clock_gettime()
  • Windows: Uses QueryPerformanceCounter()
Note
The absolute value is arbitrary; only differences are meaningful.
Wraps after approximately 584,942 years (uint64_t).

Referenced by main(), ui_status_update(), and webrtc_is_gathering_timed_out().

◆ platform_get_pid()

pid_t platform_get_pid ( void )

#include <include/ascii-chat/os/process.h>

Get the current process ID.

Returns
Process ID of the calling process

Platform-specific implementations:

  • POSIX: Uses getpid()
  • Windows: Uses _getpid()

Referenced by asciichat_instr_runtime_get(), and options_state_init().

◆ platform_get_username()

const char * platform_get_username ( void )

#include <include/ascii-chat/os/system.h>

Get the current username.

Returns
Pointer to username string (may be static, do not free)

Returns the username of the current user.

Note
The returned string may be a static buffer. Do not modify or free it.

◆ platform_getenv()

const char * platform_getenv ( const char * name)

#include <include/ascii-chat/os/system.h>

Get an environment variable value.

Parameters
nameEnvironment variable name
Returns
Pointer to value string (or NULL if not set), do not free

Returns the value of the specified environment variable.

Note
The returned string may be a static buffer. Do not modify or free it.

Referenced by client_audio_pipeline_process_duplex(), crypto_handshake_client_key_exchange(), ed25519_verify_signature(), http_renderer_process(), path_validate_user_path(), and prompt_unknown_host().

◆ platform_gtime()

asciichat_error_t platform_gtime ( const time_t * timer,
struct tm * result )

#include <include/ascii-chat/os/system.h>

Platform-safe gmtime wrapper.

Uses gmtime_s on Windows and gmtime_r on POSIX. Thread-safe on all platforms.

Parameters
timerPointer to time_t value
resultPointer to struct tm to receive result
Returns
ASCIICHAT_OK on success, error code on error

Referenced by asciichat_instr_log_line(), and mcp_download_finalize().

◆ platform_init()

asciichat_error_t platform_init ( void )

#include <include/ascii-chat/os/system.h>

Initialize platform-specific subsystems.

Returns
ASCIICHAT_OK on success, error code on failure

Initializes platform-specific subsystems such as Winsock on Windows. Must be called before using any platform-specific functions.

Referenced by asciichat_shared_init(), client_init(), and mirror_init().

◆ platform_install_crash_handler()

asciichat_error_t platform_install_crash_handler ( platform_crash_handler_t handler)

#include <include/ascii-chat/os/signal.h>

Install a crash signal handler.

Registers a callback to be invoked when critical signals are received. Handles platform differences:

  • POSIX: sigaction() for SIGSEGV, SIGABRT, SIGBUS, SIGILL
  • Windows: SetUnhandledExceptionFilter() for access violations, stack overflow
Parameters
handlerCallback function to invoke on crash, or NULL to uninstall
Returns
ASCIICHAT_OK on success, error code on failure
Note
Only one handler can be active at a time; installing a new handler replaces the previous one
Crashes still terminate the process after the handler runs
Signal safety: handlers should only use async-signal-safe functions
Example:
void my_crash_handler(int sig, void *ctx) {
fprintf(stderr, "Caught signal %d\n", sig);
// Perform minimal cleanup, write logs, etc.
}
void platform_install_crash_handler(void)
Install crash handlers for the application.

◆ platform_load_system_ca_certs()

asciichat_error_t platform_load_system_ca_certs ( char ** pem_data_out,
size_t * pem_size_out )

#include <include/ascii-chat/os/system.h>

Load system CA certificates for TLS/HTTPS.

Loads the operating system's trusted root CA certificates in PEM format. This allows TLS connections to trust the same CAs that the OS trusts.

Platform-specific paths:

  • Linux (Debian/Ubuntu): /etc/ssl/certs/ca-certificates.crt
  • Linux (RHEL/CentOS): /etc/pki/tls/certs/ca-bundle.crt
  • macOS: /etc/ssl/cert.pem or Security framework
  • Windows: Uses CryptoAPI certificate store
Parameters
pem_data_outPointer to receive allocated PEM data (caller must free)
pem_size_outPointer to receive size of PEM data
Returns
ASCIICHAT_OK on success, error code on failure
Note
The caller must free the allocated PEM data with SAFE_FREE() or ALLOC_FREE().
Example:
char* pem_data;
size_t pem_size;
if (platform_load_system_ca_certs(&pem_data, &pem_size) == ASCIICHAT_OK) {
// Use pem_data for TLS verification
SAFE_FREE(pem_data);
}
#define SAFE_FREE(ptr)
Definition common.h:377
@ ASCIICHAT_OK
Definition error_codes.h:46
asciichat_error_t platform_load_system_ca_certs(char **pem_data_out, size_t *pem_size_out)
Load system CA certificates for TLS/HTTPS.

Referenced by https_get().

◆ platform_localtime()

asciichat_error_t platform_localtime ( const time_t * timer,
struct tm * result )

#include <include/ascii-chat/os/system.h>

Platform-safe localtime wrapper.

Uses localtime_s on Windows and localtime_r on POSIX. Thread-safe on all platforms.

Parameters
timerPointer to time_t value
resultPointer to struct tm to receive result
Returns
ASCIICHAT_OK on success, error code on error

Referenced by get_current_time_formatted(), manpage_fmt_write_title(), and time_format_now().

◆ platform_memcpy()

asciichat_error_t platform_memcpy ( void * dest,
size_t dest_size,
const void * src,
size_t count )

#include <include/ascii-chat/os/system.h>

Platform-safe memcpy wrapper.

Uses memcpy_s on Windows when available (C11) and memcpy with bounds checking on POSIX. Provides consistent interface across platforms.

Parameters
destDestination buffer
dest_sizeSize of destination buffer
srcSource buffer
countNumber of bytes to copy
Returns
ASCIICHAT_OK on success, error code on error

◆ platform_memmove()

asciichat_error_t platform_memmove ( void * dest,
size_t dest_size,
const void * src,
size_t count )

#include <include/ascii-chat/os/system.h>

Platform-safe memmove wrapper.

Uses memmove_s on Windows when available (C11) and memmove with bounds checking on POSIX. Handles overlapping memory regions safely.

Parameters
destDestination buffer
dest_sizeSize of destination buffer
srcSource buffer
countNumber of bytes to move
Returns
ASCIICHAT_OK on success, error code on error

◆ platform_memset()

asciichat_error_t platform_memset ( void * dest,
size_t dest_size,
int ch,
size_t count )

#include <include/ascii-chat/os/system.h>

Platform-safe memset wrapper.

Uses memset_s on Windows when available (C11) and memset with bounds checking on POSIX. Provides consistent interface across platforms.

Parameters
destDestination buffer
dest_sizeSize of destination buffer
chValue to set (cast to unsigned char)
countNumber of bytes to set
Returns
ASCIICHAT_OK on success, error code on error

◆ platform_mmap_close()

void platform_mmap_close ( platform_mmap_t * mapping)

#include <include/ascii-chat/os/mmap.h>

Unmap and close a memory-mapped file.

Unmaps the memory region and closes the underlying file handle. Safe to call on an already-closed or uninitialized mapping.

Parameters
mappingMapping handle to close
Note
Does not explicitly sync before closing; kernel will flush dirty pages eventually. Call platform_mmap_sync() first if immediate persistence is required.

Referenced by log_mmap_destroy().

◆ platform_mmap_init()

void platform_mmap_init ( platform_mmap_t * mapping)

#include <include/ascii-chat/os/mmap.h>

Initialize a platform_mmap_t structure.

Sets all fields to safe initial values. Call before first use.

Parameters
mappingPointer to mapping structure to initialize

Referenced by log_mmap_init().

◆ platform_mmap_is_valid()

bool platform_mmap_is_valid ( const platform_mmap_t * mapping)

#include <include/ascii-chat/os/mmap.h>

Check if a mapping is currently valid.

Parameters
mappingMapping handle to check
Returns
true if the mapping is open and usable, false otherwise

◆ platform_mmap_open()

asciichat_error_t platform_mmap_open ( const char * name,
const char * path,
size_t size,
platform_mmap_t * out )

#include <include/ascii-chat/os/mmap.h>

Memory-map a file for read/write access.

Opens or creates a file and maps it into memory. The file is created if it doesn't exist, and resized to the specified size.

The mapping uses shared mode (MAP_SHARED on POSIX, FILE_MAP_ALL_ACCESS on Windows) so changes are visible to other processes and persist to the file.

Parameters
pathFile path to map (created if doesn't exist)
sizeDesired mapping size in bytes
[out]outOutput mapping handle (must be initialized with platform_mmap_init)
Returns
ASCIICHAT_OK on success, error code on failure
Note
On success, out->addr contains the mapped memory address
Call platform_mmap_close() to unmap and close

Example:

if (platform_mmap_open("/tmp/log.mmap", 1024 * 1024, &mapping) == ASCIICHAT_OK) {
// Use mapping.addr as normal memory
memset(mapping.addr, 0, mapping.size);
}
void platform_mmap_close(platform_mmap_t *mapping)
Unmap and close a memory-mapped file.
asciichat_error_t platform_mmap_open(const char *name, const char *path, size_t size, platform_mmap_t *out)
Memory-map a file for read/write access.
struct platform_mmap platform_mmap_t
For platform mmap, this is the live record that ties addr, size, fd together. The owning code creates...
void platform_mmap_init(platform_mmap_t *mapping)
Initialize a platform_mmap_t structure.
size_t size
Definition os/mmap.h:49
void * addr
Definition os/mmap.h:48

References out.

Referenced by log_mmap_init().

◆ platform_mmap_sync()

void platform_mmap_sync ( platform_mmap_t * mapping,
bool async )

#include <include/ascii-chat/os/mmap.h>

Flush memory-mapped changes to disk.

Requests the kernel to flush any modified pages to the underlying file. This is typically not needed as the kernel flushes automatically, but can be used to ensure data persistence at specific points.

Parameters
mappingMapping handle to sync
asyncIf true, return immediately (async flush). If false, block until flush completes (sync flush).
Note
On crash, unflushed data may be lost. For crash-critical data, call platform_mmap_sync(mapping, false) after important writes.

Referenced by log_mmap_destroy(), log_mmap_rotate(), log_mmap_sync(), and log_mmap_write().

◆ platform_pipe_close()

int platform_pipe_close ( pipe_t pipe)

#include <include/ascii-chat/os/pipe.h>

Close a pipe connection.

Parameters
pipePipe handle to close
Returns
0 on success, non-zero on error

Closes the pipe connection using the appropriate platform-specific function:

  • Windows: CloseHandle()
  • POSIX: close()

Referenced by gpg_agent_connect(), gpg_agent_disconnect(), ssh_agent_add_key(), ssh_agent_has_key(), ssh_agent_is_available(), and ssh_agent_sign().

◆ platform_pipe_connect()

pipe_t platform_pipe_connect ( const char * path)

#include <include/ascii-chat/os/pipe.h>

Connect to an agent via named pipe (Windows) or Unix socket (POSIX).

Parameters
pathPath to agent (named pipe path on Windows, socket path on POSIX)
Returns
Pipe handle on success, INVALID_PIPE_VALUE on error

Connects to an agent using the appropriate platform-specific mechanism:

  • Windows: Opens named pipe via CreateFileA
  • POSIX: Connects to Unix domain socket via socket() + connect()
Note
The path format differs by platform:
  • Windows: Named pipe path (e.g., "\\\\.\\pipe\\openssh-ssh-agent")
  • POSIX: Unix socket path (e.g., "/tmp/ssh-XXXXXX/agent.XXXXXX")

Referenced by gpg_agent_connect().

◆ platform_pipe_is_valid()

bool platform_pipe_is_valid ( pipe_t pipe)

#include <include/ascii-chat/os/pipe.h>

Check if a pipe handle is valid.

Parameters
pipePipe handle to check
Returns
true if pipe is valid, false otherwise

Referenced by gpg_agent_connect().

◆ platform_pipe_read()

ssize_t platform_pipe_read ( pipe_t pipe,
void * buf,
size_t len )

#include <include/ascii-chat/os/pipe.h>

Read data from a pipe.

Parameters
pipePipe handle to read from
bufBuffer to store read data
lenMaximum number of bytes to read
Returns
Number of bytes read on success, -1 on error, 0 on connection closed

Reads data from the pipe using the appropriate platform-specific function:

  • Windows: ReadFile()
  • POSIX: read()
Note
This function may read fewer bytes than requested (short read). Caller should handle partial reads if needed.

Referenced by gpg_get_public_key(), ssh_agent_add_key(), ssh_agent_has_key(), and ssh_agent_sign().

◆ platform_pipe_write()

ssize_t platform_pipe_write ( pipe_t pipe,
const void * buf,
size_t len )

#include <include/ascii-chat/os/pipe.h>

Write data to a pipe.

Parameters
pipePipe handle to write to
bufData buffer to write
lenNumber of bytes to write
Returns
Number of bytes written on success, -1 on error

Writes data to the pipe using the appropriate platform-specific function:

  • Windows: WriteFile()
  • POSIX: write()
Note
This function may write fewer bytes than requested (short write). Caller should handle partial writes if needed.

Referenced by gpg_get_public_key(), ssh_agent_add_key(), ssh_agent_has_key(), and ssh_agent_sign().

◆ platform_process_destroy()

void platform_process_destroy ( platform_process_t * process)

#include <include/ascii-chat/os/process.h>

Free process handle.

Releases resources associated with a process handle. Must be called for every process created with platform_process_spawn.

Parameters
processProcess handle to free
Note
Safe to call with NULL

◆ platform_process_is_alive()

bool platform_process_is_alive ( platform_process_t * process)

#include <include/ascii-chat/os/process.h>

Check if process is still running.

Parameters
processProcess handle
Returns
true if process is still running, false if terminated
Note
Non-blocking check

◆ platform_process_kill()

asciichat_error_t platform_process_kill ( platform_process_t * process)

#include <include/ascii-chat/os/process.h>

Terminate a process.

Forcefully terminates a running process.

Parameters
processProcess handle
Returns
ASCIICHAT_OK on success, error code on failure
Note
Does not wait for termination; use platform_process_wait to wait

◆ platform_process_spawn()

asciichat_error_t platform_process_spawn ( platform_process_t ** process_out,
const char * path,
const char *const * argv,
int stdin_fd,
int stdout_fd,
int stderr_fd )

#include <include/ascii-chat/os/process.h>

Spawn a child process.

Creates and starts a new process with the specified command and arguments.

Platform-specific behavior:

  • Windows: Uses CreateProcessA with PROCESS_INFORMATION
  • POSIX: Uses fork() and exec()
Parameters
process_outOutput parameter: process handle (caller must free with platform_process_destroy)
pathPath to executable (can be relative or absolute)
argvArgument array, NULL-terminated (argv[0] should be program name)
stdin_fdFile descriptor for stdin, or -1 to use parent's stdin
stdout_fdFile descriptor for stdout, or -1 to use parent's stdout
stderr_fdFile descriptor for stderr, or -1 to use parent's stderr
Returns
ASCIICHAT_OK on success, error code on failure
Note
argv must be NULL-terminated
File descriptors are duplicated, not closed

◆ platform_process_stats()

asciichat_error_t platform_process_stats ( platform_process_stats_t * out)

#include <include/ascii-chat/os/process.h>

References out.

◆ platform_process_title_destroy()

void platform_process_title_destroy ( void )

#include <include/ascii-chat/os/process.h>

Restore Unix argument storage and release title allocations.

Note
Call after workers stop, before the final memory report. Idempotent. The copied argv becomes invalid; g_argv is restored automatically.

References ASCIICHAT_API.

Referenced by asciichat_shared_destroy(), and main().

◆ platform_process_title_init()

asciichat_error_t platform_process_title_init ( int argc,
char *** argv )

#include <include/ascii-chat/os/process.h>

Reserve process-title storage before option parsing or environment use.

Parameters
argcOriginal main argument count.
argvOriginal main argument vector, replaced with a preserved copy on Unix.
Note
Call once on the main thread, after allocation tracking is initialized but before starting workers. Keep the returned argv alive until destroy. Windows and WASM require no storage. Failure leaves argv unchanged.

References ASCIICHAT_API.

Referenced by main().

◆ platform_process_title_set()

asciichat_error_t platform_process_title_set ( const char * title)

#include <include/ascii-chat/os/process.h>

Update the OS process naming surfaces through one platform API.

Note
Main-thread only. Never writes to the terminal. Windows and WASM are no-ops. Unix titles exceeding the reserved storage fail without changing the title. Linux updates argv and the main thread's comm (15 visible bytes). macOS updates argv, the main-thread name, and the Launch Services display name used by Activity Monitor. Does not rename the executable file or Windows Task Manager image name. A native-name failure returns an error after the Unix argv title is updated; the command-line update is retained, including when macOS Launch Services is unavailable. The caller may treat this as a nonfatal cosmetic failure.

References ASCIICHAT_API.

◆ platform_process_title_set_args()

asciichat_error_t platform_process_title_set_args ( const char * prefix,
const char * mode,
int argc,
char ** argv,
int mode_arg_index )

#include <include/ascii-chat/os/process.h>

Set "ascii-chat: <mode> mode - <arguments>" with secret values redacted.

Parameters
modeCanonical mode name.
argcOriginal argument count.
argvPreserved application arguments (not modified).
mode_arg_indexExplicit mode token to omit, or -1 for implicit mode.
Note
Password, TLS password, TURN credential/secret values and inline private key blocks are redacted. Arguments are quoted/escaped for display, not execution. Only supplied CLI arguments are shown, never environment/config values. Sanitized output is truncated to available storage; raw arguments are never used as a fallback. No separator is added if there are no remaining arguments. Also sets a compact main-thread/comm name: ascii:server, ascii:client, ascii:mirror, ascii:discovery, or ascii:acds for discovery-service.

References ASCIICHAT_API.

Referenced by main().

◆ platform_process_wait()

asciichat_error_t platform_process_wait ( platform_process_t * process,
int timeout_ms,
int * exit_code_out )

#include <include/ascii-chat/os/process.h>

Wait for process to terminate with timeout.

Waits for a spawned process to complete execution.

Parameters
processProcess handle from platform_process_spawn
timeout_msTimeout in milliseconds, or -1 for infinite wait
exit_code_outOptional output: process exit code
Returns
ASCIICHAT_OK if process exited, ERROR_TIMEOUT if timeout
Note
On Windows, exit code is from GetExitCodeProcess
On POSIX, exit code is from waitpid

◆ platform_raise_fd_limit()

void platform_raise_fd_limit ( unsigned int limit)

#include <include/ascii-chat/os/system.h>

Raise the file descriptor limit for the current process.

Parameters
limitDesired soft limit (0 = use platform default maximum)

Referenced by session_server_like_run().

◆ platform_register_signal_handlers()

asciichat_error_t platform_register_signal_handlers ( const platform_signal_handler_t * handlers,
int count )

#include <include/ascii-chat/os/system.h>

Register multiple signal handlers at once.

Parameters
handlersArray of signal handler descriptors
countNumber of handlers in the array
Returns
ASCIICHAT_OK on success, error code on failure

Registers multiple signal handlers in one call, reducing repeated #ifdef _WIN32 blocks. On Windows, this handles SIGINT and SIGTERM via console control handlers. On POSIX, uses platform_signal() for each.

Example:
{SIGTERM, sigterm_handler},
{SIGINT, sigint_handler},
};
asciichat_error_t platform_register_signal_handlers(const platform_signal_handler_t *handlers, int count)
Register multiple signal handlers at once.
Signal handler descriptor for bulk registration.
Definition system.h:299

Referenced by setup_signal_handlers().

◆ platform_request_timer_precision()

asciichat_error_t platform_request_timer_precision ( int precision)

#include <include/ascii-chat/os/system.h>

Request coarse (reduced resolution) timer precision.

Requests the OS to use coarse timer precision, reducing power consumption and improving system responsiveness at the cost of lower timer accuracy.

Platform-specific implementations:

  • Windows: Calls timeBeginPeriod(1) to reduce timer resolution from ~15ms to ~1ms
  • POSIX: No-op (POSIX systems don't provide this feature)

This is typically called during application startup if you need timer precision (e.g., for real-time audio/video). Must be balanced with platform_restore_timer_resolution().

Parameters
precisionDesired timer precision in milliseconds (typically 1)
Returns
ASCIICHAT_OK on success, error code on failure
Note
On Windows, this increases power consumption slightly
POSIX systems return ASCIICHAT_OK but do nothing
Must call platform_restore_timer_resolution() to restore default behavior

◆ platform_resolve_hostname_to_ipv4()

asciichat_error_t platform_resolve_hostname_to_ipv4 ( const char * hostname,
char * ipv4_out,
size_t ipv4_out_size )

#include <include/ascii-chat/os/system.h>

Resolve hostname to IPv4 address.

Performs DNS resolution to convert a hostname to an IPv4 address string. Handles platform-specific networking initialization and cleanup.

Parameters
hostnameHostname to resolve (e.g., "example.com")
ipv4_outBuffer to store the resolved IPv4 address (e.g., "192.168.1.1")
ipv4_out_sizeSize of the output buffer
Returns
ASCIICHAT_OK on success, error code on failure

Referenced by validate_opt_ip_address().

◆ platform_restore_timer_resolution()

asciichat_error_t platform_restore_timer_resolution ( void )

#include <include/ascii-chat/os/system.h>

Restore default timer precision.

Restores the default system timer precision, undoing a previous call to platform_request_timer_precision(). Reduces power consumption.

Platform-specific implementations:

  • Windows: Calls timeEndPeriod(1) to restore default timer resolution
  • POSIX: No-op (POSIX systems don't provide this feature)
Returns
ASCIICHAT_OK on success, error code on failure
Note
Safe to call without a matching platform_request_timer_precision() call
POSIX systems return ASCIICHAT_OK but do nothing

Referenced by asciichat_shared_destroy().

◆ platform_setenv()

int platform_setenv ( const char * name,
const char * value )

#include <include/ascii-chat/os/system.h>

Set an environment variable.

Parameters
nameEnvironment variable name
valueEnvironment variable value (or NULL to unset)
Returns
0 on success, non-zero on error

Sets or unsets an environment variable.

Referenced by __attribute__(), and env_pop_prompt_response().

◆ platform_signal()

signal_handler_t platform_signal ( int sig,
signal_handler_t handler )

#include <include/ascii-chat/os/system.h>

Set a signal handler.

Parameters
sigSignal number (e.g., SIGINT, SIGTERM)
handlerSignal handler function (or SIG_DFL, SIG_IGN)
Returns
Previous signal handler, or SIG_ERR on error

Registers a signal handler for the specified signal.

Referenced by main(), and session_server_like_run().

◆ platform_signal_name()

const char * platform_signal_name ( int signal)

#include <include/ascii-chat/os/signal.h>

Get human-readable name for signal number.

Parameters
signalSignal number (SIGSEGV, SIGABRT, etc.)
Returns
Human-readable signal name (e.g., "SIGSEGV"), or "UNKNOWN_SIGNAL"
Note
Returned string is not allocated; valid for program lifetime

◆ platform_sleep_ms()

void platform_sleep_ms ( unsigned int ms)

#include <include/ascii-chat/os/system.h>

Sleep for a specified number of milliseconds.

Parameters
msNumber of milliseconds to sleep

Sleeps the current thread for the specified duration.

Referenced by ascii_otel_shutdown(), client_video_render_thread(), discovery_main(), http_renderer_render_file(), main(), network_connection_open(), session_pipeline_run_main(), splash_wait_for_animation(), stats_runtime_start(), ui_controller_finish(), ui_sync_start(), and update_check_perform().

◆ platform_stderr_redirect_to_null()

platform_stderr_redirect_handle_t platform_stderr_redirect_to_null ( void )

#include <include/ascii-chat/os/system.h>

Redirect stderr to /dev/null temporarily.

This is useful for suppressing noisy warnings from third-party libraries (e.g., PortAudio backend probes) that are harmless but clutter output.

Returns
Handle for restoring stderr, or {-1, -1} on failure
Note
On Windows, this function returns {-1, -1} and has no effect
You must call platform_stderr_restore() with the returned handle to restore stderr

Example:

noisy_third_party_function(); // stderr output suppressed
platform_stderr_restore(handle); // stderr restored
platform_stderr_redirect_handle_t platform_stderr_redirect_to_null(void)
Redirect stderr to /dev/null temporarily.
void platform_stderr_restore(platform_stderr_redirect_handle_t handle)
Restore stderr from a redirect handle.
Handle for temporary stderr redirection.
Definition system.h:379

◆ platform_stderr_restore()

void platform_stderr_restore ( platform_stderr_redirect_handle_t handle)

#include <include/ascii-chat/os/system.h>

Restore stderr from a redirect handle.

Restores stderr to its original destination and closes the /dev/null file descriptor.

Parameters
handleHandle returned by platform_stderr_redirect_to_null()
Note
Safe to call with invalid handle (e.g., {-1, -1}) - will do nothing
After calling this, the handle is invalidated and should not be reused

◆ platform_stdio_redirect_to_null_permanent()

void platform_stdio_redirect_to_null_permanent ( void )

#include <include/ascii-chat/os/system.h>

Permanently redirect stderr and stdout to /dev/null.

This is used before exit() to prevent cleanup handlers from writing to the console after we've already displayed final messages to the user.

Note
On Windows, this function has no effect
This is a one-way operation - streams cannot be restored

◆ platform_stdout_stderr_redirect_to_null()

platform_stderr_redirect_handle_t platform_stdout_stderr_redirect_to_null ( void )

#include <include/ascii-chat/os/system.h>

Redirect both stdout and stderr to /dev/null (restorable).

Suppresses output from both stdout and stderr. This is useful when initializing libraries that may output diagnostic messages that would corrupt terminal rendering.

Returns
Handle to pass to platform_stdout_stderr_restore() to restore streams
Note
Always call platform_stdout_stderr_restore() with the returned handle
The returned handle uses original_fd for stdout, devnull_fd for stderr

◆ platform_stdout_stderr_restore()

void platform_stdout_stderr_restore ( platform_stderr_redirect_handle_t handle)

#include <include/ascii-chat/os/system.h>

Restore stdout and stderr after platform_stdout_stderr_redirect_to_null().

Restores both stdout and stderr to their original destinations.

Parameters
handleHandle returned by platform_stdout_stderr_redirect_to_null()
Note
Safe to call with invalid handle - will do nothing

◆ platform_strcpy()

asciichat_error_t platform_strcpy ( char * dest,
size_t dest_size,
const char * src )

#include <include/ascii-chat/os/system.h>

Platform-safe strcpy wrapper.

Uses strcpy_s on Windows when available (C11) and strncpy with bounds checking on POSIX. Always null-terminates the destination string.

Parameters
destDestination buffer
dest_sizeSize of destination buffer
srcSource string
Returns
ASCIICHAT_OK on success, error code on error

◆ platform_strerror()

const char * platform_strerror ( int errnum)

#include <include/ascii-chat/os/system.h>

Get human-readable error message for a system error code.

Converts a system error code into a readable error message string. Uses strerror_r on POSIX and FormatMessageA on Windows.

Parameters
errnumSystem error code
Returns
Pointer to error message string (may be static, do not modify or free)
Note
The returned string may be a static buffer. Do not modify or free it.
On POSIX, uses strerror_r with thread-local storage
On Windows, uses FormatMessageA with proper cleanup

◆ platform_uninstall_crash_handler()

asciichat_error_t platform_uninstall_crash_handler ( void )

#include <include/ascii-chat/os/signal.h>

Uninstall the crash signal handler.

Removes any installed crash handler and restores default signal behavior.

Returns
ASCIICHAT_OK on success, error code on failure

◆ platform_unsetenv()

int platform_unsetenv ( const char * name)

#include <include/ascii-chat/os/system.h>

Remove an environment variable.

Parameters
nameVariable name to unset
Returns
0 on success, -1 on failure

Referenced by env_pop_prompt_response().

◆ platform_write()

ssize_t platform_write ( int fd,
const void * buf,
size_t count )

#include <include/ascii-chat/os/system.h>

Platform-safe write function.

Parameters
fdFile descriptor to write to
bufBuffer containing data to write
countNumber of bytes to write
Returns
Number of bytes written on success, -1 on error

Cross-platform write function that handles Windows-specific quirks (e.g., CRLF line endings) and provides consistent behavior across platforms.

Note
On Windows, automatically handles line ending conversion if needed.
On POSIX, equivalent to standard write().

◆ platform_write_all()

size_t platform_write_all ( int fd,
const void * buf,
size_t count )

#include <include/ascii-chat/os/system.h>

Write all bytes to a file descriptor, handling partial writes.

Parameters
fdFile descriptor to write to
bufBuffer containing data to write
countNumber of bytes to write
Returns
Number of bytes successfully written (may be less than count on failure)

Handles partial writes, EINTR, and EAGAIN, retrying transient failures up to 1000 times before giving up. Permanent failures return immediately. This ensures that data is fully written even when dealing with non-blocking I/O or interrupted syscalls.

Note
On EAGAIN/EWOULDBLOCK, sleeps 100us before retrying instead of busy-waiting
Does not log failures: logging may itself be using the failed descriptor
If NULL buffer or 0 count is passed, returns 0 immediately

Referenced by config_create_default(), log_json_async_safe(), log_json_write(), mcp_stdio_send(), session_display_write_ascii_frame(), ui_controller_finish(), ui_error_popup_flush(), ui_input_timeout_report(), ui_notice_flush_snapshot(), and ui_output_write().

◆ process_utf8_arguments()

asciichat_error_t process_utf8_arguments ( int * argc,
char *** argv )

#include <include/ascii-chat/os/process.h>

Normalize process arguments to UTF-8 where necessary.

References ASCIICHAT_API.

Referenced by main().

◆ rwlock_destroy()

int rwlock_destroy ( rwlock_t * lock)

#include <include/ascii-chat/os/rwlock.h>

Destroy a read-write lock.

Parameters
lockPointer to read-write lock to destroy
Returns
0 on success, non-zero on error

Destroys the read-write lock and frees any associated resources. The lock must not be held by any thread when this is called.

Referenced by mixer_create_channels(), mixer_destroy(), and named_destroy().

◆ rwlock_destroy_impl()

int rwlock_destroy_impl ( rwlock_t * lock)

#include <include/ascii-chat/os/rwlock.h>

Destroy a read-write lock (implementation function).

Parameters
lockPointer to read-write lock to destroy
Returns
0 on success, non-zero on error
Note
This is the implementation function. Use rwlock_destroy() instead.

◆ rwlock_init()

int rwlock_init ( rwlock_t * lock,
const char * name )

#include <include/ascii-chat/os/rwlock.h>

Initialize a read-write lock with a name.

Parameters
lockPointer to read-write lock to initialize
nameHuman-readable name for debugging (e.g., "client_list_lock")
Returns
0 on success, non-zero on error

Initializes the read-write lock for use. Must be called before any other lock operations. The name is stored for debugging and automatically suffixed with a unique counter.

Referenced by mixer_create_channels(), and named_init().

◆ rwlock_init_impl()

int rwlock_init_impl ( rwlock_t * lock)

#include <include/ascii-chat/os/rwlock.h>

Initialize a read-write lock (implementation function).

Parameters
lockPointer to read-write lock to initialize
Returns
0 on success, non-zero on error
Note
This is the implementation function. Use rwlock_init() instead.

◆ rwlock_log_state()

void rwlock_log_state ( const rwlock_t * rwlock,
const char * file,
int line,
const char * func )

#include <include/ascii-chat/os/rwlock.h>

Format and log the current state of a read-write lock.

Parameters
rwlockPointer to the read-write lock
fileSource file of the caller
lineSource line of the caller
funcSource function of the caller

Logs detailed state information about the rwlock (timing, counts, held-by info) at the specified location. Debug builds only; no-op in release builds.

References rwlock.

◆ rwlock_on_rdlock()

void rwlock_on_rdlock ( rwlock_t * rwlock)

#include <include/ascii-chat/os/rwlock.h>

Hook called when a read lock is successfully acquired.

Parameters
rwlockPointer to the rwlock that was read-locked

Called by platform-specific implementations after read lock acquisition. Records timing and other diagnostic data (debug builds only).

References rwlock.

◆ rwlock_on_unlock()

void rwlock_on_unlock ( rwlock_t * rwlock)

#include <include/ascii-chat/os/rwlock.h>

Hook called when an rwlock is unlocked (read or write).

Parameters
rwlockPointer to the rwlock that was unlocked

Called by platform-specific implementations before lock release. Records timing and other diagnostic data (debug builds only).

References rwlock.

◆ rwlock_on_wrlock()

void rwlock_on_wrlock ( rwlock_t * rwlock)

#include <include/ascii-chat/os/rwlock.h>

Hook called when a write lock is successfully acquired.

Parameters
rwlockPointer to the rwlock that was write-locked

Called by platform-specific implementations after write lock acquisition. Records timing and other diagnostic data (debug builds only).

References rwlock.

◆ rwlock_rdlock_impl()

int rwlock_rdlock_impl ( rwlock_t * lock)

#include <include/ascii-chat/os/rwlock.h>

Acquire a read lock (implementation function).

Parameters
lockPointer to read-write lock
Returns
0 on success, non-zero on error

Acquires a shared read lock. Multiple threads can hold read locks simultaneously. Blocks if a write lock is held.

Note
This is the implementation function. Use rwlock_rdlock() macro instead, which includes debug tracking in debug builds.

◆ rwlock_rdunlock_impl()

int rwlock_rdunlock_impl ( rwlock_t * lock)

#include <include/ascii-chat/os/rwlock.h>

Release a read lock (implementation function).

Parameters
lockPointer to read-write lock
Returns
0 on success, non-zero on error

Releases a shared read lock held by the calling thread.

Note
This is the implementation function. Use rwlock_rdunlock() macro instead, which includes debug tracking in debug builds.

◆ rwlock_tryrdlock()

asciichat_error_t rwlock_tryrdlock ( rwlock_t * lock,
bool * acquired )

#include <include/ascii-chat/os/rwlock.h>

Try a shared lock without waiting. Contention succeeds with *acquired = false.

Referenced by named_metadata_copy(), named_registry_for_each(), named_registry_read(), and named_registry_try_snapshot().

◆ rwlock_wrlock_impl()

int rwlock_wrlock_impl ( rwlock_t * lock)

#include <include/ascii-chat/os/rwlock.h>

Acquire a write lock (implementation function).

Parameters
lockPointer to read-write lock
Returns
0 on success, non-zero on error

Acquires an exclusive write lock. Only one thread can hold a write lock, and it excludes all read locks. Blocks if any locks are held.

Note
This is the implementation function. Use rwlock_wrlock() macro instead, which includes debug tracking in debug builds.

◆ rwlock_wrunlock_impl()

int rwlock_wrunlock_impl ( rwlock_t * lock)

#include <include/ascii-chat/os/rwlock.h>

Release a write lock (implementation function).

Parameters
lockPointer to read-write lock
Returns
0 on success, non-zero on error

Releases an exclusive write lock held by the calling thread.

Note
This is the implementation function. Use rwlock_wrunlock() macro instead, which includes debug tracking in debug builds.

◆ safe_fprintf()

int safe_fprintf ( FILE * stream,
const char * format,
... )

#include <include/ascii-chat/os/system.h>

Platform-safe fprintf wrapper.

Uses fprintf_s on Windows and fprintf on POSIX.

Parameters
streamFile stream
formatFormat string
...Variable arguments
Returns
Number of characters written or negative on error

Referenced by add_known_host(), and webcam_print_init_error_help().

◆ safe_snprintf()

int safe_snprintf ( char * buffer,
size_t buffer_size,
const char * format,
... )

#include <include/ascii-chat/os/system.h>

Platform-safe snprintf wrapper.

Uses snprintf_s on Windows and snprintf with additional safety on POSIX. Always null-terminates the output buffer.

Parameters
bufferOutput buffer
buffer_sizeSize of output buffer
formatFormat string
...Variable arguments
Returns
Number of characters written (excluding null terminator) or negative on error

References buffer_size.

Referenced by acds_identity_default_path(), acds_identity_fingerprint(), acds_string_generate(), action_completions(), ascii_otel_error(), ascii_otel_error_code(), ascii_otel_http(), ascii_otel_init(), ascii_otel_packet(), asciichat_instr_log_line(), asciichat_instr_log_pc(), asciichat_mdns_advertise(), asciichat_mdns_query(), audio_analysis_init(), audio_client_init(), build_github_gpg_url(), build_github_ssh_url(), build_gitlab_gpg_url(), build_gitlab_ssh_url(), capture_init(), check_gpg_key_expiry(), check_known_host_no_identity(), check_known_host_with_key(), client_audio_pipeline_create(), client_get_crypto_error_message(), colored_string(), colorize_log_message_with_color(), colorize_named_string(), colorscheme_compile_scheme(), colorscheme_current_palette(), colorscheme_export_scheme(), config_create_default(), config_load_and_apply(), create_client_render_threads(), crypto_get_rekey_status(), crypto_handshake_client_key_exchange(), crypto_handshake_server_auth_challenge(), crypto_handshake_server_start(), discovery_keys_get_cache_path(), discovery_keys_save_cached(), discovery_keys_verify_change(), display_mitm_warning(), expand_path(), find_similar_option_with_mode(), format_available_modes(), format_bytes_pretty(), format_gpg_key_display(), format_mode_names(), format_number_compact(), format_public_key(), format_uptime_hms(), get_current_time_formatted(), get_known_hosts_path(), get_log_dir(), get_manpage_template(), gpg_agent_sign(), gpg_get_public_key(), gpg_sign_detached_ed25519(), gpg_verify_detached_ed25519(), gpg_verify_signature(), gpg_verify_signature_with_binary(), http2_connection_submit_response(), http_response_finish(), http_server_authorize(), http_server_http3_create(), https_get(), ice_format_candidate(), key_identity_format(), log_mmap_write(), log_recolor_plain_entry(), log_template_apply(), manpage_content_generate_environment(), manpage_content_generate_environment_with_manual(), manpage_content_generate_examples(), manpage_content_generate_options(), manpage_content_generate_positional(), manpage_content_generate_usage(), manpage_fmt_write_title(), manpage_merger_generate_synopsis(), manpage_merger_generate_usage(), mcp_dispatch(), mcp_download_finalize(), mcp_download_prune(), mcp_request_parse(), nat_upnp_close(), nat_upnp_get_address(), options_format_default_value(), options_preset_unified(), parallel_connect(), parse_client_address(), parse_color_filter(), parse_color_mode(), parse_gpg_key(), parse_gpg_key_binary(), parse_gpg_keys_from_response(), parse_log_level(), parse_palette_chars(), parse_palette_type(), parse_port_option(), parse_private_key(), parse_render_mode(), parse_render_theme(), parse_server_bind_address(), path_validate_user_path(), prompt_unknown_host(), prompt_unknown_host_no_identity(), pubkey_to_hex(), query_init(), remove_known_host(), rgb_to_truecolor_ansi(), sdp_generate_answer(), sdp_generate_offer(), session_capture_create(), session_display_write_ascii_frame(), session_network_capture_create(), session_participant_start_video(), stats_logger_thread(), test_get_binary_path(), time_pretty(), turn_generate_credentials(), ui_error_popup_preserve(), and ui_error_popup_render().

◆ safe_vsnprintf()

int safe_vsnprintf ( char * buffer,
size_t buffer_size,
const char * format,
va_list ap )

#include <include/ascii-chat/os/system.h>

Platform-safe vsnprintf wrapper.

Uses the appropriate vsnprintf implementation for the platform. Safely formats a string with va_list argument.

Parameters
bufferOutput buffer
buffer_sizeSize of output buffer
formatFormat string
apVariable argument list
Returns
Number of characters written (excluding null terminator) or negative on error

References buffer_size.

Referenced by ascii_otel_log(), disconnect_client_for_bad_data(), format_message(), log_file_msg(), log_mmap_write(), log_msg(), and log_plain_msg().

◆ symbol_cache_destroy()

void symbol_cache_destroy ( void )

#include <include/ascii-chat/os/symbols.h>

Clean up the symbol cache and free all resources.

Destroys the symbol cache and frees all cached symbols and internal structures. Should be called at application shutdown after all backtraces are complete.

Note
Safe to call multiple times (no-op after first call).
All cached symbol strings are freed automatically.

Referenced by asciichat_shared_destroy().

◆ symbol_cache_free_symbols()

void symbol_cache_free_symbols ( char ** symbols)

#include <include/ascii-chat/os/symbols.h>

Free symbol array returned by symbol_cache_resolve_batch.

Parameters
symbolsArray of symbol strings (can be NULL)

Frees the array structure returned by symbol_cache_resolve_batch(). This only frees the array itself, not the individual symbol strings (which are owned by the cache).

Note
Safe to call with NULL pointer (no-op).
This function only frees the array structure, not cached symbol strings.

◆ symbol_cache_get_stats()

void symbol_cache_get_stats ( uint64_t * hits_out,
uint64_t * misses_out,
size_t * entries_out )

#include <include/ascii-chat/os/symbols.h>

Get cache statistics.

Parameters
hits_outPointer to receive hit count (can be NULL)
misses_outPointer to receive miss count (can be NULL)
entries_outPointer to receive entry count (can be NULL)

Retrieves cumulative statistics from the symbol cache. Useful for performance monitoring and cache efficiency analysis.

Note
All counters are cumulative since cache initialization.
Thread-safe: Can be called from any thread.

◆ symbol_cache_init()

asciichat_error_t symbol_cache_init ( void )

#include <include/ascii-chat/os/symbols.h>

Initialize the symbol cache.

Returns
ASCIICHAT_OK on success, error code on failure

Initializes the global symbol cache system. Creates the hashtable and initializes statistics counters. Must be called before using any other symbol cache functions.

Note
Idempotent: Safe to call multiple times (no-op after first call).
Thread-safe: Can be called from any thread during initialization.

Referenced by asciichat_shared_init().

◆ symbol_cache_insert()

bool symbol_cache_insert ( void * addr,
const char * symbol )

#include <include/ascii-chat/os/symbols.h>

Insert a symbol into the cache.

Parameters
addrAddress to cache (must not be NULL)
symbolSymbol string to cache (must not be NULL, will be copied)
Returns
true on success, false on failure (memory allocation error)

Inserts a symbol into the cache for future lookups. The symbol string is copied and owned by the cache. If the address already exists in the cache, the symbol is updated.

Note
Symbol string is copied, so caller can free the original string.
Thread-safe: Can be called from multiple threads simultaneously.
Statistics are updated (entry count, etc.).
Warning
Memory allocation failures return false. Check return value.

◆ symbol_cache_lookup()

const char * symbol_cache_lookup ( void * addr)

#include <include/ascii-chat/os/symbols.h>

Look up a symbol for a given address.

Parameters
addrAddress to resolve (must not be NULL)
Returns
Cached symbol string, or NULL if not in cache

Performs a hashtable lookup to find the cached symbol for the given address. Returns NULL if the address is not in the cache (cache miss). Use symbol_cache_resolve_batch() to resolve uncached addresses.

Note
This is a fast O(1) lookup operation (hashtable lookup).
Returned string is owned by the cache and should not be freed.
String remains valid until cache is cleaned up.
Thread-safe: Can be called from multiple threads simultaneously.
For batch resolution, use symbol_cache_resolve_batch() which handles both cache lookup and addr2line resolution automatically.

◆ symbol_cache_print_stats()

void symbol_cache_print_stats ( void )

#include <include/ascii-chat/os/symbols.h>

Print cache statistics to logging system.

Logs detailed statistics from the symbol cache including hit rate, miss count, and entry count. Useful for periodic performance monitoring.

Note
Requires logging system to be initialized.
Statistics are formatted and logged at INFO level.

◆ symbol_cache_resolve_batch()

char ** symbol_cache_resolve_batch ( void *const * buffer,
int size,
const char *const * owned_dirs )

#include <include/ascii-chat/os/symbols.h>

Resolve multiple addresses using addr2line and cache results.

Parameters
bufferArray of addresses to resolve (must not be NULL)
sizeNumber of addresses in buffer (must be > 0)
Returns
Array of symbol strings (caller must free with symbol_cache_free_symbols), or NULL on error

Resolves multiple addresses to symbol names using addr2line. For each address:

  1. Checks cache first (fast O(1) lookup)
  2. If not cached, resolves using addr2line subprocess
  3. Caches resolved symbol for future lookups
  4. Returns symbol string in output array

This function is optimized for batch backtrace processing:

  • Checks cache for all addresses first (fast)
  • Resolves only uncached addresses in single addr2line invocation
  • Caches all resolved symbols automatically
Note
Returned array has size elements (one per input address).
Array elements are NULL if symbol resolution failed for that address.
Array elements point to cached symbol strings (owned by cache).
Call symbol_cache_free_symbols() to free the array (not the strings).
addr2line must be available in PATH for resolution to work.
Debug symbols must be available in the executable.
Warning
Caller must free the returned array using symbol_cache_free_symbols(). Do NOT free individual strings (owned by cache).

◆ symbol_format_source_path()

asciichat_error_t symbol_format_source_path ( const char * module_name,
const char * source_path,
char * output,
size_t output_size,
bool * external,
const char *const * owned_dirs )

#include <include/ascii-chat/os/symbols.h>

Format a source path for a symbolized frame.

Parameters
module_nameModule basename or path
source_pathSource path reported by debug information
owned_dirsNULL-terminated list of owned directory prefixes to strip
owned_dirsNULL-terminated list of owned directory prefixes to strip
outputDestination buffer
output_sizeDestination buffer size
externalOutput set to true when the source belongs to external code
Returns
ASCIICHAT_OK on success, error code on failure

Project sources use repository-relative paths. External sources retain at most four parent directories and the filename.

◆ symbol_module_is_project()

bool symbol_module_is_project ( const char * module_name)

#include <include/ascii-chat/os/symbols.h>

Check whether a module belongs to ascii-chat.

Parameters
module_nameModule basename or path

Variable Documentation

◆ errno

◆ impl

pthread_rwlock_t rwlock_t::impl

Underlying POSIX rwlock.

Definition at line 64 of file rwlock.h.

◆ name

const char* rwlock_t::name

Human-readable name for named registry (all builds).

Definition at line 65 of file rwlock.h.

◆ read_lock_count

atomic_t rwlock_t::read_lock_count

Number of threads holding read locks (thread-safe atomic).

Definition at line 71 of file rwlock.h.