Menu

Application Lifecycle and Entry Points

Relevant source files

Purpose and Scope

This document details the application startup, execution, and shutdown lifecycle of fastfetch, focusing on the entry points, initialization sequence, and the global state management through the FFinstance singleton. This covers the journey from when the user executes the fastfetch binary to when the program exits and cleans up resources.

For information about configuration parsing and JSON schema validation, see Configuration and Schema System. For details about the module execution system, see Module System Architecture.

Program Entry Points

Fastfetch provides two primary entry points in separate executables:

Main Entry Point: fastfetch

The primary entry point is the main() function in src/fastfetch.c This function implements a complete command-line interface with extensive argument parsing, configuration loading, and module execution based on user-provided structure definitions.

Key responsibilities:

  • Parse command-line arguments using the parseCommand() and parseOption() functions
  • Handle special commands (--help, --version, --list-*, --print-*, --gen-config)
  • Load configuration files via optionParseConfigFile()
  • Execute the module structure defined by the user or configuration
  • Output results in text or JSON format

Simplified Entry Point: flashfetch

An alternative entry point exists in src/flashfetch.c7-142 which provides a hardcoded execution path designed to replicate neofetch's default behavior. Unlike the main fastfetch binary, flashfetch:

  • Has no command-line argument parsing
  • Uses a fixed, hardcoded module sequence
  • Configures specific display options to match neofetch's output format
  • Serves as a demonstration of minimal startup overhead

Sources: src/fastfetch.c src/flashfetch.c1-143

Global Instance Singleton

FFinstance Structure

The entire application state is managed through a single global variable instance of type FFinstance, defined in src/common/init.c20 This singleton pattern centralizes all configuration and runtime state.

Structure breakdown:

ComponentTypePurposeDefined In
instance.config.logoFFOptionsLogoLogo rendering configurationsrc/options/logo.h
instance.config.displayFFOptionsDisplayOutput formatting optionssrc/options/display.h
instance.config.generalFFOptionsGeneralGeneral behavior settingssrc/options/general.h
instance.state.platformFFPlatformOS-specific paths and datasrc/util/platform/FFPlatform.h
instance.state.configDocyyjson_doc*Parsed JSON configurationsrc/fastfetch.h45
instance.state.resultDocyyjson_mut_doc*JSON output accumulatorsrc/fastfetch.h46

Sources: src/fastfetch.h29-58 src/common/init.c20

Application Lifecycle Phases

Sources: src/fastfetch.c src/common/init.c

Phase 1: Initialization

The ffInitInstance() function in src/common/init.c49-61 performs the initial application setup:

Key operations:

  1. Locale Setup src/common/init.c51-57: Calls setlocale() to configure character encoding (UTF-8 on Windows, time locale on Unix)
  2. State Initialization src/common/init.c22-40:
    • Calls ffPlatformInit() to detect OS type, config directories, data directories, and executable path
    • Detects terminal theme (light/dark) via ffDetectTerminalTheme()
    • Initializes state variables to zero
  3. Default Configuration src/common/init.c42-47: Initializes all option structures with default values

Sources: src/common/init.c49-61 src/common/init.c22-47

Phase 2: Configuration

Configuration happens in two stages within the main() function:

Stage 2a: Command-Line Argument Parsing

The parseCommand() function src/fastfetch.c572-680 handles special commands that cause immediate program exit:

Command PatternHandlerAction
-h, --helpprintCommandHelp()Display help and exit
-v, --versionprintVersion()Display version and exit
--print-*Various print functionsPrint built-in data and exit
--list-*Various list functionsList available options and exit
--gen-config*generateConfigFile()Generate config file and continue
-c, --configoptionParseConfigFile()Load configuration file
-j, --jsonenableJsonOutput()Enable JSON output mode

After parseCommand(), the parseOption() function src/fastfetch.c682-824 processes module-specific and display options.

Sources: src/fastfetch.c572-824

Stage 2b: Configuration File Loading

The optionParseConfigFile() function src/fastfetch.c461-544 implements a cascading search strategy:

