mirror of
https://github.com/profanity-im/profanity.git
synced 2024-12-04 14:46:46 -05:00
Merge remote-tracking branch 'peetah/externalCallWithGSpawnSync' into
peetah-external-cmd Merge peetahs external command calling improvements from his mirror at https://framagit.org/peetah/profanity.
This commit is contained in:
commit
b7d5b964a2
@ -8921,9 +8921,10 @@ cmd_urlopen(ProfWin *window, const char *const command, gchar **args)
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gchar* cmd = prefs_get_string(PREF_URL_OPEN_CMD);
|
gchar *argv[] = {prefs_get_string(PREF_URL_OPEN_CMD), args[0], NULL};
|
||||||
call_external(cmd, args[0]);
|
if (!call_external(argv, NULL, NULL)) {
|
||||||
g_free(cmd);
|
cons_show_error("Unable to open url: check the logs for more information.");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cons_show("urlopen not supported in this window");
|
cons_show("urlopen not supported in this window");
|
||||||
}
|
}
|
||||||
|
91
src/common.c
91
src/common.c
@ -484,15 +484,90 @@ get_mentions(gboolean whole_word, gboolean case_sensitive, const char *const mes
|
|||||||
return mentions;
|
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;
|
||||||
|
|
||||||
g_string_append_printf(cmd, "%s %s > /dev/null 2>&1", exe, param);
|
cmd = g_strjoinv(" ", argv);
|
||||||
log_debug("Calling external: %s", cmd->str);
|
log_debug("Calling external: %s", cmd);
|
||||||
FILE *stream = popen(cmd->str, "r");
|
|
||||||
|
|
||||||
pclose(stream);
|
if (!output_ptr) {
|
||||||
g_string_free(cmd, TRUE);
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
@ -106,6 +106,6 @@ void get_file_paths_recursive(const char *directory, GSList **contents);
|
|||||||
|
|
||||||
char* get_random_string(int length);
|
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
|
#endif
|
||||||
|
@ -194,32 +194,30 @@ account_eval_password(ProfAccount *account)
|
|||||||
assert(account != NULL);
|
assert(account != NULL);
|
||||||
assert(account->eval_password != NULL);
|
assert(account->eval_password != NULL);
|
||||||
|
|
||||||
// Evaluate as shell command to retrieve password
|
gchar **output = NULL;
|
||||||
GString *cmd = g_string_new("");
|
gchar **argv = g_strsplit(account->eval_password, " ", 0);
|
||||||
g_string_append_printf(cmd, "%s 2>/dev/null", account->eval_password);
|
|
||||||
|
|
||||||
FILE *stream = popen(cmd->str, "r");
|
if (!call_external(argv, &output, NULL)) {
|
||||||
g_string_free(cmd, TRUE);
|
g_strfreev(argv);
|
||||||
if (stream) {
|
argv = NULL;
|
||||||
// Limit to READ_BUF_SIZE bytes to prevent overflows in the case of a poorly chosen command
|
return FALSE;
|
||||||
account->password = g_malloc(READ_BUF_SIZE);
|
}
|
||||||
if (!account->password) {
|
|
||||||
log_error("Failed to allocate enough memory to read eval_password output");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
account->password = fgets(account->password, READ_BUF_SIZE, stream);
|
|
||||||
pclose(stream);
|
|
||||||
if (!account->password) {
|
|
||||||
log_error("No result from eval_password.");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// strip trailing newline
|
g_strfreev(argv);
|
||||||
if (g_str_has_suffix(account->password, "\n")) {
|
|
||||||
account->password[strlen(account->password)-1] = '\0';
|
if (!output || !output[0]) {
|
||||||
}
|
log_error("Failed to read eval_password output");
|
||||||
} else {
|
g_strfreev(output);
|
||||||
log_error("popen failed when running eval_password.");
|
output = NULL;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
account->password = strdup(output[0]);
|
||||||
|
g_strfreev(output);
|
||||||
|
output = NULL;
|
||||||
|
|
||||||
|
if (!account->password) {
|
||||||
|
log_error("Failed to allocate enough memory to read eval_password output");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -266,7 +266,10 @@ _avatar_request_item_result_handler(xmpp_stanza_t *const stanza, void *const use
|
|||||||
|
|
||||||
// if we shall open it
|
// if we shall open it
|
||||||
if (g_hash_table_contains(shall_open, from_attr)) {
|
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);
|
g_hash_table_remove(shall_open, from_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user