#include "ProvisioningBackend.h" #include #include #include #include #include #include #include #include #include #include #include #include #include int main(int argc, char *argv[]) { // --diagnose doit aussi fonctionner depuis un TTY sans session graphique. // QGuiApplication reste utilisé pour partager exactement le même parsing, // mais la plate-forme Qt passe alors en mode offscreen si rien n'est imposé. bool diagnoseRequested = false; for (int i = 1; i < argc; ++i) { if (std::strcmp(argv[i], "--diagnose") == 0) { diagnoseRequested = true; break; } } if (diagnoseRequested && qEnvironmentVariableIsEmpty("QT_QPA_PLATFORM")) { qputenv("QT_QPA_PLATFORM", QByteArrayLiteral("offscreen")); } // Les champs contiennent temporairement des secrets : aucun core dump. rlimit coreLimit { 0, 0 }; setrlimit(RLIMIT_CORE, &coreLimit); QGuiApplication app(argc, argv); QGuiApplication::setOrganizationName(QStringLiteral("Raspot")); QGuiApplication::setOrganizationDomain(QStringLiteral("raspot.in")); QGuiApplication::setApplicationName(QStringLiteral("NixOS Workstations Setup")); QGuiApplication::setApplicationVersion(QStringLiteral("1.9.0")); QGuiApplication::setDesktopFileName(QStringLiteral("org.raspot.nixosworkstations.setup")); QCommandLineParser parser; parser.setApplicationDescription(QStringLiteral("Assistant de finalisation NixOS Workstations")); parser.addHelpOption(); parser.addVersionOption(); QCommandLineOption targetUserOption( QStringList { QStringLiteral("u"), QStringLiteral("target-user") }, QStringLiteral("Compte autorisé à exécuter l'assistant."), QStringLiteral("user")); parser.addOption(targetUserOption); QCommandLineOption diagnoseOption( QStringList { QStringLiteral("diagnose") }, QStringLiteral("Affiche l'état de l'assistant puis quitte.")); parser.addOption(diagnoseOption); QCommandLineOption forceUiOption( QStringList { QStringLiteral("force-ui") }, QStringLiteral("Affiche l'interface même si la configuration est déjà terminée.")); parser.addOption(forceUiOption); parser.process(app); const QString targetUser = parser.value(targetUserOption).trimmed(); if (targetUser.isEmpty()) { qCritical().noquote() << "ERREUR: --target-user est obligatoire. Exemple:" << QCoreApplication::applicationName() << "--target-user "; return 2; } ProvisioningBackend provisioning(targetUser); if (parser.isSet(diagnoseOption)) { qInfo().noquote() << QStringLiteral("version=") + QCoreApplication::applicationVersion(); qInfo().noquote() << "current_user=" + provisioning.currentUser(); qInfo().noquote() << "target_user=" + provisioning.targetUser(); qInfo().noquote() << "current_user_utf8_hex=" + QString::fromLatin1(provisioning.currentUser().toUtf8().toHex()); qInfo().noquote() << "target_user_utf8_hex=" + QString::fromLatin1(provisioning.targetUser().toUtf8().toHex()); qInfo().noquote() << "authorized=" + (provisioning.authorizedUser() ? QStringLiteral("yes") : QStringLiteral("no")); qInfo().noquote() << "state_dir=" + provisioning.stateDirectory(); qInfo().noquote() << "password_marker=" + provisioning.passwordMarker(); qInfo().noquote() << "password_done=" + (provisioning.passwordDone() ? QStringLiteral("yes") : QStringLiteral("no")); qInfo().noquote() << "pin_marker=" + provisioning.pinMarker(); qInfo().noquote() << "pin_done=" + (provisioning.pinDone() ? QStringLiteral("yes") : QStringLiteral("no")); qInfo().noquote() << "log=" + provisioning.diagnosticLogPath(); return provisioning.authorizedUser() ? 0 : 3; } // Le lanceur filtre déjà le compte, mais le backend vérifie également. // Contrairement à la V1, on ne quitte plus sans explication. if (!provisioning.authorizedUser()) { qCritical().noquote() << "ERREUR: l'assistant est prévu pour" << provisioning.targetUser() << "mais il est exécuté par" << provisioning.currentUser(); return 3; } if (provisioning.complete() && !parser.isSet(forceUiOption)) { qInfo().noquote() << "NixOS Workstations Setup: configuration déjà terminée." << "Utilisez --force-ui pour afficher l'écran récapitulatif."; return 0; } QIcon::setThemeName(QStringLiteral("breeze")); if (qEnvironmentVariableIsEmpty("QT_QUICK_CONTROLS_STYLE")) { QQuickStyle::setStyle(QStringLiteral("Basic")); } QQmlApplicationEngine engine; engine.rootContext()->setContextProperty(QStringLiteral("provisioning"), &provisioning); engine.loadFromModule(QStringLiteral("org.raspot.nixosworkstations.setup"), QStringLiteral("Main")); if (engine.rootObjects().isEmpty()) { qCritical() << "ERREUR: impossible de charger l'interface QML."; return 4; } return app.exec(); }