1
0
mirror of https://github.com/profanity-im/profanity.git synced 2024-11-03 19:37:16 -05:00

Refactor call_external

This commit is contained in:
William Wennerström 2020-12-11 15:51:01 +01:00
parent 46e938b638
commit 32cfea4bd2
No known key found for this signature in database
GPG Key ID: E1382990BEDD319B
3 changed files with 41 additions and 90 deletions

View File

@ -471,92 +471,35 @@ get_mentions(gboolean whole_word, gboolean case_sensitive, const char* const mes
return mentions;
}
/*
* Take an NULL-terminated array used as the tokens of a command, and optionally
* pointers to the string arrays that will store each lines of the call standard
* output and standard error.
*
* argv - NULL-terminated string array containing the tokens of the command
* line to spawn
* output_ptr - a pointer to the string array where to store spawned command
* standard output
* set to NULL to ignore the command standard output
* error_ptr - a pointer to the string array where to store spawned command
* standard error
* set to NULL to ignore the command standard error
*
* Returns:
* - TRUE if the command has been successfully spawned and exited normally
* - FALSE otherwise
*/
gboolean
call_external(gchar** argv, gchar*** const output_ptr, gchar*** const error_ptr)
call_external(gchar** argv, gchar** std_out, gchar** std_err)
{
gchar* stdout_str = NULL;
gchar** stdout_str_ptr = &stdout_str;
gchar* stderr_str = NULL;
gchar** stderr_str_ptr = &stderr_str;
GSpawnFlags flags = G_SPAWN_SEARCH_PATH;
gint status;
GError* error = NULL;
gchar* cmd = NULL;
cmd = g_strjoinv(" ", argv);
log_debug("Calling external: %s", cmd);
if (!output_ptr) {
stdout_str_ptr = NULL;
GSpawnFlags flags = G_SPAWN_SEARCH_PATH | G_SPAWN_CHILD_INHERITS_STDIN;
if (std_out == NULL)
flags |= G_SPAWN_STDOUT_TO_DEV_NULL;
}
if (!error_ptr) {
stderr_str_ptr = NULL;
if (std_err == NULL)
flags |= G_SPAWN_STDERR_TO_DEV_NULL;
}
if (!g_spawn_sync(NULL, argv, NULL, flags, NULL, NULL, stdout_str_ptr, stderr_str_ptr, &status, &error)) {
log_error("Spawning '%s' failed: %s.", cmd, error->message);
g_error_free(error);
error = NULL;
return FALSE;
}
gint exit_status;
gboolean spawn_result;
GError* spawn_error;
spawn_result = g_spawn_sync(NULL, // Inherit the parent PWD.
argv,
NULL, // Inherit the parent environment.
flags,
NULL, NULL, // No func. before exec() in child.
std_out, std_err,
&exit_status, &spawn_error);
if (!g_spawn_check_exit_status(status, &error)) {
log_error("Calling '%s' failed: %s.", cmd, error->message);
g_error_free(error);
error = NULL;
if (!spawn_result
|| !g_spawn_check_exit_status(exit_status, &spawn_error)) {
gchar* cmd = g_strjoinv(" ", argv);
log_error("Spawning '%s' failed with '%s'.", cmd, spawn_error->message);
g_free(cmd);
cmd = NULL;
g_free(stdout_str);
stdout_str = NULL;
stdout_str_ptr = NULL;
if (stderr_str && strlen(stderr_str)) {
log_error("Called command returned the following on stderr: %s.", stderr_str);
}
g_free(stderr_str);
stderr_str = NULL;
stderr_str_ptr = NULL;
return FALSE;
g_error_free(spawn_error);
}
g_free(cmd);
cmd = NULL;
if (output_ptr) {
*output_ptr = g_strsplit(stdout_str, "\n", 0);
g_free(stdout_str);
stdout_str = NULL;
stdout_str_ptr = NULL;
}
if (error_ptr) {
*error_ptr = g_strsplit(stderr_str, "\n", 0);
g_free(stderr_str);
stderr_str = NULL;
stderr_str_ptr = NULL;
}
return TRUE;
return spawn_result;
}
gchar**

View File

@ -104,10 +104,10 @@ void get_file_paths_recursive(const char* directory, GSList** contents);
char* get_random_string(int length);
gboolean call_external(gchar** argv, gchar*** const output_ptr, gchar*** const error_ptr);
gboolean call_external(gchar** argv, gchar** std_out, gchar** std_err);
gchar** format_call_external_argv(const char* template, const char* url, const char* filename);
gchar* unique_filename_from_url(const char* url, const char* path);
gchar* get_expanded_path(const char *path);
gchar* get_expanded_path(const char* path);
#endif

View File

@ -200,27 +200,35 @@ account_eval_password(ProfAccount* account)
assert(account != NULL);
assert(account->eval_password != NULL);
gchar** output = NULL;
gchar** error = NULL;
gchar* std_out = NULL;
gchar* std_err = NULL;
gchar* argv[] = { "sh", "-c", account->eval_password, NULL };
if (!call_external(argv, &output, &error)) {
if (!call_external(argv, &std_out, &std_err)) {
log_error("Password command failed with: %s", std_err);
g_free(std_out);
g_free(std_err);
return FALSE;
}
if (!output || !output[0]) {
log_error("Failed to read eval_password output");
g_strfreev(output);
output = NULL;
if (!std_out || !std_out[0]) {
log_error("Password command returned empty output.");
g_free(std_out);
g_free(std_err);
return FALSE;
}
account->password = strdup(output[0]);
g_strfreev(output);
output = NULL;
// Remove leading and trailing whitespace from command output.
gchar* password = g_strdup(std_out);
g_strstrip(password);
account->password = password;
g_free(std_out);
g_free(std_err);
if (!account->password) {
log_error("Failed to allocate enough memory to read eval_password output");
log_error("Failed to allocate enough memory to read password command "
"output");
return FALSE;
}