mirror of
https://github.com/exo-explore/exo.git
synced 2026-02-04 11:11:45 -05:00
Compare commits
1 Commits
main
...
JakeHillio
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4891f72a3 |
@@ -14,7 +14,6 @@ import SwiftUI
|
||||
import UserNotifications
|
||||
import os.log
|
||||
|
||||
@main
|
||||
struct EXOApp: App {
|
||||
@StateObject private var controller: ExoProcessController
|
||||
@StateObject private var stateService: ClusterStateService
|
||||
|
||||
@@ -288,6 +288,61 @@ enum NetworkSetupHelper {
|
||||
"""
|
||||
}
|
||||
|
||||
/// Direct install without GUI (requires root).
|
||||
/// Returns true on success, false on failure.
|
||||
static func installDirectly() -> Bool {
|
||||
let script = makeInstallerScript()
|
||||
return runShellDirectly(script)
|
||||
}
|
||||
|
||||
/// Direct uninstall without GUI (requires root).
|
||||
/// Returns true on success, false on failure.
|
||||
static func uninstallDirectly() -> Bool {
|
||||
let script = makeUninstallScript()
|
||||
return runShellDirectly(script)
|
||||
}
|
||||
|
||||
/// Run a shell script directly via Process (no AppleScript, requires root).
|
||||
/// Returns true on success, false on failure.
|
||||
private static func runShellDirectly(_ script: String) -> Bool {
|
||||
let process = Process()
|
||||
process.executableURL = URL(fileURLWithPath: "/bin/bash")
|
||||
process.arguments = ["-c", script]
|
||||
|
||||
let outputPipe = Pipe()
|
||||
let errorPipe = Pipe()
|
||||
process.standardOutput = outputPipe
|
||||
process.standardError = errorPipe
|
||||
|
||||
do {
|
||||
try process.run()
|
||||
process.waitUntilExit()
|
||||
|
||||
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
|
||||
let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
|
||||
|
||||
if let output = String(data: outputData, encoding: .utf8), !output.isEmpty {
|
||||
print(output)
|
||||
}
|
||||
if let errorOutput = String(data: errorData, encoding: .utf8), !errorOutput.isEmpty {
|
||||
fputs(errorOutput, stderr)
|
||||
}
|
||||
|
||||
if process.terminationStatus == 0 {
|
||||
logger.info("Shell script completed successfully")
|
||||
return true
|
||||
} else {
|
||||
logger.error("Shell script failed with exit code \(process.terminationStatus)")
|
||||
return false
|
||||
}
|
||||
} catch {
|
||||
logger.error(
|
||||
"Failed to run shell script: \(error.localizedDescription, privacy: .public)")
|
||||
fputs("Error: \(error.localizedDescription)\n", stderr)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
private static func runShellAsAdmin(_ script: String) throws {
|
||||
let escapedScript =
|
||||
script
|
||||
|
||||
85
app/EXO/EXO/main.swift
Normal file
85
app/EXO/EXO/main.swift
Normal file
@@ -0,0 +1,85 @@
|
||||
//
|
||||
// main.swift
|
||||
// EXO
|
||||
//
|
||||
// Created by Jake Hillion on 2025-02-03.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
/// Command line options for the EXO app
|
||||
enum CLICommand {
|
||||
case install
|
||||
case uninstall
|
||||
case help
|
||||
case none
|
||||
}
|
||||
|
||||
/// Parse command line arguments to determine the CLI command
|
||||
func parseArguments() -> CLICommand {
|
||||
let args = CommandLine.arguments
|
||||
if args.contains("--help") || args.contains("-h") {
|
||||
return .help
|
||||
}
|
||||
if args.contains("--install") {
|
||||
return .install
|
||||
}
|
||||
if args.contains("--uninstall") {
|
||||
return .uninstall
|
||||
}
|
||||
return .none
|
||||
}
|
||||
|
||||
/// Print usage information
|
||||
func printUsage() {
|
||||
let programName = (CommandLine.arguments.first as NSString?)?.lastPathComponent ?? "EXO"
|
||||
print(
|
||||
"""
|
||||
Usage: \(programName) [OPTIONS]
|
||||
|
||||
Options:
|
||||
--install Install EXO network configuration (requires root)
|
||||
--uninstall Uninstall EXO network configuration (requires root)
|
||||
--help, -h Show this help message
|
||||
|
||||
When run without options, starts the normal GUI application.
|
||||
|
||||
Examples:
|
||||
sudo \(programName) --install Install network components as root
|
||||
sudo \(programName) --uninstall Remove network components as root
|
||||
""")
|
||||
}
|
||||
|
||||
/// Check if running as root
|
||||
func isRunningAsRoot() -> Bool {
|
||||
return getuid() == 0
|
||||
}
|
||||
|
||||
// Main entry point
|
||||
let command = parseArguments()
|
||||
|
||||
switch command {
|
||||
case .help:
|
||||
printUsage()
|
||||
exit(0)
|
||||
|
||||
case .install:
|
||||
if !isRunningAsRoot() {
|
||||
fputs("Error: --install requires root privileges. Run with sudo.\n", stderr)
|
||||
exit(1)
|
||||
}
|
||||
let success = NetworkSetupHelper.installDirectly()
|
||||
exit(success ? 0 : 1)
|
||||
|
||||
case .uninstall:
|
||||
if !isRunningAsRoot() {
|
||||
fputs("Error: --uninstall requires root privileges. Run with sudo.\n", stderr)
|
||||
exit(1)
|
||||
}
|
||||
let success = NetworkSetupHelper.uninstallDirectly()
|
||||
exit(success ? 0 : 1)
|
||||
|
||||
case .none:
|
||||
// Start normal GUI application
|
||||
EXOApp.main()
|
||||
}
|
||||
Reference in New Issue
Block a user