Przeglądaj źródła

Add an extension to create a read/write pipe to a process

mingodad 7 lat temu
rodzic
commit
2647a62551
2 zmienionych plików z 227 dodań i 0 usunięć
  1. 223 0
      SquiLu-ext/sq_spawnx.cpp
  2. 4 0
      SquiLu/sq/sq.c

+ 223 - 0
SquiLu-ext/sq_spawnx.cpp

@@ -0,0 +1,223 @@
+//adapted from http://mysite.mweb.co.za/residents/sdonovan/lua/lua-gdb.zip
+#ifdef SQ_USE_SPAWNX
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "squirrel.h"
+#include "sqstdblobimpl.h"
+
+static char buff[2048];
+
+#ifdef WIN32
+#include <windows.h>
+static HANDLE hPipeRead,hWriteSubProcess;
+
+static SQRESULT sq_spawn_open(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, cmd);
+	SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), 0, 0};
+	SECURITY_DESCRIPTOR sd;
+	STARTUPINFO si = {
+		sizeof(STARTUPINFO), 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+	};
+	HANDLE hRead2,hPipeWrite;
+	BOOL running;
+	PROCESS_INFORMATION pi;
+	HANDLE hProcess = GetCurrentProcess();
+	sa.bInheritHandle = TRUE;
+	sa.lpSecurityDescriptor = NULL;
+	InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
+	SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE);
+	sa.nLength = sizeof(SECURITY_ATTRIBUTES);
+	sa.lpSecurityDescriptor = &sd;
+
+	// Create pipe for output redirection
+	// read handle, write handle, security attributes,  number of bytes reserved for pipe - 0 default
+	CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0);
+
+	// Create pipe for input redirection. In this code, you do not
+	// redirect the output of the child process, but you need a handle
+	// to set the hStdInput field in the STARTUP_INFO struct. For safety,
+	// you should not set the handles to an invalid handle.
+
+	hRead2 = NULL;
+	// read handle, write handle, security attributes,  number of bytes reserved for pipe - 0 default
+	CreatePipe(&hRead2, &hWriteSubProcess, &sa, 0);
+
+	SetHandleInformation(hPipeRead, HANDLE_FLAG_INHERIT, 0);
+	SetHandleInformation(hWriteSubProcess, HANDLE_FLAG_INHERIT, 0);
+
+	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
+	si.wShowWindow = SW_HIDE;
+	si.hStdInput = hRead2;
+	si.hStdOutput = hPipeWrite;
+	si.hStdError = hPipeWrite;
+
+	running = CreateProcess(
+			  NULL,
+			  (char*)cmd,
+			  NULL, NULL,
+			  TRUE, CREATE_NEW_PROCESS_GROUP,
+			  NULL,
+			  NULL, // start directory
+			  &si, &pi);
+
+	CloseHandle(pi.hThread);
+	CloseHandle(hRead2);
+	CloseHandle(hPipeWrite);
+
+	if (running) {
+        lua_pushnumber(L,(int)hPipeRead);
+	} else {
+        lua_pushnil(L);
+	}
+	return 1;
+}
+
+static SQRESULT sq_spawn_reads(HSQUIRRELVM v)
+{
+    DWORD bytesRead;
+    int res = ReadFile(hPipeRead,buff,sizeof(buff), &bytesRead, NULL);
+    buff[bytesRead] = '\0';
+    if (res == 0) {
+        sq_pushnull(v);
+    } else {
+        sq_pushstring(L,buff, bytesRead);
+    }
+    return 1;
+}
+
+static SQRESULT sq_spawn_writes(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, str);
+    DWORD bytesWrote;
+    WriteFile(hWriteSubProcess,str,str_size,&bytesWrote, NULL);
+    sq_pushinteger(v, bytesWrote);
+    return 1;
+}
+#else
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+#include <pty.h>
+#include <unistd.h>
+#include <termios.h>
+#ifdef __cplusplus
+}
+#endif
+
+
+static int spawn_fd;
+
+static char *quote_strtok(char *str, char str_delim)
+{
+// a specialized version of strtok() which treats quoted strings specially
+// (used for handling command-line parms)
+    static char *tok;
+    if(str != NULL) tok = str;
+
+    while (*tok && isspace(*tok)) tok++;
+    if (*tok == '\0') return NULL;
+
+    if (*tok == str_delim) {
+       tok++;            // skip "
+       str = tok;
+       while (*tok && *tok != str_delim) tok++;
+    } else {
+       str = tok;
+       while (*tok && ! isspace(*tok)) tok++;
+    }
+    if (*tok) *tok++ = '\0';
+    return str;
+}
+
+static SQRESULT sq_spawn_open(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, cmd);
+    const char *args[30];
+    int pid, i = 0;
+    struct termios tm;
+    char* argline = strdup(cmd);
+    char* arg = quote_strtok(argline,'"');
+    if (arg == NULL) return 0;
+    while (arg != NULL) {
+        args[i++] = arg;
+        //fprintf(stderr,"%d %s\n",i,arg);
+        arg = quote_strtok(NULL,'"');
+    }
+    args[i] = NULL;
+    memset(&tm,0,sizeof(tm));
+    cfmakeraw(&tm);
+    errno = 0;
+    pid = forkpty(&spawn_fd,NULL,&tm,NULL);
+    if (pid == 0) { // child
+        execvp(args[0], (char*const*)args);
+        // if we get here, it's an error!
+        perror("'unable to spawn process");
+    } else {
+        sq_pushinteger(v,pid);
+        //sq_pushstring(L,strerror(errno));
+        return 1;
+    }
+    return 0;
+}
+
+static SQRESULT sq_spawn_reads(HSQUIRRELVM v)
+{
+    int sz = read(spawn_fd,buff,sizeof(buff));
+    buff[sz] = '\0';
+    if (errno != 0) {
+        sq_pushinteger(v, errno);
+        //sq_pushstring(v,strerror(errno));
+    } else {
+        sq_pushstring(v,buff, sz);
+    }
+    return 1;
+}
+
+static SQRESULT sq_spawn_writes(HSQUIRRELVM v)
+{
+    SQ_FUNC_VARS_NO_TOP(v);
+    SQ_GET_STRING(v, 2, str);
+    ssize_t n = write(spawn_fd,str,str_size);
+    sq_pushinteger(v, n);
+    return 1;
+}
+#endif
+
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_spawn_##name,nparams,tycheck}
+static SQRegFunction sq_spawn_methods[] =
+{
+    _DECL_FUNC(open,2,_SC(".s")),
+    _DECL_FUNC(reads,1,_SC(".")),
+    _DECL_FUNC(writes,2,_SC(".s")),
+    {0,0}
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SQRESULT sqext_register_sq_spawnx(HSQUIRRELVM v)
+{
+    sq_pushliteral(v,_SC("sqspawnx"));
+    sq_newtable(v);
+    sq_insert_reg_funcs(v, sq_spawn_methods);
+
+    sq_newslot(v,-3,SQTrue);
+    return 1;
+}
+#ifdef __cplusplus
+}
+#endif
+
+#endif // SQ_USE_SPAWNX

+ 4 - 0
SquiLu/sq/sq.c

@@ -634,6 +634,7 @@ SQRESULT sqext_register_numarray (HSQUIRRELVM v);
 SQRESULT sqext_register_fann (HSQUIRRELVM v);
 SQRESULT sqext_register_numarray (HSQUIRRELVM v);
 SQRESULT sqext_register_Snowball (HSQUIRRELVM v);
+SQRESULT sqext_register_sq_spawnx(HSQUIRRELVM v);
 
 static sq_modules_preload_st modules_preload[] = {
     {"blob", sqstd_register_bloblib},
@@ -685,6 +686,9 @@ static sq_modules_preload_st modules_preload[] = {
 #ifdef SQ_USE_BLOSC
     {"blosc", sqext_register_sq_blosc},
 #endif // SQ_USE_BLOSC
+#ifdef SQ_USE_SPAWNX
+    {"sqspawnx", sqext_register_sq_spawnx},
+#endif // SQ_USE_SPAWNX
 #ifdef SQ_USE_LAPACK
     {"lapack", sqext_register_lapack},
 #endif // SQ_USE_LAPACK