/* See COPYING.txt for the full license governing this code. */ | |
/** | |
* \file linux_process.c | |
* | |
* Source file for the process API on linux. | |
*/ | |
#include <SDL.h> | |
#include <SDL_test.h> | |
#include <sys/types.h> | |
#include <sys/wait.h> | |
#include <unistd.h> | |
#include <errno.h> | |
#include "SDL_visualtest_process.h" | |
#include "SDL_visualtest_harness_argparser.h" | |
#include "SDL_visualtest_parsehelper.h" | |
#if defined(__LINUX__) | |
static void | |
LogLastError(char* str) | |
{ | |
char* error = (char*)strerror(errno); | |
if(!str || !error) | |
return; | |
SDLTest_LogError("%s: %s", str, error); | |
} | |
int | |
SDL_LaunchProcess(char* file, char* args, SDL_ProcessInfo* pinfo) | |
{ | |
pid_t pid; | |
char** argv; | |
if(!file) | |
{ | |
SDLTest_LogError("file argument cannot be NULL"); | |
return 0; | |
} | |
if(!pinfo) | |
{ | |
SDLTest_LogError("pinfo cannot be NULL"); | |
return 0; | |
} | |
pid = fork(); | |
if(pid == -1) | |
{ | |
LogLastError("fork() failed"); | |
return 0; | |
} | |
else if(pid == 0) | |
{ | |
/* parse the arguments string */ | |
argv = SDLVisualTest_ParseArgsToArgv(args); | |
argv[0] = file; | |
execv(file, argv); | |
LogLastError("execv() failed"); | |
return 0; | |
} | |
else | |
{ | |
pinfo->pid = pid; | |
return 1; | |
} | |
/* never executed */ | |
return 0; | |
} | |
int | |
SDL_GetProcessExitStatus(SDL_ProcessInfo* pinfo, SDL_ProcessExitStatus* ps) | |
{ | |
int success, status; | |
if(!pinfo) | |
{ | |
SDLTest_LogError("pinfo argument cannot be NULL"); | |
return 0; | |
} | |
if(!ps) | |
{ | |
SDLTest_LogError("ps argument cannot be NULL"); | |
return 0; | |
} | |
success = waitpid(pinfo->pid, &status, WNOHANG); | |
if(success == -1) | |
{ | |
LogLastError("waitpid() failed"); | |
return 0; | |
} | |
else if(success == 0) | |
{ | |
ps->exit_status = -1; | |
ps->exit_success = 1; | |
} | |
else | |
{ | |
ps->exit_success = WIFEXITED(status); | |
ps->exit_status = WEXITSTATUS(status); | |
} | |
return 1; | |
} | |
int | |
SDL_IsProcessRunning(SDL_ProcessInfo* pinfo) | |
{ | |
int success; | |
if(!pinfo) | |
{ | |
SDLTest_LogError("pinfo cannot be NULL"); | |
return -1; | |
} | |
success = kill(pinfo->pid, 0); | |
if(success == -1) | |
{ | |
if(errno == ESRCH) /* process is not running */ | |
return 0; | |
else | |
{ | |
LogLastError("kill() failed"); | |
return -1; | |
} | |
} | |
return 1; | |
} | |
int | |
SDL_QuitProcess(SDL_ProcessInfo* pinfo, SDL_ProcessExitStatus* ps) | |
{ | |
int success, status; | |
if(!pinfo) | |
{ | |
SDLTest_LogError("pinfo argument cannot be NULL"); | |
return 0; | |
} | |
if(!ps) | |
{ | |
SDLTest_LogError("ps argument cannot be NULL"); | |
return 0; | |
} | |
success = kill(pinfo->pid, SIGQUIT); | |
if(success == -1) | |
{ | |
LogLastError("kill() failed"); | |
return 0; | |
} | |
success = waitpid(pinfo->pid, &status, 0); | |
if(success == -1) | |
{ | |
LogLastError("waitpid() failed"); | |
return 0; | |
} | |
ps->exit_success = WIFEXITED(status); | |
ps->exit_status = WEXITSTATUS(status); | |
return 1; | |
} | |
int | |
SDL_KillProcess(SDL_ProcessInfo* pinfo, SDL_ProcessExitStatus* ps) | |
{ | |
int success, status; | |
if(!pinfo) | |
{ | |
SDLTest_LogError("pinfo argument cannot be NULL"); | |
return 0; | |
} | |
if(!ps) | |
{ | |
SDLTest_LogError("ps argument cannot be NULL"); | |
return 0; | |
} | |
success = kill(pinfo->pid, SIGKILL); | |
if(success == -1) | |
{ | |
LogLastError("kill() failed"); | |
return 0; | |
} | |
success = waitpid(pinfo->pid, &status, 0); | |
if(success == -1) | |
{ | |
LogLastError("waitpid() failed"); | |
return 0; | |
} | |
ps->exit_success = WIFEXITED(status); | |
ps->exit_status = WEXITSTATUS(status); | |
return 1; | |
} | |
#endif |