157 lines
4.4 KiB
C++
157 lines
4.4 KiB
C++
#include "shutdown.hpp"
|
|
|
|
#include <sys/types.h> // Para pid_t
|
|
|
|
#include <cstdlib> // Para WEXITSTATUS
|
|
#include <iostream> // Para char_traits, basic_ostream, operator<<, cerr
|
|
#include <vector> // Para vector
|
|
|
|
#ifdef _WIN32
|
|
#include <windows.h>
|
|
#else
|
|
#include <sys/wait.h> // Para waitpid
|
|
#include <unistd.h> // Para _exit, execvp, fork
|
|
#endif
|
|
|
|
namespace SystemShutdown {
|
|
|
|
#ifndef _WIN32
|
|
// Función auxiliar para sistemas Unix-like
|
|
auto executeUnixShutdown(const char* command, const std::vector<char*>& 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<char*> args = {
|
|
const_cast<char*>("shutdown"),
|
|
const_cast<char*>("-h"),
|
|
const_cast<char*>("now"),
|
|
nullptr};
|
|
|
|
return executeUnixShutdown("shutdown", args);
|
|
|
|
#elif __linux__
|
|
// Linux - apagado inmediato
|
|
std::vector<char*> args = {
|
|
const_cast<char*>("shutdown"),
|
|
const_cast<char*>("-h"),
|
|
const_cast<char*>("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
|