1
0
mirror of https://github.com/VCMP-SqMod/SqMod.git synced 2024-11-08 16:57:16 +01:00
SqMod/source/Library/System.cpp
Sandu Liviu Catalin f300e7ff4a Massive code reduction in the binding utility by using variadic templates.
Extensive code refactoring surrounding the StackStrF helper to facilitate the new changes.
Various other miscellaneous changes and code refactoring to facilitate the new changes.
2018-07-30 00:58:27 +03:00

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);
// Have we failed to retrieve the string?
if (SQ_FAILED(val.Proc(true)))
{
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