diff options
-rw-r--r-- | ChangeLog | 3 | ||||
-rw-r--r-- | doc/en/weechat_plugin_api.en.txt | 61 | ||||
-rw-r--r-- | doc/fr/weechat_plugin_api.fr.txt | 63 | ||||
-rw-r--r-- | doc/it/weechat_plugin_api.it.txt | 69 | ||||
-rw-r--r-- | src/core/wee-hook.c | 178 | ||||
-rw-r--r-- | src/core/wee-hook.h | 15 | ||||
-rw-r--r-- | src/plugins/guile/weechat-guile-api.c | 16 | ||||
-rw-r--r-- | src/plugins/lua/weechat-lua-api.c | 19 | ||||
-rw-r--r-- | src/plugins/perl/weechat-perl-api.c | 19 | ||||
-rw-r--r-- | src/plugins/python/weechat-python-api.c | 20 | ||||
-rw-r--r-- | src/plugins/ruby/weechat-ruby-api.c | 26 | ||||
-rw-r--r-- | src/plugins/tcl/weechat-tcl-api.c | 22 |
12 files changed, 428 insertions, 83 deletions
@@ -64,6 +64,9 @@ http://weechat.org/files/releasenotes/ReleaseNotes-devel.html[release notes] * core: add options to customize default text search in buffers: weechat.look.buffer_search_{case_sensitive|force_default|regex|where} * doc: add polish man page and user's guide +* api: add stdin options in functions hook_process_hashtable and hook_set + to send data on stdin of child process, add function hook_set in script API + (task #10847, task #13031) * api: add hdata "buffer_visited" * api: add support of infos with format `${info:name,arguments}` in function string_eval_expression and command /eval diff --git a/doc/en/weechat_plugin_api.en.txt b/doc/en/weechat_plugin_api.en.txt index 9b1251a03..e83cf2614 100644 --- a/doc/en/weechat_plugin_api.en.txt +++ b/doc/en/weechat_plugin_api.en.txt @@ -6991,10 +6991,26 @@ with an extra argument: * 'options': options for command executed; the hashtable is duplicated in function, so it's safe to free it after this call -For a standard command (not beginning with "url:"), the hashtable 'options' can -contain arguments for command (and then 'command' must be only the command -without arguments) _(WeeChat ≥ 0.4.0)_. + -The keys in hashtable must be: 'arg1', 'arg2', ... +For a standard command (not beginning with "url:"), following options are +available: + +[width="100%",cols="^1,1,3",options="header"] +|=== +| Option | Value | Description + +| argN (N ≥ 1) + + _(WeeChat ≥ 0.4.0)_ | + any string | + Arguments for command; if no argument is given with these options, + the command is automatically split like the shell does (and then command + arguments are read in the 'command' argument) + +| stdin + + _(WeeChat ≥ 0.4.3)_ | + (not used) | + Create a pipe for writing data on standard input (stdin) of child process + (see function <<_weechat_hook_set,weechat_hook_set>>) +|=== For command "url:...", following options are available (see `man curl_easy_setopt` for a description of each option): @@ -9426,7 +9442,7 @@ hook = weechat.hook_focus("buffer_nicklist", "my_focus_nicklist_cb", "") ==== weechat_hook_set -_WeeChat ≥ 0.3.9._ +_WeeChat ≥ 0.3.9 (script: WeeChat ≥ 0.4.3)._ Set string value of a hook property. @@ -9446,13 +9462,23 @@ Arguments: Properties: -[width="100%",cols="^2,4,8",options="header"] +[width="100%",cols="^2,2,2,5",options="header"] |=== -| Name | Value | Description +| Name | Hook type | Value | Description -| subplugin | any string | +| subplugin | any type | any string | Name of sub plugin (commonly script name, which is displayed in `/help command` for a hook of type 'command') + +| stdin + + _(WeeChat ≥ 0.4.3)_ | + 'process', 'process_hashtable' | any string | + Send data on standard input ('stdin') of child process + +| stdin_close + + _(WeeChat ≥ 0.4.3)_ | + 'process', 'process_hashtable' | (not used) | + Close pipe used to send data on standard input ('stdin') of child process |=== C example: @@ -9466,8 +9492,23 @@ struct t_hook *my_command_hook = weechat_hook_set (my_command_hook, "subplugin", "test"); ---- -[NOTE] -This function is not available in scripting API. +Script (Python): + +[source,python] +---- +# prototype +weechat.hook_set(hook, property, value) + +# example +def my_process_cb(data, command, return_code, out, err): + # ... + return weechat.WEECHAT_RC_OK + +hook = weechat.hook_process_hashtable("/path/to/command", { "stdin": "1" }, + 20000, "my_process_cb", "") +weechat.hook_set(hook, "stdin", "data sent to stdin of child process") +weechat.hook_set(hook, "stdin_close", "") # optional +---- ==== weechat_unhook diff --git a/doc/fr/weechat_plugin_api.fr.txt b/doc/fr/weechat_plugin_api.fr.txt index 410f6d2e2..f1c816875 100644 --- a/doc/fr/weechat_plugin_api.fr.txt +++ b/doc/fr/weechat_plugin_api.fr.txt @@ -7098,11 +7098,26 @@ supplémentaire : * 'options' : options pour la commande exécutée; la hashtable est dupliquée dans la fonction, donc il est possible de la supprimer après cet appel -Pour une commande standard (ne commençant pas par "url:"), la hashtable -'options' peut contenir les paramètres pour la commande (et donc 'command' doit -être seulement la commande sans les paramètres) -_(WeeChat ≥ 0.4.0)_. + -Les clés dans la hashtable doivent être: 'arg1', 'arg2', ... +Pour une commande standard (ne commençant pas par "url:"), les options suivantes +sont disponibles : + +[width="100%",cols="^1,1,3",options="header"] +|=== +| Option | Valeur | Description + +| argN (N ≥ 1) + + _(WeeChat ≥ 0.4.0)_ | + toute chaîne | + Paramètres pour la commande ; si aucun paramètre n'est donné avec ces options, + la commande sera automatiquement découpée comme le fait le shell (et donc les + paramètres de la commande sont lus dans le paramètre 'command') + +| stdin + + _(WeeChat ≥ 0.4.3)_ | + (non utilisée) | + Créer un tuyau pour écrire sur l'entrée standard (stdin) du processus fils + (voir la fonction <<_weechat_hook_set,weechat_hook_set>>) +|=== Pour la commande "url:...", les options suivantes sont disponibles (voir `man curl_easy_setopt` pour une description de chaque option) : @@ -9592,7 +9607,7 @@ hook = weechat.hook_focus("buffer_nicklist", "my_focus_nicklist_cb", "") ==== weechat_hook_set -_WeeChat ≥ 0.3.9._ +_WeeChat ≥ 0.3.9 (script: WeeChat ≥ 0.4.3)._ Affecte une valeur à une propriété d'un hook. @@ -9612,13 +9627,24 @@ Paramètres : Propriétés : -[width="100%",cols="^2,4,8",options="header"] +[width="100%",cols="^2,2,2,5",options="header"] |=== -| Nom | Valeur | Description +| Nom | Type de hook | Valeur | Description -| subplugin | toute chaîne | +| subplugin | tout type | toute chaîne | Nom de la sous-extension (couramment un nom de script, qui est affiché dans `/help commande` pour un hook de type 'command') + +| stdin + + _(WeeChat ≥ 0.4.3)_ | + 'process', 'process_hashtable' | toute chaîne | + Envoyer les données sur l'entrée standard ('stdin') du processus fils + +| stdin_close + + _(WeeChat ≥ 0.4.3)_ | + 'process', 'process_hashtable' | (non utilisée) | + Fermer le tuyau utilisé pour envoyer les données sur l'entrée standard + ('stdin') du processus fils |=== Exemple en C : @@ -9632,8 +9658,23 @@ struct t_hook *my_command_hook = weechat_hook_set (my_command_hook, "subplugin", "test"); ---- -[NOTE] -Cette fonction n'est pas disponible dans l'API script. +Script (Python) : + +[source,python] +---- +# prototype +weechat.hook_set(hook, property, value) + +# exemple +def my_process_cb(data, command, return_code, out, err): + # ... + return weechat.WEECHAT_RC_OK + +hook = weechat.hook_process_hashtable("/chemin/vers/commande", { "stdin": "1" }, + 20000, "my_process_cb", "") +weechat.hook_set(hook, "stdin", "données envoyées sur le stdin du processus fils") +weechat.hook_set(hook, "stdin_close", "") # facultatif +---- ==== weechat_unhook diff --git a/doc/it/weechat_plugin_api.it.txt b/doc/it/weechat_plugin_api.it.txt index 2364339ab..ea810640b 100644 --- a/doc/it/weechat_plugin_api.it.txt +++ b/doc/it/weechat_plugin_api.it.txt @@ -7090,10 +7090,29 @@ Gli argomenti sono gli stessi della funzione nella funzione, per cui è possibile liberarla dopo questa chiamata // TRANSLATION MISSING -For a standard command (not beginning with "url:"), the hashtable 'options' can -contain arguments for command (and then 'command' must be only the command -without arguments) _(WeeChat ≥ 0.4.0)_. + -The keys in hashtable must be: 'arg1', 'arg2', ... +For a standard command (not beginning with "url:"), following options are +available: + +// TRANSLATION MISSING +[width="100%",cols="^1,1,3",options="header"] +|=== +| Option | Value | Description + +// TRANSLATION MISSING +| argN (N ≥ 1) + + _(WeeChat ≥ 0.4.0)_ | + any string | + Arguments for command; if no argument is given with these options, + the command is automatically split like the shell does (and then command + arguments are read in the 'command' argument) + +// TRANSLATION MISSING +| stdin + + _(WeeChat ≥ 0.4.3)_ | + (not used) | + Create a pipe for writing data on standard input (stdin) of child process + (see function <<_weechat_hook_set,weechat_hook_set>>) +|=== Per il comando "url:..." sono disponibili le seguenti opzioni (consultare `man curl_easy_setopt` per la descrizione di ogni opzione): @@ -9624,7 +9643,7 @@ hook = weechat.hook_focus("buffer_nicklist", "my_focus_nicklist_cb", "") ==== weechat_hook_set -_WeeChat ≥ 0.3.9._ +_WeeChat ≥ 0.3.9 (script: WeeChat ≥ 0.4.3)._ // TRANSLATION MISSING Set string value of a hook property. @@ -9648,14 +9667,29 @@ Argomenti: // TRANSLATION MISSING Properties: -[width="100%",cols="^2,4,8",options="header"] +// TRANSLATION MISSING +[width="100%",cols="^2,2,2,5",options="header"] |=== -| Nome | Valore | Descrizione +| Nome | Hook type | Valore | Descrizione -| subplugin | qualsiasi stringa | +// TRANSLATION MISSING +| subplugin | any type | qualsiasi stringa | // TRANSLATION MISSING Name of sub plugin (commonly script name, which is displayed in `/help command` for a hook of type 'command') + +| stdin + + _(WeeChat ≥ 0.4.3)_ | + 'process', 'process_hashtable' | qualsiasi stringa | +// TRANSLATION MISSING + Send data on standard input ('stdin') of child process + +| stdin_close + + _(WeeChat ≥ 0.4.3)_ | +// TRANSLATION MISSING + 'process', 'process_hashtable' | (not used) | +// TRANSLATION MISSING + Close pipe used to send data on standard input ('stdin') of child process |=== Esempio in C: @@ -9669,8 +9703,23 @@ struct t_hook *my_command_hook = weechat_hook_set (my_command_hook, "subplugin", "test"); ---- -[NOTE] -Questa funzione non è disponibile nelle API per lo scripting. +Script (Python): + +[source,python] +---- +# prototipo +weechat.hook_set(hook, property, value) + +# esempio +def my_process_cb(data, command, return_code, out, err): + # ... + return weechat.WEECHAT_RC_OK + +hook = weechat.hook_process_hashtable("/path/to/command", { "stdin": "1" }, + 20000, "my_process_cb", "") +weechat.hook_set(hook, "stdin", "data sent to stdin of child process") +weechat.hook_set(hook, "stdin_close", "") # optional +---- ==== weechat_unhook diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index 150bbc168..bb8895592 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -1353,35 +1353,29 @@ hook_process_hashtable (struct t_weechat_plugin *plugin, struct t_hook_process *new_hook_process; char *stdout_buffer, *stderr_buffer; + stdout_buffer = NULL; + stderr_buffer = NULL; + new_hook = NULL; + new_hook_process = NULL; + if (!command || !command[0] || !callback) - return NULL; + goto error; stdout_buffer = malloc (HOOK_PROCESS_BUFFER_SIZE + 1); if (!stdout_buffer) - return NULL; + goto error; stderr_buffer = malloc (HOOK_PROCESS_BUFFER_SIZE + 1); if (!stderr_buffer) - { - free (stdout_buffer); - return NULL; - } + goto error; new_hook = malloc (sizeof (*new_hook)); if (!new_hook) - { - free (stdout_buffer); - free (stderr_buffer); - return NULL; - } + goto error; + new_hook_process = malloc (sizeof (*new_hook_process)); if (!new_hook_process) - { - free (stdout_buffer); - free (stderr_buffer); - free (new_hook); - return NULL; - } + goto error; hook_init_data (new_hook, plugin, HOOK_TYPE_PROCESS, HOOK_PRIORITY_DEFAULT, callback_data); @@ -1391,16 +1385,21 @@ hook_process_hashtable (struct t_weechat_plugin *plugin, new_hook_process->command = strdup (command); new_hook_process->options = (options) ? hashtable_dup (options) : NULL; new_hook_process->timeout = timeout; + new_hook_process->child_read[HOOK_PROCESS_STDIN] = -1; new_hook_process->child_read[HOOK_PROCESS_STDOUT] = -1; new_hook_process->child_read[HOOK_PROCESS_STDERR] = -1; + new_hook_process->child_write[HOOK_PROCESS_STDIN] = -1; new_hook_process->child_write[HOOK_PROCESS_STDOUT] = -1; new_hook_process->child_write[HOOK_PROCESS_STDERR] = -1; new_hook_process->child_pid = 0; + new_hook_process->hook_fd[HOOK_PROCESS_STDIN] = NULL; new_hook_process->hook_fd[HOOK_PROCESS_STDOUT] = NULL; new_hook_process->hook_fd[HOOK_PROCESS_STDERR] = NULL; new_hook_process->hook_timer = NULL; + new_hook_process->buffer[HOOK_PROCESS_STDIN] = NULL; new_hook_process->buffer[HOOK_PROCESS_STDOUT] = stdout_buffer; new_hook_process->buffer[HOOK_PROCESS_STDERR] = stderr_buffer; + new_hook_process->buffer_size[HOOK_PROCESS_STDIN] = 0; new_hook_process->buffer_size[HOOK_PROCESS_STDOUT] = 0; new_hook_process->buffer_size[HOOK_PROCESS_STDERR] = 0; @@ -1409,6 +1408,17 @@ hook_process_hashtable (struct t_weechat_plugin *plugin, hook_process_run (new_hook); return new_hook; + +error: + if (stdout_buffer) + free (stdout_buffer); + if (stderr_buffer) + free (stderr_buffer); + if (new_hook) + free (new_hook); + if (new_hook_process) + free (new_hook_process); + return NULL; } /* @@ -1439,11 +1449,25 @@ hook_process_child (struct t_hook *hook_process) int rc, i, num_args; FILE *f; - /* use "/dev/null" for stdin stream */ - f = freopen ("/dev/null", "r", stdin); - (void) f; + /* read stdin from parent, if a pipe was defined */ + if (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]) >= 0) + { + if (dup2 (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]), + STDIN_FILENO) < 0) + { + _exit (EXIT_FAILURE); + } + } + else + { + /* no stdin pipe from parent, use "/dev/null" for stdin stream */ + f = freopen ("/dev/null", "r", stdin); + (void) f; + } + if (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDIN]) >= 0) + close (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDIN])); - /* redirect stdout/stderr to pipe (so that father process can read them) */ + /* redirect stdout/stderr to pipe (so that parent process can read them) */ close (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDOUT])); close (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDERR])); if (dup2 (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDOUT]), @@ -1718,40 +1742,38 @@ hook_process_timer_cb (void *arg_hook_process, int remaining_calls) void hook_process_run (struct t_hook *hook_process) { - int pipe_stdout[2], pipe_stderr[2], timeout, max_calls, rc; + int pipes[3][2], timeout, max_calls, rc, i; long interval; pid_t pid; - /* create pipe for child process (stdout) */ - if (pipe (pipe_stdout) < 0) + for (i = 0; i < 3; i++) { - (void) (HOOK_PROCESS(hook_process, callback)) - (hook_process->callback_data, - HOOK_PROCESS(hook_process, command), - WEECHAT_HOOK_PROCESS_ERROR, - NULL, NULL); - unhook (hook_process); - return; + pipes[i][0] = -1; + pipes[i][1] = -1; } - if (pipe (pipe_stderr) < 0) + + /* create pipe for stdin (only if stdin was given in options) */ + if (HOOK_PROCESS(hook_process, options) + && hashtable_has_key (HOOK_PROCESS(hook_process, options), "stdin")) { - close (pipe_stdout[0]); - close (pipe_stdout[1]); - (void) (HOOK_PROCESS(hook_process, callback)) - (hook_process->callback_data, - HOOK_PROCESS(hook_process, command), - WEECHAT_HOOK_PROCESS_ERROR, - NULL, NULL); - unhook (hook_process); - return; + if (pipe (pipes[HOOK_PROCESS_STDIN]) < 0) + goto error; } - HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDOUT]) = pipe_stdout[0]; - HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDOUT]) = pipe_stdout[1]; + /* create pipes for stdout/err */ + if (pipe (pipes[HOOK_PROCESS_STDOUT]) < 0) + goto error; + if (pipe (pipes[HOOK_PROCESS_STDERR]) < 0) + goto error; - HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDERR]) = pipe_stderr[0]; - HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDERR]) = pipe_stderr[1]; + /* assign pipes to variables in hook */ + for (i = 0; i < 3; i++) + { + HOOK_PROCESS(hook_process, child_read[i]) = pipes[i][0]; + HOOK_PROCESS(hook_process, child_write[i]) = pipes[i][1]; + } + /* fork */ switch (pid = fork ()) { /* fork failed */ @@ -1772,8 +1794,14 @@ hook_process_run (struct t_hook *hook_process) _exit (EXIT_SUCCESS); break; } + /* parent process */ HOOK_PROCESS(hook_process, child_pid) = pid; + if (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]) >= 0) + { + close (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN])); + HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]) = -1; + } close (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDOUT])); HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDOUT]) = -1; close (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDERR])); @@ -1815,6 +1843,22 @@ hook_process_run (struct t_hook *hook_process) interval, 0, max_calls, &hook_process_timer_cb, hook_process); + return; + +error: + for (i = 0; i < 3; i++) + { + if (pipes[i][0] >= 0) + close (pipes[i][0]); + if (pipes[i][1] >= 0) + close (pipes[i][1]); + } + (void) (HOOK_PROCESS(hook_process, callback)) + (hook_process->callback_data, + HOOK_PROCESS(hook_process, command), + WEECHAT_HOOK_PROCESS_ERROR, + NULL, NULL); + unhook (hook_process); } /* @@ -3157,12 +3201,39 @@ hook_focus_get_data (struct t_hashtable *hashtable_focus1, void hook_set (struct t_hook *hook, const char *property, const char *value) { + /* invalid hook? */ + if (!hook_valid (hook)) + return; + if (string_strcasecmp (property, "subplugin") == 0) { if (hook->subplugin) free(hook->subplugin); hook->subplugin = strdup (value); } + else if (string_strcasecmp (property, "stdin") == 0) + { + if (!hook->deleted + && (hook->type == HOOK_TYPE_PROCESS) + && (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]) >= 0)) + { + /* send data on child's stdin */ + write (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]), + value, + strlen (value)); + } + } + else if (string_strcasecmp (property, "stdin_close") == 0) + { + if (!hook->deleted + && (hook->type == HOOK_TYPE_PROCESS) + && (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]) >= 0)) + { + /* close stdin pipe */ + close (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN])); + HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]) = -1; + } + } } /* @@ -3250,6 +3321,8 @@ unhook (struct t_hook *hook) free (HOOK_PROCESS(hook, command)); if (HOOK_PROCESS(hook, options)) hashtable_free (HOOK_PROCESS(hook, options)); + if (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDIN])) + unhook (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDIN])); if (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDOUT])) unhook (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDOUT])); if (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDERR])) @@ -3261,6 +3334,10 @@ unhook (struct t_hook *hook) kill (HOOK_PROCESS(hook, child_pid), SIGKILL); waitpid (HOOK_PROCESS(hook, child_pid), NULL, 0); } + if (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDIN]) != -1) + close (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDIN])); + if (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]) != -1) + close (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN])); if (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDOUT]) != -1) close (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDOUT])); if (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDOUT]) != -1) @@ -3269,6 +3346,8 @@ unhook (struct t_hook *hook) close (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDERR])); if (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDERR]) != -1) close (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDERR])); + if (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDIN])) + free (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDIN])); if (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDOUT])) free (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDOUT])); if (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDERR])) @@ -3587,6 +3666,10 @@ hook_add_to_infolist_pointer (struct t_infolist *infolist, struct t_hook *hook) return 0; if (!infolist_new_var_integer (ptr_item, "timeout", HOOK_PROCESS(hook, timeout))) return 0; + if (!infolist_new_var_integer (ptr_item, "child_read_stdin", HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDIN]))) + return 0; + if (!infolist_new_var_integer (ptr_item, "child_write_stdin", HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]))) + return 0; if (!infolist_new_var_integer (ptr_item, "child_read_stdout", HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDOUT]))) return 0; if (!infolist_new_var_integer (ptr_item, "child_write_stdout", HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDOUT]))) @@ -3597,6 +3680,8 @@ hook_add_to_infolist_pointer (struct t_infolist *infolist, struct t_hook *hook) return 0; if (!infolist_new_var_integer (ptr_item, "child_pid", HOOK_PROCESS(hook, child_pid))) return 0; + if (!infolist_new_var_pointer (ptr_item, "hook_fd_stdin", HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDIN]))) + return 0; if (!infolist_new_var_pointer (ptr_item, "hook_fd_stdout", HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDOUT]))) return 0; if (!infolist_new_var_pointer (ptr_item, "hook_fd_stderr", HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDERR]))) @@ -4062,11 +4147,14 @@ hook_print_log () hashtable_get_string (HOOK_PROCESS(ptr_hook, options), "keys_values")); log_printf (" timeout . . . . . . . : %d", HOOK_PROCESS(ptr_hook, timeout)); + log_printf (" child_read[stdin] . . : %d", HOOK_PROCESS(ptr_hook, child_read[HOOK_PROCESS_STDIN])); + log_printf (" child_write[stdin]. . : %d", HOOK_PROCESS(ptr_hook, child_write[HOOK_PROCESS_STDIN])); log_printf (" child_read[stdout]. . : %d", HOOK_PROCESS(ptr_hook, child_read[HOOK_PROCESS_STDOUT])); log_printf (" child_write[stdout] . : %d", HOOK_PROCESS(ptr_hook, child_write[HOOK_PROCESS_STDOUT])); log_printf (" child_read[stderr]. . : %d", HOOK_PROCESS(ptr_hook, child_read[HOOK_PROCESS_STDERR])); log_printf (" child_write[stderr] . : %d", HOOK_PROCESS(ptr_hook, child_write[HOOK_PROCESS_STDERR])); log_printf (" child_pid . . . . . . : %d", HOOK_PROCESS(ptr_hook, child_pid)); + log_printf (" hook_fd[stdin]. . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_fd[HOOK_PROCESS_STDIN])); log_printf (" hook_fd[stdout] . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_fd[HOOK_PROCESS_STDOUT])); log_printf (" hook_fd[stderr] . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_fd[HOOK_PROCESS_STDERR])); log_printf (" hook_timer. . . . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_timer)); diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index ca3f7b641..3f4a04ffa 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -88,8 +88,9 @@ enum t_hook_type #define HOOK_FD_FLAG_EXCEPTION 4 /* constants for hook process */ -#define HOOK_PROCESS_STDOUT 0 -#define HOOK_PROCESS_STDERR 1 +#define HOOK_PROCESS_STDIN 0 +#define HOOK_PROCESS_STDOUT 1 +#define HOOK_PROCESS_STDERR 2 #define HOOK_PROCESS_BUFFER_SIZE 65536 /* macros to access hook specific data */ @@ -213,13 +214,13 @@ struct t_hook_process char *command; /* command executed by child */ struct t_hashtable *options; /* options for process (see doc) */ long timeout; /* timeout (ms) (0 = no timeout) */ - int child_read[2]; /* to read data in pipe from child */ - int child_write[2]; /* to write data in pipe for child */ + int child_read[3]; /* read stdin/out/err data from child*/ + int child_write[3]; /* write stdin/out/err data for child*/ pid_t child_pid; /* pid of child process */ - struct t_hook *hook_fd[2]; /* hook fd for stdout/stderr */ + struct t_hook *hook_fd[3]; /* hook fd for stdin/out/err */ struct t_hook *hook_timer; /* timer to check if child has died */ - char *buffer[2]; /* buffers for child stdout/stderr */ - int buffer_size[2]; /* size of child stdout/stderr */ + char *buffer[3]; /* buffers for child stdin/out/err */ + int buffer_size[3]; /* size of child stdin/out/err */ }; /* hook connect */ diff --git a/src/plugins/guile/weechat-guile-api.c b/src/plugins/guile/weechat-guile-api.c index b79e53967..bdd47e92f 100644 --- a/src/plugins/guile/weechat-guile-api.c +++ b/src/plugins/guile/weechat-guile-api.c @@ -2965,6 +2965,21 @@ weechat_guile_api_hook_focus (SCM area, SCM function, SCM data) } SCM +weechat_guile_api_hook_set (SCM hook, SCM property, SCM value) +{ + API_FUNC(1, "hook_set", API_RETURN_ERROR); + if (!scm_is_string (hook) || !scm_is_string (property) + || !scm_is_string (value)) + API_WRONG_ARGS(API_RETURN_ERROR); + + weechat_hook_set (API_STR2PTR(API_SCM_TO_STRING(hook)), + API_SCM_TO_STRING(property), + API_SCM_TO_STRING(value)); + + API_RETURN_OK; +} + +SCM weechat_guile_api_unhook (SCM hook) { API_FUNC(1, "unhook", API_RETURN_ERROR); @@ -4726,6 +4741,7 @@ weechat_guile_api_module_init (void *data) API_DEF_FUNC(hook_info_hashtable, 6); API_DEF_FUNC(hook_infolist, 6); API_DEF_FUNC(hook_focus, 3); + API_DEF_FUNC(hook_set, 3); API_DEF_FUNC(unhook, 1); API_DEF_FUNC(unhook_all, 0); API_DEF_FUNC(buffer_new, 5); diff --git a/src/plugins/lua/weechat-lua-api.c b/src/plugins/lua/weechat-lua-api.c index 4c0009f44..d3e333de0 100644 --- a/src/plugins/lua/weechat-lua-api.c +++ b/src/plugins/lua/weechat-lua-api.c @@ -3202,6 +3202,24 @@ weechat_lua_api_hook_focus (lua_State *L) } static int +weechat_lua_api_hook_set (lua_State *L) +{ + const char *hook, *property, *value; + + API_FUNC(1, "hook_set", API_RETURN_ERROR); + if (lua_gettop (L) < 3) + API_WRONG_ARGS(API_RETURN_ERROR); + + hook = lua_tostring (L, -3); + property = lua_tostring (L, -2); + value = lua_tostring (L, -1); + + weechat_hook_set (API_STR2PTR(hook), property, value); + + API_RETURN_OK; +} + +static int weechat_lua_api_unhook (lua_State *L) { const char *hook; @@ -5210,6 +5228,7 @@ const struct luaL_Reg weechat_lua_api_funcs[] = { API_DEF_FUNC(hook_info_hashtable), API_DEF_FUNC(hook_infolist), API_DEF_FUNC(hook_focus), + API_DEF_FUNC(hook_set), API_DEF_FUNC(unhook), API_DEF_FUNC(unhook_all), API_DEF_FUNC(buffer_new), diff --git a/src/plugins/perl/weechat-perl-api.c b/src/plugins/perl/weechat-perl-api.c index 7d6c9d668..632e17872 100644 --- a/src/plugins/perl/weechat-perl-api.c +++ b/src/plugins/perl/weechat-perl-api.c @@ -3019,6 +3019,24 @@ XS (XS_weechat_api_hook_focus) API_RETURN_STRING_FREE(result); } +XS (XS_weechat_api_hook_set) +{ + char *hook, *property, *value; + dXSARGS; + + API_FUNC(1, "hook_set", API_RETURN_ERROR); + if (items < 3) + API_WRONG_ARGS(API_RETURN_ERROR); + + hook = SvPV_nolen (ST (0)); + property = SvPV_nolen (ST (1)); + value = SvPV_nolen (ST (2)); + + weechat_hook_set (API_STR2PTR(hook), property, value); + + API_RETURN_OK; +} + XS (XS_weechat_api_unhook) { dXSARGS; @@ -4963,6 +4981,7 @@ weechat_perl_api_init (pTHX) API_DEF_FUNC(hook_info_hashtable); API_DEF_FUNC(hook_infolist); API_DEF_FUNC(hook_focus); + API_DEF_FUNC(hook_set); API_DEF_FUNC(unhook); API_DEF_FUNC(unhook_all); API_DEF_FUNC(buffer_new); diff --git a/src/plugins/python/weechat-python-api.c b/src/plugins/python/weechat-python-api.c index 4b6128edd..3a3cc7b68 100644 --- a/src/plugins/python/weechat-python-api.c +++ b/src/plugins/python/weechat-python-api.c @@ -3159,6 +3159,25 @@ weechat_python_api_hook_focus (PyObject *self, PyObject *args) } static PyObject * +weechat_python_api_hook_set (PyObject *self, PyObject *args) +{ + char *hook, *property, *value; + + API_FUNC(1, "hook_set", API_RETURN_ERROR); + hook = NULL; + property = NULL; + value = NULL; + if (!PyArg_ParseTuple (args, "sss", &hook, &property, &value)) + API_WRONG_ARGS(API_RETURN_ERROR); + + weechat_hook_set (API_STR2PTR(hook), + property, + value); + + API_RETURN_OK; +} + +static PyObject * weechat_python_api_unhook (PyObject *self, PyObject *args) { char *hook; @@ -5122,6 +5141,7 @@ PyMethodDef weechat_python_funcs[] = API_DEF_FUNC(hook_info_hashtable), API_DEF_FUNC(hook_infolist), API_DEF_FUNC(hook_focus), + API_DEF_FUNC(hook_set), API_DEF_FUNC(unhook), API_DEF_FUNC(unhook_all), API_DEF_FUNC(buffer_new), diff --git a/src/plugins/ruby/weechat-ruby-api.c b/src/plugins/ruby/weechat-ruby-api.c index 6ceadef11..471f038a6 100644 --- a/src/plugins/ruby/weechat-ruby-api.c +++ b/src/plugins/ruby/weechat-ruby-api.c @@ -3649,6 +3649,31 @@ weechat_ruby_api_hook_focus (VALUE class, VALUE area, VALUE function, } static VALUE +weechat_ruby_api_hook_set (VALUE class, VALUE hook, VALUE property, + VALUE value) +{ + char *c_hook, *c_property, *c_value; + + API_FUNC(1, "hook_set", API_RETURN_ERROR); + if (NIL_P (hook) || NIL_P (property) || NIL_P (value)) + API_WRONG_ARGS(API_RETURN_ERROR); + + Check_Type (hook, T_STRING); + Check_Type (property, T_STRING); + Check_Type (value, T_STRING); + + c_hook = StringValuePtr (hook); + c_property = StringValuePtr (property); + c_value = StringValuePtr (value); + + weechat_hook_set (API_STR2PTR(c_hook), + c_property, + c_value); + + API_RETURN_OK; +} + +static VALUE weechat_ruby_api_unhook (VALUE class, VALUE hook) { char *c_hook; @@ -6066,6 +6091,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat) API_DEF_FUNC(hook_info_hashtable, 6); API_DEF_FUNC(hook_infolist, 6); API_DEF_FUNC(hook_focus, 3); + API_DEF_FUNC(hook_set, 3); API_DEF_FUNC(unhook, 1); API_DEF_FUNC(unhook_all, 0); API_DEF_FUNC(buffer_new, 5); diff --git a/src/plugins/tcl/weechat-tcl-api.c b/src/plugins/tcl/weechat-tcl-api.c index 0730cac48..bcaecb999 100644 --- a/src/plugins/tcl/weechat-tcl-api.c +++ b/src/plugins/tcl/weechat-tcl-api.c @@ -3505,6 +3505,27 @@ weechat_tcl_api_hook_focus (ClientData clientData, Tcl_Interp *interp, } static int +weechat_tcl_api_hook_set (ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + Tcl_Obj *objp; + char *hook, *property, *value; + int i; + + API_FUNC(1, "hook_set", API_RETURN_ERROR); + if (objc < 4) + API_WRONG_ARGS(API_RETURN_ERROR); + + hook = Tcl_GetStringFromObj (objv[1], &i); + property = Tcl_GetStringFromObj (objv[2], &i); + value = Tcl_GetStringFromObj (objv[3], &i); + + weechat_hook_set (API_STR2PTR(hook), property, value); + + API_RETURN_OK; +} + +static int weechat_tcl_api_unhook (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { @@ -5809,6 +5830,7 @@ void weechat_tcl_api_init (Tcl_Interp *interp) API_DEF_FUNC(hook_info_hashtable); API_DEF_FUNC(hook_infolist); API_DEF_FUNC(hook_focus); + API_DEF_FUNC(hook_set); API_DEF_FUNC(unhook); API_DEF_FUNC(unhook_all); API_DEF_FUNC(buffer_new); |