Search paths (in order):

  1. stdin (if --config -)
  2. Absolute path as given (with extension inference)
  3. Relative paths in platform.dataDirs + fastfetch/presets/
  4. Relative paths in executable directory
  5. Relative paths in executable directory + presets/

The parseJsoncFile() function src/fastfetch.c381-431 uses the yyjson library to parse JSON/JSONC/JSON5 formats based on file extension:

  • .json: Strict JSON (no comments or trailing commas)
  • .jsonc: JSON with comments and trailing commas
  • .json5: Full JSON5 support

Sources: src/fastfetch.c461-544 src/fastfetch.c381-431

Phase 3: Execution Start

The ffStart() function src/common/init.c97-134 prepares the terminal for output:

Console State Management:

Signal handlers:

Console modifications:

  • Hide cursor (\033<FileRef file-url="https://github.com/fastfetch-cli/fastfetch/blob/f0759acd/?25l) to prevent flicker during output\n- Disable line wrapping (\\033[?7l) to control output layout\n- Enable Windows virtual terminal processing for ANSI escape codes\n\nSources#LNaN-LNaN" NaN file-path="?25l) to prevent flicker during output\n- Disable line wrapping (\033[?7l`) to control output layout\n- Enable Windows virtual terminal processing for ANSI escape codes\n\nSources">Hii src/common/init.c63-95

Phase 4: Module Processing

Module execution is handled by the main loop in src/fastfetch.c826-949 This phase is documented in detail in Module System Architecture.

Sources: src/fastfetch.c826-949

Phase 5: Finalization

The ffFinish() function src/common/init.c136-142 performs cleanup:

Operations:

  1. Print any remaining logo lines if config.logo.printRemaining is true
  2. Restore terminal state by re-enabling linewrap and showing cursor
  3. Flush output buffer on Windows

Sources: src/common/init.c136-142 src/common/init.c66-77

Phase 6: Cleanup

The ffDestroyInstance() function src/common/init.c159-163 deallocates all resources:

Memory deallocation:

  • Config structures: Each option structure (logo, general, display) has a destroy function that frees owned strings and lists
  • State structures: Platform-specific data, JSON documents, and dynamic strings are freed
  • No explicit instance deallocation: Since instance is a global variable, its memory is reclaimed by the OS on process exit

Sources: src/common/init.c159-163 src/common/init.c144-157

Signal Handling and Console State Management

Signal Handler Architecture

Fastfetch installs signal handlers to ensure proper terminal cleanup even when interrupted:

Platform-specific implementation:

PlatformMechanismSignals Handled
WindowsSetConsoleCtrlHandler()CTRL_C_EVENT, CTRL_BREAK_EVENT, etc.
Unixsigaction()SIGINT, SIGTERM, SIGQUIT, SIGCHLD

Handler behavior:

  • Exit handlers src/common/init.c80-90: Call resetConsole() to restore terminal state, then call exit(0)
  • SIGCHLD handler src/common/init.c91-94: Empty handler used to interrupt blocking system calls (like poll()) when child processes exit

Sources: src/common/init.c79-95 src/common/init.c116-121

Console State Restoration

The resetConsole() function src/common/init.c66-77 ensures the terminal is left in a usable state:

State restoration:

  • Re-enables line wrapping if it was disabled
  • Shows cursor if it was hidden
  • Flushes output buffer on Windows to ensure escape sequences are processed

This function is called in three scenarios:

  1. Normal termination in ffFinish() src/common/init.c141
  2. Signal handler interruption src/common/init.c82 (Windows) or src/common/init.c88 (Unix)
  3. Via atexit() registration (not currently used, but pattern supports it)

Sources: src/common/init.c66-77 src/common/init.c97-121

Execution Flow Example: flashfetch

The simplified flashfetch entry point demonstrates the minimal lifecycle:

Key differences from main fastfetch:

  • No command-line argument parsing
  • Direct configuration modification src/flashfetch.c12-16
  • Fixed module sequence src/flashfetch.c22-137
  • Each module uses cleanup attribute for automatic option destruction: __attribute__((cleanup(ffDestroyXxxOptions)))

Sources: src/flashfetch.c7-142