#include "shutdown.h" #include #include #include #ifdef _WIN32 #include #else #include #include #include #endif namespace SystemShutdown { #ifndef _WIN32 // Función auxiliar para sistemas Unix-like auto executeUnixShutdown(const char* command, const std::vector& args) -> ShutdownResult { pid_t pid = fork(); if (pid == 0) { // Proceso hijo execvp(command, args.data()); // Si llegamos aquí, execvp falló std::cerr << "Error: No se pudo ejecutar " << command << '\n'; _exit(1); } else if (pid > 0) { // Proceso padre int status; waitpid(pid, &status, 0); return (WEXITSTATUS(status) == 0) ? ShutdownResult::SUCCESS : ShutdownResult::ERROR_SYSTEM_CALL; } else { return ShutdownResult::ERROR_FORK_FAILED; } } #endif // Implementación de las funciones públicas auto shutdownSystem() -> ShutdownResult { ShutdownConfig config; return shutdownSystem(config); } auto shutdownSystem(int delay_seconds, bool force_apps) -> ShutdownResult { ShutdownConfig config; config.delay_seconds = delay_seconds; config.force_close_apps = force_apps; return shutdownSystem(config); } auto shutdownSystem(const ShutdownConfig& config) -> ShutdownResult { #ifdef _WIN32 // Windows: Usar CreateProcess STARTUPINFOA si = {0}; PROCESS_INFORMATION pi = {0}; si.cb = sizeof(si); // Crear comando con el delay especificado std::string command = "shutdown.exe /s /t " + std::to_string(config.delay_seconds); if (config.force_close_apps) { command += " /f"; } // CreateProcess necesita un array de char modificable char* cmd_buffer = new char[command.length() + 1]; strcpy(cmd_buffer, command.c_str()); bool success = CreateProcessA( NULL, // lpApplicationName cmd_buffer, // lpCommandLine NULL, // lpProcessAttributes NULL, // lpThreadAttributes FALSE, // bInheritHandles 0, // dwCreationFlags NULL, // lpEnvironment NULL, // lpCurrentDirectory &si, // lpStartupInfo &pi // lpProcessInformation ); delete[] cmd_buffer; if (success) { CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return ShutdownResult::SUCCESS; } else { DWORD error = GetLastError(); if (error == ERROR_ACCESS_DENIED) { return ShutdownResult::ERROR_PERMISSION; } return ShutdownResult::ERROR_SYSTEM_CALL; } #elif __APPLE__ // macOS - apagado inmediato std::vector args = { const_cast("shutdown"), const_cast("-h"), const_cast("now"), nullptr}; return executeUnixShutdown("shutdown", args); #elif __linux__ // Linux - apagado inmediato std::vector args = { const_cast("shutdown"), const_cast("-h"), const_cast("now"), nullptr}; return executeUnixShutdown("shutdown", args); #else return ShutdownResult::ERROR_UNSUPPORTED; #endif } auto resultToString(ShutdownResult result) -> const char* { switch (result) { case ShutdownResult::SUCCESS: return "Apagado iniciado exitosamente"; case ShutdownResult::ERROR_PERMISSION: return "Error: Permisos insuficientes"; case ShutdownResult::ERROR_SYSTEM_CALL: return "Error: Fallo en la llamada al sistema"; case ShutdownResult::ERROR_FORK_FAILED: return "Error: No se pudo crear proceso hijo"; case ShutdownResult::ERROR_UNSUPPORTED: return "Error: Sistema operativo no soportado"; default: return "Error desconocido"; } } auto isShutdownSupported() -> bool { #if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) return true; #else return false; #endif } auto getRequiredPermissions() -> const char* { #ifdef _WIN32 return "Requiere permisos de Administrador en Windows"; #elif defined(__APPLE__) || defined(__linux__) return "Requiere permisos de root/sudo en Unix"; #else return "Sistema no soportado"; #endif } } // namespace SystemShutdown