summaryrefslogtreecommitdiffstats
path: root/src/VBox/Main/src-server/NetworkServiceRunner.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/VBox/Main/src-server/NetworkServiceRunner.cpp181
1 files changed, 181 insertions, 0 deletions
diff --git a/src/VBox/Main/src-server/NetworkServiceRunner.cpp b/src/VBox/Main/src-server/NetworkServiceRunner.cpp
new file mode 100644
index 00000000..c03f126c
--- /dev/null
+++ b/src/VBox/Main/src-server/NetworkServiceRunner.cpp
@@ -0,0 +1,181 @@
+/* $Id: NetworkServiceRunner.cpp $ */
+/** @file
+ * VirtualBox Main - interface for VBox DHCP server
+ */
+
+/*
+ * Copyright (C) 2009-2019 Oracle Corporation
+ *
+ * This file is part of VirtualBox Open Source Edition (OSE), as
+ * available from http://www.virtualbox.org. This file is free software;
+ * you can redistribute it and/or modify it under the terms of the GNU
+ * General Public License (GPL) as published by the Free Software
+ * Foundation, in version 2 as it comes in the "COPYING" file of the
+ * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
+ * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
+ */
+
+#include <map>
+#include <string>
+#include "NetworkServiceRunner.h"
+#include <iprt/process.h>
+#include <iprt/param.h>
+#include <iprt/env.h>
+#include <iprt/log.h>
+#include <iprt/thread.h>
+
+
+const std::string NetworkServiceRunner::kNsrKeyName = "--name";
+const std::string NetworkServiceRunner::kNsrKeyNetwork = "--network";
+const std::string NetworkServiceRunner::kNsrKeyTrunkType = "--trunk-type";
+const std::string NetworkServiceRunner::kNsrTrunkName = "--trunk-name";
+const std::string NetworkServiceRunner::kNsrMacAddress = "--mac-address";
+const std::string NetworkServiceRunner::kNsrIpAddress = "--ip-address";
+const std::string NetworkServiceRunner::kNsrIpNetmask = "--netmask";
+const std::string NetworkServiceRunner::kNsrKeyNeedMain = "--need-main";
+
+struct NetworkServiceRunner::Data
+{
+ Data(const char* aProcName)
+ : mProcName(aProcName)
+ , mProcess(NIL_RTPROCESS)
+ , mKillProcOnStop(false)
+ {}
+ const char *mProcName;
+ RTPROCESS mProcess;
+ std::map<std::string, std::string> mOptions;
+ bool mKillProcOnStop;
+};
+
+NetworkServiceRunner::NetworkServiceRunner(const char *aProcName)
+{
+ m = new NetworkServiceRunner::Data(aProcName);
+}
+
+
+NetworkServiceRunner::~NetworkServiceRunner()
+{
+ stop();
+ delete m;
+ m = NULL;
+}
+
+
+int NetworkServiceRunner::setOption(const std::string& key, const std::string& val)
+{
+ m->mOptions.insert(std::map<std::string, std::string>::value_type(key, val));
+ return VINF_SUCCESS;
+}
+
+
+void NetworkServiceRunner::clearOptions()
+{
+ m->mOptions.clear();
+}
+
+
+void NetworkServiceRunner::detachFromServer()
+{
+ m->mProcess = NIL_RTPROCESS;
+}
+
+
+int NetworkServiceRunner::start(bool aKillProcOnStop)
+{
+ if (isRunning())
+ return VINF_ALREADY_INITIALIZED;
+
+ const char * args[10*2];
+
+ AssertReturn(m->mOptions.size() < 10, VERR_INTERNAL_ERROR);
+
+ /* get the path to the executable */
+ char exePathBuf[RTPATH_MAX];
+ const char *exePath = RTProcGetExecutablePath(exePathBuf, RTPATH_MAX);
+ char *substrSl = strrchr(exePathBuf, '/');
+ char *substrBs = strrchr(exePathBuf, '\\');
+ char *suffix = substrSl ? substrSl : substrBs;
+
+ if (suffix)
+ {
+ suffix++;
+ strcpy(suffix, m->mProcName);
+ }
+
+ int index = 0;
+
+ args[index++] = exePath;
+
+ std::map<std::string, std::string>::const_iterator it;
+ for(it = m->mOptions.begin(); it != m->mOptions.end(); ++it)
+ {
+ args[index++] = it->first.c_str();
+ args[index++] = it->second.c_str();
+ }
+
+ args[index++] = NULL;
+
+ int rc = RTProcCreate(suffix ? exePath : m->mProcName, args, RTENV_DEFAULT, 0, &m->mProcess);
+ if (RT_FAILURE(rc))
+ m->mProcess = NIL_RTPROCESS;
+
+ m->mKillProcOnStop = aKillProcOnStop;
+ return rc;
+}
+
+
+int NetworkServiceRunner::stop()
+{
+ /*
+ * If the process already terminated, this function will also grab the exit
+ * status and transition the process out of zombie status.
+ */
+ if (!isRunning())
+ return VINF_OBJECT_DESTROYED;
+
+ bool fDoKillProc = true;
+
+ if (!m->mKillProcOnStop)
+ {
+ /*
+ * This is a VBoxSVC Main client. Do NOT kill it but assume it was shut
+ * down politely. Wait up to 1 second until the process is killed before
+ * doing the final hard kill.
+ */
+ int rc = VINF_SUCCESS;
+ for (unsigned int i = 0; i < 100; i++)
+ {
+ rc = RTProcWait(m->mProcess, RTPROCWAIT_FLAGS_NOBLOCK, NULL);
+ if (RT_SUCCESS(rc))
+ break;
+ RTThreadSleep(10);
+ }
+ if (rc != VERR_PROCESS_RUNNING)
+ fDoKillProc = false;
+ }
+
+ if (fDoKillProc)
+ {
+ RTProcTerminate(m->mProcess);
+ int rc = RTProcWait(m->mProcess, RTPROCWAIT_FLAGS_BLOCK, NULL);
+ NOREF(rc);
+ }
+
+ m->mProcess = NIL_RTPROCESS;
+ return VINF_SUCCESS;
+}
+
+bool NetworkServiceRunner::isRunning()
+{
+ if (m->mProcess == NIL_RTPROCESS)
+ return false;
+
+ RTPROCSTATUS status;
+ int rc = RTProcWait(m->mProcess, RTPROCWAIT_FLAGS_NOBLOCK, &status);
+
+ if (rc == VERR_PROCESS_RUNNING)
+ return true;
+
+ m->mProcess = NIL_RTPROCESS;
+ return false;
+}