aboutsummaryrefslogtreecommitdiff
path: root/src/zen/cmds/service_cmd.cpp
diff options
context:
space:
mode:
authorDan Engelbrecht <[email protected]>2025-09-05 13:02:27 +0200
committerGitHub Enterprise <[email protected]>2025-09-05 13:02:27 +0200
commit45b0307d42b22e04cee63467a8fdb898a2d8d552 (patch)
tree905b3eb62af89269be5b15f4c407d900ce86f7f3 /src/zen/cmds/service_cmd.cpp
parentAvoid mutating executable paths when copying files during full service instal... (diff)
downloadarchived-zen-45b0307d42b22e04cee63467a8fdb898a2d8d552.tar.xz
archived-zen-45b0307d42b22e04cee63467a8fdb898a2d8d552.zip
refactor zen command return value handling (#487)
- Improvement: Use consistent language for command line argument parsing errors - Improvement: Changed zen command parsing errors to output help first and error last to make it easier to spot the error - Improvement: Refactor zen command return codes to conform to valid Linux range (0-255) kSuccess = 0, kOtherError = 1, kBadInput = 2, kOutOfMemory = 16, kOutOfDisk = 17, kAssertError = 70, kHttpOtherClientError = 80, kHttpCantConnectError = 81, kHttpNotFound = 66, // NotFound(404) kHttpUnauthorized = 77, // Unauthorized(401), kHttpSLLError = 82, kHttpForbidden = 83, // Forbidden(403) kHttpTimeout = 84, // RequestTimeout(408) kHttpConflict = 85, // Conflict(409) kHttpNoHost = 86, kHttpOtherServerError = 90, kHttpInternalServerError = 91, // InternalServerError(500) kHttpServiceUnavailable = 69, // ServiceUnavailable(503) kHttpBadGateway = 92, // BadGateway(502) kHttpGatewayTimeout = 93, // GatewayTimeout(504)
Diffstat (limited to 'src/zen/cmds/service_cmd.cpp')
-rw-r--r--src/zen/cmds/service_cmd.cpp136
1 files changed, 56 insertions, 80 deletions
diff --git a/src/zen/cmds/service_cmd.cpp b/src/zen/cmds/service_cmd.cpp
index 398bbfc83..cf3a0bcd0 100644
--- a/src/zen/cmds/service_cmd.cpp
+++ b/src/zen/cmds/service_cmd.cpp
@@ -52,7 +52,7 @@ namespace {
return fRet;
}
- int WinRelaunchElevated()
+ void WinRelaunchElevated()
{
TCHAR CurrentDir[4096];
GetCurrentDirectory(4096, CurrentDir);
@@ -75,27 +75,26 @@ namespace {
shExInfo.nShow = SW_SHOW;
shExInfo.hInstApp = 0;
- DWORD ReturnCode = 1;
+ DWORD ProcessReturnCode = 1;
if (ShellExecuteEx(&shExInfo))
{
WaitForSingleObject(shExInfo.hProcess, INFINITE);
- GetExitCodeProcess(shExInfo.hProcess, &ReturnCode);
+ GetExitCodeProcess(shExInfo.hProcess, &ProcessReturnCode);
CloseHandle(shExInfo.hProcess);
- if (ReturnCode == 0)
+ if (ProcessReturnCode == 0)
{
ZEN_CONSOLE("Elevated execution completed successfully.");
}
else
{
- ZEN_CONSOLE("Elevated execution completed unsuccessfully, return code: '{}'.", ReturnCode);
+ throw ErrorWithReturnCode(fmt::format("Elevated execution completed unsuccessfully, return code: '{}'.", ProcessReturnCode),
+ (int)ProcessReturnCode);
}
}
else
{
- ZEN_CONSOLE("Failed to run elevated, operation did not complete.");
- ReturnCode = DWORD(-1);
+ ThrowLastError("Failed to run elevated, operation did not complete");
}
- return (int)ReturnCode;
}
#else // ZEN_PLATFORM_WINDOWS
@@ -104,25 +103,23 @@ namespace {
#endif // ZEN_PLATFORM_WINDOWS
- int RunElevated(bool AllowElevation)
+ void RunElevated(bool AllowElevation)
{
#if ZEN_PLATFORM_WINDOWS
if (AllowElevation)
{
- return WinRelaunchElevated();
+ WinRelaunchElevated();
}
else
{
- ZEN_CONSOLE(
+ throw std::runtime_error(fmt::format(
"This command requires elevated priviliges. Run command with elevated priviliges or add '--allow-elevation' command line "
- "option.");
- return 1;
+ "option."));
}
#endif // ZEN_PLATFORM_WINDOWS
#if ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
ZEN_UNUSED(AllowElevation);
- ZEN_CONSOLE("This command requires elevated priviliges. Run the command with `sudo`");
- return 1;
+ throw std::runtime_error(fmt::format("This command requires elevated priviliges. Run the command with `sudo`"));
#endif // ZEN_PLATFORM_LINUX || ZEN_PLATFORM_MAC
}
@@ -295,11 +292,9 @@ enum class ServiceStatusReturnCode
UnknownError
};
-int
+void
ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
- ZEN_UNUSED(GlobalOptions);
-
using namespace std::literals;
std::vector<char*> SubCommandArguments;
@@ -307,17 +302,17 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
int ParentCommandArgCount = GetSubCommand(m_Options, argc, argv, m_SubCommands, SubOption, SubCommandArguments);
if (!ParseOptions(ParentCommandArgCount, argv))
{
- return 0;
+ return;
}
if (SubOption == nullptr)
{
- throw zen::OptionParseException("command verb is missing");
+ throw OptionParseException("'verb' option is required", m_Options.help());
}
if (!ParseOptions(*SubOption, gsl::narrow<int>(SubCommandArguments.size()), SubCommandArguments.data()))
{
- return 0;
+ return;
}
if (SubOption == &m_StatusOptions)
@@ -326,18 +321,15 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
std::error_code Ec = QueryInstalledService(m_ServiceName, Info);
if (Ec)
{
- ZEN_CONSOLE("Can't get information about service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
- return gsl::narrow<int>(ServiceStatusReturnCode::UnknownError);
+ throw std::runtime_error(fmt::format("Can't get information about service '{}'. Reason: '{}'", m_ServiceName, Ec.message()));
}
if (Info.Status == ServiceStatus::NotInstalled)
{
- ZEN_CONSOLE("Service '{}' is not installed", m_ServiceName);
- return gsl::narrow<int>(ServiceStatusReturnCode::NotInstalled);
+ throw std::runtime_error(fmt::format("Service '{}' is not installed", m_ServiceName));
}
else if (Info.Status != ServiceStatus::Running)
{
- ZEN_CONSOLE("Service '{}' is not running", m_ServiceName);
- return gsl::narrow<int>(ServiceStatusReturnCode::NotRunning);
+ throw std::runtime_error(fmt::format("Service '{}' is not running", m_ServiceName));
}
else
{
@@ -349,7 +341,8 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
if (!IsElevated())
{
- return RunElevated(m_AllowElevation);
+ RunElevated(m_AllowElevation);
+ return;
}
ServiceInfo Info;
@@ -363,12 +356,10 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
Ec = StopService(m_ServiceName);
if (Ec)
{
- ZEN_CONSOLE("Failed to stop service '{}' using '{}'. Reason: '{}'",
- m_ServiceName,
- m_ServerExecutable,
- Ec.message());
-
- return 1;
+ throw std::runtime_error(fmt::format("Failed to stop service '{}' using '{}'. Reason: '{}'",
+ m_ServiceName,
+ m_ServerExecutable,
+ Ec.message()));
}
int Timeout = 30000; // Wait up to 30 seconds for the service to fully stop before uninstalling
@@ -377,8 +368,7 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
Ec = QueryInstalledService(m_ServiceName, Info);
if (Ec)
{
- ZEN_CONSOLE("Failed to wait for service to stop: '{}'", Ec.message());
- return 1;
+ throw std::runtime_error(fmt::format("Failed to wait for service to stop: '{}'", Ec.message()));
}
if (Info.Status == ServiceStatus::Stopped)
@@ -392,26 +382,23 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
if (Info.Status != ServiceStatus::Stopped)
{
- ZEN_CONSOLE("Timed out waiting for service to stop");
- return 1;
+ throw std::runtime_error("Timed out waiting for service to stop");
}
}
Ec = UninstallService(m_ServiceName);
if (Ec)
{
- ZEN_CONSOLE("Failed to uninstall running service '{}' using '{}'. Reason: '{}'",
- m_ServiceName,
- m_ServerExecutable,
- Ec.message());
-
- return 1;
+ throw std::runtime_error(fmt::format("Failed to uninstall running service '{}' using '{}'. Reason: '{}'",
+ m_ServiceName,
+ m_ServerExecutable,
+ Ec.message()));
}
}
else
{
ZEN_CONSOLE("Service '{}' already installed:\n{}", m_ServiceName, FmtServiceInfo(Info, " "));
- return 1;
+ return;
}
}
if (m_ServerExecutable.empty())
@@ -426,7 +413,7 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
{
if (m_InstallPath.empty())
{
- throw zen::OptionParseException("--full requires --install-path to be specified");
+ throw OptionParseException("'--full' requires '--install-path'", SubOption->help());
}
std::filesystem::path ExePath = zen::GetRunningExecutablePath();
@@ -451,8 +438,7 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
if (!std::filesystem::is_directory(m_InstallPath) && !CreateDirectories(m_InstallPath))
{
- ZEN_CONSOLE("Unable to create install directory '{}'", m_InstallPath);
- return 1;
+ throw std::runtime_error(fmt::format("Unable to create install directory '{}'", m_InstallPath));
}
for (const std::filesystem::path& File : FilesToCopy)
@@ -461,8 +447,7 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
if (!CopyFile(File, Destination, {.EnableClone = false}))
{
- ZEN_CONSOLE("Failed to copy '{}' to '{}'", File, Destination);
- return 1;
+ throw std::runtime_error(fmt::format("Failed to copy '{}' to '{}'", File, Destination));
}
ZEN_INFO("Copied '{}' to '{}'", File, Destination);
@@ -487,8 +472,8 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
});
if (Ec)
{
- ZEN_CONSOLE("Failed to install service '{}' using '{}' . Reason: '{}'", m_ServiceName, m_ServerExecutable, Ec.message());
- return 1;
+ throw std::runtime_error(
+ fmt::format("Failed to install service '{}' using '{}' . Reason: '{}'", m_ServiceName, m_ServerExecutable, Ec.message()));
}
ZEN_CONSOLE("Installed service '{}' using '{}' successfully", m_ServiceName, m_ServerExecutable);
@@ -497,8 +482,7 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
Ec = StartService(m_ServiceName);
if (Ec)
{
- ZEN_CONSOLE("Failed to start service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
- return 1;
+ throw std::runtime_error(fmt::format("Failed to start service '{}'. Reason: '{}'", m_ServiceName, Ec.message()));
}
}
}
@@ -509,30 +493,28 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
std::error_code Ec = QueryInstalledService(m_ServiceName, Info);
if (Ec)
{
- ZEN_CONSOLE("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
- return 1;
+ throw std::runtime_error(fmt::format("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message()));
}
if (Info.Status == ServiceStatus::NotInstalled)
{
ZEN_CONSOLE("Service '{}' is not installed", m_ServiceName);
- return 0;
+ return;
}
if (Info.Status != ServiceStatus::Stopped)
{
- ZEN_CONSOLE("Service '{}' is running, stop before uninstalling", m_ServiceName);
- return 0;
+ throw std::runtime_error(fmt::format("Service '{}' is running, stop before uninstalling", m_ServiceName));
}
if (!IsElevated())
{
- return RunElevated(m_AllowElevation);
+ RunElevated(m_AllowElevation);
+ return;
}
Ec = UninstallService(m_ServiceName);
if (Ec)
{
- ZEN_CONSOLE("Failed to uninstall service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
- return 1;
+ throw std::runtime_error(fmt::format("Failed to uninstall service '{}'. Reason: '{}'", m_ServiceName, Ec.message()));
}
ZEN_CONSOLE("Uninstalled service {} successfully", m_ServiceName);
}
@@ -543,30 +525,28 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
std::error_code Ec = QueryInstalledService(m_ServiceName, Info);
if (Ec)
{
- ZEN_CONSOLE("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
- return 1;
+ throw std::runtime_error(fmt::format("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message()));
}
if (Info.Status == ServiceStatus::NotInstalled)
{
- ZEN_CONSOLE("Service '{}' is not installed", m_ServiceName);
- return 1;
+ throw std::runtime_error(fmt::format("Service '{}' is not installed", m_ServiceName));
}
if (Info.Status != ServiceStatus::Stopped)
{
ZEN_CONSOLE("Service '{}' is already running", m_ServiceName);
- return 1;
+ return;
}
if (!IsElevated())
{
- return RunElevated(m_AllowElevation);
+ RunElevated(m_AllowElevation);
+ return;
}
Ec = StartService(m_ServiceName);
if (Ec)
{
- ZEN_CONSOLE("Failed to start service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
- return 1;
+ throw std::runtime_error(fmt::format("Failed to start service '{}'. Reason: '{}'", m_ServiceName, Ec.message()));
}
ZEN_CONSOLE("Started service '{}' successfully", m_ServiceName);
}
@@ -577,35 +557,31 @@ ServiceCommand::Run(const ZenCliOptions& GlobalOptions, int argc, char** argv)
std::error_code Ec = QueryInstalledService(m_ServiceName, Info);
if (Ec)
{
- ZEN_CONSOLE("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
- return 1;
+ throw std::runtime_error(fmt::format("Failed to inspect installed service '{}'. Reason: '{}'", m_ServiceName, Ec.message()));
}
if (Info.Status == ServiceStatus::NotInstalled)
{
- ZEN_CONSOLE("Service '{}' is not installed", m_ServiceName);
- return 1;
+ throw std::runtime_error(fmt::format("Service '{}' is not installed", m_ServiceName));
}
if (Info.Status != ServiceStatus::Running)
{
ZEN_CONSOLE("Service '{}' is not running", m_ServiceName);
- return 1;
+ return;
}
if (!IsElevated())
{
- return RunElevated(m_AllowElevation);
+ RunElevated(m_AllowElevation);
+ return;
}
Ec = StopService(m_ServiceName);
if (Ec)
{
- ZEN_CONSOLE("Failed to stop service '{}'. Reason: '{}'", m_ServiceName, Ec.message());
- return 1;
+ throw std::runtime_error(fmt::format("Failed to stop service '{}'. Reason: '{}'", m_ServiceName, Ec.message()));
}
ZEN_CONSOLE("Stopped service '{}' successfully", m_ServiceName);
}
-
- return 0;
}
} // namespace zen