mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-08 16:57:16 +01:00
109 lines
3.2 KiB
C++
109 lines
3.2 KiB
C++
// ------------------------------------------------------------------------------------------------
|
|
#include "Library/System.hpp"
|
|
#include "Base/Shared.hpp"
|
|
#include "Base/Buffer.hpp"
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
#include <cstdio>
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include <stdexcept>
|
|
#include <string>
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
namespace SqMod {
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
extern void Register_SysEnv(HSQUIRRELVM vm);
|
|
extern void Register_SysPath(HSQUIRRELVM vm);
|
|
|
|
// ------------------------------------------------------------------------------------------------
|
|
static SQInteger SqSysExec(HSQUIRRELVM vm)
|
|
{
|
|
// Attempt to retrieve the value from the stack as a string
|
|
StackStrF val(vm, 2, true);
|
|
// Have we failed to retrieve the string?
|
|
if (SQ_FAILED(val.mRes))
|
|
{
|
|
return val.mRes; // Propagate the error!
|
|
}
|
|
// Allocate a temp buffer to retrieve chunks from output
|
|
char buffer[128];
|
|
// Allocate a buffer which will contain the final output
|
|
Buffer b(128);
|
|
// Attempt to open the specified process
|
|
FILE * pipe = popen(val.mPtr, "r");
|
|
// The process return status
|
|
Int32 status = -1;
|
|
// Did we fail to open the process?
|
|
if (!pipe)
|
|
{
|
|
return sq_throwerror(vm, ToStrF("Unable to open process [%s]", val.mPtr));
|
|
}
|
|
// Attempt to read process output
|
|
try
|
|
{
|
|
while (!std::feof(pipe))
|
|
{
|
|
if (std::fgets(buffer, 128, pipe) != NULL)
|
|
{
|
|
b.AppendS(buffer);
|
|
}
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
// Close the process
|
|
status = pclose(pipe);
|
|
// Now throw the error
|
|
return sq_throwerror(vm, ToStrF("Unable read process output [%d]", status));
|
|
}
|
|
// Close the process and obtain the exit status
|
|
status = pclose(pipe);
|
|
// Remember the top of the stack
|
|
const Int32 top = sq_gettop(vm);
|
|
// Create a new table on the stack
|
|
sq_newtable(vm);
|
|
// Push the element name
|
|
sq_pushstring(vm, _SC("Status"), -1);
|
|
// Push the element value
|
|
sq_pushinteger(vm, status);
|
|
// Create the element in the table
|
|
SQRESULT res = sq_rawset(vm, -3);
|
|
// Check the result
|
|
if (SQ_FAILED(res))
|
|
{
|
|
// Clean the stack
|
|
sq_settop(vm, top);
|
|
// Return the error
|
|
return res;
|
|
}
|
|
// Push the element name
|
|
sq_pushstring(vm, _SC("Output"), -1);
|
|
// Push the element value
|
|
sq_pushstring(vm, b.Get< SQChar >(), b.Position());
|
|
// Create the element in the table
|
|
res = sq_rawset(vm, -3);
|
|
// Check the result
|
|
if (SQ_FAILED(res))
|
|
{
|
|
// Clean the stack
|
|
sq_settop(vm, top);
|
|
// Return the error
|
|
return res;
|
|
}
|
|
// Specify that we want to return the table we created
|
|
return 1;
|
|
}
|
|
|
|
// ================================================================================================
|
|
void Register_System(HSQUIRRELVM vm)
|
|
{
|
|
Register_SysEnv(vm);
|
|
Register_SysPath(vm);
|
|
|
|
RootTable(vm).SquirrelFunc(_SC("SysExec"), &SqSysExec);
|
|
}
|
|
|
|
} // Namespace:: SqMod
|