Skip to content
API Documentation
BastionGuard™
main.cpp
Go to the documentation of this file.
1/*
2 * BastionGuard™ Secure Connection
3 * Copyright (C) 2025–2026 Calogero Scarnà
4 * GPL-3.0 — BastionGuard™ is a trademark of Calogero Scarnà.
5 */
6
7#include "Application.hpp"
8
9#include <cstdlib> // getenv, setenv, unsetenv
10#include <cstdio> // perror, fprintf
11#include <fstream>
12#include <string>
13#include <locale.h>
14#include <libintl.h>
15#include <pwd.h> // getpwuid
16#include <unistd.h> // getuid
17
18#ifndef LOCALEDIR
19#define LOCALEDIR "/usr/share/locale"
20#endif
21
22// ---------------------------------------------------------------------------
23// Ricava la home directory in modo sicuro SENZA GLib (che non è ancora init).
24// Usa $HOME se disponibile, altrimenti getpwuid().
25// ---------------------------------------------------------------------------
26static std::string homeDir()
27{
28 if (const char* h = ::getenv("HOME"))
29 return h;
30 if (struct passwd* pw = ::getpwuid(::getuid()))
31 return pw->pw_dir;
32 return {};
33}
34
35// ---------------------------------------------------------------------------
36// Legge "language=<locale>" da settings.ini usando solo POSIX — niente GLib.
37// ---------------------------------------------------------------------------
38static std::string readLanguageFromConfig()
39{
40 const std::string home = homeDir();
41 if (home.empty()) return {};
42
43 // XDG_CONFIG_HOME ha precedenza su ~/.config
44 std::string configDir;
45 if (const char* xdg = ::getenv("XDG_CONFIG_HOME"))
46 configDir = xdg;
47 else
48 configDir = home + "/.config";
49
50 const std::string path = configDir + "/bastionguard-sc/settings.ini";
51
52 std::ifstream f(path);
53 if (!f.is_open()) return {};
54
55 const std::string key = "language=";
56 std::string line;
57 while (std::getline(f, line)) {
58 if (line.empty() || line[0] == '#' || line[0] == '[') continue;
59
60 auto pos = line.find(key);
61 if (pos == 0) {
62 std::string val = line.substr(key.size());
63
64 // Rimuovi eventuale CR finale (file Windows)
65 if (!val.empty() && val.back() == '\r')
66 val.pop_back();
67
68 return val;
69 }
70 }
71
72 return {};
73}
74
75// ---------------------------------------------------------------------------
76// Applica un locale completo all'ambiente e a setlocale()
77// Esempio: "en_US" -> LANGUAGE=en_US / LANG=en_US.UTF-8 / LC_ALL=en_US.UTF-8
78// ---------------------------------------------------------------------------
79static void applyLanguage(const std::string& lang)
80{
81 if (lang.empty()) {
82 ::setlocale(LC_ALL, "");
83 return;
84 }
85
86 const std::string lang_utf8 = lang + ".UTF-8";
87
88 ::setenv("LANGUAGE", lang.c_str(), 1);
89 ::setenv("LANG", lang_utf8.c_str(), 1);
90 ::setenv("LC_ALL", lang_utf8.c_str(), 1);
91 ::setenv("LC_MESSAGES", lang_utf8.c_str(), 1);
92
93 ::setlocale(LC_ALL, lang_utf8.c_str());
94}
95
96int main(int argc, char* argv[])
97{
98 // ── 1. Lingua salvata dall'utente o default en_US ─────────────────────
99 // Se LANGUAGE è già impostata, non la sovrascriviamo.
100 const bool langAlreadySet =
101 (::getenv("LANGUAGE") != nullptr && ::getenv("LANGUAGE")[0] != '\0');
102
103 if (!langAlreadySet) {
104 const std::string lang = readLanguageFromConfig();
105
106 if (!lang.empty()) {
107 // Usa la lingua salvata dall'utente
108 applyLanguage(lang);
109 } else {
110 // Default fisso: en_US
111 applyLanguage("en_US");
112 }
113 } else {
114 // LANGUAGE già impostata da LanguageDialog via execvp o da ambiente
115 const char* envLang = ::getenv("LANGUAGE");
116 if (envLang && envLang[0] != '\0')
117 applyLanguage(envLang);
118 else
119 applyLanguage("en_US");
120 }
121
122 // ── 2. Inizializzazione gettext ────────────────────────────────────────
123 ::bindtextdomain("bastionguard-sc", LOCALEDIR);
124 ::bind_textdomain_codeset("bastionguard-sc", "UTF-8");
125 ::textdomain("bastionguard-sc");
126
127 // ── 3. Rileva --start-minimized e RIMUOVILO dall'argv ───────────────────
128 // GTK non conosce questo flag e produce un warning se lo riceve.
129 // Lo intercettiamo qui, prima di passare argc/argv a run().
130 bool startMinimized = false;
131 for (int i = 1; i < argc; ++i) {
132 if (argv[i] && std::string(argv[i]) == "--start-minimized") {
133 startMinimized = true;
134 // Compatta l'array: sposta tutti gli elementi successivi indietro
135 for (int j = i; j < argc - 1; ++j)
136 argv[j] = argv[j + 1];
137 argv[--argc] = nullptr;
138 break;
139 }
140 }
141
142 // ── 4. Avvio applicazione ──────────────────────────────────────────────
143 auto app = Application::create();
144 app->setStartMinimized(startMinimized);
145 return app->run(argc, argv); // argc/argv senza --start-minimized
146}
int main(int argc, char *argv[])
#define LOCALEDIR
static Glib::RefPtr< Application > create()
static std::string homeDir()
Definition main.cpp:26
static void applyLanguage(const std::string &lang)
Definition main.cpp:79
static std::string readLanguageFromConfig()
Definition main.cpp:38