소스 검색

Make spawnx as "class" to allow multiple instances

mingodad 6 년 전
부모
커밋
a756d5b3db
1개의 변경된 파일124개의 추가작업 그리고 83개의 파일을 삭제
  1. 124 83
      SquiLu-ext/sq_spawnx.cpp

+ 124 - 83
SquiLu-ext/sq_spawnx.cpp

@@ -11,16 +11,35 @@
 #include "squirrel.h"
 #include "sqstdblobimpl.h"
 
-static char buff[2048];
+#ifdef WIN32
+    #include <windows.h>
+#else
+    #ifdef __cplusplus
+    extern "C" {
+    #endif
+    #include <pty.h>
+    #include <unistd.h>
+    #include <termios.h>
+    #ifdef __cplusplus
+    }
+    #endif
+#endif
+
+struct SQ_SpawnX {
+#ifdef WIN32
+    HANDLE hPipeRead,hWriteSubProcess;
+    PROCESS_INFORMATION pi;
+#else
+    int spawn_fd;
+    int pid;
+    struct termios tm;
+#endif // WIN32
+};
 
 #ifdef WIN32
-#include <windows.h>
-static HANDLE hPipeRead,hWriteSubProcess;
 
-static SQRESULT sq_spawn_open(HSQUIRRELVM v)
+static SQRESULT sq_spawnx_open(HSQUIRRELVM v, SQ_SpawnX *self, const char *cmd)
 {
-    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 = {
@@ -28,7 +47,6 @@ static SQRESULT sq_spawn_open(HSQUIRRELVM v)
 	};
 	HANDLE hRead2,hPipeWrite;
 	BOOL running;
-	PROCESS_INFORMATION pi;
 	HANDLE hProcess = GetCurrentProcess();
 	sa.bInheritHandle = TRUE;
 	sa.lpSecurityDescriptor = NULL;
@@ -39,7 +57,7 @@ static SQRESULT sq_spawn_open(HSQUIRRELVM v)
 
 	// Create pipe for output redirection
 	// read handle, write handle, security attributes,  number of bytes reserved for pipe - 0 default
-	CreatePipe(&hPipeRead, &hPipeWrite, &sa, 0);
+	CreatePipe(&self->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
@@ -48,10 +66,10 @@ static SQRESULT sq_spawn_open(HSQUIRRELVM v)
 
 	hRead2 = NULL;
 	// read handle, write handle, security attributes,  number of bytes reserved for pipe - 0 default
-	CreatePipe(&hRead2, &hWriteSubProcess, &sa, 0);
+	CreatePipe(&hRead2, &self->hWriteSubProcess, &sa, 0);
 
-	SetHandleInformation(hPipeRead, HANDLE_FLAG_INHERIT, 0);
-	SetHandleInformation(hWriteSubProcess, HANDLE_FLAG_INHERIT, 0);
+	SetHandleInformation(self->hPipeRead, HANDLE_FLAG_INHERIT, 0);
+	SetHandleInformation(self->hWriteSubProcess, HANDLE_FLAG_INHERIT, 0);
 
 	si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
 	si.wShowWindow = SW_HIDE;
@@ -61,62 +79,23 @@ static SQRESULT sq_spawn_open(HSQUIRRELVM v)
 
 	running = CreateProcess(
 			  NULL,
-			  (char*)cmd,
+			  (LPSTR)cmd,
 			  NULL, NULL,
 			  TRUE, CREATE_NEW_PROCESS_GROUP,
 			  NULL,
 			  NULL, // start directory
-			  &si, &pi);
+			  &si, &self->pi);
 
 	CloseHandle(pi.hThread);
 	CloseHandle(hRead2);
 	CloseHandle(hPipeWrite);
 
-	if (running) {
-        lua_pushnumber(L,(int)hPipeRead);
-	} else {
-        lua_pushnil(L);
-	}
-	return 1;
+	if (running) return 0;
+    return sq_throwerror(v, _SC("unable to spawn process"));
 }
 
-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
@@ -139,13 +118,10 @@ static char *quote_strtok(char *str, char str_delim)
     return str;
 }
 
-static SQRESULT sq_spawn_open(HSQUIRRELVM v)
+static SQRESULT sq_spawnx_open(HSQUIRRELVM v, SQ_SpawnX *self, const char *cmd)
 {
-    SQ_FUNC_VARS_NO_TOP(v);
-    SQ_GET_STRING(v, 2, cmd);
     const char *args[30];
-    int pid, i = 0;
-    struct termios tm;
+    int i = 0;
     char* argline = strdup(cmd);
     char* arg = quote_strtok(argline,'"');
     if (arg == NULL) return 0;
@@ -155,51 +131,116 @@ static SQRESULT sq_spawn_open(HSQUIRRELVM v)
         arg = quote_strtok(NULL,'"');
     }
     args[i] = NULL;
-    memset(&tm,0,sizeof(tm));
-    cfmakeraw(&tm);
+    memset(&self->tm,0,sizeof(self->tm));
+    cfmakeraw(&self->tm);
     errno = 0;
