mirror of
https://github.com/libsdl-org/SDL.git
synced 2025-10-05 01:16:26 +00:00
Switched zenity dialogs to use the new process API
This commit is contained in:
@@ -191,95 +191,62 @@ static void run_zenity(zenityArgs* arg_struct)
|
|||||||
{
|
{
|
||||||
SDL_DialogFileCallback callback = arg_struct->callback;
|
SDL_DialogFileCallback callback = arg_struct->callback;
|
||||||
void* userdata = arg_struct->userdata;
|
void* userdata = arg_struct->userdata;
|
||||||
|
SDL_Process *process = NULL;
|
||||||
int out[2];
|
SDL_Environment *env = NULL;
|
||||||
pid_t process;
|
char **process_env = NULL;
|
||||||
|
char **process_args = NULL;
|
||||||
int status = -1;
|
int status = -1;
|
||||||
|
size_t bytes_read = 0;
|
||||||
|
char *container = NULL;
|
||||||
|
size_t narray = 1;
|
||||||
|
char **array = NULL;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
if (pipe(out) < 0) {
|
process_args = generate_args(arg_struct);
|
||||||
SDL_SetError("Could not create pipe: %s", strerror(errno));
|
if (!process_args) {
|
||||||
callback(userdata, NULL, -1);
|
goto done;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Args are only needed in the forked process, but generating them early
|
env = SDL_CreateEnvironment(SDL_FALSE);
|
||||||
allows catching the error messages in the main process */
|
if (!env) {
|
||||||
char **args = generate_args(arg_struct);
|
goto done;
|
||||||
|
|
||||||
if (!args) {
|
|
||||||
// SDL_SetError will have been called already
|
|
||||||
callback(userdata, NULL, -1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
process = fork();
|
|
||||||
|
|
||||||
if (process < 0) {
|
|
||||||
SDL_SetError("Could not fork process: %s", strerror(errno));
|
|
||||||
close(out[0]);
|
|
||||||
close(out[1]);
|
|
||||||
free_args(args);
|
|
||||||
callback(userdata, NULL, -1);
|
|
||||||
return;
|
|
||||||
} else if (process == 0){
|
|
||||||
dup2(out[1], STDOUT_FILENO);
|
|
||||||
close(STDERR_FILENO); // Hide errors from Zenity to stderr
|
|
||||||
close(out[0]);
|
|
||||||
close(out[1]);
|
|
||||||
|
|
||||||
/* Recent versions of Zenity have different exit codes, but picks up
|
/* Recent versions of Zenity have different exit codes, but picks up
|
||||||
different codes from the environment */
|
different codes from the environment */
|
||||||
SDL_setenv_unsafe("ZENITY_OK", "0", 1);
|
SDL_SetEnvironmentVariable(env, "ZENITY_OK", "0", SDL_TRUE);
|
||||||
SDL_setenv_unsafe("ZENITY_CANCEL", "1", 1);
|
SDL_SetEnvironmentVariable(env, "ZENITY_CANCEL", "1", SDL_TRUE);
|
||||||
SDL_setenv_unsafe("ZENITY_ESC", "1", 1);
|
SDL_SetEnvironmentVariable(env, "ZENITY_ESC", "1", SDL_TRUE);
|
||||||
SDL_setenv_unsafe("ZENITY_EXTRA", "2", 1);
|
SDL_SetEnvironmentVariable(env, "ZENITY_EXTRA", "2", SDL_TRUE);
|
||||||
SDL_setenv_unsafe("ZENITY_ERROR", "2", 1);
|
SDL_SetEnvironmentVariable(env, "ZENITY_ERROR", "2", SDL_TRUE);
|
||||||
SDL_setenv_unsafe("ZENITY_TIMEOUT", "2", 1);
|
SDL_SetEnvironmentVariable(env, "ZENITY_TIMEOUT", "2", SDL_TRUE);
|
||||||
|
|
||||||
execv(args[0], args);
|
process_env = SDL_GetEnvironmentVariables(env);
|
||||||
|
if (!process_env) {
|
||||||
exit(errno + 128);
|
goto done;
|
||||||
} else {
|
|
||||||
char readbuffer[2048];
|
|
||||||
size_t bytes_read = 0, bytes_last_read;
|
|
||||||
char *container = NULL;
|
|
||||||
close(out[1]);
|
|
||||||
free_args(args);
|
|
||||||
|
|
||||||
while ((bytes_last_read = read(out[0], readbuffer, sizeof(readbuffer)))) {
|
|
||||||
char *new_container = SDL_realloc(container, bytes_read + bytes_last_read);
|
|
||||||
if (!new_container) {
|
|
||||||
SDL_free(container);
|
|
||||||
close(out[0]);
|
|
||||||
callback(userdata, NULL, -1);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
container = new_container;
|
|
||||||
SDL_memcpy(container + bytes_read, readbuffer, bytes_last_read);
|
|
||||||
bytes_read += bytes_last_read;
|
|
||||||
}
|
|
||||||
close(out[0]);
|
|
||||||
|
|
||||||
if (waitpid(process, &status, 0) == -1) {
|
|
||||||
SDL_SetError("waitpid failed");
|
|
||||||
SDL_free(container);
|
|
||||||
callback(userdata, NULL, -1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
SDL_PropertiesID props = SDL_CreateProperties();
|
||||||
status = WEXITSTATUS(status);
|
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, process_args);
|
||||||
|
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ENVIRONMENT_POINTER, process_env);
|
||||||
|
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
|
||||||
|
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_APP);
|
||||||
|
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_NULL);
|
||||||
|
process = SDL_CreateProcessWithProperties(props);
|
||||||
|
SDL_DestroyProperties(props);
|
||||||
|
if (!process) {
|
||||||
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t narray = 1;
|
container = SDL_ReadProcess(process, &bytes_read, &status);
|
||||||
char **array = (char **) SDL_malloc((narray + 1) * sizeof(char *));
|
if (!container) {
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
array = (char **)SDL_malloc((narray + 1) * sizeof(char *));
|
||||||
if (!array) {
|
if (!array) {
|
||||||
SDL_free(container);
|
goto done;
|
||||||
callback(userdata, NULL, -1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
array[0] = container;
|
array[0] = container;
|
||||||
array[1] = NULL;
|
array[1] = NULL;
|
||||||
|
|
||||||
@@ -292,10 +259,7 @@ static void run_zenity(zenityArgs* arg_struct)
|
|||||||
narray++;
|
narray++;
|
||||||
char **new_array = (char **) SDL_realloc(array, (narray + 1) * sizeof(char *));
|
char **new_array = (char **) SDL_realloc(array, (narray + 1) * sizeof(char *));
|
||||||
if (!new_array) {
|
if (!new_array) {
|
||||||
SDL_free(container);
|
goto done;
|
||||||
SDL_free(array);
|
|
||||||
callback(userdata, NULL, -1);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
array = new_array;
|
array = new_array;
|
||||||
array[narray] = NULL;
|
array[narray] = NULL;
|
||||||
@@ -305,14 +269,24 @@ static void run_zenity(zenityArgs* arg_struct)
|
|||||||
|
|
||||||
// 0 = the user chose one or more files, 1 = the user canceled the dialog
|
// 0 = the user chose one or more files, 1 = the user canceled the dialog
|
||||||
if (status == 0 || status == 1) {
|
if (status == 0 || status == 1) {
|
||||||
callback(userdata, (const char * const*) array, -1);
|
callback(userdata, (const char * const*)array, -1);
|
||||||
} else {
|
} else {
|
||||||
SDL_SetError("Could not run zenity: exit code %d (may be zenity or execv+128)", status);
|
SDL_SetError("Could not run zenity: exit code %d", status);
|
||||||
callback(userdata, NULL, -1);
|
callback(userdata, NULL, -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
done:
|
||||||
SDL_free(array);
|
SDL_free(array);
|
||||||
SDL_free(container);
|
SDL_free(container);
|
||||||
|
free_args(process_args);
|
||||||
|
SDL_free(process_env);
|
||||||
|
SDL_DestroyEnvironment(env);
|
||||||
|
SDL_DestroyProcess(process);
|
||||||
|
|
||||||
|
if (!result) {
|
||||||
|
callback(userdata, NULL, -1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -409,30 +383,21 @@ void SDL_Zenity_ShowOpenFolderDialog(SDL_DialogFileCallback callback, void* user
|
|||||||
|
|
||||||
bool SDL_Zenity_detect(void)
|
bool SDL_Zenity_detect(void)
|
||||||
{
|
{
|
||||||
pid_t process;
|
const char *args[] = {
|
||||||
|
"/usr/bin/env", "zenity", "--version", NULL
|
||||||
|
};
|
||||||
int status = -1;
|
int status = -1;
|
||||||
|
|
||||||
process = fork();
|
SDL_PropertiesID props = SDL_CreateProperties();
|
||||||
|
SDL_SetPointerProperty(props, SDL_PROP_PROCESS_CREATE_ARGS_POINTER, args);
|
||||||
if (process < 0) {
|
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDIN_NUMBER, SDL_PROCESS_STDIO_NULL);
|
||||||
SDL_SetError("Could not fork process: %s", strerror(errno));
|
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDOUT_NUMBER, SDL_PROCESS_STDIO_NULL);
|
||||||
return false;
|
SDL_SetNumberProperty(props, SDL_PROP_PROCESS_CREATE_STDERR_NUMBER, SDL_PROCESS_STDIO_NULL);
|
||||||
} else if (process == 0){
|
SDL_Process *process = SDL_CreateProcessWithProperties(props);
|
||||||
// Disable output
|
SDL_DestroyProperties(props);
|
||||||
close(STDERR_FILENO);
|
if (process) {
|
||||||
close(STDOUT_FILENO);
|
SDL_WaitProcess(process, true, &status);
|
||||||
execl("/usr/bin/env", "/usr/bin/env", "zenity", "--version", NULL);
|
SDL_DestroyProcess(process);
|
||||||
exit(errno + 128);
|
|
||||||
} else {
|
|
||||||
if (waitpid(process, &status, 0) == -1) {
|
|
||||||
SDL_SetError("waitpid failed");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WIFEXITED(status)) {
|
|
||||||
status = WEXITSTATUS(status);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (status == 0);
|
return (status == 0);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user