diff options
author | Pierre Mazière <pierre.maziere@gmx.com> | 2020-05-24 16:38:56 +0200 |
---|---|---|
committer | Pierre Mazière <pierre.maziere@gmx.com> | 2020-06-03 13:09:29 +0200 |
commit | d92c576aa53505d712715b1acc6344af3262c84f (patch) | |
tree | 9e7215751fb9c7b185115a816be5002ce3ecc1a9 | |
parent | f1fe18b47442aed5a0b427bc9450bd7111ec7314 (diff) | |
download | profani-tty-d92c576aa53505d712715b1acc6344af3262c84f.tar.gz |
Get output and error streams from the command spawned by external_call()
Signed-off-by: Pierre Mazière <pierre.maziere@gmx.com>
-rw-r--r-- | src/command/cmd_funcs.c | 9 | ||||
-rw-r--r-- | src/common.c | 91 | ||||
-rw-r--r-- | src/common.h | 2 | ||||
-rw-r--r-- | src/xmpp/avatar.c | 5 |
4 files changed, 93 insertions, 14 deletions
diff --git a/src/command/cmd_funcs.c b/src/command/cmd_funcs.c index 55082765..59702fe3 100644 --- a/src/command/cmd_funcs.c +++ b/src/command/cmd_funcs.c @@ -4900,7 +4900,7 @@ cmd_sendfile(ProfWin *window, const char *const command, gchar **args) free(filename); return TRUE; } - + if (access(filename, R_OK) != 0) { cons_show_error("Uploading '%s' failed: File not found!", filename); free(filename); @@ -8921,9 +8921,10 @@ cmd_urlopen(ProfWin *window, const char *const command, gchar **args) return TRUE; } - gchar* cmd = prefs_get_string(PREF_URL_OPEN_CMD); - call_external(cmd, args[0]); - g_free(cmd); + gchar *argv[] = {prefs_get_string(PREF_URL_OPEN_CMD), args[0], NULL}; + if (!call_external(argv, NULL, NULL)) { + cons_show_error("Unable to open url: check the logs for more information."); + } } else { cons_show("urlopen not supported in this window"); } diff --git a/src/common.c b/src/common.c index 821acd3e..1de5f4ba 100644 --- a/src/common.c +++ b/src/common.c @@ -484,15 +484,90 @@ get_mentions(gboolean whole_word, gboolean case_sensitive, const char *const mes return mentions; } -void -call_external(const char *const exe, const char *const param) +/* + * 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) { - GString *cmd = g_string_new(""); + 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; + flags |= G_SPAWN_STDOUT_TO_DEV_NULL; + } + + if (!error_ptr) { + stderr_str_ptr = 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; + } - g_string_append_printf(cmd, "%s %s > /dev/null 2>&1", exe, param); - log_debug("Calling external: %s", cmd->str); - FILE *stream = popen(cmd->str, "r"); + if (!g_spawn_check_exit_status(status, &error)) { + log_error("Calling '%s' failed: %s.", cmd, error->message); + g_error_free(error); + error = NULL; + 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; + } - pclose(stream); - g_string_free(cmd, TRUE); + 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; } diff --git a/src/common.h b/src/common.h index 108536ed..93e4a609 100644 --- a/src/common.h +++ b/src/common.h @@ -106,6 +106,6 @@ void get_file_paths_recursive(const char *directory, GSList **contents); char* get_random_string(int length); -void call_external(const char *const exe, const char *const param); +gboolean call_external(gchar **argv, gchar ***const output_ptr, gchar ***const error_ptr); #endif diff --git a/src/xmpp/avatar.c b/src/xmpp/avatar.c index 701d6cb7..c5b44411 100644 --- a/src/xmpp/avatar.c +++ b/src/xmpp/avatar.c @@ -266,7 +266,10 @@ _avatar_request_item_result_handler(xmpp_stanza_t *const stanza, void *const use // if we shall open it if (g_hash_table_contains(shall_open, from_attr)) { - call_external(prefs_get_string(PREF_AVATAR_CMD), filename->str); + gchar *argv[] = {prefs_get_string(PREF_AVATAR_CMD), filename->str, NULL}; + if (!call_external(argv, NULL, NULL)) { + cons_show_error("Unable to display avatar: check the logs for more information."); + } g_hash_table_remove(shall_open, from_attr); } |