-    pid = forkpty(&spawn_fd,NULL,&tm,NULL);
-    if (pid == 0) { // child
+    self->pid = forkpty(&self->spawn_fd,NULL,&self->tm,NULL);
+    if (self->pid == 0) { // child
         execvp(args[0], (char*const*)args);
         // if we get here, it's an error!
-        perror("'unable to spawn process");
+        perror("unable to spawn process");
     } else {
-        sq_pushinteger(v,pid);
-        //sq_pushstring(L,strerror(errno));
-        return 1;
+        return 0;
     }
-    return 0;
+    return sq_throwerror(v, _SC("unable to spawn process"));
+}
+#endif
+
+static const SQChar sq_spawnx_TAG[] = _SC("SQ_SpawnX");
+
+static SQRESULT get_spawnx_instance(HSQUIRRELVM v, SQInteger idx, SQ_SpawnX **spawnx_st)
+{
+    if(sq_getinstanceup(v, idx, (SQUserPointer*)spawnx_st, (void*)sq_spawnx_TAG) != SQ_OK) return SQ_ERROR;
+    if(!*spawnx_st) return sq_throwerror(v, _SC("%s"), _SC("spawnx already closed"));
+    return SQ_OK;
+}
+
+#define GET_sq_spawnx_INSTANCE(v, idx) \
+    SQ_SpawnX *self=NULL; \
+    if(get_spawnx_instance(v, idx, &self) != SQ_OK) return SQ_ERROR;
+
+
+static SQRESULT sq_spawnx_releasehook(SQUserPointer p, SQInteger /*size*/, void */*ep*/)
+{
+	SQ_SpawnX *self = ((SQ_SpawnX *)p);
+	if(self)
+    {
+        sq_free(self, sizeof(SQ_SpawnX));
+    }
+	return 1;
+}
+
+static SQRESULT sq_spawnx_constructor(HSQUIRRELVM v)
+{
+	SQ_FUNC_VARS_NO_TOP(v);
+	SQ_GET_STRING(v, 2, cmd);
+
+    SQ_SpawnX *self = (SQ_SpawnX*)sq_malloc(sizeof(SQ_SpawnX));
+
+    _rc_ = sq_spawnx_open(v, self, cmd);
+
+	sq_setinstanceup(v,1,self);
+	sq_setreleasehook(v,1,sq_spawnx_releasehook);
+	return 0;
 }
 
-static SQRESULT sq_spawn_reads(HSQUIRRELVM v)
+static SQRESULT sq_spawnx_read(HSQUIRRELVM v)
 {
-    int sz = read(spawn_fd,buff,sizeof(buff));
-    buff[sz] = '\0';
+    SQ_FUNC_VARS(v);
+    GET_sq_spawnx_INSTANCE(v, 1);
+    SQ_OPT_INTEGER(v, 2, read_sz, 2048);
+    SQChar *buf = sq_getscratchpad(v, read_sz);
+#ifdef WIN32
+    DWORD bytesRead;
+    int res = ReadFile(self->hPipeRead,buf,read_sz, &bytesRead, NULL);
+    if (res == 0) {
+        sq_pushnull(v);
+#else
+    int bytesRead = read(self->spawn_fd, buf, read_sz);
     if (errno != 0) {
         sq_pushinteger(v, errno);
         //sq_pushstring(v,strerror(errno));
+#endif
     } else {
-        sq_pushstring(v,buff, sz);
+        sq_pushstring(v,buf, bytesRead);
     }
     return 1;
 }
 
-static SQRESULT sq_spawn_writes(HSQUIRRELVM v)
+static SQRESULT sq_spawnx_write(HSQUIRRELVM v)
 {
     SQ_FUNC_VARS_NO_TOP(v);
+    GET_sq_spawnx_INSTANCE(v, 1);
     SQ_GET_STRING(v, 2, str);
-    ssize_t n = write(spawn_fd,str,str_size);
+#ifdef WIN32
+    DWORD bytesWrote;
+    WriteFile(self->hWriteSubProcess,str,str_size,&bytesWrote, NULL);
+    sq_pushinteger(v, bytesWrote);
+#else
+    ssize_t n = write(self->spawn_fd,str,str_size);
     sq_pushinteger(v, n);
+#endif
     return 1;
 }
+
+static SQRESULT sq_spawnx_pid(HSQUIRRELVM v)
+{
+    GET_sq_spawnx_INSTANCE(v, 1);
+#ifdef WIN32
+    sq_pushinteger(v, (int)(self->hPipeRead));
+#else
+    sq_pushinteger(v, self->pid);
 #endif
+    return 1;
+}
 
-#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_spawn_##name,nparams,tycheck}
-static SQRegFunction sq_spawn_methods[] =
+#define _DECL_FUNC(name,nparams,tycheck) {_SC(#name), sq_spawnx_##name,nparams,tycheck}
+static SQRegFunction sq_spawnx_methods[] =
 {
-    _DECL_FUNC(open,2,_SC(".s")),
-    _DECL_FUNC(reads,1,_SC(".")),
-    _DECL_FUNC(writes,2,_SC(".s")),
+    _DECL_FUNC(constructor,2,_SC(".s")),
+    _DECL_FUNC(read,-1,_SC("xi")),
+    _DECL_FUNC(write,2,_SC("xs")),
+    _DECL_FUNC(pid,1,_SC("x")),
     {0,0}
 };
 
@@ -209,10 +250,10 @@ extern "C" {
 
 SQRESULT sqext_register_sq_spawnx(HSQUIRRELVM v)
 {
-    sq_pushliteral(v,_SC("sqspawnx"));
-    sq_newtable(v);
-    sq_insert_reg_funcs(v, sq_spawn_methods);
-
+    sq_pushstring(v, sq_spawnx_TAG, -1);
+    sq_newclass(v, SQFalse);
+    sq_settypetag(v,-1,(void*)sq_spawnx_TAG);
+    sq_insert_reg_funcs(v, sq_spawnx_methods);
     sq_newslot(v,-3,SQTrue);
     return 1;
 }