summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/wee-hook.c178
-rw-r--r--src/core/wee-hook.h15
-rw-r--r--src/plugins/guile/weechat-guile-api.c16
-rw-r--r--src/plugins/lua/weechat-lua-api.c19
-rw-r--r--src/plugins/perl/weechat-perl-api.c19
-rw-r--r--src/plugins/python/weechat-python-api.c20
-rw-r--r--src/plugins/ruby/weechat-ruby-api.c26
-rw-r--r--src/plugins/tcl/weechat-tcl-api.c22
8 files changed, 263 insertions, 52 deletions
diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c
index 150bbc168..bb8895592 100644
--- a/src/core/wee-hook.c
+++ b/src/core/wee-hook.c
@@ -1353,35 +1353,29 @@ hook_process_hashtable (struct t_weechat_plugin *plugin,
struct t_hook_process *new_hook_process;
char *stdout_buffer, *stderr_buffer;
+ stdout_buffer = NULL;
+ stderr_buffer = NULL;
+ new_hook = NULL;
+ new_hook_process = NULL;
+
if (!command || !command[0] || !callback)
- return NULL;
+ goto error;
stdout_buffer = malloc (HOOK_PROCESS_BUFFER_SIZE + 1);
if (!stdout_buffer)
- return NULL;
+ goto error;
stderr_buffer = malloc (HOOK_PROCESS_BUFFER_SIZE + 1);
if (!stderr_buffer)
- {
- free (stdout_buffer);
- return NULL;
- }
+ goto error;
new_hook = malloc (sizeof (*new_hook));
if (!new_hook)
- {
- free (stdout_buffer);
- free (stderr_buffer);
- return NULL;
- }
+ goto error;
+
new_hook_process = malloc (sizeof (*new_hook_process));
if (!new_hook_process)
- {
- free (stdout_buffer);
- free (stderr_buffer);
- free (new_hook);
- return NULL;
- }
+ goto error;
hook_init_data (new_hook, plugin, HOOK_TYPE_PROCESS, HOOK_PRIORITY_DEFAULT,
callback_data);
@@ -1391,16 +1385,21 @@ hook_process_hashtable (struct t_weechat_plugin *plugin,
new_hook_process->command = strdup (command);
new_hook_process->options = (options) ? hashtable_dup (options) : NULL;
new_hook_process->timeout = timeout;
+ new_hook_process->child_read[HOOK_PROCESS_STDIN] = -1;
new_hook_process->child_read[HOOK_PROCESS_STDOUT] = -1;
new_hook_process->child_read[HOOK_PROCESS_STDERR] = -1;
+ new_hook_process->child_write[HOOK_PROCESS_STDIN] = -1;
new_hook_process->child_write[HOOK_PROCESS_STDOUT] = -1;
new_hook_process->child_write[HOOK_PROCESS_STDERR] = -1;
new_hook_process->child_pid = 0;
+ new_hook_process->hook_fd[HOOK_PROCESS_STDIN] = NULL;
new_hook_process->hook_fd[HOOK_PROCESS_STDOUT] = NULL;
new_hook_process->hook_fd[HOOK_PROCESS_STDERR] = NULL;
new_hook_process->hook_timer = NULL;
+ new_hook_process->buffer[HOOK_PROCESS_STDIN] = NULL;
new_hook_process->buffer[HOOK_PROCESS_STDOUT] = stdout_buffer;
new_hook_process->buffer[HOOK_PROCESS_STDERR] = stderr_buffer;
+ new_hook_process->buffer_size[HOOK_PROCESS_STDIN] = 0;
new_hook_process->buffer_size[HOOK_PROCESS_STDOUT] = 0;
new_hook_process->buffer_size[HOOK_PROCESS_STDERR] = 0;
@@ -1409,6 +1408,17 @@ hook_process_hashtable (struct t_weechat_plugin *plugin,
hook_process_run (new_hook);
return new_hook;
+
+error:
+ if (stdout_buffer)
+ free (stdout_buffer);
+ if (stderr_buffer)
+ free (stderr_buffer);
+ if (new_hook)
+ free (new_hook);
+ if (new_hook_process)
+ free (new_hook_process);
+ return NULL;
}
/*
@@ -1439,11 +1449,25 @@ hook_process_child (struct t_hook *hook_process)
int rc, i, num_args;
FILE *f;
- /* use "/dev/null" for stdin stream */
- f = freopen ("/dev/null", "r", stdin);
- (void) f;
+ /* read stdin from parent, if a pipe was defined */
+ if (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]) >= 0)
+ {
+ if (dup2 (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]),
+ STDIN_FILENO) < 0)
+ {
+ _exit (EXIT_FAILURE);
+ }
+ }
+ else
+ {
+ /* no stdin pipe from parent, use "/dev/null" for stdin stream */
+ f = freopen ("/dev/null", "r", stdin);
+ (void) f;
+ }
+ if (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDIN]) >= 0)
+ close (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDIN]));
- /* redirect stdout/stderr to pipe (so that father process can read them) */
+ /* redirect stdout/stderr to pipe (so that parent process can read them) */
close (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDOUT]));
close (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDERR]));
if (dup2 (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDOUT]),
@@ -1718,40 +1742,38 @@ hook_process_timer_cb (void *arg_hook_process, int remaining_calls)
void
hook_process_run (struct t_hook *hook_process)
{
- int pipe_stdout[2], pipe_stderr[2], timeout, max_calls, rc;
+ int pipes[3][2], timeout, max_calls, rc, i;
long interval;
pid_t pid;
- /* create pipe for child process (stdout) */
- if (pipe (pipe_stdout) < 0)
+ for (i = 0; i < 3; i++)
{
- (void) (HOOK_PROCESS(hook_process, callback))
- (hook_process->callback_data,
- HOOK_PROCESS(hook_process, command),
- WEECHAT_HOOK_PROCESS_ERROR,
- NULL, NULL);
- unhook (hook_process);
- return;
+ pipes[i][0] = -1;
+ pipes[i][1] = -1;
}
- if (pipe (pipe_stderr) < 0)
+
+ /* create pipe for stdin (only if stdin was given in options) */
+ if (HOOK_PROCESS(hook_process, options)
+ && hashtable_has_key (HOOK_PROCESS(hook_process, options), "stdin"))
{
- close (pipe_stdout[0]);
- close (pipe_stdout[1]);
- (void) (HOOK_PROCESS(hook_process, callback))
- (hook_process->callback_data,
- HOOK_PROCESS(hook_process, command),
- WEECHAT_HOOK_PROCESS_ERROR,
- NULL, NULL);
- unhook (hook_process);
- return;
+ if (pipe (pipes[HOOK_PROCESS_STDIN]) < 0)
+ goto error;
}
- HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDOUT]) = pipe_stdout[0];
- HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDOUT]) = pipe_stdout[1];
+ /* create pipes for stdout/err */
+ if (pipe (pipes[HOOK_PROCESS_STDOUT]) < 0)
+ goto error;
+ if (pipe (pipes[HOOK_PROCESS_STDERR]) < 0)
+ goto error;
- HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDERR]) = pipe_stderr[0];
- HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDERR]) = pipe_stderr[1];
+ /* assign pipes to variables in hook */
+ for (i = 0; i < 3; i++)
+ {
+ HOOK_PROCESS(hook_process, child_read[i]) = pipes[i][0];
+ HOOK_PROCESS(hook_process, child_write[i]) = pipes[i][1];
+ }
+ /* fork */
switch (pid = fork ())
{
/* fork failed */
@@ -1772,8 +1794,14 @@ hook_process_run (struct t_hook *hook_process)
_exit (EXIT_SUCCESS);
break;
}
+
/* parent process */
HOOK_PROCESS(hook_process, child_pid) = pid;
+ if (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]) >= 0)
+ {
+ close (HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]));
+ HOOK_PROCESS(hook_process, child_read[HOOK_PROCESS_STDIN]) = -1;
+ }
close (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDOUT]));
HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDOUT]) = -1;
close (HOOK_PROCESS(hook_process, child_write[HOOK_PROCESS_STDERR]));
@@ -1815,6 +1843,22 @@ hook_process_run (struct t_hook *hook_process)
interval, 0, max_calls,
&hook_process_timer_cb,
hook_process);
+ return;
+
+error:
+ for (i = 0; i < 3; i++)
+ {
+ if (pipes[i][0] >= 0)
+ close (pipes[i][0]);
+ if (pipes[i][1] >= 0)
+ close (pipes[i][1]);
+ }
+ (void) (HOOK_PROCESS(hook_process, callback))
+ (hook_process->callback_data,
+ HOOK_PROCESS(hook_process, command),
+ WEECHAT_HOOK_PROCESS_ERROR,
+ NULL, NULL);
+ unhook (hook_process);
}
/*
@@ -3157,12 +3201,39 @@ hook_focus_get_data (struct t_hashtable *hashtable_focus1,
void
hook_set (struct t_hook *hook, const char *property, const char *value)
{
+ /* invalid hook? */
+ if (!hook_valid (hook))
+ return;
+
if (string_strcasecmp (property, "subplugin") == 0)
{
if (hook->subplugin)
free(hook->subplugin);
hook->subplugin = strdup (value);
}
+ else if (string_strcasecmp (property, "stdin") == 0)
+ {
+ if (!hook->deleted
+ && (hook->type == HOOK_TYPE_PROCESS)
+ && (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]) >= 0))
+ {
+ /* send data on child's stdin */
+ write (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]),
+ value,
+ strlen (value));
+ }
+ }
+ else if (string_strcasecmp (property, "stdin_close") == 0)
+ {
+ if (!hook->deleted
+ && (hook->type == HOOK_TYPE_PROCESS)
+ && (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]) >= 0))
+ {
+ /* close stdin pipe */
+ close (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]));
+ HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]) = -1;
+ }
+ }
}
/*
@@ -3250,6 +3321,8 @@ unhook (struct t_hook *hook)
free (HOOK_PROCESS(hook, command));
if (HOOK_PROCESS(hook, options))
hashtable_free (HOOK_PROCESS(hook, options));
+ if (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDIN]))
+ unhook (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDIN]));
if (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDOUT]))
unhook (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDOUT]));
if (HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDERR]))
@@ -3261,6 +3334,10 @@ unhook (struct t_hook *hook)
kill (HOOK_PROCESS(hook, child_pid), SIGKILL);
waitpid (HOOK_PROCESS(hook, child_pid), NULL, 0);
}
+ if (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDIN]) != -1)
+ close (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDIN]));
+ if (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]) != -1)
+ close (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN]));
if (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDOUT]) != -1)
close (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDOUT]));
if (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDOUT]) != -1)
@@ -3269,6 +3346,8 @@ unhook (struct t_hook *hook)
close (HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDERR]));
if (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDERR]) != -1)
close (HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDERR]));
+ if (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDIN]))
+ free (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDIN]));
if (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDOUT]))
free (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDOUT]));
if (HOOK_PROCESS(hook, buffer[HOOK_PROCESS_STDERR]))
@@ -3587,6 +3666,10 @@ hook_add_to_infolist_pointer (struct t_infolist *infolist, struct t_hook *hook)
return 0;
if (!infolist_new_var_integer (ptr_item, "timeout", HOOK_PROCESS(hook, timeout)))
return 0;
+ if (!infolist_new_var_integer (ptr_item, "child_read_stdin", HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDIN])))
+ return 0;
+ if (!infolist_new_var_integer (ptr_item, "child_write_stdin", HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDIN])))
+ return 0;
if (!infolist_new_var_integer (ptr_item, "child_read_stdout", HOOK_PROCESS(hook, child_read[HOOK_PROCESS_STDOUT])))
return 0;
if (!infolist_new_var_integer (ptr_item, "child_write_stdout", HOOK_PROCESS(hook, child_write[HOOK_PROCESS_STDOUT])))
@@ -3597,6 +3680,8 @@ hook_add_to_infolist_pointer (struct t_infolist *infolist, struct t_hook *hook)
return 0;
if (!infolist_new_var_integer (ptr_item, "child_pid", HOOK_PROCESS(hook, child_pid)))
return 0;
+ if (!infolist_new_var_pointer (ptr_item, "hook_fd_stdin", HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDIN])))
+ return 0;
if (!infolist_new_var_pointer (ptr_item, "hook_fd_stdout", HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDOUT])))
return 0;
if (!infolist_new_var_pointer (ptr_item, "hook_fd_stderr", HOOK_PROCESS(hook, hook_fd[HOOK_PROCESS_STDERR])))
@@ -4062,11 +4147,14 @@ hook_print_log ()
hashtable_get_string (HOOK_PROCESS(ptr_hook, options),
"keys_values"));
log_printf (" timeout . . . . . . . : %d", HOOK_PROCESS(ptr_hook, timeout));
+ log_printf (" child_read[stdin] . . : %d", HOOK_PROCESS(ptr_hook, child_read[HOOK_PROCESS_STDIN]));
+ log_printf (" child_write[stdin]. . : %d", HOOK_PROCESS(ptr_hook, child_write[HOOK_PROCESS_STDIN]));
log_printf (" child_read[stdout]. . : %d", HOOK_PROCESS(ptr_hook, child_read[HOOK_PROCESS_STDOUT]));
log_printf (" child_write[stdout] . : %d", HOOK_PROCESS(ptr_hook, child_write[HOOK_PROCESS_STDOUT]));
log_printf (" child_read[stderr]. . : %d", HOOK_PROCESS(ptr_hook, child_read[HOOK_PROCESS_STDERR]));
log_printf (" child_write[stderr] . : %d", HOOK_PROCESS(ptr_hook, child_write[HOOK_PROCESS_STDERR]));
log_printf (" child_pid . . . . . . : %d", HOOK_PROCESS(ptr_hook, child_pid));
+ log_printf (" hook_fd[stdin]. . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_fd[HOOK_PROCESS_STDIN]));
log_printf (" hook_fd[stdout] . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_fd[HOOK_PROCESS_STDOUT]));
log_printf (" hook_fd[stderr] . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_fd[HOOK_PROCESS_STDERR]));
log_printf (" hook_timer. . . . . . : 0x%lx", HOOK_PROCESS(ptr_hook, hook_timer));
diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h
index ca3f7b641..3f4a04ffa 100644
--- a/src/core/wee-hook.h
+++ b/src/core/wee-hook.h
@@ -88,8 +88,9 @@ enum t_hook_type
#define HOOK_FD_FLAG_EXCEPTION 4
/* constants for hook process */
-#define HOOK_PROCESS_STDOUT 0
-#define HOOK_PROCESS_STDERR 1
+#define HOOK_PROCESS_STDIN 0
+#define HOOK_PROCESS_STDOUT 1
+#define HOOK_PROCESS_STDERR 2
#define HOOK_PROCESS_BUFFER_SIZE 65536
/* macros to access hook specific data */
@@ -213,13 +214,13 @@ struct t_hook_process
char *command; /* command executed by child */
struct t_hashtable *options; /* options for process (see doc) */
long timeout; /* timeout (ms) (0 = no timeout) */
- int child_read[2]; /* to read data in pipe from child */
- int child_write[2]; /* to write data in pipe for child */
+ int child_read[3]; /* read stdin/out/err data from child*/
+ int child_write[3]; /* write stdin/out/err data for child*/
pid_t child_pid; /* pid of child process */
- struct t_hook *hook_fd[2]; /* hook fd for stdout/stderr */
+ struct t_hook *hook_fd[3]; /* hook fd for stdin/out/err */
struct t_hook *hook_timer; /* timer to check if child has died */
- char *buffer[2]; /* buffers for child stdout/stderr */
- int buffer_size[2]; /* size of child stdout/stderr */
+ char *buffer[3]; /* buffers for child stdin/out/err */
+ int buffer_size[3]; /* size of child stdin/out/err */
};
/* hook connect */
diff --git a/src/plugins/guile/weechat-guile-api.c b/src/plugins/guile/weechat-guile-api.c
index b79e53967..bdd47e92f 100644
--- a/src/plugins/guile/weechat-guile-api.c
+++ b/src/plugins/guile/weechat-guile-api.c
@@ -2965,6 +2965,21 @@ weechat_guile_api_hook_focus (SCM area, SCM function, SCM data)
}
SCM
+weechat_guile_api_hook_set (SCM hook, SCM property, SCM value)
+{
+ API_FUNC(1, "hook_set", API_RETURN_ERROR);
+ if (!scm_is_string (hook) || !scm_is_string (property)
+ || !scm_is_string (value))
+ API_WRONG_ARGS(API_RETURN_ERROR);
+
+ weechat_hook_set (API_STR2PTR(API_SCM_TO_STRING(hook)),
+ API_SCM_TO_STRING(property),
+ API_SCM_TO_STRING(value));
+
+ API_RETURN_OK;
+}
+
+SCM
weechat_guile_api_unhook (SCM hook)
{
API_FUNC(1, "unhook", API_RETURN_ERROR);
@@ -4726,6 +4741,7 @@ weechat_guile_api_module_init (void *data)
API_DEF_FUNC(hook_info_hashtable, 6);
API_DEF_FUNC(hook_infolist, 6);
API_DEF_FUNC(hook_focus, 3);
+ API_DEF_FUNC(hook_set, 3);
API_DEF_FUNC(unhook, 1);
API_DEF_FUNC(unhook_all, 0);
API_DEF_FUNC(buffer_new, 5);
diff --git a/src/plugins/lua/weechat-lua-api.c b/src/plugins/lua/weechat-lua-api.c
index 4c0009f44..d3e333de0 100644
--- a/src/plugins/lua/weechat-lua-api.c
+++ b/src/plugins/lua/weechat-lua-api.c
@@ -3202,6 +3202,24 @@ weechat_lua_api_hook_focus (lua_State *L)
}
static int
+weechat_lua_api_hook_set (lua_State *L)
+{
+ const char *hook, *property, *value;
+
+ API_FUNC(1, "hook_set", API_RETURN_ERROR);
+ if (lua_gettop (L) < 3)
+ API_WRONG_ARGS(API_RETURN_ERROR);
+
+ hook = lua_tostring (L, -3);
+ property = lua_tostring (L, -2);
+ value = lua_tostring (L, -1);
+
+ weechat_hook_set (API_STR2PTR(hook), property, value);
+
+ API_RETURN_OK;
+}
+
+static int
weechat_lua_api_unhook (lua_State *L)
{
const char *hook;
@@ -5210,6 +5228,7 @@ const struct luaL_Reg weechat_lua_api_funcs[] = {
API_DEF_FUNC(hook_info_hashtable),
API_DEF_FUNC(hook_infolist),
API_DEF_FUNC(hook_focus),
+ API_DEF_FUNC(hook_set),
API_DEF_FUNC(unhook),
API_DEF_FUNC(unhook_all),
API_DEF_FUNC(buffer_new),
diff --git a/src/plugins/perl/weechat-perl-api.c b/src/plugins/perl/weechat-perl-api.c
index 7d6c9d668..632e17872 100644
--- a/src/plugins/perl/weechat-perl-api.c
+++ b/src/plugins/perl/weechat-perl-api.c
@@ -3019,6 +3019,24 @@ XS (XS_weechat_api_hook_focus)
API_RETURN_STRING_FREE(result);
}
+XS (XS_weechat_api_hook_set)
+{
+ char *hook, *property, *value;
+ dXSARGS;
+
+ API_FUNC(1, "hook_set", API_RETURN_ERROR);
+ if (items < 3)
+ API_WRONG_ARGS(API_RETURN_ERROR);
+
+ hook = SvPV_nolen (ST (0));
+ property = SvPV_nolen (ST (1));
+ value = SvPV_nolen (ST (2));
+
+ weechat_hook_set (API_STR2PTR(hook), property, value);
+
+ API_RETURN_OK;
+}
+
XS (XS_weechat_api_unhook)
{
dXSARGS;
@@ -4963,6 +4981,7 @@ weechat_perl_api_init (pTHX)
API_DEF_FUNC(hook_info_hashtable);
API_DEF_FUNC(hook_infolist);
API_DEF_FUNC(hook_focus);
+ API_DEF_FUNC(hook_set);
API_DEF_FUNC(unhook);
API_DEF_FUNC(unhook_all);
API_DEF_FUNC(buffer_new);
diff --git a/src/plugins/python/weechat-python-api.c b/src/plugins/python/weechat-python-api.c
index 4b6128edd..3a3cc7b68 100644
--- a/src/plugins/python/weechat-python-api.c
+++ b/src/plugins/python/weechat-python-api.c
@@ -3159,6 +3159,25 @@ weechat_python_api_hook_focus (PyObject *self, PyObject *args)
}
static PyObject *
+weechat_python_api_hook_set (PyObject *self, PyObject *args)
+{
+ char *hook, *property, *value;
+
+ API_FUNC(1, "hook_set", API_RETURN_ERROR);
+ hook = NULL;
+ property = NULL;
+ value = NULL;
+ if (!PyArg_ParseTuple (args, "sss", &hook, &property, &value))
+ API_WRONG_ARGS(API_RETURN_ERROR);
+
+ weechat_hook_set (API_STR2PTR(hook),
+ property,
+ value);
+
+ API_RETURN_OK;
+}
+
+static PyObject *
weechat_python_api_unhook (PyObject *self, PyObject *args)
{
char *hook;
@@ -5122,6 +5141,7 @@ PyMethodDef weechat_python_funcs[] =
API_DEF_FUNC(hook_info_hashtable),
API_DEF_FUNC(hook_infolist),
API_DEF_FUNC(hook_focus),
+ API_DEF_FUNC(hook_set),
API_DEF_FUNC(unhook),
API_DEF_FUNC(unhook_all),
API_DEF_FUNC(buffer_new),
diff --git a/src/plugins/ruby/weechat-ruby-api.c b/src/plugins/ruby/weechat-ruby-api.c
index 6ceadef11..471f038a6 100644
--- a/src/plugins/ruby/weechat-ruby-api.c
+++ b/src/plugins/ruby/weechat-ruby-api.c
@@ -3649,6 +3649,31 @@ weechat_ruby_api_hook_focus (VALUE class, VALUE area, VALUE function,
}
static VALUE
+weechat_ruby_api_hook_set (VALUE class, VALUE hook, VALUE property,
+ VALUE value)
+{
+ char *c_hook, *c_property, *c_value;
+
+ API_FUNC(1, "hook_set", API_RETURN_ERROR);
+ if (NIL_P (hook) || NIL_P (property) || NIL_P (value))
+ API_WRONG_ARGS(API_RETURN_ERROR);
+
+ Check_Type (hook, T_STRING);
+ Check_Type (property, T_STRING);
+ Check_Type (value, T_STRING);
+
+ c_hook = StringValuePtr (hook);
+ c_property = StringValuePtr (property);
+ c_value = StringValuePtr (value);
+
+ weechat_hook_set (API_STR2PTR(c_hook),
+ c_property,
+ c_value);
+
+ API_RETURN_OK;
+}
+
+static VALUE
weechat_ruby_api_unhook (VALUE class, VALUE hook)
{
char *c_hook;
@@ -6066,6 +6091,7 @@ weechat_ruby_api_init (VALUE ruby_mWeechat)
API_DEF_FUNC(hook_info_hashtable, 6);
API_DEF_FUNC(hook_infolist, 6);
API_DEF_FUNC(hook_focus, 3);
+ API_DEF_FUNC(hook_set, 3);
API_DEF_FUNC(unhook, 1);
API_DEF_FUNC(unhook_all, 0);
API_DEF_FUNC(buffer_new, 5);
diff --git a/src/plugins/tcl/weechat-tcl-api.c b/src/plugins/tcl/weechat-tcl-api.c
index 0730cac48..bcaecb999 100644
--- a/src/plugins/tcl/weechat-tcl-api.c
+++ b/src/plugins/tcl/weechat-tcl-api.c
@@ -3505,6 +3505,27 @@ weechat_tcl_api_hook_focus (ClientData clientData, Tcl_Interp *interp,
}
static int
+weechat_tcl_api_hook_set (ClientData clientData, Tcl_Interp *interp,
+ int objc, Tcl_Obj *CONST objv[])
+{
+ Tcl_Obj *objp;
+ char *hook, *property, *value;
+ int i;
+
+ API_FUNC(1, "hook_set", API_RETURN_ERROR);
+ if (objc < 4)
+ API_WRONG_ARGS(API_RETURN_ERROR);
+
+ hook = Tcl_GetStringFromObj (objv[1], &i);
+ property = Tcl_GetStringFromObj (objv[2], &i);
+ value = Tcl_GetStringFromObj (objv[3], &i);
+
+ weechat_hook_set (API_STR2PTR(hook), property, value);
+
+ API_RETURN_OK;
+}
+
+static int
weechat_tcl_api_unhook (ClientData clientData, Tcl_Interp *interp,
int objc, Tcl_Obj *CONST objv[])
{
@@ -5809,6 +5830,7 @@ void weechat_tcl_api_init (Tcl_Interp *interp)
API_DEF_FUNC(hook_info_hashtable);
API_DEF_FUNC(hook_infolist);
API_DEF_FUNC(hook_focus);
+ API_DEF_FUNC(hook_set);
API_DEF_FUNC(unhook);
API_DEF_FUNC(unhook_all);
API_DEF_FUNC(buffer_new);