diff --git a/doc/en/dev/plugin_c_api.en.xml b/doc/en/dev/plugin_c_api.en.xml index 22651faf8..9f4f123e4 100644 --- a/doc/en/dev/plugin_c_api.en.xml +++ b/doc/en/dev/plugin_c_api.en.xml @@ -5256,7 +5256,7 @@ struct t_hook *weechat_hook_timer ( long interval, const char *align_second, const char *max_calls, - int (*callback)(void *data), + int (*callback)(void *data, int remaining_calls), void *callback_data); @@ -5305,6 +5305,11 @@ struct t_hook *weechat_hook_timer ( data pointer + + int + remaining_calls + remaining calls (-1 if timer has no end) + @@ -5325,7 +5330,7 @@ struct t_hook *weechat_hook_timer ( Example: int -my_timer_cb (void *data) +my_timer_cb (void *data, int remaining_calls) { /* ... */ return WEECHAT_RC_OK; @@ -5442,6 +5447,128 @@ struct t_hook *my_fd_hook = +
+ weechat_hook_process + + + Prototype: + +struct t_hook *weechat_hook_process ( + const char *command, + int timeout, + int (*callback)(void *data, + const char *command, + int return_code, + const char *stdout, + const char *stderr), + void *callback_data); + + + + Hook a process (with fork), and catch output. + + + Arguments: + + + + : command to launch in child process + + + + + : timeout for command (in milliseconds): + after this timeout, child process is killed (0 means no timeout) + + + + + : function called when data from child + is available, or when child has ended, arguments: + + + + + Type + Name + Description + + + + + void * + data + pointer + + + const char * + command + command executed by child + + + int + return_code + + if >= 0, it's child (command) return code (it's last + call to this callback), if < 0, it can be + WEECHAT_HOOK_PROCESS_OK_RUNNING (data available, but + child still running) or WEECHAT_HOOK_PROCESS_ERROR + (error when launching command). + + + + + + + + + + : pointer given to callback when it + is called by WeeeChat + + + + + + Return value: pointer to new hook, NULL if error occured. + + + Example: + +int +my_process_cb (void *data, const char *command, int return_code, + const char *stdout, const char *stderr) +{ + if (return_code == WEECHAT_HOOK_PROCESS_ERROR) + { + weechat_printf (NULL, "Error with command '%s'", command); + return; + } + + if (return_code >= 0) + { + weechat_printf (NULL, "return_code = %d", return_code); + } + + if (stdout) + { + weechat_printf (NULL, "stdout: %s", stdout); + } + + if (stderr) + { + weechat_printf (NULL, "stderr: %s", stderr); + } + + return WEECHAT_RC_OK; +} + +struct t_hook *my_process_hook = + weechat_hook_process ("ls", 5000, &my_process_cb, NULL); + + +
+
weechat_hook_connect @@ -5608,7 +5735,7 @@ my_connect_cb (void *data, int status, const char *ip_address) } struct t_hook *my_connect_hook = - weechat_hook_fd (sock, 1, 0, 0, &my_connect_cb, NULL); + weechat_hook_connect (sock, 1, 0, 0, &my_connect_cb, NULL);
diff --git a/po/cs.po b/po/cs.po index 0a8bf65c7..d6fd1a036 100644 --- a/po/cs.po +++ b/po/cs.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.2.7-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2009-03-02 10:33+0100\n" +"POT-Creation-Date: 2009-03-06 18:11+0100\n" "PO-Revision-Date: 2009-01-03 00:42+0100\n" "Last-Translator: Jiri Golembiovsky \n" "Language-Team: weechat-dev \n" @@ -477,11 +477,19 @@ msgstr " zápis" msgid " exception" msgstr " vyjímka" +#, fuzzy +msgid " process hooked:" +msgstr " napojené tisky:" + +#, fuzzy, c-format +msgid " command: '%s', child pid: %d" +msgstr " signál: %s" + msgid " connect hooked:" msgstr " napojené spojení:" -#, c-format -msgid " socket: %d, address: %s, port: %d" +#, fuzzy, c-format +msgid " socket: %d, address: %s, port: %d, child pid: %d" msgstr " soket: %d, adresa: %s, port: %d" msgid " prints hooked:" @@ -646,6 +654,12 @@ msgstr "Volba odebrána: %s" msgid "%d option(s) reset, %d option(s) removed" msgstr "%d volba/volby resetovány, %d volba/volby smazány" +#, c-format +msgid "" +"%sCan't upgrade: there is one or more background process (hook type " +"'process' or 'connect')" +msgstr "" + #, c-format msgid "%sCan't upgrade: WeeChat binary \"%s\" does not exist" msgstr "" @@ -1731,6 +1745,10 @@ msgstr "Ukládám konfiguraci na disk\n" msgid "System clock skew detected (%+ld seconds), reinitializing all timers" msgstr "" +#, c-format +msgid "End of command '%s', timeout reached (%.1fs)" +msgstr "" + #, fuzzy, c-format msgid "%sYou can not write text in this buffer" msgstr "%s nemohu zavřít jediný buffer\n" diff --git a/po/de.po b/po/de.po index 14b957a8f..eda0d8215 100644 --- a/po/de.po +++ b/po/de.po @@ -9,7 +9,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.2.7-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2009-03-02 10:33+0100\n" +"POT-Creation-Date: 2009-03-06 18:11+0100\n" "PO-Revision-Date: 2009-01-03 00:42+0100\n" "Last-Translator: Thomas Schuetz \n" "Language-Team: weechat-dev \n" @@ -523,12 +523,20 @@ msgstr "" msgid " exception" msgstr " . Beschreibung: %s\n" +#, fuzzy +msgid " process hooked:" +msgstr " Timer-Handler:\n" + +#, fuzzy, c-format +msgid " command: '%s', child pid: %d" +msgstr " IRC(%s)\n" + #, fuzzy msgid " connect hooked:" msgstr " Befehls-Handler:\n" #, c-format -msgid " socket: %d, address: %s, port: %d" +msgid " socket: %d, address: %s, port: %d, child pid: %d" msgstr "" #, fuzzy @@ -703,6 +711,12 @@ msgstr "Sie sind nicht im Channel" msgid "%d option(s) reset, %d option(s) removed" msgstr "" +#, c-format +msgid "" +"%sCan't upgrade: there is one or more background process (hook type " +"'process' or 'connect')" +msgstr "" + #, c-format msgid "%sCan't upgrade: WeeChat binary \"%s\" does not exist" msgstr "" @@ -1748,6 +1762,10 @@ msgstr "Konfiguration wird gespeichert\n" msgid "System clock skew detected (%+ld seconds), reinitializing all timers" msgstr "" +#, c-format +msgid "End of command '%s', timeout reached (%.1fs)" +msgstr "" + #, fuzzy, c-format msgid "%sYou can not write text in this buffer" msgstr "%s der einzige Puffer kann nicht geschlossen werden\n" diff --git a/po/es.po b/po/es.po index a1fa7176e..0f2ada3ef 100644 --- a/po/es.po +++ b/po/es.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.2.7-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2009-03-02 10:33+0100\n" +"POT-Creation-Date: 2009-03-06 18:11+0100\n" "PO-Revision-Date: 2009-01-03 00:42+0100\n" "Last-Translator: Roberto González Cardenete \n" "Language-Team: weechat-dev \n" @@ -518,12 +518,20 @@ msgstr "" msgid " exception" msgstr " . descripción: %s\n" +#, fuzzy +msgid " process hooked:" +msgstr " manejadores de temporización:\n" + +#, fuzzy, c-format +msgid " command: '%s', child pid: %d" +msgstr " IRC(%s)\n" + #, fuzzy msgid " connect hooked:" msgstr " manejadores de comando:\n" #, c-format -msgid " socket: %d, address: %s, port: %d" +msgid " socket: %d, address: %s, port: %d, child pid: %d" msgstr "" #, fuzzy @@ -698,6 +706,12 @@ msgstr "no presente en el canal" msgid "%d option(s) reset, %d option(s) removed" msgstr "" +#, c-format +msgid "" +"%sCan't upgrade: there is one or more background process (hook type " +"'process' or 'connect')" +msgstr "" + #, c-format msgid "%sCan't upgrade: WeeChat binary \"%s\" does not exist" msgstr "" @@ -1733,6 +1747,10 @@ msgstr "Guardar configuración a disco\n" msgid "System clock skew detected (%+ld seconds), reinitializing all timers" msgstr "" +#, c-format +msgid "End of command '%s', timeout reached (%.1fs)" +msgstr "" + #, fuzzy, c-format msgid "%sYou can not write text in this buffer" msgstr "%s no es posible cerrar el único búfer\n" diff --git a/po/fr.po b/po/fr.po index 55359839b..a913684e6 100644 --- a/po/fr.po +++ b/po/fr.po @@ -6,8 +6,8 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.2.7-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2009-03-02 10:33+0100\n" -"PO-Revision-Date: 2009-03-02 10:34+0100\n" +"POT-Creation-Date: 2009-03-06 18:11+0100\n" +"PO-Revision-Date: 2009-03-06 18:11+0100\n" "Last-Translator: FlashCode \n" "Language-Team: weechat-dev \n" "MIME-Version: 1.0\n" @@ -480,12 +480,19 @@ msgstr " écriture" msgid " exception" msgstr " exception" +msgid " process hooked:" +msgstr " processus accrochés:" + +#, c-format +msgid " command: '%s', child pid: %d" +msgstr " commande: '%s', pid fils: %d" + msgid " connect hooked:" msgstr " connexions accrochées:" #, c-format -msgid " socket: %d, address: %s, port: %d" -msgstr " socket: %d, addresse: %s, port: %d" +msgid " socket: %d, address: %s, port: %d, child pid: %d" +msgstr " socket: %d, addresse: %s, port: %d, pid fils: %d" msgid " prints hooked:" msgstr " impressions accrochées:" @@ -645,6 +652,14 @@ msgstr "Option supprimée: %s" msgid "%d option(s) reset, %d option(s) removed" msgstr "%d option(s) réinitialisée(s), %d option(s) supprimée(s)" +#, c-format +msgid "" +"%sCan't upgrade: there is one or more background process (hook type " +"'process' or 'connect')" +msgstr "" +"%sImpossible de mettre à jour: il y a un ou plusieurs processus en tâche de " +"fond (hook de type 'process' ou 'connect')" + #, c-format msgid "%sCan't upgrade: WeeChat binary \"%s\" does not exist" msgstr "%sImpossible de mettre à jour: le binaire WeeChat \"%s\" n'existe pas" @@ -1830,6 +1845,10 @@ msgstr "" "Décalage de l'horloge système détecté (%+ld secondes), réinitialisation de " "tous les minuteurs" +#, c-format +msgid "End of command '%s', timeout reached (%.1fs)" +msgstr "Fin de la commande '%s', temps maximum atteint (%.1fs)" + #, c-format msgid "%sYou can not write text in this buffer" msgstr "%sVous ne pouvez pas écrire de texte dans ce tampon" diff --git a/po/hu.po b/po/hu.po index d729c6fed..2a9b28b58 100644 --- a/po/hu.po +++ b/po/hu.po @@ -12,7 +12,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.2.7-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2009-03-02 10:33+0100\n" +"POT-Creation-Date: 2009-03-06 18:11+0100\n" "PO-Revision-Date: 2009-01-03 00:42+0100\n" "Last-Translator: Andras Voroskoi \n" "Language-Team: weechat-dev \n" @@ -524,12 +524,20 @@ msgstr "" msgid " exception" msgstr " . leírás : %s\n" +#, fuzzy +msgid " process hooked:" +msgstr " időkezelők:\n" + +#, fuzzy, c-format +msgid " command: '%s', child pid: %d" +msgstr " IRC(%s)\n" + #, fuzzy msgid " connect hooked:" msgstr " parancskezelők:\n" #, c-format -msgid " socket: %d, address: %s, port: %d" +msgid " socket: %d, address: %s, port: %d, child pid: %d" msgstr "" #, fuzzy @@ -704,6 +712,12 @@ msgstr "nincs a szobában" msgid "%d option(s) reset, %d option(s) removed" msgstr "" +#, c-format +msgid "" +"%sCan't upgrade: there is one or more background process (hook type " +"'process' or 'connect')" +msgstr "" + #, c-format msgid "%sCan't upgrade: WeeChat binary \"%s\" does not exist" msgstr "" @@ -1761,6 +1775,10 @@ msgstr "Beállítások mentése a lemezre\n" msgid "System clock skew detected (%+ld seconds), reinitializing all timers" msgstr "" +#, c-format +msgid "End of command '%s', timeout reached (%.1fs)" +msgstr "" + #, fuzzy, c-format msgid "%sYou can not write text in this buffer" msgstr "%s az utolsó puffert nem lehet bezárni\n" diff --git a/po/ru.po b/po/ru.po index 054c359b4..59200b320 100644 --- a/po/ru.po +++ b/po/ru.po @@ -6,7 +6,7 @@ msgid "" msgstr "" "Project-Id-Version: WeeChat 0.2.7-dev\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2009-03-02 10:33+0100\n" +"POT-Creation-Date: 2009-03-06 18:11+0100\n" "PO-Revision-Date: 2009-01-03 00:42+0100\n" "Last-Translator: Pavel Shevchuk \n" "Language-Team: weechat-dev \n" @@ -519,12 +519,20 @@ msgstr "" msgid " exception" msgstr " . описание: %s\n" +#, fuzzy +msgid " process hooked:" +msgstr " обработчики таймера:\n" + +#, fuzzy, c-format +msgid " command: '%s', child pid: %d" +msgstr " IRC(%s)\n" + #, fuzzy msgid " connect hooked:" msgstr " обработчики команд:\n" #, c-format -msgid " socket: %d, address: %s, port: %d" +msgid " socket: %d, address: %s, port: %d, child pid: %d" msgstr "" #, fuzzy @@ -699,6 +707,12 @@ msgstr "не на канале" msgid "%d option(s) reset, %d option(s) removed" msgstr "" +#, c-format +msgid "" +"%sCan't upgrade: there is one or more background process (hook type " +"'process' or 'connect')" +msgstr "" + #, c-format msgid "%sCan't upgrade: WeeChat binary \"%s\" does not exist" msgstr "" @@ -1762,6 +1776,10 @@ msgstr "Сохраняю конфигурацию\n" msgid "System clock skew detected (%+ld seconds), reinitializing all timers" msgstr "" +#, c-format +msgid "End of command '%s', timeout reached (%.1fs)" +msgstr "" + #, fuzzy, c-format msgid "%sYou can not write text in this buffer" msgstr "%s невозможно закрыть единственный буфер\n" diff --git a/po/weechat.pot b/po/weechat.pot index 9281c9710..6fa1fbe43 100644 --- a/po/weechat.pot +++ b/po/weechat.pot @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PACKAGE VERSION\n" "Report-Msgid-Bugs-To: flashcode@flashtux.org\n" -"POT-Creation-Date: 2009-03-02 10:33+0100\n" +"POT-Creation-Date: 2009-03-06 18:11+0100\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -455,11 +455,18 @@ msgstr "" msgid " exception" msgstr "" +msgid " process hooked:" +msgstr "" + +#, c-format +msgid " command: '%s', child pid: %d" +msgstr "" + msgid " connect hooked:" msgstr "" #, c-format -msgid " socket: %d, address: %s, port: %d" +msgid " socket: %d, address: %s, port: %d, child pid: %d" msgstr "" msgid " prints hooked:" @@ -618,6 +625,12 @@ msgstr "" msgid "%d option(s) reset, %d option(s) removed" msgstr "" +#, c-format +msgid "" +"%sCan't upgrade: there is one or more background process (hook type " +"'process' or 'connect')" +msgstr "" + #, c-format msgid "%sCan't upgrade: WeeChat binary \"%s\" does not exist" msgstr "" @@ -1480,6 +1493,10 @@ msgstr "" msgid "System clock skew detected (%+ld seconds), reinitializing all timers" msgstr "" +#, c-format +msgid "End of command '%s', timeout reached (%.1fs)" +msgstr "" + #, c-format msgid "%sYou can not write text in this buffer" msgstr "" diff --git a/src/core/wee-command.c b/src/core/wee-command.c index 10295959c..45734d590 100644 --- a/src/core/wee-command.c +++ b/src/core/wee-command.c @@ -2053,6 +2053,7 @@ command_plugin_list (const char *name, int full) plugins_found++; /* plugin info */ + gui_chat_printf (NULL, ""); gui_chat_printf (NULL, " %s%s%s v%s - %s (%s)", GUI_COLOR(GUI_COLOR_CHAT_BUFFER), @@ -2161,7 +2162,26 @@ command_plugin_list (const char *name, int full) _(" exception") : ""); } } - + + /* process hooked */ + hook_found = 0; + for (ptr_hook = weechat_hooks[HOOK_TYPE_PROCESS]; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if (!ptr_hook->deleted && (ptr_hook->plugin == ptr_plugin)) + { + if (!hook_found) + gui_chat_printf (NULL, + _(" process hooked:")); + hook_found = 1; + gui_chat_printf (NULL, + _(" command: '%s', child " + "pid: %d"), + (HOOK_PROCESS(ptr_hook, command)), + HOOK_PROCESS(ptr_hook, child_pid)); + } + } + /* connect hooked */ hook_found = 0; for (ptr_hook = weechat_hooks[HOOK_TYPE_CONNECT]; ptr_hook; @@ -2175,10 +2195,11 @@ command_plugin_list (const char *name, int full) hook_found = 1; gui_chat_printf (NULL, _(" socket: %d, address: %s, " - "port: %d"), + "port: %d, child pid: %d"), HOOK_CONNECT(ptr_hook, sock), HOOK_CONNECT(ptr_hook, address), - HOOK_CONNECT(ptr_hook, port)); + HOOK_CONNECT(ptr_hook, port), + HOOK_CONNECT(ptr_hook, child_pid)); } } @@ -3079,6 +3100,17 @@ command_upgrade (void *data, struct t_gui_buffer *buffer, (void) data; (void) buffer; (void) argv; + + /* it's forbidden to upgrade while there are some background process + (hook type "process" or "connect") */ + if (weechat_hooks[HOOK_TYPE_PROCESS] || weechat_hooks[HOOK_TYPE_CONNECT]) + { + gui_chat_printf (NULL, + _("%sCan't upgrade: there is one or more background " + "process (hook type 'process' or 'connect')"), + gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); + return WEECHAT_RC_OK; + } if (argc > 1) { @@ -3096,7 +3128,7 @@ command_upgrade (void *data, struct t_gui_buffer *buffer, gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], ptr_binary); free (ptr_binary); - return WEECHAT_RC_ERROR; + return WEECHAT_RC_OK; } if ((!(stat_buf.st_mode & S_IXUSR)) && (!(stat_buf.st_mode & S_IXGRP)) && (!(stat_buf.st_mode & S_IXOTH))) @@ -3107,7 +3139,7 @@ command_upgrade (void *data, struct t_gui_buffer *buffer, gui_chat_prefix[GUI_CHAT_PREFIX_ERROR], ptr_binary); free (ptr_binary); - return WEECHAT_RC_ERROR; + return WEECHAT_RC_OK; } } } @@ -3119,7 +3151,7 @@ command_upgrade (void *data, struct t_gui_buffer *buffer, gui_chat_printf (NULL, _("%sNot enough memory"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); - return WEECHAT_RC_ERROR; + return WEECHAT_RC_OK; } gui_chat_printf (NULL, @@ -3135,7 +3167,7 @@ command_upgrade (void *data, struct t_gui_buffer *buffer, _("%sError: unable to save session in file"), gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]); free (ptr_binary); - return WEECHAT_RC_ERROR; + return WEECHAT_RC_OK; } exec_args[0] = ptr_binary; diff --git a/src/core/wee-config.c b/src/core/wee-config.c index df2eb12bb..43ccfced1 100644 --- a/src/core/wee-config.c +++ b/src/core/wee-config.c @@ -322,7 +322,7 @@ config_change_color (void *data, struct t_config_option *option) */ int -config_day_change_timer_cb (void *data) +config_day_change_timer_cb (void *data, int remaining_calls) { struct timeval tv_time; struct tm *local_time; @@ -331,6 +331,7 @@ config_day_change_timer_cb (void *data) /* make C compiler happy */ (void) data; + (void) remaining_calls; gettimeofday (&tv_time, NULL); local_time = localtime (&tv_time.tv_sec); diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c index 9422850ed..41a38f245 100644 --- a/src/core/wee-hook.c +++ b/src/core/wee-hook.c @@ -47,8 +47,8 @@ char *hook_type_string[HOOK_NUM_TYPES] = -{ "command", "command_run", "timer", "fd", "connect", "print", "signal", - "config", "completion", "modifier", "info", "infolist" }; +{ "command", "command_run", "timer", "fd", "process", "connect", "print", + "signal", "config", "completion", "modifier", "info", "infolist" }; struct t_hook *weechat_hooks[HOOK_NUM_TYPES]; /* list of hooks */ struct t_hook *last_weechat_hook[HOOK_NUM_TYPES]; /* last hook */ int hook_exec_recursion = 0; /* 1 when a hook is executed */ @@ -56,6 +56,9 @@ time_t hook_last_system_time = 0; /* used to detect system clock skew */ int real_delete_pending = 0; /* 1 if some hooks must be deleted */ +void hook_process_run (struct t_hook *hook_process); + + /* * hook_init: init hooks lists */ @@ -797,7 +800,9 @@ hook_timer_exec () { ptr_hook->running = 1; (void) (HOOK_TIMER(ptr_hook, callback)) - (ptr_hook->callback_data); + (ptr_hook->callback_data, + (HOOK_TIMER(ptr_hook, remaining_calls) > 0) ? + HOOK_TIMER(ptr_hook, remaining_calls) - 1 : -1); ptr_hook->running = 0; if (!ptr_hook->deleted) { @@ -963,6 +968,294 @@ hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *exception_fds) hook_exec_end (); } +/* + * hook_process: hook a process (using fork) + */ + +struct t_hook * +hook_process (struct t_weechat_plugin *plugin, + const char *command, int timeout, + t_hook_callback_process *callback, void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_process *new_hook_process; + + if (!command || !command[0]) + return NULL; + + new_hook = malloc (sizeof (*new_hook)); + if (!new_hook) + return NULL; + new_hook_process = malloc (sizeof (*new_hook_process)); + if (!new_hook_process) + { + free (new_hook); + return NULL; + } + + hook_init_data (new_hook, plugin, HOOK_TYPE_PROCESS, callback_data); + + new_hook->hook_data = new_hook_process; + new_hook_process->callback = callback; + new_hook_process->command = strdup (command); + new_hook_process->timeout = timeout; + new_hook_process->child_stdout_read = -1; + new_hook_process->child_stdout_write = -1; + new_hook_process->child_stderr_read = -1; + new_hook_process->child_stderr_write = -1; + new_hook_process->child_pid = 0; + new_hook_process->hook_fd_stdout = NULL; + new_hook_process->hook_fd_stderr = NULL; + new_hook_process->hook_timer = NULL; + + hook_add_to_list (new_hook); + + hook_process_run (new_hook); + + return new_hook; +} + +/* + * hook_process_child: child process for hook process: execute function and + * return string result into pipe for WeeChat process + */ + +void +hook_process_child (struct t_hook *hook_process) +{ + char *exec_args[4] = { "sh", "-c", NULL, NULL }; + + /* close stdin, so that process will fail to read stdin (process reading + stdin should not be run inside WeeChat!) */ + close (STDIN_FILENO); + + /* redirect stdout/stderr to pipe (so that father process can read them) */ + close (HOOK_PROCESS(hook_process, child_stdout_read)); + close (HOOK_PROCESS(hook_process, child_stderr_read)); + if (dup2 (HOOK_PROCESS(hook_process, child_stdout_write), + STDOUT_FILENO) < 0) + { + _exit (EXIT_FAILURE); + } + if (dup2 (HOOK_PROCESS(hook_process, child_stderr_write), + STDERR_FILENO) < 0) + { + _exit (EXIT_FAILURE); + } + + /* launch command */ + exec_args[2] = HOOK_PROCESS(hook_process, command); + execvp (exec_args[0], exec_args); + + /* should not be executed if execvp was ok */ + fprintf (stderr, "Error with command '%s'\n", + HOOK_PROCESS(hook_process, command)); + _exit (EXIT_FAILURE); +} + +/* + * hook_process_child_read: read process output (stdout or stderr) from child + * process + */ + +void +hook_process_child_read (struct t_hook *hook_process, int fd, + int stdout, struct t_hook **hook_fd) +{ + char buffer[4096]; + int num_read; + + num_read = read (fd, buffer, sizeof (buffer) - 1); + if (num_read > 0) + { + buffer[num_read] = '\0'; + (void) (HOOK_PROCESS(hook_process, callback)) + (hook_process->callback_data, + HOOK_PROCESS(hook_process, command), + WEECHAT_HOOK_PROCESS_RUNNING, + (stdout) ? buffer : NULL, + (stdout) ? NULL : buffer); + } + else if (num_read == 0) + { + unhook (*hook_fd); + *hook_fd = NULL; + } +} + +/* + * hook_process_child_read_stdout_cb: read process output (stdout) from child + * process + */ + +int +hook_process_child_read_stdout_cb (void *arg_hook_process, int fd) +{ + struct t_hook *hook_process; + + hook_process = (struct t_hook *)arg_hook_process; + hook_process_child_read (hook_process, fd, 1, + &(HOOK_PROCESS(hook_process, hook_fd_stdout))); + return WEECHAT_RC_OK; +} + +/* + * hook_process_child_read_stderr_cb: read process output (stderr) from child + * process + */ + +int +hook_process_child_read_stderr_cb (void *arg_hook_process, int fd) +{ + struct t_hook *hook_process; + + hook_process = (struct t_hook *)arg_hook_process; + hook_process_child_read (hook_process, fd, 0, + &(HOOK_PROCESS(hook_process, hook_fd_stderr))); + return WEECHAT_RC_OK; +} + +/* + * hook_process_timer_cb: timer to check if child is died or not + */ + +int +hook_process_timer_cb (void *arg_hook_process, int remaining_calls) +{ + struct t_hook *hook_process; + int status, rc; + + /* make C compiler happy */ + (void) remaining_calls; + + hook_process = (struct t_hook *)arg_hook_process; + + if (remaining_calls == 0) + { + gui_chat_printf (NULL, + _("End of command '%s', timeout reached (%.1fs)"), + HOOK_PROCESS(hook_process, command), + ((float)HOOK_PROCESS(hook_process, timeout)) / 1000); + kill (HOOK_PROCESS(hook_process, child_pid), SIGKILL); + usleep (1000); + } + + if (waitpid (HOOK_PROCESS(hook_process, child_pid), &status, WNOHANG) > 0) + { + rc = WEXITSTATUS(status); + (void) (HOOK_PROCESS(hook_process, callback)) + (hook_process->callback_data, + HOOK_PROCESS(hook_process, command), + rc, NULL, NULL); + unhook (hook_process); + } + + return WEECHAT_RC_OK; +} + +/* + * hook_process_run: fork, execute process function in child, and read data in + * current process, with fd hook + */ + +void +hook_process_run (struct t_hook *hook_process) +{ + int pipe_stdout[2], pipe_stderr[2], timeout, max_calls; + long interval; + pid_t pid; + + /* create pipe for child process (stdout) */ + if (pipe (pipe_stdout) < 0) + { + (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 (pipe_stderr) < 0) + { + 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; + } + + HOOK_PROCESS(hook_process, child_stdout_read) = pipe_stdout[0]; + HOOK_PROCESS(hook_process, child_stdout_write) = pipe_stdout[1]; + + HOOK_PROCESS(hook_process, child_stderr_read) = pipe_stderr[0]; + HOOK_PROCESS(hook_process, child_stderr_write) = pipe_stderr[1]; + + switch (pid = fork ()) + { + /* fork failed */ + case -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; + /* child process */ + case 0: + setuid (getuid ()); + hook_process_child (hook_process); + /* never executed */ + _exit (EXIT_SUCCESS); + break; + } + /* parent process */ + HOOK_PROCESS(hook_process, child_pid) = pid; + close (HOOK_PROCESS(hook_process, child_stdout_write)); + HOOK_PROCESS(hook_process, child_stdout_write) = -1; + close (HOOK_PROCESS(hook_process, child_stderr_write)); + HOOK_PROCESS(hook_process, child_stderr_write) = -1; + HOOK_PROCESS(hook_process, hook_fd_stdout) = hook_fd (hook_process->plugin, + HOOK_PROCESS(hook_process, child_stdout_read), + 1, 0, 0, + &hook_process_child_read_stdout_cb, + hook_process); + + HOOK_PROCESS(hook_process, hook_fd_stderr) = hook_fd (hook_process->plugin, + HOOK_PROCESS(hook_process, child_stderr_read), + 1, 0, 0, + &hook_process_child_read_stderr_cb, + hook_process); + + timeout = HOOK_PROCESS(hook_process, timeout); + interval = 100; + max_calls = 0; + if (timeout > 0) + { + if (timeout <= 100) + { + interval = timeout; + max_calls = 1; + } + else + { + interval = 100; + max_calls = timeout / 100; + if (timeout % 100 == 0) + max_calls++; + } + } + HOOK_PROCESS(hook_process, hook_timer) = hook_timer (hook_process->plugin, + interval, 0, max_calls, + &hook_process_timer_cb, + hook_process); +} + /* * hook_connect: hook a connection to peer (using fork) */ @@ -1704,18 +1997,37 @@ unhook (struct t_hook *hook) free (HOOK_COMMAND(hook, args_description)); if (HOOK_COMMAND(hook, completion)) free (HOOK_COMMAND(hook, completion)); - free ((struct t_hook_command *)hook->hook_data); break; case HOOK_TYPE_COMMAND_RUN: if (HOOK_COMMAND_RUN(hook, command)) free (HOOK_COMMAND_RUN(hook, command)); - free ((struct t_hook_command *)hook->hook_data); break; case HOOK_TYPE_TIMER: - free ((struct t_hook_timer *)hook->hook_data); break; case HOOK_TYPE_FD: - free ((struct t_hook_fd *)hook->hook_data); + break; + case HOOK_TYPE_PROCESS: + if (HOOK_PROCESS(hook, command)) + free (HOOK_PROCESS(hook, command)); + if (HOOK_PROCESS(hook, hook_fd_stdout)) + unhook (HOOK_PROCESS(hook, hook_fd_stdout)); + if (HOOK_PROCESS(hook, hook_fd_stderr)) + unhook (HOOK_PROCESS(hook, hook_fd_stderr)); + if (HOOK_PROCESS(hook, hook_timer)) + unhook (HOOK_PROCESS(hook, hook_timer)); + if (HOOK_PROCESS(hook, child_pid) > 0) + { + kill (HOOK_PROCESS(hook, child_pid), SIGKILL); + waitpid (HOOK_PROCESS(hook, child_pid), NULL, 0); + } + if (HOOK_PROCESS(hook, child_stdout_read) != -1) + close (HOOK_PROCESS(hook, child_stdout_read)); + if (HOOK_PROCESS(hook, child_stdout_write) != -1) + close (HOOK_PROCESS(hook, child_stdout_write)); + if (HOOK_PROCESS(hook, child_stderr_read) != -1) + close (HOOK_PROCESS(hook, child_stderr_read)); + if (HOOK_PROCESS(hook, child_stderr_write) != -1) + close (HOOK_PROCESS(hook, child_stderr_write)); break; case HOOK_TYPE_CONNECT: if (HOOK_CONNECT(hook, proxy)) @@ -1735,52 +2047,45 @@ unhook (struct t_hook *hook) close (HOOK_CONNECT(hook, child_read)); if (HOOK_CONNECT(hook, child_write) != -1) close (HOOK_CONNECT(hook, child_write)); - free ((struct t_hook_connect *)hook->hook_data); break; case HOOK_TYPE_PRINT: if (HOOK_PRINT(hook, message)) free (HOOK_PRINT(hook, message)); - free ((struct t_hook_print *)hook->hook_data); break; case HOOK_TYPE_SIGNAL: if (HOOK_SIGNAL(hook, signal)) free (HOOK_SIGNAL(hook, signal)); - free ((struct t_hook_signal *)hook->hook_data); break; case HOOK_TYPE_CONFIG: if (HOOK_CONFIG(hook, option)) free (HOOK_CONFIG(hook, option)); - free ((struct t_hook_config *)hook->hook_data); break; case HOOK_TYPE_COMPLETION: if (HOOK_COMPLETION(hook, completion_item)) free (HOOK_COMPLETION(hook, completion_item)); - free ((struct t_hook_completion *)hook->hook_data); break; case HOOK_TYPE_MODIFIER: if (HOOK_MODIFIER(hook, modifier)) free (HOOK_MODIFIER(hook, modifier)); - free ((struct t_hook_modifier *)hook->hook_data); break; case HOOK_TYPE_INFO: if (HOOK_INFO(hook, info_name)) free (HOOK_INFO(hook, info_name)); if (HOOK_INFO(hook, description)) free (HOOK_INFO(hook, description)); - free ((struct t_hook_info *)hook->hook_data); break; case HOOK_TYPE_INFOLIST: if (HOOK_INFOLIST(hook, infolist_name)) free (HOOK_INFOLIST(hook, infolist_name)); if (HOOK_INFOLIST(hook, description)) free (HOOK_INFOLIST(hook, description)); - free ((struct t_hook_infolist *)hook->hook_data); break; case HOOK_NUM_TYPES: /* this constant is used to count types only, it is never used as type */ break; } + free (hook->hook_data); hook->hook_data = NULL; } @@ -1957,6 +2262,33 @@ hook_add_to_infolist_type (struct t_infolist *infolist, return 0; } break; + case HOOK_TYPE_PROCESS: + if (!ptr_hook->deleted) + { + if (!infolist_new_var_pointer (ptr_item, "callback", HOOK_PROCESS(ptr_hook, callback))) + return 0; + if (!infolist_new_var_string (ptr_item, "command", HOOK_PROCESS(ptr_hook, command))) + return 0; + if (!infolist_new_var_integer (ptr_item, "timeout", HOOK_PROCESS(ptr_hook, timeout))) + return 0; + if (!infolist_new_var_integer (ptr_item, "child_stdout_read", HOOK_PROCESS(ptr_hook, child_stdout_read))) + return 0; + if (!infolist_new_var_integer (ptr_item, "child_stdout_write", HOOK_PROCESS(ptr_hook, child_stdout_write))) + return 0; + if (!infolist_new_var_integer (ptr_item, "child_stderr_read", HOOK_PROCESS(ptr_hook, child_stderr_read))) + return 0; + if (!infolist_new_var_integer (ptr_item, "child_stderr_write", HOOK_PROCESS(ptr_hook, child_stderr_write))) + return 0; + if (!infolist_new_var_integer (ptr_item, "child_pid", HOOK_PROCESS(ptr_hook, child_pid))) + return 0; + if (!infolist_new_var_pointer (ptr_item, "hook_fd_stdout", HOOK_PROCESS(ptr_hook, hook_fd_stdout))) + return 0; + if (!infolist_new_var_pointer (ptr_item, "hook_fd_stderr", HOOK_PROCESS(ptr_hook, hook_fd_stderr))) + return 0; + if (!infolist_new_var_pointer (ptr_item, "hook_timer", HOOK_PROCESS(ptr_hook, hook_timer))) + return 0; + } + break; case HOOK_TYPE_CONNECT: if (!ptr_hook->deleted) { @@ -2189,6 +2521,23 @@ hook_print_log () log_printf (" flags. . . . . . . . : %d", HOOK_FD(ptr_hook, flags)); } break; + case HOOK_TYPE_PROCESS: + if (!ptr_hook->deleted) + { + log_printf (" process data:"); + log_printf (" callback . . . . . . : 0x%lx", HOOK_PROCESS(ptr_hook, callback)); + log_printf (" command. . . . . . . : '%s'", HOOK_PROCESS(ptr_hook, command)); + log_printf (" timeout. . . . . . . : %d", HOOK_PROCESS(ptr_hook, timeout)); + log_printf (" child_stdout_read. . : %d", HOOK_PROCESS(ptr_hook, child_stdout_read)); + log_printf (" child_stdout_write . : %d", HOOK_PROCESS(ptr_hook, child_stdout_write)); + log_printf (" child_stderr_read. . : %d", HOOK_PROCESS(ptr_hook, child_stderr_read)); + log_printf (" child_stderr_write . : %d", HOOK_PROCESS(ptr_hook, child_stderr_write)); + log_printf (" child_pid. . . . . . : %d", HOOK_PROCESS(ptr_hook, child_pid)); + log_printf (" hook_fd_stdout . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_fd_stdout)); + log_printf (" hook_fd_stderr . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_fd_stderr)); + log_printf (" hook_timer . . . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_timer)); + } + break; case HOOK_TYPE_CONNECT: if (!ptr_hook->deleted) { @@ -2204,6 +2553,7 @@ hook_print_log () log_printf (" local_hostname . . . : '%s'", HOOK_CONNECT(ptr_hook, local_hostname)); log_printf (" child_read . . . . . : %d", HOOK_CONNECT(ptr_hook, child_read)); log_printf (" child_write. . . . . : %d", HOOK_CONNECT(ptr_hook, child_write)); + log_printf (" child_pid. . . . . . : %d", HOOK_CONNECT(ptr_hook, child_pid)); log_printf (" hook_fd. . . . . . . : 0x%lx", HOOK_CONNECT(ptr_hook, hook_fd)); } break; diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h index 397156abf..833473684 100644 --- a/src/core/wee-hook.h +++ b/src/core/wee-hook.h @@ -38,6 +38,7 @@ enum t_hook_type HOOK_TYPE_COMMAND_RUN, /* when a command is executed */ HOOK_TYPE_TIMER, /* timer */ HOOK_TYPE_FD, /* socket of file descriptor */ + HOOK_TYPE_PROCESS, /* sub-process (fork) */ HOOK_TYPE_CONNECT, /* connect to peer with fork */ HOOK_TYPE_PRINT, /* printed message */ HOOK_TYPE_SIGNAL, /* signal */ @@ -63,6 +64,7 @@ enum t_hook_type #define HOOK_COMMAND_RUN(hook, var) (((struct t_hook_command_run *)hook->hook_data)->var) #define HOOK_TIMER(hook, var) (((struct t_hook_timer *)hook->hook_data)->var) #define HOOK_FD(hook, var) (((struct t_hook_fd *)hook->hook_data)->var) +#define HOOK_PROCESS(hook, var) (((struct t_hook_process *)hook->hook_data)->var) #define HOOK_CONNECT(hook, var) (((struct t_hook_connect *)hook->hook_data)->var) #define HOOK_PRINT(hook, var) (((struct t_hook_print *)hook->hook_data)->var) #define HOOK_SIGNAL(hook, var) (((struct t_hook_signal *)hook->hook_data)->var) @@ -88,6 +90,8 @@ struct t_hook struct t_hook *next_hook; /* link to next hook */ }; +/* hook command */ + typedef int (t_hook_callback_command)(void *data, struct t_gui_buffer *buffer, int argc, char **argv, char **argv_eol); @@ -103,6 +107,8 @@ struct t_hook_command char *completion; /* template for completion */ }; +/* hook command run */ + typedef int (t_hook_callback_command_run)(void *data, struct t_gui_buffer *buffer, const char *command); @@ -113,7 +119,9 @@ struct t_hook_command_run char *command; /* name of command (without '/') */ }; -typedef int (t_hook_callback_timer)(void *data); +/* hook timer */ + +typedef int (t_hook_callback_timer)(void *data, int remaining_calls); struct t_hook_timer { @@ -126,6 +134,8 @@ struct t_hook_timer struct timeval next_exec; /* next scheduled execution */ }; +/* hook fd */ + typedef int (t_hook_callback_fd)(void *data, int fd); struct t_hook_fd @@ -135,6 +145,29 @@ struct t_hook_fd int flags; /* fd flags (read,write,..) */ }; +/* hook process */ + +typedef int (t_hook_callback_process)(void *data, const char *command, + int return_code, const char *stdout, + const char *stderr); + +struct t_hook_process +{ + t_hook_callback_process *callback; /* process callback (after child end)*/ + char *command; /* command executed by child */ + long timeout; /* timeout (ms) (0 = no timeout) */ + int child_stdout_read; /* to read data in pipe from child */ + int child_stdout_write; /* to write data in pipe for child */ + int child_stderr_read; /* to read data in pipe from child */ + int child_stderr_write; /* to write data in pipe for child */ + pid_t child_pid; /* pid of child process */ + struct t_hook *hook_fd_stdout; /* hook fd for stdout */ + struct t_hook *hook_fd_stderr; /* hook fd for stderr */ + struct t_hook *hook_timer; /* timer to check if child has died */ +}; + +/* hook connect */ + typedef int (t_hook_callback_connect)(void *data, int status, const char *ip_address); @@ -150,12 +183,14 @@ struct t_hook_connect gnutls_session_t *gnutls_sess; /* GnuTLS session (SSL connection) */ #endif char *local_hostname; /* force local hostname (optional) */ - int child_read; /* to read into child pipe */ - int child_write; /* to write into child pipe */ + int child_read; /* to read data in pipe from child */ + int child_write; /* to write data in pipe for child */ pid_t child_pid; /* pid of child process (connecting) */ struct t_hook *hook_fd; /* pointer to fd hook */ }; +/* hook print */ + typedef int (t_hook_callback_print)(void *data, struct t_gui_buffer *buffer, time_t date, int tags_count, const char **tags, int displayed, @@ -172,6 +207,8 @@ struct t_hook_print int strip_colors; /* strip colors in msg for callback? */ }; +/* hook signal */ + typedef int (t_hook_callback_signal)(void *data, const char *signal, const char *type_data, void *signal_data); @@ -182,6 +219,8 @@ struct t_hook_signal /* with "*", "*" == any signal) */ }; +/* hook config */ + typedef int (t_hook_callback_config)(void *data, const char *option, const char *value); @@ -192,6 +231,8 @@ struct t_hook_config /* (NULL = hook for all options) */ }; +/* hook completion */ + typedef int (t_hook_callback_completion)(void *data, const char *completion_item, struct t_gui_buffer *buffer, @@ -203,6 +244,8 @@ struct t_hook_completion char *completion_item; /* name of completion */ }; +/* hook modifier */ + typedef char *(t_hook_callback_modifier)(void *data, const char *modifier, const char *modifier_data, const char *string); @@ -213,6 +256,8 @@ struct t_hook_modifier char *modifier; /* name of modifier */ }; +/* hook info */ + typedef const char *(t_hook_callback_info)(void *data, const char *info_name, const char *arguments); @@ -223,6 +268,8 @@ struct t_hook_info char *description; /* description */ }; +/* hook infolist */ + typedef struct t_infolist *(t_hook_callback_infolist)(void *data, const char *infolist_name, void *pointer, @@ -276,6 +323,11 @@ extern int hook_fd_set (fd_set *read_fds, fd_set *write_fds, fd_set *exception_fds); extern void hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *exception_fds); +extern struct t_hook *hook_process (struct t_weechat_plugin *plugin, + const char *command, + int timeout, + t_hook_callback_process *callback, + void *callback_data); extern struct t_hook *hook_connect (struct t_weechat_plugin *plugin, const char *proxy, const char *address, int port, int sock, int ipv6, diff --git a/src/core/wee-network.c b/src/core/wee-network.c index 10c8f12eb..d3468ab49 100644 --- a/src/core/wee-network.c +++ b/src/core/wee-network.c @@ -909,12 +909,15 @@ network_connect_with_fork (struct t_hook *hook_connect) /* child process */ case 0: setuid (getuid ()); + close (HOOK_CONNECT(hook_connect, child_read)); network_connect_child (hook_connect); _exit (EXIT_SUCCESS); } /* parent process */ HOOK_CONNECT(hook_connect, child_pid) = pid; - HOOK_CONNECT(hook_connect, hook_fd) = hook_fd (NULL, + close (HOOK_CONNECT(hook_connect, child_write)); + HOOK_CONNECT(hook_connect, child_write) = -1; + HOOK_CONNECT(hook_connect, hook_fd) = hook_fd (hook_connect->plugin, HOOK_CONNECT(hook_connect, child_read), 1, 0, 0, &network_connect_child_read_cb, diff --git a/src/gui/gui-bar-item.c b/src/gui/gui-bar-item.c index 4892a2027..150c7af43 100644 --- a/src/gui/gui-bar-item.c +++ b/src/gui/gui-bar-item.c @@ -1225,13 +1225,16 @@ gui_bar_item_default_buffer_nicklist (void *data, struct t_gui_bar_item *item, */ int -gui_bar_item_timer_cb (void *data) +gui_bar_item_timer_cb (void *data, int remaining_calls) { time_t date; struct tm *local_time; static char item_time_text[128] = { '\0' }; char new_item_time_text[128]; + /* make C compiler happy */ + (void) remaining_calls; + date = time (NULL); local_time = localtime (&date); if (strftime (new_item_time_text, sizeof (new_item_time_text), diff --git a/src/gui/gui-chat.c b/src/gui/gui-chat.c index 9b8854df7..7831b1147 100644 --- a/src/gui/gui-chat.c +++ b/src/gui/gui-chat.c @@ -1123,21 +1123,29 @@ gui_chat_printf_date_tags (struct t_gui_buffer *buffer, time_t date, display_time = 1; ptr_msg = (new_msg) ? new_msg : pos; - /* if two first chars are tab, then do not display time */ - if ((ptr_msg[0] == '\t') && (ptr_msg[1] == '\t')) + /* space followed by tab => prefix ignored */ + if ((ptr_msg[0] == ' ') && (ptr_msg[1] == '\t')) { - display_time = 0; ptr_msg += 2; } else { - /* if tab found, use prefix (before tab) */ - pos_tab = strchr (ptr_msg, '\t'); - if (pos_tab) + /* if two first chars are tab, then do not display time */ + if ((ptr_msg[0] == '\t') && (ptr_msg[1] == '\t')) { - pos_tab[0] = '\0'; - pos_prefix = ptr_msg; - ptr_msg = pos_tab + 1; + display_time = 0; + ptr_msg += 2; + } + else + { + /* if tab found, use prefix (before tab) */ + pos_tab = strchr (ptr_msg, '\t'); + if (pos_tab) + { + pos_tab[0] = '\0'; + pos_prefix = ptr_msg; + ptr_msg = pos_tab + 1; + } } } diff --git a/src/plugins/irc/irc-server.c b/src/plugins/irc/irc-server.c index 112d9608a..429f048f2 100644 --- a/src/plugins/irc/irc-server.c +++ b/src/plugins/irc/irc-server.c @@ -1599,7 +1599,7 @@ irc_server_recv_cb (void *arg_server, int fd) */ int -irc_server_timer_cb (void *data) +irc_server_timer_cb (void *data, int remaining_calls) { struct t_irc_server *ptr_server; time_t new_time; @@ -1608,6 +1608,7 @@ irc_server_timer_cb (void *data) /* make C compiler happy */ (void) data; + (void) remaining_calls; new_time = time (NULL); @@ -1677,10 +1678,11 @@ irc_server_timer_cb (void *data) */ int -irc_server_timer_check_away_cb (void *data) +irc_server_timer_check_away_cb (void *data, int remaining_calls) { /* make C compiler happy */ (void) data; + (void) remaining_calls; if (weechat_config_integer (irc_config_network_away_check) > 0) irc_server_check_away (); diff --git a/src/plugins/irc/irc-server.h b/src/plugins/irc/irc-server.h index bddbc71d2..92c286402 100644 --- a/src/plugins/irc/irc-server.h +++ b/src/plugins/irc/irc-server.h @@ -198,8 +198,8 @@ extern int irc_server_connect (struct t_irc_server *server); extern void irc_server_auto_connect (); extern void irc_server_autojoin_channels (); extern int irc_server_recv_cb (void *arg_server, int fd); -extern int irc_server_timer_cb (void *data); -extern int irc_server_timer_check_away_cb (void *data); +extern int irc_server_timer_cb (void *data, int remaining_calls); +extern int irc_server_timer_check_away_cb (void *data, int remaining_calls); extern void irc_server_outqueue_free_all (struct t_irc_server *server); extern int irc_server_get_channel_count (struct t_irc_server *server); extern int irc_server_get_pv_count (struct t_irc_server *server); diff --git a/src/plugins/jabber/jabber-server.c b/src/plugins/jabber/jabber-server.c index 86c1401ae..7c09f2500 100644 --- a/src/plugins/jabber/jabber-server.c +++ b/src/plugins/jabber/jabber-server.c @@ -1630,7 +1630,7 @@ jabber_server_recv_cb (void *arg_server, int fd) */ int -jabber_server_timer_cb (void *data) +jabber_server_timer_cb (void *data, int remaining_calls) { struct t_jabber_server *ptr_server; time_t new_time; @@ -1639,6 +1639,7 @@ jabber_server_timer_cb (void *data) /* make C compiler happy */ (void) data; + (void) remaining_calls; new_time = time (NULL); diff --git a/src/plugins/jabber/jabber-server.h b/src/plugins/jabber/jabber-server.h index e77b14a15..fb7841636 100644 --- a/src/plugins/jabber/jabber-server.h +++ b/src/plugins/jabber/jabber-server.h @@ -197,7 +197,7 @@ extern struct t_jabber_server *jabber_server_copy (struct t_jabber_server *serve extern int jabber_server_rename (struct t_jabber_server *server, const char *new_server_name); extern int jabber_server_recv_cb (void *arg_server, int fd); -extern int jabber_server_timer_cb (void *data); +extern int jabber_server_timer_cb (void *data, int remaining_calls); extern int jabber_server_add_to_infolist (struct t_infolist *infolist, struct t_jabber_server *server); extern void jabber_server_print_log (); diff --git a/src/plugins/plugin.c b/src/plugins/plugin.c index 26588ff5b..ed6b0e860 100644 --- a/src/plugins/plugin.c +++ b/src/plugins/plugin.c @@ -439,6 +439,7 @@ plugin_load (const char *filename) new_plugin->hook_command_run = &hook_command_run; new_plugin->hook_timer = &hook_timer; new_plugin->hook_fd = &hook_fd; + new_plugin->hook_process = &hook_process; new_plugin->hook_connect = &hook_connect; new_plugin->hook_print = &hook_print; new_plugin->hook_signal = &hook_signal; diff --git a/src/plugins/scripts/lua/weechat-lua-api.c b/src/plugins/scripts/lua/weechat-lua-api.c index 9393dd0a4..21348194f 100644 --- a/src/plugins/scripts/lua/weechat-lua-api.c +++ b/src/plugins/scripts/lua/weechat-lua-api.c @@ -3150,17 +3150,21 @@ weechat_lua_api_hook_command_run (lua_State *L) */ int -weechat_lua_api_hook_timer_cb (void *data) +weechat_lua_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *lua_argv[1]; + char *lua_argv[2], str_remaining_calls[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; - + if (script_callback && script_callback->function && script_callback->function[0]) { + snprintf (str_remaining_calls, sizeof (str_remaining_calls), + "%d", remaining_calls); + lua_argv[0] = NULL; + lua_argv[1] = NULL; rc = (int *) weechat_lua_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, @@ -3321,6 +3325,96 @@ weechat_lua_api_hook_fd (lua_State *L) LUA_RETURN_STRING_FREE(result); } +/* + * weechat_lua_api_hook_process_cb: callback for process hooked + */ + +int +weechat_lua_api_hook_process_cb (void *data, + const char *command, int return_code, + const char *stdout, const char *stderr) +{ + struct t_script_callback *script_callback; + char *lua_argv[5], str_rc[32], empty_arg[1] = { '\0' }; + int *rc, ret; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + snprintf (str_rc, sizeof (str_rc), "%d", return_code); + + lua_argv[0] = (char *)command; + lua_argv[1] = str_rc; + lua_argv[2] = (stdout) ? (char *)stdout : empty_arg; + lua_argv[3] = (stderr) ? (char *)stderr : empty_arg; + lua_argv[4] = NULL; + + rc = (int *) weechat_lua_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_INT, + script_callback->function, + lua_argv); + + if (!rc) + ret = WEECHAT_RC_ERROR; + else + { + ret = *rc; + free (rc); + } + + return ret; + } + + return WEECHAT_RC_ERROR; +} + +/* + * weechat_lua_api_hook_process: hook a process + */ + +static int +weechat_lua_api_hook_process (lua_State *L) +{ + const char *command, *function; + int n, timeout; + char *result; + + /* make C compiler happy */ + (void) L; + + if (!lua_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("hook_process"); + LUA_RETURN_EMPTY; + } + + command = NULL; + timeout = 0; + function = NULL; + + n = lua_gettop (lua_current_interpreter); + + if (n < 3) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_process"); + LUA_RETURN_EMPTY; + } + + command = lua_tostring (lua_current_interpreter, -3); + timeout = lua_tonumber (lua_current_interpreter, -2); + function = lua_tostring (lua_current_interpreter, -1); + + result = script_ptr2str (script_api_hook_process (weechat_lua_plugin, + lua_current_script, + command, + timeout, + &weechat_lua_api_hook_process_cb, + function)); + + LUA_RETURN_STRING_FREE(result); +} + /* * weechat_lua_api_hook_connect_cb: callback for connect hooked */ @@ -6595,6 +6689,26 @@ weechat_lua_api_constant_weechat_hotlist_highlight (lua_State *L) return 1; } +static int +weechat_lua_api_constant_weechat_hook_process_running (lua_State *L) +{ + /* make C compiler happy */ + (void) L; + + lua_pushnumber (lua_current_interpreter, WEECHAT_HOOK_PROCESS_RUNNING); + return 1; +} + +static int +weechat_lua_api_constant_weechat_hook_process_error (lua_State *L) +{ + /* make C compiler happy */ + (void) L; + + lua_pushnumber (lua_current_interpreter, WEECHAT_HOOK_PROCESS_ERROR); + return 1; +} + static int weechat_lua_api_constant_weechat_hook_connect_ok (lua_State *L) { @@ -6788,6 +6902,7 @@ const struct luaL_reg weechat_lua_api_funcs[] = { { "hook_command_run", &weechat_lua_api_hook_command_run }, { "hook_timer", &weechat_lua_api_hook_timer }, { "hook_fd", &weechat_lua_api_hook_fd }, + { "hook_process", &weechat_lua_api_hook_process }, { "hook_connect", &weechat_lua_api_hook_connect }, { "hook_print", &weechat_lua_api_hook_print }, { "hook_signal", &weechat_lua_api_hook_signal }, @@ -6881,6 +6996,9 @@ const struct luaL_reg weechat_lua_api_funcs[] = { { "WEECHAT_HOTLIST_PRIVATE", &weechat_lua_api_constant_weechat_hotlist_private }, { "WEECHAT_HOTLIST_HIGHLIGHT", &weechat_lua_api_constant_weechat_hotlist_highlight }, + { "WEECHAT_HOOK_PROCESS_RUNNING", &weechat_lua_api_constant_weechat_hook_process_running }, + { "WEECHAT_HOOK_PROCESS_ERROR", &weechat_lua_api_constant_weechat_hook_process_error }, + { "WEECHAT_HOOK_CONNECT_OK", &weechat_lua_api_constant_weechat_hook_connect_ok }, { "WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", &weechat_lua_api_constant_weechat_hook_connect_address_not_found }, { "WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", &weechat_lua_api_constant_weechat_hook_connect_ip_address_not_found }, diff --git a/src/plugins/scripts/perl/weechat-perl-api.c b/src/plugins/scripts/perl/weechat-perl-api.c index 1c4f08e90..43e53a4ff 100644 --- a/src/plugins/scripts/perl/weechat-perl-api.c +++ b/src/plugins/scripts/perl/weechat-perl-api.c @@ -2626,17 +2626,21 @@ static XS (XS_weechat_api_hook_command_run) */ int -weechat_perl_api_hook_timer_cb (void *data) +weechat_perl_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *perl_argv[1]; + char *perl_argv[2], str_remaining_calls[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; if (script_callback && script_callback->function && script_callback->function[0]) { - perl_argv[0] = NULL; + snprintf (str_remaining_calls, sizeof (str_remaining_calls), + "%d", remaining_calls); + + perl_argv[0] = str_remaining_calls; + perl_argv[1] = NULL; rc = (int *) weechat_perl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, @@ -2767,6 +2771,87 @@ static XS (XS_weechat_api_hook_fd) PERL_RETURN_STRING_FREE(result); } +/* + * weechat_perl_api_hook_process_cb: callback for process hooked + */ + +int +weechat_perl_api_hook_process_cb (void *data, + const char *command, int return_code, + const char *stdout, const char *stderr) +{ + struct t_script_callback *script_callback; + char *perl_argv[5], str_rc[32], empty_arg[1] = { '\0' }; + int *rc, ret; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + snprintf (str_rc, sizeof (str_rc), "%d", return_code); + + perl_argv[0] = (char *)command; + perl_argv[1] = str_rc; + perl_argv[2] = (stdout) ? (char *)stdout : empty_arg; + perl_argv[3] = (stderr) ? (char *)stderr : empty_arg; + perl_argv[4] = NULL; + + rc = (int *) weechat_perl_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_INT, + script_callback->function, + perl_argv); + + if (!rc) + ret = WEECHAT_RC_ERROR; + else + { + ret = *rc; + free (rc); + } + + return ret; + } + + return WEECHAT_RC_ERROR; +} + +/* + * weechat::hook_process: hook a process + */ + +static XS (XS_weechat_api_hook_process) +{ + char *command, *function, *result; + dXSARGS; + + /* make C compiler happy */ + (void) cv; + + if (!perl_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("hook_process"); + PERL_RETURN_EMPTY; + } + + if (items < 3) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_process"); + PERL_RETURN_EMPTY; + } + + command = SvPV (ST (0), PL_na); + function = SvPV (ST (2), PL_na); + + result = script_ptr2str (script_api_hook_process (weechat_perl_plugin, + perl_current_script, + command, + SvIV (ST (1)), /* timeout */ + &weechat_perl_api_hook_process_cb, + function)); + + PERL_RETURN_STRING_FREE(result); +} + /* * weechat_perl_api_hook_connect_cb: callback for connect hooked */ @@ -3315,7 +3400,7 @@ weechat_perl_api_hook_modifier_cb (void *data, const char *modifier, script_callback->function, perl_argv); } - + return NULL; } @@ -5393,6 +5478,7 @@ weechat_perl_api_init (pTHX) newXS ("weechat::hook_command_run", XS_weechat_api_hook_command_run, "weechat"); newXS ("weechat::hook_timer", XS_weechat_api_hook_timer, "weechat"); newXS ("weechat::hook_fd", XS_weechat_api_hook_fd, "weechat"); + newXS ("weechat::hook_process", XS_weechat_api_hook_process, "weechat"); newXS ("weechat::hook_connect", XS_weechat_api_hook_connect, "weechat"); newXS ("weechat::hook_print", XS_weechat_api_hook_print, "weechat"); newXS ("weechat::hook_signal", XS_weechat_api_hook_signal, "weechat"); @@ -5485,7 +5571,10 @@ weechat_perl_api_init (pTHX) newCONSTSUB (stash, "weechat::WEECHAT_HOTLIST_MESSAGE", newSVpv (WEECHAT_HOTLIST_MESSAGE, PL_na)); newCONSTSUB (stash, "weechat::WEECHAT_HOTLIST_PRIVATE", newSVpv (WEECHAT_HOTLIST_PRIVATE, PL_na)); newCONSTSUB (stash, "weechat::WEECHAT_HOTLIST_HIGHLIGHT", newSVpv (WEECHAT_HOTLIST_HIGHLIGHT, PL_na)); - + + newCONSTSUB (stash, "weechat::WEECHAT_HOOK_PROCESS_RUNNING", newSViv (WEECHAT_HOOK_PROCESS_RUNNING)); + newCONSTSUB (stash, "weechat::WEECHAT_HOOK_PROCESS_ERROR", newSViv (WEECHAT_HOOK_PROCESS_ERROR)); + newCONSTSUB (stash, "weechat::WEECHAT_HOOK_CONNECT_OK", newSViv (WEECHAT_HOOK_CONNECT_OK)); newCONSTSUB (stash, "weechat::WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", newSViv (WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND)); newCONSTSUB (stash, "weechat::WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", newSViv (WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND)); diff --git a/src/plugins/scripts/python/weechat-python-api.c b/src/plugins/scripts/python/weechat-python-api.c index 265304ef5..df416e0e5 100644 --- a/src/plugins/scripts/python/weechat-python-api.c +++ b/src/plugins/scripts/python/weechat-python-api.c @@ -2798,17 +2798,21 @@ weechat_python_api_hook_command_run (PyObject *self, PyObject *args) */ int -weechat_python_api_hook_timer_cb (void *data) +weechat_python_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *python_argv[1]; + char *python_argv[2], str_remaining_calls[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; if (script_callback && script_callback->function && script_callback->function[0]) { - python_argv[0] = NULL; + snprintf (str_remaining_calls, sizeof (str_remaining_calls), + "%d", remaining_calls); + + python_argv[0] = str_remaining_calls; + python_argv[1] = NULL; rc = (int *) weechat_python_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, @@ -2956,6 +2960,90 @@ weechat_python_api_hook_fd (PyObject *self, PyObject *args) PYTHON_RETURN_STRING_FREE(result); } +/* + * weechat_python_api_hook_process_cb: callback for process hooked + */ + +int +weechat_python_api_hook_process_cb (void *data, + const char *command, int return_code, + const char *stdout, const char *stderr) +{ + struct t_script_callback *script_callback; + char *python_argv[5], str_rc[32], empty_arg[1] = { '\0' }; + int *rc, ret; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + snprintf (str_rc, sizeof (str_rc), "%d", return_code); + + python_argv[0] = (char *)command; + python_argv[1] = str_rc; + python_argv[2] = (stdout) ? (char *)stdout : empty_arg; + python_argv[3] = (stderr) ? (char *)stderr : empty_arg; + python_argv[4] = NULL; + + rc = (int *) weechat_python_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_INT, + script_callback->function, + python_argv); + + if (!rc) + ret = WEECHAT_RC_ERROR; + else + { + ret = *rc; + free (rc); + } + + return ret; + } + + return WEECHAT_RC_ERROR; +} + +/* + * weechat_python_api_hook_process: hook a process + */ + +static PyObject * +weechat_python_api_hook_process (PyObject *self, PyObject *args) +{ + char *command, *function, *result; + int timeout; + PyObject *object; + + /* make C compiler happy */ + (void) self; + + if (!python_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("hook_process"); + PYTHON_RETURN_EMPTY; + } + + command = NULL; + timeout = 0; + function = NULL; + + if (!PyArg_ParseTuple (args, "sis", &command, &timeout, &function)) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_process"); + PYTHON_RETURN_EMPTY; + } + + result = script_ptr2str (script_api_hook_process (weechat_python_plugin, + python_current_script, + command, + timeout, + &weechat_python_api_hook_process_cb, + function)); + + PYTHON_RETURN_STRING_FREE(result); +} + /* * weechat_python_api_hook_connect_cb: callback for connect hooked */ @@ -5722,6 +5810,7 @@ PyMethodDef weechat_python_funcs[] = { "hook_command_run", &weechat_python_api_hook_command_run, METH_VARARGS, "" }, { "hook_timer", &weechat_python_api_hook_timer, METH_VARARGS, "" }, { "hook_fd", &weechat_python_api_hook_fd, METH_VARARGS, "" }, + { "hook_process", &weechat_python_api_hook_process, METH_VARARGS, "" }, { "hook_connect", &weechat_python_api_hook_connect, METH_VARARGS, "" }, { "hook_print", &weechat_python_api_hook_print, METH_VARARGS, "" }, { "hook_signal", &weechat_python_api_hook_signal, METH_VARARGS, "" }, diff --git a/src/plugins/scripts/python/weechat-python.c b/src/plugins/scripts/python/weechat-python.c index fd4c68ffa..8cc68459b 100644 --- a/src/plugins/scripts/python/weechat-python.c +++ b/src/plugins/scripts/python/weechat-python.c @@ -371,7 +371,10 @@ weechat_python_load (const char *filename) PyDict_SetItemString(weechat_dict, "WEECHAT_HOTLIST_MESSAGE", PyString_FromString(WEECHAT_HOTLIST_MESSAGE)); PyDict_SetItemString(weechat_dict, "WEECHAT_HOTLIST_PRIVATE", PyString_FromString(WEECHAT_HOTLIST_PRIVATE)); PyDict_SetItemString(weechat_dict, "WEECHAT_HOTLIST_HIGHLIGHT", PyString_FromString(WEECHAT_HOTLIST_HIGHLIGHT)); - + + PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_PROCESS_RUNNING", PyInt_FromLong((long) WEECHAT_HOOK_PROCESS_RUNNING)); + PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_PROCESS_ERROR", PyInt_FromLong((long) WEECHAT_HOOK_PROCESS_ERROR)); + PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_OK", PyInt_FromLong((long) WEECHAT_HOOK_CONNECT_OK)); PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", PyInt_FromLong((long) WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND)); PyDict_SetItemString(weechat_dict, "WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", PyInt_FromLong((long) WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND)); diff --git a/src/plugins/scripts/ruby/weechat-ruby-api.c b/src/plugins/scripts/ruby/weechat-ruby-api.c index 8c795e3cb..9f4284d31 100644 --- a/src/plugins/scripts/ruby/weechat-ruby-api.c +++ b/src/plugins/scripts/ruby/weechat-ruby-api.c @@ -3202,17 +3202,21 @@ weechat_ruby_api_hook_command_run (VALUE class, VALUE command, VALUE function) */ int -weechat_ruby_api_hook_timer_cb (void *data) +weechat_ruby_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *ruby_argv[1]; + char *ruby_argv[2], str_remaining_calls[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; - + if (script_callback && script_callback->function && script_callback->function[0]) { - ruby_argv[0] = NULL; + snprintf (str_remaining_calls, sizeof (str_remaining_calls), + "%d", remaining_calls); + + ruby_argv[0] = str_remaining_calls; + ruby_argv[1] = NULL; rc = (int *) weechat_ruby_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, @@ -3384,6 +3388,99 @@ weechat_ruby_api_hook_fd (VALUE class, VALUE fd, VALUE read, VALUE write, RUBY_RETURN_STRING_FREE(result); } +/* + * weechat_ruby_api_hook_process_cb: callback for process hooked + */ + +int +weechat_ruby_api_hook_process_cb (void *data, + const char *command, int return_code, + const char *stdout, const char *stderr) +{ + struct t_script_callback *script_callback; + char *ruby_argv[5], str_rc[32], empty_arg[1] = { '\0' }; + int *rc, ret; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + snprintf (str_rc, sizeof (str_rc), "%d", return_code); + + ruby_argv[0] = (char *)command; + ruby_argv[1] = str_rc; + ruby_argv[2] = (stdout) ? (char *)stdout : empty_arg; + ruby_argv[3] = (stderr) ? (char *)stderr : empty_arg; + ruby_argv[4] = NULL; + + rc = (int *) weechat_ruby_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_INT, + script_callback->function, + ruby_argv); + + if (!rc) + ret = WEECHAT_RC_ERROR; + else + { + ret = *rc; + free (rc); + } + + return ret; + } + + return WEECHAT_RC_ERROR; +} + +/* + * weechat_ruby_api_hook_process: hook a process + */ + +static VALUE +weechat_ruby_api_hook_process (VALUE class, VALUE command, VALUE timeout, + VALUE function) +{ + char *c_command, *c_function, *result; + int c_timeout; + VALUE return_value; + + /* make C compiler happy */ + (void) class; + + if (!ruby_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("hook_process"); + RUBY_RETURN_EMPTY; + } + + c_command = NULL; + c_timeout = 0; + c_function = NULL; + + if (NIL_P (command) || NIL_P (timeout) || NIL_P (function)) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_process"); + RUBY_RETURN_EMPTY; + } + + Check_Type (command, T_STRING); + Check_Type (timeout, T_FIXNUM); + Check_Type (function, T_STRING); + + c_command = STR2CSTR (command); + c_timeout = FIX2INT (timeout); + c_function = STR2CSTR (function); + + result = script_ptr2str (script_api_hook_process (weechat_ruby_plugin, + ruby_current_script, + c_command, + c_timeout, + &weechat_ruby_api_hook_process_cb, + c_function)); + + RUBY_RETURN_STRING_FREE(result); +} + /* * weechat_ruby_api_hook_connect_cb: callback for connect hooked */ @@ -6456,6 +6553,9 @@ weechat_ruby_api_init (VALUE ruby_mWeechat) rb_define_const(ruby_mWeechat, "WEECHAT_HOTLIST_PRIVATE", rb_str_new2(WEECHAT_HOTLIST_PRIVATE)); rb_define_const(ruby_mWeechat, "WEECHAT_HOTLIST_HIGHLIGHT", rb_str_new2(WEECHAT_HOTLIST_HIGHLIGHT)); + rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_PROCESS_RUNNING", INT2NUM(WEECHAT_HOOK_PROCESS_RUNNING)); + rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_PROCESS_ERROR", INT2NUM(WEECHAT_HOOK_PROCESS_ERROR)); + rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_OK", INT2NUM(WEECHAT_HOOK_CONNECT_OK)); rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", INT2NUM(WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND)); rb_define_const(ruby_mWeechat, "WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", INT2NUM(WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND)); @@ -6538,6 +6638,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat) rb_define_module_function (ruby_mWeechat, "hook_command_run", &weechat_ruby_api_hook_command_run, 2); rb_define_module_function (ruby_mWeechat, "hook_timer", &weechat_ruby_api_hook_timer, 4); rb_define_module_function (ruby_mWeechat, "hook_fd", &weechat_ruby_api_hook_fd, 5); + rb_define_module_function (ruby_mWeechat, "hook_process", &weechat_ruby_api_hook_process, 3); rb_define_module_function (ruby_mWeechat, "hook_connect", &weechat_ruby_api_hook_connect, 7); rb_define_module_function (ruby_mWeechat, "hook_print", &weechat_ruby_api_hook_print, 5); rb_define_module_function (ruby_mWeechat, "hook_signal", &weechat_ruby_api_hook_signal, 2); diff --git a/src/plugins/scripts/script-api.c b/src/plugins/scripts/script-api.c index e43cc50f0..8784fba3e 100644 --- a/src/plugins/scripts/script-api.c +++ b/src/plugins/scripts/script-api.c @@ -798,7 +798,7 @@ struct t_hook * script_api_hook_timer (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *script, int interval, int align_second, int max_calls, - int (*callback)(void *data), + int (*callback)(void *data, int remaining_calls), const char *function) { struct t_script_callback *new_script_callback; @@ -864,6 +864,48 @@ script_api_hook_fd (struct t_weechat_plugin *weechat_plugin, return new_hook; } +/* + * script_api_hook_connect: hook a connection + * return new hook, NULL if error + */ + +struct t_hook * +script_api_hook_process (struct t_weechat_plugin *weechat_plugin, + struct t_plugin_script *script, + const char *command, + int timeout, + int (*callback)(void *data, + const char *command, + int return_code, + const char *stdout, + const char *stderr), + const char *function) +{ + struct t_script_callback *new_script_callback; + struct t_hook *new_hook; + + new_script_callback = script_callback_alloc (); + if (!new_script_callback) + return NULL; + + new_script_callback->script = script; + new_script_callback->function = strdup (function); + script_callback_add (script, new_script_callback); + + new_hook = weechat_hook_process (command, timeout, callback, + new_script_callback); + + if (!new_hook) + { + script_callback_remove (script, new_script_callback); + return NULL; + } + + new_script_callback->hook = new_hook; + + return new_hook; +} + /* * script_api_hook_connect: hook a connection * return new hook, NULL if error diff --git a/src/plugins/scripts/script-api.h b/src/plugins/scripts/script-api.h index 37e3c6ca3..1bb20f0e5 100644 --- a/src/plugins/scripts/script-api.h +++ b/src/plugins/scripts/script-api.h @@ -129,7 +129,8 @@ extern struct t_hook *script_api_hook_timer (struct t_weechat_plugin *weechat_pl struct t_plugin_script *script, int interval, int align_second, int max_calls, - int (*callback)(void *data), + int (*callback)(void *data, + int remaining_calls), const char *function); extern struct t_hook *script_api_hook_fd (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *script, @@ -137,6 +138,16 @@ extern struct t_hook *script_api_hook_fd (struct t_weechat_plugin *weechat_plugi int flag_write, int flag_exception, int (*callback)(void *data, int fd), const char *function); +extern struct t_hook *script_api_hook_process (struct t_weechat_plugin *weechat_plugin, + struct t_plugin_script *script, + const char *command, + int timeout, + int (*callback)(void *data, + const char *command, + int return_code, + const char *stdout, + const char *stderr), + const char *function); extern struct t_hook *script_api_hook_connect (struct t_weechat_plugin *weechat_plugin, struct t_plugin_script *script, const char *proxy, diff --git a/src/plugins/scripts/tcl/weechat-tcl-api.c b/src/plugins/scripts/tcl/weechat-tcl-api.c index 56efc436a..09cd94ea0 100644 --- a/src/plugins/scripts/tcl/weechat-tcl-api.c +++ b/src/plugins/scripts/tcl/weechat-tcl-api.c @@ -39,12 +39,12 @@ { \ objp = Tcl_DuplicateObj (objp); \ Tcl_IncrRefCount (objp); \ - Tcl_SetIntObj (objp,1); \ + Tcl_SetIntObj (objp, 1); \ Tcl_SetObjResult (interp, objp); \ Tcl_DecrRefCount (objp); \ } \ else \ - Tcl_SetIntObj (objp,1); \ + Tcl_SetIntObj (objp, 1); \ return TCL_OK; \ } #define TCL_RETURN_ERROR \ @@ -54,12 +54,12 @@ { \ objp = Tcl_DuplicateObj (objp); \ Tcl_IncrRefCount (objp); \ - Tcl_SetIntObj (objp,0); \ + Tcl_SetIntObj (objp, 0); \ Tcl_SetObjResult (interp, objp); \ Tcl_DecrRefCount (objp); \ } \ else \ - Tcl_SetIntObj (objp,0); \ + Tcl_SetIntObj (objp, 0); \ return TCL_ERROR; \ } #define TCL_RETURN_EMPTY \ @@ -69,12 +69,12 @@ { \ objp = Tcl_DuplicateObj (objp); \ Tcl_IncrRefCount (objp); \ - Tcl_SetStringObj (objp,"",-1); \ + Tcl_SetStringObj (objp, "", -1); \ Tcl_SetObjResult (interp, objp); \ Tcl_DecrRefCount (objp); \ } \ else \ - Tcl_SetStringObj (objp,"",-1); \ + Tcl_SetStringObj (objp, "", -1); \ return TCL_OK; \ } #define TCL_RETURN_STRING(__string) \ @@ -86,12 +86,12 @@ Tcl_IncrRefCount (objp); \ if (__string) \ { \ - Tcl_SetStringObj (objp,__string,-1); \ + Tcl_SetStringObj (objp, __string, -1); \ Tcl_SetObjResult (interp, objp); \ Tcl_DecrRefCount (objp); \ return TCL_OK; \ } \ - Tcl_SetStringObj (objp,"",-1); \ + Tcl_SetStringObj (objp, "", -1); \ Tcl_SetObjResult (interp, objp); \ Tcl_DecrRefCount (objp); \ } \ @@ -99,10 +99,10 @@ { \ if (__string) \ { \ - Tcl_SetStringObj (objp,__string,-1); \ + Tcl_SetStringObj (objp, __string, -1); \ return TCL_OK; \ } \ - Tcl_SetStringObj (objp,"",-1); \ + Tcl_SetStringObj (objp, "", -1); \ } \ return TCL_OK; \ } @@ -115,13 +115,13 @@ Tcl_IncrRefCount (objp); \ if (__string) \ { \ - Tcl_SetStringObj (objp,__string,-1); \ + Tcl_SetStringObj (objp, __string, -1); \ Tcl_SetObjResult (interp, objp); \ Tcl_DecrRefCount (objp); \ free (__string); \ return TCL_OK; \ } \ - Tcl_SetStringObj (objp,"",-1); \ + Tcl_SetStringObj (objp, "", -1); \ Tcl_SetObjResult (interp, objp); \ Tcl_DecrRefCount (objp); \ } \ @@ -129,11 +129,11 @@ { \ if (__string) \ { \ - Tcl_SetStringObj (objp,__string,-1); \ + Tcl_SetStringObj (objp, __string, -1); \ free(__string); \ return TCL_OK; \ } \ - Tcl_SetStringObj (objp,"",-1); \ + Tcl_SetStringObj (objp, "", -1); \ } \ return TCL_OK; \ } @@ -144,12 +144,12 @@ { \ objp = Tcl_DuplicateObj (objp); \ Tcl_IncrRefCount (objp); \ - Tcl_SetIntObj (objp,__int); \ + Tcl_SetIntObj (objp, __int); \ Tcl_SetObjResult (interp, objp); \ Tcl_DecrRefCount (objp); \ } \ else \ - Tcl_SetIntObj (objp,__int); \ + Tcl_SetIntObj (objp, __int); \ return TCL_OK; \ } @@ -1318,7 +1318,7 @@ weechat_tcl_api_config_new_section (ClientData clientData, Tcl_Interp *interp, char *result, *cfg_file, *name, *function_read, *function_write; char *function_write_default, *function_create_option; char *function_delete_option; - int i,can_add,can_delete; + int i, can_add, can_delete; /* make C compiler happy */ (void) clientData; @@ -2716,7 +2716,7 @@ weechat_tcl_api_print_date_tags (ClientData clientData, Tcl_Interp *interp, { Tcl_Obj *objp; char *buffer, *tags, *message; - int i,tdate; + int i, tdate; /* make C compiler happy */ (void) clientData; @@ -2762,7 +2762,7 @@ weechat_tcl_api_print_y (ClientData clientData, Tcl_Interp *interp, { Tcl_Obj *objp; char *buffer, *message; - int i,y; + int i, y; /* make C compiler happy */ (void) clientData; @@ -3004,17 +3004,21 @@ weechat_tcl_api_hook_command_run (ClientData clientData, Tcl_Interp *interp, */ int -weechat_tcl_api_hook_timer_cb (void *data) +weechat_tcl_api_hook_timer_cb (void *data, int remaining_calls) { struct t_script_callback *script_callback; - char *tcl_argv[1]; + char *tcl_argv[2], str_remaining_calls[32]; int *rc, ret; script_callback = (struct t_script_callback *)data; - + if (script_callback && script_callback->function && script_callback->function[0]) { - tcl_argv[0] = NULL; + snprintf (str_remaining_calls, sizeof (str_remaining_calls), + "%d", remaining_calls); + + tcl_argv[0] = str_remaining_calls; + tcl_argv[1] = NULL; rc = (int *) weechat_tcl_exec (script_callback->script, WEECHAT_SCRIPT_EXEC_INT, @@ -3045,7 +3049,7 @@ weechat_tcl_api_hook_timer (ClientData clientData, Tcl_Interp *interp, { Tcl_Obj *objp; char *result; - int i,interval,align_second,max_calls; + int i, interval, align_second, max_calls; /* make C compiler happy */ @@ -3132,7 +3136,7 @@ weechat_tcl_api_hook_fd (ClientData clientData, Tcl_Interp *interp, { Tcl_Obj *objp; char *result; - int i,fd,read,write,exception; + int i, fd, read, write, exception; /* make C compiler happy */ (void) clientData; @@ -3170,6 +3174,96 @@ weechat_tcl_api_hook_fd (ClientData clientData, Tcl_Interp *interp, TCL_RETURN_STRING_FREE(result); } +/* + * weechat_tcl_api_hook_process_cb: callback for process hooked + */ + +int +weechat_tcl_api_hook_process_cb (void *data, + const char *command, int return_code, + const char *stdout, const char *stderr) +{ + struct t_script_callback *script_callback; + char *tcl_argv[5], str_rc[32], empty_arg[1] = { '\0' }; + int *rc, ret; + + script_callback = (struct t_script_callback *)data; + + if (script_callback && script_callback->function && script_callback->function[0]) + { + snprintf (str_rc, sizeof (str_rc), "%d", return_code); + + tcl_argv[0] = (char *)command; + tcl_argv[1] = str_rc; + tcl_argv[2] = (stdout) ? (char *)stdout : empty_arg; + tcl_argv[3] = (stderr) ? (char *)stderr : empty_arg; + tcl_argv[4] = NULL; + + rc = (int *) weechat_tcl_exec (script_callback->script, + WEECHAT_SCRIPT_EXEC_INT, + script_callback->function, + tcl_argv); + + if (!rc) + ret = WEECHAT_RC_ERROR; + else + { + ret = *rc; + free (rc); + } + + return ret; + } + + return WEECHAT_RC_ERROR; +} + +/* + * weechat_tcl_api_hook_process: hook a process + */ + +static int +weechat_tcl_api_hook_process (ClientData clientData, Tcl_Interp *interp, + int objc, Tcl_Obj *CONST objv[]) +{ + Tcl_Obj *objp; + char *command, *function, *result; + int i, timeout; + + /* make C compiler happy */ + (void) clientData; + + if (!tcl_current_script) + { + WEECHAT_SCRIPT_MSG_NOT_INITIALIZED("hook_process"); + TCL_RETURN_EMPTY; + } + + if (objc < 4) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_process"); + TCL_RETURN_EMPTY; + } + + if ((Tcl_GetIntFromObj (interp, objv[2], &timeout) != TCL_OK)) + { + WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_process"); + TCL_RETURN_EMPTY; + } + + command = Tcl_GetStringFromObj (objv[1], &i); + function = Tcl_GetStringFromObj (objv[3], &i); + + result = script_ptr2str (script_api_hook_process (weechat_tcl_plugin, + tcl_current_script, + command, + timeout, + &weechat_tcl_api_hook_process_cb, + function)); + + TCL_RETURN_STRING_FREE(result); +} + /* * weechat_tcl_api_hook_connect_cb: callback for connect hooked */ @@ -3220,7 +3314,7 @@ weechat_tcl_api_hook_connect (ClientData clientData, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { Tcl_Obj *objp; - char *proxy, *address, *local_hostname, *result; + char *proxy, *address, *local_hostname, *function, *result; int i, port, sock, ipv6; /* make C compiler happy */ @@ -3232,7 +3326,7 @@ weechat_tcl_api_hook_connect (ClientData clientData, Tcl_Interp *interp, TCL_RETURN_EMPTY; } - if (objc < 7) + if (objc < 8) { WEECHAT_SCRIPT_MSG_WRONG_ARGUMENTS("hook_connect"); TCL_RETURN_EMPTY; @@ -3249,6 +3343,7 @@ weechat_tcl_api_hook_connect (ClientData clientData, Tcl_Interp *interp, proxy = Tcl_GetStringFromObj (objv[1], &i); address = Tcl_GetStringFromObj (objv[2], &i); local_hostname = Tcl_GetStringFromObj (objv[6], &i); + function = Tcl_GetStringFromObj (objv[7], &i); result = script_ptr2str (script_api_hook_connect (weechat_tcl_plugin, tcl_current_script, @@ -3260,7 +3355,7 @@ weechat_tcl_api_hook_connect (ClientData clientData, Tcl_Interp *interp, NULL, /* gnutls session */ local_hostname, &weechat_tcl_api_hook_connect_cb, - Tcl_GetStringFromObj (objv[7], &i))); /* tcl function */ + function)); TCL_RETURN_STRING_FREE(result); } @@ -3338,7 +3433,7 @@ weechat_tcl_api_hook_print (ClientData clientData, Tcl_Interp *interp, { Tcl_Obj *objp; char *result, *buffer, *tags, *message, *function; - int i,strip_colors; + int i, strip_colors; /* make C compiler happy */ (void) clientData; @@ -3702,7 +3797,7 @@ weechat_tcl_api_hook_completion_list_add (ClientData clientData, Tcl_Interp *int { Tcl_Obj *objp; char *completion, *word, *where; - int i,nick_completion; + int i, nick_completion; /* make C compiler happy */ (void) clientData; @@ -4574,7 +4669,7 @@ weechat_tcl_api_nicklist_add_group (ClientData clientData, Tcl_Interp *interp, { Tcl_Obj* objp; char *result, *buffer, *parent_group, *name, *color; - int i,visible; + int i, visible; /* make C compiler happy */ (void) clientData; @@ -5970,7 +6065,7 @@ void weechat_tcl_api_init (Tcl_Interp *interp) { #ifdef HAVE_TCL_CREATE_NS /* create weechat namespace */ - Tcl_CreateNamespace (interp, "weechat",(ClientData)0,NULL); + Tcl_CreateNamespace (interp, "weechat", (ClientData)0, NULL); #endif /* interface constants */ @@ -5979,344 +6074,351 @@ void weechat_tcl_api_init (Tcl_Interp *interp) { objp = Tcl_NewIntObj (WEECHAT_RC_OK); Tcl_IncrRefCount (objp); - Tcl_SetVar (interp, "weechat::WEECHAT_RC_OK", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_RC_OK_EAT); - Tcl_SetVar (interp, "weechat::WEECHAT_RC_OK_EAT", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_RC_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_RC_ERROR", Tcl_GetStringFromObj (objp, &i),0); + Tcl_SetVar (interp, "weechat::WEECHAT_RC_OK", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_RC_OK_EAT); + Tcl_SetVar (interp, "weechat::WEECHAT_RC_OK_EAT", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_RC_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_RC_ERROR", Tcl_GetStringFromObj (objp, &i), 0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_READ_OK); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_READ_OK", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_READ_MEMORY_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_READ_MEMORY_ERROR", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_READ_FILE_NOT_FOUND); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_READ_FILE_NOT_FOUND", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_WRITE_OK); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_WRITE_OK", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_WRITE_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_WRITE_ERROR", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_WRITE_MEMORY_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_WRITE_MEMORY_ERROR", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_OPTION_SET_OK_CHANGED); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_SET_OK_CHANGED", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_OPTION_SET_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_SET_ERROR", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_OPTION_UNSET_OK_RESET); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_RESET", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_CONFIG_OPTION_UNSET_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_UNSET_ERROR", Tcl_GetStringFromObj (objp, &i),0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_READ_OK); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_READ_OK", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_READ_MEMORY_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_READ_MEMORY_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_READ_FILE_NOT_FOUND); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_READ_FILE_NOT_FOUND", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_WRITE_OK); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_WRITE_OK", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_WRITE_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_WRITE_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_WRITE_MEMORY_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_WRITE_MEMORY_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_OPTION_SET_OK_CHANGED); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_SET_OK_CHANGED", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_SET_OK_SAME_VALUE", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_OPTION_SET_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_SET_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_SET_OPTION_NOT_FOUND", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_NO_RESET", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_OPTION_UNSET_OK_RESET); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_RESET", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_UNSET_OK_REMOVED", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_CONFIG_OPTION_UNSET_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_CONFIG_OPTION_UNSET_ERROR", Tcl_GetStringFromObj (objp, &i), 0); - Tcl_SetStringObj (objp,WEECHAT_LIST_POS_SORT,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_LIST_POS_SORT", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetStringObj (objp,WEECHAT_LIST_POS_BEGINNING,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_LIST_POS_BEGINNING", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetStringObj (objp,WEECHAT_LIST_POS_END,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_LIST_POS_END", Tcl_GetStringFromObj (objp, &i),0); + Tcl_SetStringObj (objp, WEECHAT_LIST_POS_SORT, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_LIST_POS_SORT", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetStringObj (objp, WEECHAT_LIST_POS_BEGINNING, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_LIST_POS_BEGINNING", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetStringObj (objp, WEECHAT_LIST_POS_END, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_LIST_POS_END", Tcl_GetStringFromObj (objp, &i), 0); - Tcl_SetStringObj (objp,WEECHAT_HOTLIST_LOW,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_HOTLIST_LOW", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetStringObj (objp,WEECHAT_HOTLIST_MESSAGE,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_HOTLIST_MESSAGE", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetStringObj (objp,WEECHAT_HOTLIST_PRIVATE,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_HOTLIST_PRIVATE", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetStringObj (objp,WEECHAT_HOTLIST_HIGHLIGHT,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_HOTLIST_HIGHLIGHT", Tcl_GetStringFromObj (objp, &i),0); + Tcl_SetStringObj (objp, WEECHAT_HOTLIST_LOW, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_HOTLIST_LOW", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetStringObj (objp, WEECHAT_HOTLIST_MESSAGE, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_HOTLIST_MESSAGE", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetStringObj (objp, WEECHAT_HOTLIST_PRIVATE, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_HOTLIST_PRIVATE", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetStringObj (objp, WEECHAT_HOTLIST_HIGHLIGHT, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_HOTLIST_HIGHLIGHT", Tcl_GetStringFromObj (objp, &i), 0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_OK); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_OK", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_PROXY_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_PROXY_ERROR", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetIntObj (objp,WEECHAT_HOOK_CONNECT_MEMORY_ERROR); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_MEMORY_ERROR", Tcl_GetStringFromObj (objp, &i),0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_PROCESS_RUNNING); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_PROCESS_RUNNING", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_PROCESS_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_PROCESS_ERROR", Tcl_GetStringFromObj (objp, &i), 0); - Tcl_SetStringObj (objp,WEECHAT_HOOK_SIGNAL_STRING,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_SIGNAL_STRING", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetStringObj (objp,WEECHAT_HOOK_SIGNAL_INT,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_SIGNAL_INT", Tcl_GetStringFromObj (objp, &i),0); - Tcl_SetStringObj (objp,WEECHAT_HOOK_SIGNAL_POINTER,-1); - Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_SIGNAL_POINTER", Tcl_GetStringFromObj (objp, &i),0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_OK); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_OK", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_IP_ADDRESS_NOT_FOUND", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_CONNECTION_REFUSED", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_PROXY_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_PROXY_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_LOCAL_HOSTNAME_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_GNUTLS_INIT_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_GNUTLS_HANDSHAKE_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetIntObj (objp, WEECHAT_HOOK_CONNECT_MEMORY_ERROR); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_CONNECT_MEMORY_ERROR", Tcl_GetStringFromObj (objp, &i), 0); + + Tcl_SetStringObj (objp, WEECHAT_HOOK_SIGNAL_STRING, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_SIGNAL_STRING", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetStringObj (objp, WEECHAT_HOOK_SIGNAL_INT, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_SIGNAL_INT", Tcl_GetStringFromObj (objp, &i), 0); + Tcl_SetStringObj (objp, WEECHAT_HOOK_SIGNAL_POINTER, -1); + Tcl_SetVar (interp, "weechat::WEECHAT_HOOK_SIGNAL_POINTER", Tcl_GetStringFromObj (objp, &i), 0); Tcl_DecrRefCount (objp); /* interface functions */ - Tcl_CreateObjCommand (interp,"weechat::register", + Tcl_CreateObjCommand (interp, "weechat::register", weechat_tcl_api_register, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::plugin_get_name", + Tcl_CreateObjCommand (interp, "weechat::plugin_get_name", weechat_tcl_api_plugin_get_name, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::charset_set", + Tcl_CreateObjCommand (interp, "weechat::charset_set", weechat_tcl_api_charset_set, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::iconv_to_internal", + Tcl_CreateObjCommand (interp, "weechat::iconv_to_internal", weechat_tcl_api_iconv_to_internal, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::iconv_from_internal", + Tcl_CreateObjCommand (interp, "weechat::iconv_from_internal", weechat_tcl_api_iconv_from_internal, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::gettext", + Tcl_CreateObjCommand (interp, "weechat::gettext", weechat_tcl_api_gettext, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::ngettext", + Tcl_CreateObjCommand (interp, "weechat::ngettext", weechat_tcl_api_ngettext, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::string_remove_color", + Tcl_CreateObjCommand (interp, "weechat::string_remove_color", weechat_tcl_api_string_remove_color, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::mkdir_home", + Tcl_CreateObjCommand (interp, "weechat::mkdir_home", weechat_tcl_api_mkdir_home, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::mkdir", + Tcl_CreateObjCommand (interp, "weechat::mkdir", weechat_tcl_api_mkdir, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::mkdir_parents", + Tcl_CreateObjCommand (interp, "weechat::mkdir_parents", weechat_tcl_api_mkdir_parents, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_new", + Tcl_CreateObjCommand (interp, "weechat::list_new", weechat_tcl_api_list_new, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_add", + Tcl_CreateObjCommand (interp, "weechat::list_add", weechat_tcl_api_list_add, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_search", + Tcl_CreateObjCommand (interp, "weechat::list_search", weechat_tcl_api_list_search, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_casesearch", + Tcl_CreateObjCommand (interp, "weechat::list_casesearch", weechat_tcl_api_list_casesearch, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_get", + Tcl_CreateObjCommand (interp, "weechat::list_get", weechat_tcl_api_list_get, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_set", + Tcl_CreateObjCommand (interp, "weechat::list_set", weechat_tcl_api_list_set, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_next", + Tcl_CreateObjCommand (interp, "weechat::list_next", weechat_tcl_api_list_next, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_prev", + Tcl_CreateObjCommand (interp, "weechat::list_prev", weechat_tcl_api_list_prev, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_string", + Tcl_CreateObjCommand (interp, "weechat::list_string", weechat_tcl_api_list_string, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_size", + Tcl_CreateObjCommand (interp, "weechat::list_size", weechat_tcl_api_list_size, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_remove", + Tcl_CreateObjCommand (interp, "weechat::list_remove", weechat_tcl_api_list_remove, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_remove_all", + Tcl_CreateObjCommand (interp, "weechat::list_remove_all", weechat_tcl_api_list_remove_all, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::list_free", + Tcl_CreateObjCommand (interp, "weechat::list_free", weechat_tcl_api_list_free, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_new", + Tcl_CreateObjCommand (interp, "weechat::config_new", weechat_tcl_api_config_new, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_new_section", + Tcl_CreateObjCommand (interp, "weechat::config_new_section", weechat_tcl_api_config_new_section, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_search_section", + Tcl_CreateObjCommand (interp, "weechat::config_search_section", weechat_tcl_api_config_search_section, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_new_option", + Tcl_CreateObjCommand (interp, "weechat::config_new_option", weechat_tcl_api_config_new_option, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_search_option", + Tcl_CreateObjCommand (interp, "weechat::config_search_option", weechat_tcl_api_config_search_option, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_string_to_boolean", + Tcl_CreateObjCommand (interp, "weechat::config_string_to_boolean", weechat_tcl_api_config_string_to_boolean, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_option_reset", + Tcl_CreateObjCommand (interp, "weechat::config_option_reset", weechat_tcl_api_config_option_reset, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_option_set", + Tcl_CreateObjCommand (interp, "weechat::config_option_set", weechat_tcl_api_config_option_set, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_option_set_null", + Tcl_CreateObjCommand (interp, "weechat::config_option_set_null", weechat_tcl_api_config_option_set_null, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_option_unset", + Tcl_CreateObjCommand (interp, "weechat::config_option_unset", weechat_tcl_api_config_option_unset, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_option_rename", + Tcl_CreateObjCommand (interp, "weechat::config_option_rename", weechat_tcl_api_config_option_rename, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_option_is_null", + Tcl_CreateObjCommand (interp, "weechat::config_option_is_null", weechat_tcl_api_config_option_is_null, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_option_default_is_null", + Tcl_CreateObjCommand (interp, "weechat::config_option_default_is_null", weechat_tcl_api_config_option_default_is_null, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_boolean", + Tcl_CreateObjCommand (interp, "weechat::config_boolean", weechat_tcl_api_config_boolean, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_boolean_default", + Tcl_CreateObjCommand (interp, "weechat::config_boolean_default", weechat_tcl_api_config_boolean_default, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_integer", + Tcl_CreateObjCommand (interp, "weechat::config_integer", weechat_tcl_api_config_integer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_integer_default", + Tcl_CreateObjCommand (interp, "weechat::config_integer_default", weechat_tcl_api_config_integer_default, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_string", + Tcl_CreateObjCommand (interp, "weechat::config_string", weechat_tcl_api_config_string, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_string_default", + Tcl_CreateObjCommand (interp, "weechat::config_string_default", weechat_tcl_api_config_string_default, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_color", + Tcl_CreateObjCommand (interp, "weechat::config_color", weechat_tcl_api_config_color, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_color_default", + Tcl_CreateObjCommand (interp, "weechat::config_color_default", weechat_tcl_api_config_color_default, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_write_option", + Tcl_CreateObjCommand (interp, "weechat::config_write_option", weechat_tcl_api_config_write_option, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_write_line", + Tcl_CreateObjCommand (interp, "weechat::config_write_line", weechat_tcl_api_config_write_line, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_write", + Tcl_CreateObjCommand (interp, "weechat::config_write", weechat_tcl_api_config_write, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_read", + Tcl_CreateObjCommand (interp, "weechat::config_read", weechat_tcl_api_config_read, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_reload", + Tcl_CreateObjCommand (interp, "weechat::config_reload", weechat_tcl_api_config_reload, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_option_free", + Tcl_CreateObjCommand (interp, "weechat::config_option_free", weechat_tcl_api_config_option_free, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_section_free_options", + Tcl_CreateObjCommand (interp, "weechat::config_section_free_options", weechat_tcl_api_config_section_free_options, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_section_free", + Tcl_CreateObjCommand (interp, "weechat::config_section_free", weechat_tcl_api_config_section_free, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_free", + Tcl_CreateObjCommand (interp, "weechat::config_free", weechat_tcl_api_config_free, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_get", + Tcl_CreateObjCommand (interp, "weechat::config_get", weechat_tcl_api_config_get, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_get_plugin", + Tcl_CreateObjCommand (interp, "weechat::config_get_plugin", weechat_tcl_api_config_get_plugin, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_set_plugin", + Tcl_CreateObjCommand (interp, "weechat::config_set_plugin", weechat_tcl_api_config_set_plugin, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::config_unset_plugin", + Tcl_CreateObjCommand (interp, "weechat::config_unset_plugin", weechat_tcl_api_config_unset_plugin, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::prefix", + Tcl_CreateObjCommand (interp, "weechat::prefix", weechat_tcl_api_prefix, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::color", + Tcl_CreateObjCommand (interp, "weechat::color", weechat_tcl_api_color, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::print", + Tcl_CreateObjCommand (interp, "weechat::print", weechat_tcl_api_print, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::print_date_tags", + Tcl_CreateObjCommand (interp, "weechat::print_date_tags", weechat_tcl_api_print_date_tags, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::print_y", + Tcl_CreateObjCommand (interp, "weechat::print_y", weechat_tcl_api_print_y, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::log_print", + Tcl_CreateObjCommand (interp, "weechat::log_print", weechat_tcl_api_log_print, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_command", + Tcl_CreateObjCommand (interp, "weechat::hook_command", weechat_tcl_api_hook_command, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_command_run", + Tcl_CreateObjCommand (interp, "weechat::hook_command_run", weechat_tcl_api_hook_command_run, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_timer", + Tcl_CreateObjCommand (interp, "weechat::hook_timer", weechat_tcl_api_hook_timer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_fd", + Tcl_CreateObjCommand (interp, "weechat::hook_fd", weechat_tcl_api_hook_fd, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_connect", + Tcl_CreateObjCommand (interp, "weechat::hook_process", + weechat_tcl_api_hook_process, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); + Tcl_CreateObjCommand (interp, "weechat::hook_connect", weechat_tcl_api_hook_connect, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_print", + Tcl_CreateObjCommand (interp, "weechat::hook_print", weechat_tcl_api_hook_print, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_signal", + Tcl_CreateObjCommand (interp, "weechat::hook_signal", weechat_tcl_api_hook_signal, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_signal_send", + Tcl_CreateObjCommand (interp, "weechat::hook_signal_send", weechat_tcl_api_hook_signal_send, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_config", + Tcl_CreateObjCommand (interp, "weechat::hook_config", weechat_tcl_api_hook_config, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_completion", + Tcl_CreateObjCommand (interp, "weechat::hook_completion", weechat_tcl_api_hook_completion, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_completion_list_add", + Tcl_CreateObjCommand (interp, "weechat::hook_completion_list_add", weechat_tcl_api_hook_completion_list_add, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_modifier", + Tcl_CreateObjCommand (interp, "weechat::hook_modifier", weechat_tcl_api_hook_modifier, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_modifier_exec", + Tcl_CreateObjCommand (interp, "weechat::hook_modifier_exec", weechat_tcl_api_hook_modifier_exec, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_info", + Tcl_CreateObjCommand (interp, "weechat::hook_info", weechat_tcl_api_hook_info, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::hook_infolist", + Tcl_CreateObjCommand (interp, "weechat::hook_infolist", weechat_tcl_api_hook_infolist, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::unhook", + Tcl_CreateObjCommand (interp, "weechat::unhook", weechat_tcl_api_unhook, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::unhook_all", + Tcl_CreateObjCommand (interp, "weechat::unhook_all", weechat_tcl_api_unhook_all, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::buffer_new", + Tcl_CreateObjCommand (interp, "weechat::buffer_new", weechat_tcl_api_buffer_new, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::buffer_search", + Tcl_CreateObjCommand (interp, "weechat::buffer_search", weechat_tcl_api_buffer_search, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::current_buffer", + Tcl_CreateObjCommand (interp, "weechat::current_buffer", weechat_tcl_api_current_buffer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::buffer_clear", + Tcl_CreateObjCommand (interp, "weechat::buffer_clear", weechat_tcl_api_buffer_clear, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::buffer_close", + Tcl_CreateObjCommand (interp, "weechat::buffer_close", weechat_tcl_api_buffer_close, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::buffer_get_integer", + Tcl_CreateObjCommand (interp, "weechat::buffer_get_integer", weechat_tcl_api_buffer_get_integer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::buffer_get_string", + Tcl_CreateObjCommand (interp, "weechat::buffer_get_string", weechat_tcl_api_buffer_get_string, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::buffer_get_pointer", + Tcl_CreateObjCommand (interp, "weechat::buffer_get_pointer", weechat_tcl_api_buffer_get_pointer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::buffer_set", + Tcl_CreateObjCommand (interp, "weechat::buffer_set", weechat_tcl_api_buffer_set, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::current_window", + Tcl_CreateObjCommand (interp, "weechat::current_window", weechat_tcl_api_current_window, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::window_get_integer", + Tcl_CreateObjCommand (interp, "weechat::window_get_integer", weechat_tcl_api_window_get_integer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::window_get_string", + Tcl_CreateObjCommand (interp, "weechat::window_get_string", weechat_tcl_api_window_get_string, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::window_get_pointer", + Tcl_CreateObjCommand (interp, "weechat::window_get_pointer", weechat_tcl_api_window_get_pointer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::nicklist_add_group", + Tcl_CreateObjCommand (interp, "weechat::nicklist_add_group", weechat_tcl_api_nicklist_add_group, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::nicklist_search_group", + Tcl_CreateObjCommand (interp, "weechat::nicklist_search_group", weechat_tcl_api_nicklist_search_group, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::nicklist_add_nick", + Tcl_CreateObjCommand (interp, "weechat::nicklist_add_nick", weechat_tcl_api_nicklist_add_nick, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::nicklist_search_nick", + Tcl_CreateObjCommand (interp, "weechat::nicklist_search_nick", weechat_tcl_api_nicklist_search_nick, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::nicklist_remove_group", + Tcl_CreateObjCommand (interp, "weechat::nicklist_remove_group", weechat_tcl_api_nicklist_remove_group, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::nicklist_remove_nick", + Tcl_CreateObjCommand (interp, "weechat::nicklist_remove_nick", weechat_tcl_api_nicklist_remove_nick, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::nicklist_remove_all", + Tcl_CreateObjCommand (interp, "weechat::nicklist_remove_all", weechat_tcl_api_nicklist_remove_all, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_item_search", + Tcl_CreateObjCommand (interp, "weechat::bar_item_search", weechat_tcl_api_bar_item_search, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_item_new", + Tcl_CreateObjCommand (interp, "weechat::bar_item_new", weechat_tcl_api_bar_item_new, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_item_update", + Tcl_CreateObjCommand (interp, "weechat::bar_item_update", weechat_tcl_api_bar_item_update, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_item_remove", + Tcl_CreateObjCommand (interp, "weechat::bar_item_remove", weechat_tcl_api_bar_item_remove, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_search", + Tcl_CreateObjCommand (interp, "weechat::bar_search", weechat_tcl_api_bar_search, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_new", + Tcl_CreateObjCommand (interp, "weechat::bar_new", weechat_tcl_api_bar_new, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_set", + Tcl_CreateObjCommand (interp, "weechat::bar_set", weechat_tcl_api_bar_set, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_update", + Tcl_CreateObjCommand (interp, "weechat::bar_update", weechat_tcl_api_bar_update, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::bar_remove", + Tcl_CreateObjCommand (interp, "weechat::bar_remove", weechat_tcl_api_bar_remove, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::command", + Tcl_CreateObjCommand (interp, "weechat::command", weechat_tcl_api_command, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::info_get", + Tcl_CreateObjCommand (interp, "weechat::info_get", weechat_tcl_api_info_get, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_new", + Tcl_CreateObjCommand (interp, "weechat::infolist_new", weechat_tcl_api_infolist_new, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_new_var_integer", + Tcl_CreateObjCommand (interp, "weechat::infolist_new_var_integer", weechat_tcl_api_infolist_new_var_integer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_new_var_string", + Tcl_CreateObjCommand (interp, "weechat::infolist_new_var_string", weechat_tcl_api_infolist_new_var_string, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_new_var_pointer", + Tcl_CreateObjCommand (interp, "weechat::infolist_new_var_pointer", weechat_tcl_api_infolist_new_var_pointer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_new_var_time", + Tcl_CreateObjCommand (interp, "weechat::infolist_new_var_time", weechat_tcl_api_infolist_new_var_time, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_get", + Tcl_CreateObjCommand (interp, "weechat::infolist_get", weechat_tcl_api_infolist_get, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_next", + Tcl_CreateObjCommand (interp, "weechat::infolist_next", weechat_tcl_api_infolist_next, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_prev", + Tcl_CreateObjCommand (interp, "weechat::infolist_prev", weechat_tcl_api_infolist_prev, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_fields", + Tcl_CreateObjCommand (interp, "weechat::infolist_fields", weechat_tcl_api_infolist_fields, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_integer", + Tcl_CreateObjCommand (interp, "weechat::infolist_integer", weechat_tcl_api_infolist_integer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_string", + Tcl_CreateObjCommand (interp, "weechat::infolist_string", weechat_tcl_api_infolist_string, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_pointer", + Tcl_CreateObjCommand (interp, "weechat::infolist_pointer", weechat_tcl_api_infolist_pointer, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_time", + Tcl_CreateObjCommand (interp, "weechat::infolist_time", weechat_tcl_api_infolist_time, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::infolist_free", + Tcl_CreateObjCommand (interp, "weechat::infolist_free", weechat_tcl_api_infolist_free, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::upgrade_new", + Tcl_CreateObjCommand (interp, "weechat::upgrade_new", weechat_tcl_api_upgrade_new, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::upgrade_write_object", + Tcl_CreateObjCommand (interp, "weechat::upgrade_write_object", weechat_tcl_api_upgrade_write_object, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::upgrade_read", + Tcl_CreateObjCommand (interp, "weechat::upgrade_read", weechat_tcl_api_upgrade_read, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); - Tcl_CreateObjCommand (interp,"weechat::upgrade_close", + Tcl_CreateObjCommand (interp, "weechat::upgrade_close", weechat_tcl_api_upgrade_close, (ClientData)NULL, (Tcl_CmdDeleteProc*)NULL); } diff --git a/src/plugins/weechat-plugin.h b/src/plugins/weechat-plugin.h index a5bc6ff72..ffbb3dec1 100644 --- a/src/plugins/weechat-plugin.h +++ b/src/plugins/weechat-plugin.h @@ -87,6 +87,13 @@ struct t_weelist; #define WEECHAT_HOTLIST_PRIVATE "2" #define WEECHAT_HOTLIST_HIGHLIGHT "3" +/* process return code (for callback): + if >= 0, then process ended and it's return code of command + if < 0, then it's running or error +*/ +#define WEECHAT_HOOK_PROCESS_RUNNING -1 +#define WEECHAT_HOOK_PROCESS_ERROR -2 + /* connect status for connection hooked */ #define WEECHAT_HOOK_CONNECT_OK 0 #define WEECHAT_HOOK_CONNECT_ADDRESS_NOT_FOUND 1 @@ -356,7 +363,8 @@ struct t_weechat_plugin long interval, int align_second, int max_calls, - int (*callback)(void *data), + int (*callback)(void *data, + int remaining_calls), void *callback_data); struct t_hook *(*hook_fd) (struct t_weechat_plugin *plugin, int fd, @@ -365,6 +373,15 @@ struct t_weechat_plugin int flag_exception, int (*callback)(void *data, int fd), void *callback_data); + struct t_hook *(*hook_process) (struct t_weechat_plugin *plugin, + const char *command, + int timeout, + int (*callback)(void *data, + const char *command, + int return_code, + const char *stdout, + const char *stderr), + void *callback_data); struct t_hook *(*hook_connect) (struct t_weechat_plugin *plugin, const char *proxy, const char *address, @@ -926,6 +943,10 @@ extern int weechat_plugin_end (struct t_weechat_plugin *plugin); weechat_plugin->hook_fd(weechat_plugin, __fd, __flag_read, \ __flag_write, __flag_exception, __callback, \ __data) +#define weechat_hook_process(__command, __timeout, __callback, \ + __callback_data) \ + weechat_plugin->hook_process(weechat_plugin, __command, __timeout, \ + __callback, __callback_data) #define weechat_hook_connect(__proxy, __address, __port, __sock, \ __ipv6, __gnutls_sess, __local_hostname, \ __callback, __data) \ diff --git a/src/plugins/xfer/xfer-network.c b/src/plugins/xfer/xfer-network.c index e5fe700c4..948b52b2e 100644 --- a/src/plugins/xfer/xfer-network.c +++ b/src/plugins/xfer/xfer-network.c @@ -198,6 +198,7 @@ xfer_network_send_file_fork (struct t_xfer *xfer) /* child process */ case 0: setuid (getuid ()); + close (xfer->child_read); switch (xfer->protocol) { case XFER_NO_PROTOCOL: @@ -214,6 +215,8 @@ xfer_network_send_file_fork (struct t_xfer *xfer) /* parent process */ xfer->child_pid = pid; + close (xfer->child_write); + xfer->child_write = -1; xfer->hook_fd = weechat_hook_fd (xfer->child_read, 1, 0, 0, &xfer_network_child_read_cb, @@ -250,9 +253,10 @@ xfer_network_recv_file_fork (struct t_xfer *xfer) xfer_close (xfer, XFER_STATUS_FAILED); xfer_buffer_refresh (WEECHAT_HOTLIST_MESSAGE); return; - /* child process */ + /* child process */ case 0: setuid (getuid ()); + close (xfer->child_read); switch (xfer->protocol) { case XFER_NO_PROTOCOL: @@ -269,6 +273,8 @@ xfer_network_recv_file_fork (struct t_xfer *xfer) /* parent process */ xfer->child_pid = pid; + close (xfer->child_write); + xfer->child_write = -1; xfer->hook_fd = weechat_hook_fd (xfer->child_read, 1, 0, 0, &xfer_network_child_read_cb, @@ -429,10 +435,13 @@ xfer_network_fd_cb (void *arg_xfer, int fd) */ int -xfer_network_timer_cb (void *arg_xfer) +xfer_network_timer_cb (void *arg_xfer, int remaining_calls) { struct t_xfer *xfer; + /* make C compiler happy */ + (void) remaining_calls; + xfer = (struct t_xfer *)arg_xfer; if ((xfer->status == XFER_STATUS_WAITING)