ecore_exe for Windows.
authorcaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 16 Oct 2009 09:17:26 +0000 (09:17 +0000)
committercaro <caro@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Fri, 16 Oct 2009 09:17:26 +0000 (09:17 +0000)
Not complete yet but it executes a command and kills it
TODO: pipes

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/ecore@43112 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/ecore/Ecore.h
src/lib/ecore/Makefile.am
src/lib/ecore/ecore_exe_win32.c [new file with mode: 0644]
src/lib/ecore/ecore_private.h

index b654fd7..b1e2145 100644 (file)
@@ -120,9 +120,7 @@ extern "C" {
      };
    typedef enum _Ecore_Poller_Type Ecore_Poller_Type;
 
-#ifndef _WIN32
    typedef void Ecore_Exe; /**< A handle for spawned processes */
-#endif
    typedef void Ecore_Timer; /**< A handle for timers */
    typedef void Ecore_Idler; /**< A handle for idlers */
    typedef void Ecore_Idle_Enterer; /**< A handle for idle enterers */
@@ -246,7 +244,6 @@ extern "C" {
    EAPI void                *ecore_event_current_event_get(void);
 
 
-#ifndef _WIN32
    EAPI void        ecore_exe_run_priority_set(int pri);
    EAPI int         ecore_exe_run_priority_get(void);
    EAPI Ecore_Exe  *ecore_exe_run(const char *exe_cmd, const void *data);
@@ -270,7 +267,6 @@ extern "C" {
    EAPI void        ecore_exe_kill(Ecore_Exe *exe);
    EAPI void        ecore_exe_signal(Ecore_Exe *exe, int num);
    EAPI void        ecore_exe_hup(Ecore_Exe *exe);
-#endif
 
    EAPI Ecore_Idler *ecore_idler_add(int (*func) (void *data), const void *data);
    EAPI void        *ecore_idler_del(Ecore_Idler *idler);
index 46369f8..bf8d839 100644 (file)
@@ -16,6 +16,7 @@ ecore_anim.c \
 ecore_app.c \
 ecore_events.c \
 ecore_exe.c \
+ecore_exe_win32.c \
 ecore_getopt.c \
 ecore_hash.c \
 ecore_idle_enterer.c \
diff --git a/src/lib/ecore/ecore_exe_win32.c b/src/lib/ecore/ecore_exe_win32.c
new file mode 100644 (file)
index 0000000..d77ae32
--- /dev/null
@@ -0,0 +1,392 @@
+/*
+ * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
+ */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#undef WIN32_LEAN_AND_MEAN
+
+#include "ecore_private.h"
+#include "Ecore.h"
+
+#ifdef _WIN32
+
+#define ECORE_EXE_WIN32_TIMEOUT 3000
+
+typedef enum
+{
+  ECORE_EXE_WIN32_SIGINT,
+  ECORE_EXE_WIN32_SIGQUIT,
+  ECORE_EXE_WIN32_SIGTERM,
+  ECORE_EXE_WIN32_SIGKILL
+} Ecore_Exe_Win32_Signal;
+
+struct _Ecore_Exe
+{
+   EINA_INLIST;
+   ECORE_MAGIC;
+
+   HANDLE process; /* CloseHandle */
+   HANDLE thread;
+   DWORD  process_id;
+   DWORD  thread_id;
+   void  *data;
+   char  *tag;
+   char  *cmd;
+   Ecore_Exe_Win32_Signal sig;
+   int    is_suspended : 1;
+};
+
+static Ecore_Exe *exes = NULL;
+
+static BOOL CALLBACK _ecore_exe_enum_windows_procedure(HWND window, LPARAM data);
+
+void
+_ecore_exe_init(void)
+{
+/*    ECORE_EXE_EVENT_ADD = ecore_event_type_new(); */
+/*    ECORE_EXE_EVENT_DEL = ecore_event_type_new(); */
+/*    ECORE_EXE_EVENT_DATA = ecore_event_type_new(); */
+/*    ECORE_EXE_EVENT_ERROR = ecore_event_type_new(); */
+}
+
+void
+_ecore_exe_shutdown(void)
+{
+   while (exes)
+      ecore_exe_free(exes);
+}
+
+EAPI void ecore_exe_run_priority_set(int pri)
+{
+}
+
+EAPI int ecore_exe_run_priority_get(void)
+{
+}
+
+EAPI Ecore_Exe *ecore_exe_run(const char *exe_cmd, const void *data)
+{
+   return ecore_exe_pipe_run(exe_cmd, 0, data);
+}
+
+EAPI Ecore_Exe *ecore_exe_pipe_run(const char *exe_cmd, Ecore_Exe_Flags flags, const void *data)
+{
+   STARTUPINFO         si;
+   PROCESS_INFORMATION pi;
+   Ecore_Exe          *exe;
+   char               *ret = NULL;
+
+   exe = calloc(1, sizeof(Ecore_Exe));
+   if (!exe)
+     return NULL;
+
+   if ((flags & ECORE_EXE_USE_SH) ||
+       ((ret = strrchr(exe_cmd, ".bat")) && (ret[4] == '\0')))
+     {
+        char buf[PATH_MAX];
+        snprintf(buf, PATH_MAX, "cmd.exe /c %s", exe_cmd);
+        exe->cmd = strdup(buf);
+     }
+   else
+     exe->cmd = strdup(exe_cmd);
+
+   if (!exe->cmd)
+     goto free_exe;
+
+   ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
+
+   ZeroMemory(&si, sizeof(STARTUPINFO));
+   si.cb = sizeof(STARTUPINFO); 
+/*    si.hStdError = g_hChildStd_OUT_Wr; */
+/*    si.hStdOutput = g_hChildStd_OUT_Wr; */
+/*    si.hStdInput = g_hChildStd_IN_Rd; */
+/*    si.dwFlags |= STARTF_USESTDHANDLES; */
+
+   /* FIXME: gerer la priorite */
+
+   if (!CreateProcess(NULL, exe->cmd, NULL, NULL, TRUE,
+                      0, NULL, NULL, &si, &pi))
+     goto free_exe_cmd;
+
+   exe->thread = pi.hThread;
+   exe->process_id = pi.dwProcessId;
+   exe->thread_id = pi.dwThreadId;
+   exe->data = (void *)data;
+   CloseHandle(pi.hProcess);
+
+   if (!(exe->process = OpenProcess(PROCESS_SUSPEND_RESUME | PROCESS_TERMINATE | SYNCHRONIZE,
+                                    FALSE, pi.dwProcessId)))
+     goto close_thread;
+
+   exes = (Ecore_Exe *)eina_inlist_append(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
+   return exe;
+
+ close_thread:
+   CloseHandle(pi.hThread);
+ free_exe_cmd:
+   free(exe->cmd);
+ free_exe:
+   free(exe);
+   return NULL;
+}
+
+EAPI int ecore_exe_send(Ecore_Exe *exe, void *data, int size)
+{
+}
+
+EAPI void ecore_exe_close_stdin(Ecore_Exe *exe)
+{
+}
+
+EAPI void ecore_exe_auto_limits_set(Ecore_Exe *exe, int start_bytes, int end_bytes, int start_lines, int end_lines)
+{
+}
+
+EAPI Ecore_Exe_Event_Data *ecore_exe_event_data_get(Ecore_Exe *exe, Ecore_Exe_Flags flags)
+{
+}
+
+EAPI void ecore_exe_event_data_free(Ecore_Exe_Event_Data *data)
+{
+}
+
+EAPI void *ecore_exe_free(Ecore_Exe *exe)
+{
+   void *data;
+
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_free");
+       return NULL;
+     }
+
+   data = exe->data;
+
+   CloseHandle(exe->process);
+   CloseHandle(exe->thread);
+   free(exe->cmd);
+   exes = (Ecore_Exe *) eina_inlist_remove(EINA_INLIST_GET(exes), EINA_INLIST_GET(exe));
+   ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE);
+   if (exe->tag) free(exe->tag);
+   free(exe);
+
+   return data;
+}
+
+EAPI pid_t ecore_exe_pid_get(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pid_get");
+       return -1;
+     }
+   return exe->process_id;
+}
+
+EAPI void ecore_exe_tag_set(Ecore_Exe *exe, const char *tag)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_set");
+       return;
+     }
+   IF_FREE(exe->tag);
+   if (tag)
+      exe->tag = strdup(tag);
+}
+
+EAPI char *ecore_exe_tag_get(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_tag_get");
+       return NULL;
+     }
+   return exe->tag;
+}
+
+EAPI char *ecore_exe_cmd_get(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_cmd_get");
+       return NULL;
+     }
+   return exe->cmd;
+}
+
+EAPI void *ecore_exe_data_get(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_data_get");
+       return NULL;
+     }
+   return exe->data;
+}
+
+EAPI void ecore_exe_pause(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_pause");
+       return;
+     }
+
+   if (exe->is_suspended)
+     return;
+
+   if (SuspendThread(exe->thread) != (DWORD)-1)
+     exe->is_suspended = 1;
+}
+
+EAPI void ecore_exe_continue(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_continue");
+       return;
+     }
+
+   if (!exe->is_suspended)
+     return;
+
+   if (ResumeThread(exe->thread) != (DWORD)-1)
+     exe->is_suspended = 0;
+}
+
+EAPI void ecore_exe_interrupt(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_interrupt");
+       return;
+     }
+
+   CloseHandle(exe->process);
+   exe->sig = ECORE_EXE_WIN32_SIGINT;
+   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
+}
+
+EAPI void ecore_exe_quit(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_quit");
+       return;
+     }
+
+   CloseHandle(exe->process);
+   exe->sig = ECORE_EXE_WIN32_SIGQUIT;
+   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
+}
+
+EAPI void ecore_exe_terminate(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_terminate");
+       return;
+     }
+
+   CloseHandle(exe->process);
+   exe->sig = ECORE_EXE_WIN32_SIGTERM;
+   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
+}
+
+EAPI void ecore_exe_kill(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_kill");
+       return;
+     }
+
+   CloseHandle(exe->process);
+   exe->sig = ECORE_EXE_WIN32_SIGKILL;
+   while (EnumWindows(_ecore_exe_enum_windows_procedure, (LPARAM)exe));
+}
+
+EAPI void ecore_exe_signal(Ecore_Exe *exe, int num)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_signal");
+       return;
+     }
+
+   /* does nothing */
+}
+
+EAPI void ecore_exe_hup(Ecore_Exe *exe)
+{
+   if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE))
+     {
+       ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_hup");
+       return;
+     }
+
+   /* does nothing */
+}
+
+static DWORD WINAPI
+_ecore_exe_thread_procedure(LPVOID data)
+{
+   GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0);
+   GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0);
+   return 1;
+}
+
+static BOOL CALLBACK
+_ecore_exe_enum_windows_procedure(HWND window, LPARAM data)
+{
+   Ecore_Exe *exe;
+   DWORD      thread_id;
+
+   exe = (Ecore_Exe *)data;
+   thread_id = GetWindowThreadProcessId(window, NULL);
+
+   if (thread_id == exe->thread_id)
+     {
+        /* Ctrl-C or Ctrl-Break */
+        if (CreateRemoteThread(exe->process, NULL, 0,
+                               (LPTHREAD_START_ROUTINE)_ecore_exe_thread_procedure, NULL,
+                               0, NULL))
+          return FALSE;
+
+        if ((exe->sig == ECORE_EXE_WIN32_SIGINT) ||
+            (exe->sig == ECORE_EXE_WIN32_SIGQUIT))
+          return FALSE;
+
+        /* WM_CLOSE message */
+        PostMessage(window, WM_CLOSE, 0, 0);
+        if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)
+          return FALSE;
+
+        /* WM_QUIT message */
+        PostMessage(window, WM_QUIT, 0, 0);
+        if (WaitForSingleObject(exe->process, ECORE_EXE_WIN32_TIMEOUT) == WAIT_OBJECT_0)
+          return FALSE;
+
+        /* Exit process */
+        if (CreateRemoteThread(exe->process, NULL, 0,
+                               (LPTHREAD_START_ROUTINE)ExitProcess, NULL,
+                               0, NULL))
+          return FALSE;
+        if (exe->sig == ECORE_EXE_WIN32_SIGTERM)
+          return FALSE;
+
+        TerminateProcess(exe->process, 0);
+
+        return FALSE;
+     }
+
+   return TRUE;
+}
+
+#endif
index 6ab38e5..e3ec537 100644 (file)
@@ -207,9 +207,7 @@ enum _Ecore_Poller_Type
 };
 typedef enum _Ecore_Poller_Type Ecore_Poller_Type;
 
-#ifndef _WIN32
 typedef struct _Ecore_Exe           Ecore_Exe;
-#endif
 typedef struct _Ecore_Timer         Ecore_Timer;
 typedef struct _Ecore_Idler         Ecore_Idler;
 typedef struct _Ecore_Idle_Enterer  Ecore_Idle_Enterer;
@@ -418,12 +416,9 @@ int           _ecore_signal_count_get(void);
 void          _ecore_signal_call(void);
 #endif
 
-#ifdef _WIN32
-static inline void _ecore_exe_init(void) { }
-static inline void _ecore_exe_shutdown(void) { }
-#else
 void          _ecore_exe_init(void);
 void          _ecore_exe_shutdown(void);
+#ifndef _WIN32
 Ecore_Exe    *_ecore_exe_find(pid_t pid);
 void         *_ecore_exe_event_del_new(void);
 void          _ecore_exe_event_del_free(void *data, void *ev);