#include "shutdown.h" #include #ifdef _WIN32 #include #else #include #include #include #endif namespace SystemShutdown { #ifndef _WIN32 // Función auxiliar para sistemas Unix-like ShutdownResult executeUnixShutdown(const char* command, char* const args[]) { pid_t pid = fork(); if (pid == 0) { // Proceso hijo execvp(command, args); // Si llegamos aquí, execvp falló std::cerr << "Error: No se pudo ejecutar " << command << std::endl; _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 ShutdownResult shutdownSystem() { ShutdownConfig config; return shutdownSystem(config); } ShutdownResult shutdownSystem(int delay_seconds, bool force_apps) { ShutdownConfig config; config.delay_seconds = delay_seconds; config.force_close_apps = force_apps; return shutdownSystem(config); } ShutdownResult shutdownSystem(const ShutdownConfig& config) { #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 char* args[] = { const_cast("shutdown"), const_cast("-h"), const_cast("now"), NULL }; return executeUnixShutdown("shutdown", args); #elif __linux__ // Linux - apagado inmediato char* args[] = { const_cast("shutdown"), const_cast("-h"), const_cast("now"), NULL }; return executeUnixShutdown("shutdown", args); #else return ShutdownResult::ERROR_UNSUPPORTED; #endif } const char* resultToString(ShutdownResult result) { 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"; } } bool isShutdownSupported() { #if defined(_WIN32) || defined(__APPLE__) || defined(__linux__) return true; #else return false; #endif } const char* getRequiredPermissions() { #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