#include "ecore_private.h" #include "Ecore.h" #include #include #include #ifndef WIN32 static Ecore_Exe *exes = NULL; /** * @defgroup Ecore_Exe_Basic_Group Process Spawning Functions * * Functions that deal with spawned processes. */ /** * Spawns a child process. * * This function forks and runs the given command using @c /bin/sh. * * Note that the process handle is only valid until a child process * terminated event is received. After all handlers for the child process * terminated event have been called, the handle will be freed by Ecore. * * @param exe_cmd The command to run with @c /bin/sh. * @param data Data to attach to the returned process handle. * @return A process handle to the spawned process. * @ingroup Ecore_Exe_Basic_Group */ Ecore_Exe * ecore_exe_run(const char *exe_cmd, const void *data) { Ecore_Exe *exe; pid_t pid; if (!exe_cmd) return NULL; pid = fork(); if (pid) { exe = calloc(1, sizeof(Ecore_Exe)); if (!exe) { kill(pid, SIGKILL); return NULL; } ECORE_MAGIC_SET(exe, ECORE_MAGIC_EXE); exe->pid = pid; exe->data = (void *)data; exes = _ecore_list_append(exes, exe); return exe; } setsid(); execl("/bin/sh", "/bin/sh", "-c", exe_cmd, NULL); exit(0); return NULL; } /** * Frees the given process handle. * * Note that the process that the handle represents is unaffected by this * function. * * @param exe The given process handle. * @return The data attached to the handle when @ref ecore_exe_run was * called. * @ingroup Ecore_Exe_Basic_Group */ void * ecore_exe_free(Ecore_Exe *exe) { if (!ECORE_MAGIC_CHECK(exe, ECORE_MAGIC_EXE)) { ECORE_MAGIC_FAIL(exe, ECORE_MAGIC_EXE, "ecore_exe_free"); return NULL; } return _ecore_exe_free(exe); } /** * Retrieves the process ID of the given spawned process. * @param exe Handle to the given spawned process. * @return The process ID on success. @c -1 otherwise. * @ingroup Ecore_Exe_Basic_Group */ 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->pid; } /** * Retrieves the data attached to the given process handle. * @param exe The given process handle. * @return The data pointer attached to @p exe. * @ingroup Ecore_Exe_Basic_Group */ 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; } /** * @defgroup Ecore_Exe_Signal_Group Spawned Process Signal Functions * * Functions that send signals to spawned processes. */ /** * Pauses the given process by sending it a @c SIGSTOP signal. * @param exe Process handle to the given process. * @ingroup Ecore_Exe_Signal_Group */ 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; } kill(exe->pid, SIGSTOP); } /** * Continues the given paused process by sending it a @c SIGCONT signal. * @param exe Process handle to the given process. * @ingroup Ecore_Exe_Signal_Group */ 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; } kill(exe->pid, SIGCONT); } /** * Sends the given spawned process a terminate (@c SIGTERM) signal. * @param exe Process handle to the given process. * @ingroup Ecore_Exe_Signal_Group */ 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; } kill(exe->pid, SIGTERM); } /** * Kills the given spawned process by sending it a @c SIGKILL signal. * @param exe Process handle to the given process. * @ingroup Ecore_Exe_Signal_Group */ 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; } kill(exe->pid, SIGKILL); } /** * Sends a @c SIGUSR signal to the given spawned process. * @param exe Process handle to the given process. * @param num The number user signal to send. Must be either 1 or 2, or * the signal will be ignored. * @ingroup Ecore_Exe_Signal_Group */ 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; } if (num == 1) kill(exe->pid, SIGUSR1); else if (num == 2) kill(exe->pid, SIGUSR2); } /** * Sends a @c SIGHUP signal to the given spawned process. * @param exe Process handle to the given process. * @ingroup Ecore_Exe_Signal_Group */ 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; } kill(exe->pid, SIGHUP); } void _ecore_exe_shutdown(void) { while (exes) _ecore_exe_free(exes); } Ecore_Exe * _ecore_exe_find(pid_t pid) { Ecore_Oldlist *l; for (l = (Ecore_Oldlist *)exes; l; l = l->next) { Ecore_Exe *exe; exe = (Ecore_Exe *)l; if (exe->pid == pid) return exe; } return NULL; } void * _ecore_exe_free(Ecore_Exe *exe) { void *data; data = exe->data; exes = _ecore_list_remove(exes, exe); ECORE_MAGIC_SET(exe, ECORE_MAGIC_NONE); free(exe); return data; } #endif