Skip to content

Commit

Permalink
Get output and error streams from the command spawned by external_call()
Browse files Browse the repository at this point in the history
Signed-off-by: Pierre Mazière <pierre.maziere@gmx.com>
  • Loading branch information
Pierre Mazière committed Jun 3, 2020
1 parent f1fe18b commit d92c576
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 14 deletions.
9 changes: 5 additions & 4 deletions src/command/cmd_funcs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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");
}
Expand Down
91 changes: 83 additions & 8 deletions src/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
2 changes: 1 addition & 1 deletion src/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
5 changes: 4 additions & 1 deletion src/xmpp/avatar.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down

0 comments on commit d92c576

Please sign in to comment.