diff --git a/js/common/bootstrap/module-internal.js b/js/common/bootstrap/module-internal.js index b034c9f85c..a717518f86 100644 --- a/js/common/bootstrap/module-internal.js +++ b/js/common/bootstrap/module-internal.js @@ -19,7 +19,7 @@ COLOR_BOLD_MAGENTA, PRETTY_PRINT, VALGRIND, VERSION, UPGRADE, BYTES_SENT_DISTRIBUTION, BYTES_RECEIVED_DISTRIBUTION, CONNECTION_TIME_DISTRIBUTION, REQUEST_TIME_DISTRIBUTION, DEVELOPMENT_MODE, THREAD_NUMBER, LOGFILE_PATH, - SYS_PLATFORM */ + SYS_PLATFORM, SYS_EXECUTE_EXTERNAL, SYS_STATUS_EXTERNAL, SYS_KILL_EXTERNAL */ //////////////////////////////////////////////////////////////////////////////// /// @brief module "internal" @@ -662,6 +662,33 @@ delete SYS_HTTP_STATISTICS; } +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates an external process +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_EXECUTE_EXTERNAL !== "undefined") { + exports.executeExternal = SYS_EXECUTE_EXTERNAL; + delete SYS_EXECUTE_EXTERNAL; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief kills an external process +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_KILL_EXTERNAL !== "undefined") { + exports.killExternal = SYS_KILL_EXTERNAL; + delete SYS_KILL_EXTERNAL; + } + +//////////////////////////////////////////////////////////////////////////////// +/// @brief checks a status of an external process +//////////////////////////////////////////////////////////////////////////////// + + if (typeof SYS_STATUS_EXTERNAL !== "undefined") { + exports.statusExternal = SYS_STATUS_EXTERNAL; + delete SYS_STATUS_EXTERNAL; + } + // ----------------------------------------------------------------------------- // --SECTION-- private functions // ----------------------------------------------------------------------------- diff --git a/lib/BasicsC/process-utils.c b/lib/BasicsC/process-utils.c index 297f10eae5..6a47c16cd4 100644 --- a/lib/BasicsC/process-utils.c +++ b/lib/BasicsC/process-utils.c @@ -42,17 +42,13 @@ #endif #include "BasicsC/tri-strings.h" +#include "BasicsC/locks.h" #include "BasicsC/logging.h" // ----------------------------------------------------------------------------- // --SECTION-- private types // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup SystemProcess -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief contains all data documented by "proc" /// @@ -124,19 +120,10 @@ process_state_t; #endif -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - // ----------------------------------------------------------------------------- // --SECTION-- private variables // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup SystemProcess -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief original process name //////////////////////////////////////////////////////////////////////////////// @@ -178,18 +165,142 @@ static bool MustFreeEnvironment = false; static size_t MaximalProcessTitleSize = 0; //////////////////////////////////////////////////////////////////////////////// -/// @} +/// @brief all external processes //////////////////////////////////////////////////////////////////////////////// +static TRI_vector_pointer_t ExternalProcesses; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief lock for protected access to vector ExternalProcesses +//////////////////////////////////////////////////////////////////////////////// + +static TRI_mutex_t ExternalProcessesLock; + +// ----------------------------------------------------------------------------- +// --SECTION-- private functions +// ----------------------------------------------------------------------------- + +//////////////////////////////////////////////////////////////////////////////// +/// @brief creates pipe pair +//////////////////////////////////////////////////////////////////////////////// + +static bool CreatePipes (int* pipe_server_to_child, + int* pipe_child_to_server) { + + if (pipe(pipe_server_to_child) == -1) { + LOG_ERROR("cannot create pipe"); + return false; + } + + if (pipe(pipe_child_to_server) == -1) { + LOG_ERROR("cannot create pipe"); + + close(pipe_server_to_child[0]); + close(pipe_server_to_child[1]); + + return false; + } + + return true; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief starts external process +//////////////////////////////////////////////////////////////////////////////// + +static void StartExternalProcess (TRI_external_t* external, bool usePipes) { + int pipe_server_to_child[2]; + int pipe_child_to_server[2]; + int processPid; + bool ok; + + if (usePipes) { + ok = CreatePipes(pipe_server_to_child, pipe_child_to_server); + + if (! ok) { + external->_status = TRI_EXT_PIPE_FAILED; + return; + } + } + + processPid = fork(); + + // child process + if (processPid == 0) { + + // set stdin and stdout of child process + if (usePipes) { + dup2(pipe_server_to_child[0], 0); + dup2(pipe_child_to_server[1], 1); + + fcntl(0, F_SETFD, 0); + fcntl(1, F_SETFD, 0); + fcntl(2, F_SETFD, 0); + + // close pipes + close(pipe_server_to_child[0]); + close(pipe_server_to_child[1]); + close(pipe_child_to_server[0]); + close(pipe_child_to_server[1]); + } + else { + close(0); + fcntl(1, F_SETFD, 0); + fcntl(2, F_SETFD, 0); + } + + // ignore signals in worker process + signal(SIGINT, SIG_IGN); + signal(SIGTERM, SIG_IGN); + signal(SIGHUP, SIG_IGN); + signal(SIGUSR1, SIG_IGN); + + // execute worker + execv(external->_executable, external->_arguments); + + // should not happen + LOG_ERROR("execution of '%s' failed with %d", external->_executable, errno); + + exit(1); + } + + // parent + if (processPid == -1) { + LOG_ERROR("fork failed"); + + if (usePipes) { + close(pipe_server_to_child[0]); + close(pipe_server_to_child[1]); + close(pipe_child_to_server[0]); + close(pipe_child_to_server[1]); + } + + external->_status = TRI_EXT_FORK_FAILED; + return; + } + + LOG_DEBUG("fork succeeded %d", processPid); + + if (usePipes) { + close(pipe_server_to_child[0]); + close(pipe_child_to_server[1]); + + external->_writePipe = pipe_server_to_child[1]; + external->_readPipe = pipe_child_to_server[0]; + } + else { + external->_writePipe = -1; + external->_readPipe = -1; + } + + external->_pid = processPid; + external->_status = TRI_EXT_RUNNING; +} + // ----------------------------------------------------------------------------- // --SECTION-- public functions // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup SystemProcess -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief converts usec and sec into seconds //////////////////////////////////////////////////////////////////////////////// @@ -472,22 +583,148 @@ void TRI_SetProcessTitle (char const* title) { } //////////////////////////////////////////////////////////////////////////////// -/// @} +/// @brief starts an external process //////////////////////////////////////////////////////////////////////////////// +TRI_external_id_t TRI_CreateExternalProcess (const char* executable, + const char** arguments, + size_t n) { + TRI_external_t* external; + TRI_external_id_t pid; + size_t i; + + // create the external structure + external = TRI_Allocate(TRI_CORE_MEM_ZONE, sizeof(TRI_external_t), true); + + external->_executable = TRI_DuplicateString(executable); + external->_numberArguments = n; + + external->_arguments = TRI_Allocate(TRI_CORE_MEM_ZONE, (n + 2) * sizeof(char*), true); + external->_arguments[0] = TRI_DuplicateString(executable); + + for (i = 0; i < n; ++i) { + external->_arguments[i + 1] = TRI_DuplicateString(arguments[i]); + } + + external->_arguments[n + 1] = NULL; + external->_status = TRI_EXT_NOT_STARTED; + + StartExternalProcess(external, false); + + TRI_LockMutex(&ExternalProcessesLock); + TRI_PushBackVectorPointer(&ExternalProcesses, external); + pid = external->_pid; + TRI_UnlockMutex(&ExternalProcessesLock); + + return pid; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the status of an external process +//////////////////////////////////////////////////////////////////////////////// + +TRI_external_status_t TRI_CheckExternalProcess (pid_t pid) { + TRI_external_status_t status; + TRI_external_t* external; + int loc; + int opts; + pid_t res; + size_t i; + + TRI_LockMutex(&ExternalProcessesLock); + + status._status = TRI_EXT_NOT_FOUND; + status._exitStatus = 0; + + for (i = 0; i < ExternalProcesses._length; ++i) { + external = TRI_AtVectorPointer(&ExternalProcesses, i); + + if (external->_pid == pid) { + break; + } + } + + if (i == ExternalProcesses._length) { + TRI_UnlockMutex(&ExternalProcessesLock); + return status; + } + + if (external->_status == TRI_EXT_RUNNING || external->_status == TRI_EXT_STOPPED) { + opts = WNOHANG | WUNTRACED; + res = waitpid(external->_pid, &loc, opts); + + if (res == 0) { + external->_exitStatus = 0; + } + else if (WIFEXITED(loc)) { + external->_status = TRI_EXT_TERMINATED; + external->_exitStatus = WEXITSTATUS(loc); + } + else if (WIFSIGNALED(loc)) { + external->_status = TRI_EXT_ABORTED; + external->_exitStatus = 0; + } + else if (WIFSTOPPED(loc)) { + external->_status = TRI_EXT_STOPPED; + external->_exitStatus = 0; + } + } + + status._status = external->_status; + status._exitStatus = external->_exitStatus; + + TRI_UnlockMutex(&ExternalProcessesLock); + return status; +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief kills an external process +//////////////////////////////////////////////////////////////////////////////// + +void TRI_KillExternalProcess (pid_t pid) { + TRI_external_t* external; + size_t i; + + TRI_LockMutex(&ExternalProcessesLock); + + for (i = 0; i < ExternalProcesses._length; ++i) { + external = TRI_AtVectorPointer(&ExternalProcesses, i); + + if (external->_pid == pid) { + break; + } + } + + if (i == ExternalProcesses._length) { + TRI_UnlockMutex(&ExternalProcessesLock); + return; + } + + if (external->_status == TRI_EXT_RUNNING || external->_status == TRI_EXT_STOPPED) { + int val = kill(external->_pid , SIGKILL); + + if (val) { + external->_status = TRI_EXT_KILL_FAILED; + } + else { + TRI_RemoveVectorPointer(&ExternalProcesses, i); + } + } + else { + TRI_RemoveVectorPointer(&ExternalProcesses, i); + } + + TRI_UnlockMutex(&ExternalProcessesLock); +} + // ----------------------------------------------------------------------------- // --SECTION-- MODULE // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- -// --SECTION-- public functions +// --SECTION-- modules initialisation // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup SystemProcess -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief initialises the process components //////////////////////////////////////////////////////////////////////////////// @@ -500,10 +737,13 @@ void TRI_InitialiseProcess (int argc, char* argv[]) { ProcessName = TRI_DuplicateString(argv[0]); ARGC = argc; ARGV = argv; + + TRI_InitVectorPointer(&ExternalProcesses, TRI_CORE_MEM_ZONE); + TRI_InitMutex(&ExternalProcessesLock); } //////////////////////////////////////////////////////////////////////////////// -/// @brief shut downs the process components +/// @brief shuts down the process components //////////////////////////////////////////////////////////////////////////////// void TRI_ShutdownProcess () { @@ -523,11 +763,14 @@ void TRI_ShutdownProcess () { TRI_Free(TRI_CORE_MEM_ZONE, environ); } #endif + + TRI_DestroyVectorPointer(&ExternalProcesses); + TRI_DestroyMutex(&ExternalProcessesLock); } -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- // Local Variables: // mode: outline-minor diff --git a/lib/BasicsC/process-utils.h b/lib/BasicsC/process-utils.h index 0f94a5bcfe..04ce8398bc 100644 --- a/lib/BasicsC/process-utils.h +++ b/lib/BasicsC/process-utils.h @@ -40,30 +40,16 @@ extern "C" { // --SECTION-- public constants // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup SystemProcess -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief invalid process //////////////////////////////////////////////////////////////////////////////// #define INVALID_PROCESS (0) -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - // ----------------------------------------------------------------------------- // --SECTION-- public types // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup SystemProcess -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief returns information about the process //////////////////////////////////////////////////////////////////////////////// @@ -81,18 +67,61 @@ typedef struct TRI_process_info_s { TRI_process_info_t; //////////////////////////////////////////////////////////////////////////////// -/// @} +/// @brief status of an external process //////////////////////////////////////////////////////////////////////////////// +typedef enum { + TRI_EXT_NOT_STARTED = 0, // not yet started + TRI_EXT_PIPE_FAILED = 1, // pipe before start failed + TRI_EXT_FORK_FAILED = 2, // fork failed + TRI_EXT_RUNNING = 3, // running + TRI_EXT_NOT_FOUND = 4, // unknown pid + TRI_EXT_TERMINATED = 5, // process has terminated normally + TRI_EXT_ABORTED = 6, // process has terminated abnormally + TRI_EXT_STOPPED = 7, // process has been stopped + TRI_EXT_KILL_FAILED = 8, // kill failed +} +TRI_external_status_e; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief identifier of an external process +//////////////////////////////////////////////////////////////////////////////// + +typedef pid_t TRI_external_id_t; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief external process description +//////////////////////////////////////////////////////////////////////////////// + +typedef struct TRI_external_s { + char* _executable; + size_t _numberArguments; + char** _arguments; + + TRI_external_id_t _pid; + + int _readPipe; + int _writePipe; + + TRI_external_status_e _status; + int _exitStatus; +} +TRI_external_t; + +//////////////////////////////////////////////////////////////////////////////// +/// @brief external process status +//////////////////////////////////////////////////////////////////////////////// + +typedef struct TRI_external_status_s { + TRI_external_status_e _status; + int _exitStatus; +} +TRI_external_status_t; + // ----------------------------------------------------------------------------- // --SECTION-- public functions // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup SystemProcess -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief converts usec and sec into seconds //////////////////////////////////////////////////////////////////////////////// @@ -132,22 +161,33 @@ uint64_t TRI_ProcessSize (TRI_pid_t pid); void TRI_SetProcessTitle (char const* title); //////////////////////////////////////////////////////////////////////////////// -/// @} +/// @brief starts an external process //////////////////////////////////////////////////////////////////////////////// +TRI_external_id_t TRI_CreateExternalProcess (const char* executable, + const char** arguments, + size_t n); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the status of an external process +//////////////////////////////////////////////////////////////////////////////// + +TRI_external_status_t TRI_CheckExternalProcess (pid_t pid); + +//////////////////////////////////////////////////////////////////////////////// +/// @brief kills an external process +//////////////////////////////////////////////////////////////////////////////// + +void TRI_KillExternalProcess (pid_t pid); + // ----------------------------------------------------------------------------- // --SECTION-- MODULE // ----------------------------------------------------------------------------- // ----------------------------------------------------------------------------- -// --SECTION-- public functions +// --SECTION-- modules initialisation // ----------------------------------------------------------------------------- -//////////////////////////////////////////////////////////////////////////////// -/// @addtogroup SystemProcess -/// @{ -//////////////////////////////////////////////////////////////////////////////// - //////////////////////////////////////////////////////////////////////////////// /// @brief initialises the process components //////////////////////////////////////////////////////////////////////////////// @@ -160,16 +200,16 @@ void TRI_InitialiseProcess (int argc, char* argv[]); void TRI_ShutdownProcess (void); -//////////////////////////////////////////////////////////////////////////////// -/// @} -//////////////////////////////////////////////////////////////////////////////// - #ifdef __cplusplus } #endif #endif +// ----------------------------------------------------------------------------- +// --SECTION-- END-OF-FILE +// ----------------------------------------------------------------------------- + // Local Variables: // mode: outline-minor // outline-regexp: "/// @brief\\|/// {@inheritDoc}\\|/// @addtogroup\\|/// @page\\|// --SECTION--\\|/// @\\}" diff --git a/lib/V8/v8-utils.cpp b/lib/V8/v8-utils.cpp index cc92c8a853..62c0e4e791 100644 --- a/lib/V8/v8-utils.cpp +++ b/lib/V8/v8-utils.cpp @@ -458,6 +458,7 @@ static v8::Handle JS_Download (v8::Arguments const& argv) { } v8::Handle options = v8::Handle::Cast(argv[2]); + if (options.IsEmpty()) { TRI_V8_EXCEPTION_USAGE(scope, signature); } @@ -647,11 +648,12 @@ static v8::Handle JS_Download (v8::Arguments const& argv) { map::const_iterator it; v8::Handle headers = v8::Object::New(); + for (it = responseHeaders.begin(); it != responseHeaders.end(); ++it) { headers->Set(v8::String::New((*it).first.c_str()), v8::String::New((*it).second.c_str())); } - result->Set(v8::String::New("headers"), headers); + result->Set(v8::String::New("headers"), headers); if (returnBodyOnError || (returnCode >= 200 && returnCode <= 299)) { try { @@ -2360,6 +2362,136 @@ static v8::Handle JS_HttpStatistics (v8::Arguments const& argv) { return scope.Close(result); } +//////////////////////////////////////////////////////////////////////////////// +/// @brief executes a external program +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_ExecuteExternal (v8::Arguments const& argv) { + v8::HandleScope scope; + + // extract the arguments + if (2 < argv.Length() || argv.Length() < 1) { + TRI_V8_EXCEPTION_USAGE(scope, "executeExternal(, [])"); + } + + TRI_Utf8ValueNFC name(TRI_UNKNOWN_MEM_ZONE, argv[0]); + + if (*name == 0) { + TRI_V8_TYPE_ERROR(scope, " must be a string"); + } + + char** arguments = 0; + size_t n = 0; + + if (2 <= argv.Length()) { + v8::Handle a = argv[1]; + + if (a->IsArray()) { + v8::Handle arr = v8::Handle::Cast(a); + + n = arr->Length(); + arguments = (char**) TRI_Allocate(TRI_CORE_MEM_ZONE, n * sizeof(char*), false); + + for (size_t i = 0; i < n; ++i) { + TRI_Utf8ValueNFC arg(TRI_UNKNOWN_MEM_ZONE, arr->Get(i)); + + if (*arg == 0) { + arguments[i] = TRI_DuplicateString(""); + } + else { + arguments[i] = TRI_DuplicateString(*arg); + } + } + } + else { + n = 1; + arguments = (char**) TRI_Allocate(TRI_CORE_MEM_ZONE, n * sizeof(char*), false); + + TRI_Utf8ValueNFC arg(TRI_UNKNOWN_MEM_ZONE, a); + + if (*arg == 0) { + arguments[0] = TRI_DuplicateString(""); + } + else { + arguments[0] = TRI_DuplicateString(*arg); + } + } + } + + TRI_external_id_t external = TRI_CreateExternalProcess(*name, (const char**) arguments, n); + + if (arguments != 0) { + for (size_t i = 0; i < n; ++i) { + TRI_FreeString(TRI_CORE_MEM_ZONE, arguments[i]); + } + + TRI_Free(TRI_CORE_MEM_ZONE, arguments); + } + + // return the result + return scope.Close(v8::Number::New(external)); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief returns the status of an external process +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_StatusExternal (v8::Arguments const& argv) { + v8::HandleScope scope; + + // extract the arguments + if (argv.Length() != 1) { + TRI_V8_EXCEPTION_USAGE(scope, "statusExternal()"); + } + + TRI_external_id_t pid = TRI_ObjectToUInt64(argv[0], true); + TRI_external_status_t external = TRI_CheckExternalProcess(pid); + + v8::Handle result = v8::Object::New(); + const char* status = "UNKNOWN"; + + switch (external._status) { + case TRI_EXT_NOT_STARTED: status = "NOT-STARTED"; break; + case TRI_EXT_PIPE_FAILED: status = "FAILED"; break; + case TRI_EXT_FORK_FAILED: status = "FAILED"; break; + case TRI_EXT_RUNNING: status = "RUNNING"; break; + case TRI_EXT_NOT_FOUND: status = "NOT-FOUND"; break; + case TRI_EXT_TERMINATED: status = "TERMINATED"; break; + case TRI_EXT_ABORTED: status = "ABORTED"; break; + case TRI_EXT_STOPPED: status = "STOPPED"; break; + case TRI_EXT_KILL_FAILED: status = "ZOMBIE"; break; + } + + result->Set(v8::String::New("status"), v8::String::New(status)); + + if (external._status == TRI_EXT_TERMINATED) { + result->Set(v8::String::New("exit"), v8::Number::New(external._exitStatus)); + } + + // return the result + return scope.Close(result); +} + +//////////////////////////////////////////////////////////////////////////////// +/// @brief kills an external process +//////////////////////////////////////////////////////////////////////////////// + +static v8::Handle JS_KillExternal (v8::Arguments const& argv) { + v8::HandleScope scope; + + // extract the arguments + if (argv.Length() != 1) { + TRI_V8_EXCEPTION_USAGE(scope, "killExternal()"); + } + + TRI_external_id_t pid = TRI_ObjectToUInt64(argv[0], true); + + TRI_KillExternalProcess(pid); + + // return the result + return scope.Close(v8::Undefined()); +} + //////////////////////////////////////////////////////////////////////////////// /// @brief ArangoError //////////////////////////////////////////////////////////////////////////////// @@ -2706,7 +2838,7 @@ v8::Handle TRI_CreateErrorObject (int errorNumber, string const& mes } //////////////////////////////////////////////////////////////////////////////// -/// @brief normalize a v8 object +/// @brief normalizes a v8 object //////////////////////////////////////////////////////////////////////////////// v8::Handle TRI_normalize_V8_Obj (v8::Handle obj) { @@ -2842,20 +2974,22 @@ void TRI_InitV8Utils (v8::Handle context, TRI_AddGlobalFunctionVocbase(context, "SYS_BASE64DECODE", JS_Base64Decode); TRI_AddGlobalFunctionVocbase(context, "SYS_BASE64ENCODE", JS_Base64Encode); + TRI_AddGlobalFunctionVocbase(context, "SYS_CHECK_AND_MARK_NONCE", JS_MarkNonce); TRI_AddGlobalFunctionVocbase(context, "SYS_CLIENT_STATISTICS", JS_ClientStatistics); + TRI_AddGlobalFunctionVocbase(context, "SYS_CREATE_NONCE", JS_CreateNonce); TRI_AddGlobalFunctionVocbase(context, "SYS_DOWNLOAD", JS_Download); TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE", JS_Execute); + TRI_AddGlobalFunctionVocbase(context, "SYS_EXECUTE_EXTERNAL", JS_ExecuteExternal); + TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_ALPHA_NUMBERS", JS_RandomAlphaNum); + TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_NUMBERS", JS_RandomNumbers); + TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_SALT", JS_RandomSalt); TRI_AddGlobalFunctionVocbase(context, "SYS_GETLINE", JS_Getline); + TRI_AddGlobalFunctionVocbase(context, "SYS_HTTP_STATISTICS", JS_HttpStatistics); + TRI_AddGlobalFunctionVocbase(context, "SYS_KILL_EXTERNAL", JS_KillExternal); TRI_AddGlobalFunctionVocbase(context, "SYS_LOAD", JS_Load); TRI_AddGlobalFunctionVocbase(context, "SYS_LOG", JS_Log); TRI_AddGlobalFunctionVocbase(context, "SYS_LOG_LEVEL", JS_LogLevel); TRI_AddGlobalFunctionVocbase(context, "SYS_MD5", JS_Md5); - TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_NUMBERS", JS_RandomNumbers); - TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_ALPHA_NUMBERS", JS_RandomAlphaNum); - TRI_AddGlobalFunctionVocbase(context, "SYS_GEN_RANDOM_SALT", JS_RandomSalt); - TRI_AddGlobalFunctionVocbase(context, "SYS_HTTP_STATISTICS", JS_HttpStatistics); - TRI_AddGlobalFunctionVocbase(context, "SYS_CREATE_NONCE", JS_CreateNonce); - TRI_AddGlobalFunctionVocbase(context, "SYS_CHECK_AND_MARK_NONCE", JS_MarkNonce); TRI_AddGlobalFunctionVocbase(context, "SYS_OUTPUT", JS_Output); TRI_AddGlobalFunctionVocbase(context, "SYS_PARSE", JS_Parse); TRI_AddGlobalFunctionVocbase(context, "SYS_PROCESS_STATISTICS", JS_ProcessStatistics); @@ -2866,6 +3000,7 @@ void TRI_InitV8Utils (v8::Handle context, TRI_AddGlobalFunctionVocbase(context, "SYS_SERVER_STATISTICS", JS_ServerStatistics); TRI_AddGlobalFunctionVocbase(context, "SYS_SHA256", JS_Sha256); TRI_AddGlobalFunctionVocbase(context, "SYS_SPRINTF", JS_SPrintF); + TRI_AddGlobalFunctionVocbase(context, "SYS_STATUS_EXTERNAL", JS_StatusExternal); TRI_AddGlobalFunctionVocbase(context, "SYS_TIME", JS_Time); TRI_AddGlobalFunctionVocbase(context, "SYS_WAIT", JS_Wait);