diff options
author | Sebastien Helleu <flashcode@flashtux.org> | 2007-10-31 17:10:38 +0100 |
---|---|---|
committer | Sebastien Helleu <flashcode@flashtux.org> | 2007-10-31 17:10:38 +0100 |
commit | a664e70488d3b76c7ade51cb2e0ddc20024f2913 (patch) | |
tree | f95dc6cd1720f9bbdae67c4d57cc759b83b14dd7 /src/core | |
parent | 985db1a103087f7ec6b06f12b3dcc008aea42d51 (diff) | |
download | weechat-a664e70488d3b76c7ade51cb2e0ddc20024f2913.zip |
Added hook functions
Diffstat (limited to 'src/core')
-rw-r--r-- | src/core/wee-hook.c | 616 | ||||
-rw-r--r-- | src/core/wee-hook.h | 140 |
2 files changed, 756 insertions, 0 deletions
diff --git a/src/core/wee-hook.c b/src/core/wee-hook.c new file mode 100644 index 000000000..bdf228ed8 --- /dev/null +++ b/src/core/wee-hook.c @@ -0,0 +1,616 @@ +/* + * Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +/* wee-hook.c: WeeChat hooks management */ + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <time.h> + +#include "weechat.h" +#include "wee-hook.h" +#include "wee-command.h" +#include "wee-log.h" +#include "wee-string.h" +#include "wee-util.h" +#include "../plugins/plugin.h" + + +struct t_hook *weechat_hooks = NULL; +struct t_hook *last_weechat_hook = NULL; + + +/* + * hook_add_to_list: add a hook to list + */ + +void +hook_add_to_list (struct t_hook *new_hook) +{ + new_hook->prev_hook = last_weechat_hook; + if (weechat_hooks) + last_weechat_hook->next_hook = new_hook; + else + weechat_hooks = new_hook; + last_weechat_hook = new_hook; + new_hook->next_hook = NULL; +} + +/* + * hook_init: init a new hook with default values + */ + +void +hook_init (struct t_hook *hook, void *plugin, int type, void *callback_data) +{ + hook->plugin = plugin; + hook->type = type; + hook->callback_data = callback_data; + + hook->hook_data = NULL; + + hook->running = 0; +} + +/* + * hook_valid_for_plugin: check if a hook pointer exists for a plugin + * return 1 if hook exists for plugin + * 0 if hook is not found for plugin + */ + +int +hook_valid_for_plugin (void *plugin, struct t_hook *hook) +{ + struct t_hook *ptr_hook; + + for (ptr_hook = weechat_hooks; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if ((ptr_hook == hook) + && (ptr_hook->plugin == (struct t_weechat_plugin *)plugin)) + return 1; + } + + /* hook not found */ + return 0; +} + +/* + * hook_command: hook a command + */ + +struct t_hook * +hook_command (void *plugin, char *command, char *description, + char *args, char *args_description, char *completion, + t_hook_callback_command *callback, + void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_command *new_hook_command; + + new_hook = (struct t_hook *)malloc (sizeof (struct t_hook)); + if (!new_hook) + return NULL; + new_hook_command = (struct t_hook_command *)malloc (sizeof (struct t_hook_command)); + if (!new_hook_command) + { + free (new_hook); + return NULL; + } + + hook_init (new_hook, plugin, HOOK_TYPE_COMMAND, callback_data); + + new_hook->hook_data = new_hook_command; + new_hook_command->callback = callback; + new_hook_command->command = (command) ? + strdup (command) : strdup (""); + new_hook_command->description = (description) ? + strdup (description) : strdup (""); + new_hook_command->args = (args) ? + strdup (args) : strdup (""); + new_hook_command->args_description = (args_description) ? + strdup (args_description) : strdup (""); + new_hook_command->completion = (completion) ? + strdup (completion) : strdup (""); + + hook_add_to_list (new_hook); + + if (command && command[0]) + command_index_add (command); + + return new_hook; +} + +/* + * hook_command_exec: execute command hook + * return: 0 if command executed and failed + * 1 if command executed successfully + * -1 if command not found + */ + +int +hook_command_exec (void *plugin, char *command, char *args) +{ + struct t_hook *ptr_hook; + + for (ptr_hook = weechat_hooks; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if ((ptr_hook->type == HOOK_TYPE_COMMAND) + && (!plugin || (plugin == ptr_hook->plugin)) + && (string_strcasecmp (command, + HOOK_COMMAND(ptr_hook, command)) == 0)) + { + if ((int) (HOOK_COMMAND(ptr_hook, callback)) + (ptr_hook->callback_data, args) == PLUGIN_RC_FAILED) + return 0; + else + return 1; + } + } + + /* no hook found */ + return -1; +} + +/* + * hook_message: hook a message + */ + +struct t_hook * +hook_message (void *plugin, char *message, + t_hook_callback_message *callback, void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_message *new_hook_message; + + new_hook = (struct t_hook *)malloc (sizeof (struct t_hook)); + if (!new_hook) + return NULL; + new_hook_message = (struct t_hook_message *)malloc (sizeof (struct t_hook_message)); + if (!new_hook_message) + { + free (new_hook); + return NULL; + } + + hook_init (new_hook, plugin, HOOK_TYPE_MESSAGE, callback_data); + + new_hook->hook_data = new_hook_message; + new_hook_message->callback = callback; + new_hook_message->message = (message) ? strdup (message) : strdup (""); + + hook_add_to_list (new_hook); + + return new_hook; +} + +/* + * hook_config: hook a config option + */ + +struct t_hook * +hook_config (void *plugin, char *type, char *option, + t_hook_callback_config *callback, void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_config *new_hook_config; + + new_hook = (struct t_hook *)malloc (sizeof (struct t_hook)); + if (!new_hook) + return NULL; + new_hook_config = (struct t_hook_config *)malloc (sizeof (struct t_hook_config)); + if (!new_hook_config) + { + free (new_hook); + return NULL; + } + + hook_init (new_hook, plugin, HOOK_TYPE_CONFIG, callback_data); + + new_hook->hook_data = new_hook_config; + new_hook_config->callback = callback; + new_hook_config->type = (type) ? strdup (type) : strdup (""); + new_hook_config->option = (option) ? strdup (option) : strdup (""); + + hook_add_to_list (new_hook); + + return new_hook; +} + +/* + * hook_config_exec: execute config hooks + */ + +void +hook_config_exec (char *type, char *option, char *value) +{ + struct t_hook *ptr_hook, *next_hook; + + ptr_hook = weechat_hooks; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if ((ptr_hook->type == HOOK_TYPE_CONFIG) + && (!HOOK_CONFIG(ptr_hook, type) + || (string_strcasecmp (HOOK_CONFIG(ptr_hook, type), + type) == 0)) + && (!HOOK_CONFIG(ptr_hook, option) + || (string_strcasecmp (HOOK_CONFIG(ptr_hook, option), + option) == 0))) + { + (void) (HOOK_CONFIG(ptr_hook, callback)) + (ptr_hook->callback_data, type, option, value); + } + + ptr_hook = next_hook; + } +} + +/* + * hook_timer: hook a timer + */ + +struct t_hook * +hook_timer (void *plugin, long interval, int max_calls, + t_hook_callback_timer *callback, void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_timer *new_hook_timer; + + new_hook = (struct t_hook *)malloc (sizeof (struct t_hook)); + if (!new_hook) + return NULL; + new_hook_timer = (struct t_hook_timer *)malloc (sizeof (struct t_hook_timer)); + if (!new_hook_timer) + { + free (new_hook); + return NULL; + } + + hook_init (new_hook, plugin, HOOK_TYPE_TIMER, callback_data); + + new_hook->hook_data = new_hook_timer; + new_hook_timer->callback = callback; + new_hook_timer->interval = interval; + new_hook_timer->remaining_calls = max_calls; + gettimeofday (&new_hook_timer->last_exec, NULL); + + hook_add_to_list (new_hook); + + return new_hook; +} + +/* + * hook_timer_exec: execute timer hooks + */ + +void +hook_timer_exec (struct timeval *tv_time) +{ + struct t_hook *ptr_hook, *next_hook; + long time_diff; + + ptr_hook = weechat_hooks; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if (ptr_hook->type == HOOK_TYPE_TIMER) + { + time_diff = util_get_timeval_diff (&HOOK_TIMER(ptr_hook, last_exec), + tv_time); + if (time_diff >= HOOK_TIMER(ptr_hook, interval)) + { + (void) (HOOK_TIMER(ptr_hook, callback)) + (ptr_hook->callback_data); + HOOK_TIMER(ptr_hook, last_exec).tv_sec = tv_time->tv_sec; + HOOK_TIMER(ptr_hook, last_exec).tv_usec = tv_time->tv_usec; + if (HOOK_TIMER(ptr_hook, remaining_calls) > 0) + { + HOOK_TIMER(ptr_hook, remaining_calls)--; + if (HOOK_TIMER(ptr_hook, remaining_calls) == 0) + unhook (ptr_hook); + } + } + } + + ptr_hook = next_hook; + } +} + +/* + * hook_search_fd: search fd hook in list + */ + +struct t_hook * +hook_search_fd (int fd) +{ + struct t_hook *ptr_hook; + + for (ptr_hook = weechat_hooks; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if ((ptr_hook->type == HOOK_TYPE_FD) + && (HOOK_FD(ptr_hook, fd) == fd)) + return ptr_hook; + } + + /* fd hook not found */ + return NULL; +} + +/* + * hook_fd: hook a fd event + */ + +struct t_hook * +hook_fd (void *plugin, int fd, int flags, + t_hook_callback_fd *callback, void *callback_data) +{ + struct t_hook *new_hook; + struct t_hook_fd *new_hook_fd; + + if (hook_search_fd (fd)) + return NULL; + + new_hook = (struct t_hook *)malloc (sizeof (struct t_hook)); + if (!new_hook) + return NULL; + new_hook_fd = (struct t_hook_fd *)malloc (sizeof (struct t_hook_fd)); + if (!new_hook_fd) + { + free (new_hook); + return NULL; + } + + hook_init (new_hook, plugin, HOOK_TYPE_FD, callback_data); + + new_hook->hook_data = new_hook_fd; + new_hook_fd->callback = callback; + new_hook_fd->fd = fd; + new_hook_fd->flags = flags; + + hook_add_to_list (new_hook); + + return new_hook; +} + +/* + * hook_fd_set: fill sets according to hd hooked + */ + +void +hook_fd_set (fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) +{ + struct t_hook *ptr_hook; + + FD_ZERO (read_fds); + FD_ZERO (write_fds); + FD_ZERO (except_fds); + + for (ptr_hook = weechat_hooks; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + if (ptr_hook->type == HOOK_TYPE_FD) + { + if (HOOK_FD(ptr_hook, flags) & HOOK_FD_FLAG_READ) + FD_SET (HOOK_FD(ptr_hook, fd), read_fds); + if (HOOK_FD(ptr_hook, flags) & HOOK_FD_FLAG_WRITE) + FD_SET (HOOK_FD(ptr_hook, fd), write_fds); + if (HOOK_FD(ptr_hook, flags) & HOOK_FD_FLAG_EXCEPTION) + FD_SET (HOOK_FD(ptr_hook, fd), except_fds); + } + } +} + +/* + * hook_fd_exec: execute fd callbacks with sets + */ + +void +hook_fd_exec (fd_set *read_fds, fd_set *write_fds, fd_set *except_fds) +{ + struct t_hook *ptr_hook, *next_hook; + + ptr_hook = weechat_hooks; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if ((ptr_hook->type == HOOK_TYPE_FD) + && (((HOOK_FD(ptr_hook, flags)& HOOK_FD_FLAG_READ) + && (FD_ISSET(HOOK_FD(ptr_hook, fd), read_fds))) + || ((HOOK_FD(ptr_hook, flags) & HOOK_FD_FLAG_WRITE) + && (FD_ISSET(HOOK_FD(ptr_hook, fd), write_fds))) + || ((HOOK_FD(ptr_hook, flags) & HOOK_FD_FLAG_EXCEPTION) + && (FD_ISSET(HOOK_FD(ptr_hook, fd), except_fds))))) + (HOOK_FD(ptr_hook, callback)) (ptr_hook->callback_data); + + ptr_hook = next_hook; + } +} + +/* + * unhook: unhook something + */ + +void +unhook (struct t_hook *hook) +{ + struct t_hook *new_hooks; + + /* free data */ + if (hook->hook_data) + { + switch (hook->type) + { + case HOOK_TYPE_COMMAND: + if (HOOK_COMMAND(hook, command) + && HOOK_COMMAND(hook, command)[0]) + command_index_remove (HOOK_COMMAND(hook, command)); + if (HOOK_COMMAND(hook, command)) + free (HOOK_COMMAND(hook, command)); + if (HOOK_COMMAND(hook, description)) + free (HOOK_COMMAND(hook, description)); + if (HOOK_COMMAND(hook, args)) + free (HOOK_COMMAND(hook, args)); + if (HOOK_COMMAND(hook, args_description)) + 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_MESSAGE: + if (HOOK_MESSAGE(hook, message)) + free (HOOK_MESSAGE(hook, message)); + free ((struct t_hook_message *)hook->hook_data); + break; + case HOOK_TYPE_CONFIG: + if (HOOK_CONFIG(hook, type)) + free (HOOK_CONFIG(hook, type)); + if (HOOK_CONFIG(hook, option)) + free (HOOK_CONFIG(hook, option)); + free ((struct t_hook_config *)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_KEYBOARD: + break; + } + } + + /* remove hook from list */ + if (last_weechat_hook == hook) + last_weechat_hook = hook->prev_hook; + if (hook->prev_hook) + { + hook->prev_hook->next_hook = hook->next_hook; + new_hooks = weechat_hooks; + } + else + new_hooks = hook->next_hook; + + if (hook->next_hook) + hook->next_hook->prev_hook = hook->prev_hook; + + free (hook); + weechat_hooks = new_hooks; +} + +/* + * unhook_all_plugin: unhook all for a plugin + */ + +void +unhook_all_plugin (void *plugin) +{ + struct t_hook *ptr_hook, *next_hook; + + ptr_hook = weechat_hooks; + while (ptr_hook) + { + next_hook = ptr_hook->next_hook; + + if (ptr_hook->plugin == plugin) + unhook (ptr_hook); + + ptr_hook = next_hook; + } +} + +/* + * unhook_all: unhook all + */ + +void +unhook_all () +{ + while (weechat_hooks) + { + unhook (weechat_hooks); + } +} + +/* + * hook_print_log: print hooks in log (usually for crash dump) + */ + +void +hook_print_log () +{ + struct t_hook *ptr_hook; + + for (ptr_hook = weechat_hooks; ptr_hook; + ptr_hook = ptr_hook->next_hook) + { + weechat_log_printf ("\n"); + weechat_log_printf ("[hook (addr:0x%X)]\n", ptr_hook); + weechat_log_printf (" type . . . . . . . . . : %d\n", ptr_hook->type); + weechat_log_printf (" callback_data. . . . . : 0x%X\n", ptr_hook->callback_data); + switch (ptr_hook->type) + { + case HOOK_TYPE_COMMAND: + weechat_log_printf (" command data:\n"); + weechat_log_printf (" callback . . . . . . : 0x%X\n", HOOK_COMMAND(ptr_hook, callback)); + weechat_log_printf (" command. . . . . . . : '%s'\n", HOOK_COMMAND(ptr_hook, command)); + weechat_log_printf (" command_desc . . . . : '%s'\n", HOOK_COMMAND(ptr_hook, description)); + weechat_log_printf (" command_args . . . . : '%s'\n", HOOK_COMMAND(ptr_hook, args)); + weechat_log_printf (" command_args_desc. . : '%s'\n", HOOK_COMMAND(ptr_hook, args_description)); + weechat_log_printf (" command_completion . : '%s'\n", HOOK_COMMAND(ptr_hook, completion)); + break; + case HOOK_TYPE_MESSAGE: + weechat_log_printf (" message data:\n"); + weechat_log_printf (" message. . . . . . . : '%s'\n", HOOK_MESSAGE(ptr_hook, message)); + break; + case HOOK_TYPE_CONFIG: + weechat_log_printf (" config data:\n"); + weechat_log_printf (" type . . . . . . . . : '%s'\n", HOOK_CONFIG(ptr_hook, type)); + weechat_log_printf (" option . . . . . . . : '%s'\n", HOOK_CONFIG(ptr_hook, option)); + break; + case HOOK_TYPE_TIMER: + weechat_log_printf (" timer data:\n"); + weechat_log_printf (" interval . . . . . . : %ld\n", HOOK_TIMER(ptr_hook, interval)); + weechat_log_printf (" last_exec.tv_sec . . : %ld\n", HOOK_TIMER(ptr_hook, last_exec.tv_sec)); + weechat_log_printf (" last_exec.tv_usec. . : %ld\n", HOOK_TIMER(ptr_hook, last_exec.tv_usec)); + break; + case HOOK_TYPE_FD: + weechat_log_printf (" fd data:\n"); + weechat_log_printf (" fd . . . . . . . . . : %ld\n", HOOK_FD(ptr_hook, fd)); + weechat_log_printf (" flags. . . . . . . . : %ld\n", HOOK_FD(ptr_hook, flags)); + break; + case HOOK_TYPE_KEYBOARD: + weechat_log_printf (" keyboard data:\n"); + break; + } + weechat_log_printf (" running. . . . . . . . : %d\n", ptr_hook->running); + weechat_log_printf (" prev_hook. . . . . . . : 0x%X\n", ptr_hook->prev_hook); + weechat_log_printf (" next_hook. . . . . . . : 0x%X\n", ptr_hook->next_hook); + } +} diff --git a/src/core/wee-hook.h b/src/core/wee-hook.h new file mode 100644 index 000000000..a080e9fae --- /dev/null +++ b/src/core/wee-hook.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2003-2007 by FlashCode <flashcode@flashtux.org> + * See README for License detail, AUTHORS for developers list. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#ifndef __WEECHAT_HOOK_H +#define __WEECHAT_HOOK_H 1 + +/* hook types */ + +enum t_hook_type +{ + HOOK_TYPE_COMMAND = 0, /* new command */ + HOOK_TYPE_MESSAGE, /* message */ + HOOK_TYPE_CONFIG, /* config option */ + HOOK_TYPE_TIMER, /* timer (called each N milliseconds)*/ + /* (precision is about 20 msec) */ + HOOK_TYPE_FD, /* socket of file descriptor */ + HOOK_TYPE_KEYBOARD, /* keyboard handler */ +}; + +#define HOOK_FD_FLAG_READ 1 +#define HOOK_FD_FLAG_WRITE 2 +#define HOOK_FD_FLAG_EXCEPTION 4 + +#define HOOK_COMMAND(hook, var) (((struct t_hook_command *)hook->hook_data)->var) +#define HOOK_MESSAGE(hook, var) (((struct t_hook_message *)hook->hook_data)->var) +#define HOOK_CONFIG(hook, var) (((struct t_hook_config *)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) + +typedef int (t_hook_callback) (void *); + +struct t_hook +{ + /* data common to all hooks */ + struct t_weechat_plugin *plugin; /* plugin which created this hook */ + /* (NULL for hook created by WeeChat)*/ + enum t_hook_type type; /* hook type */ + void *callback_data; /* data sent to callback */ + + /* hook data (depends on hook type) */ + void *hook_data; /* hook specific data */ + + int running; /* 1 if hook is currently running */ + struct t_hook *prev_hook; /* pointer to previous hook */ + struct t_hook *next_hook; /* pointer to next hook */ +}; + +typedef int (t_hook_callback_command)(void *, char *); + +struct t_hook_command +{ + t_hook_callback_command *callback; /* command callback */ + char *command; /* name of command (without '/') */ + char *description; /* (for /help) short cmd description */ + char *args; /* (for /help) command arguments */ + char *args_description; /* (for /help) args long description */ + char *completion; /* template for completion */ +}; + +typedef int (t_hook_callback_message)(void *, char *); + +struct t_hook_message +{ + t_hook_callback_message *callback; /* message callback */ + char *message; /* message for hook */ +}; + +typedef int (t_hook_callback_config)(void *, char *, char *, char *); + +struct t_hook_config +{ + t_hook_callback_config *callback; /* message callback */ + char *type; /* "weechat" or "plugin" */ + char *option; /* config option for hook */ + /* (NULL = hook for all options) */ +}; + +typedef int (t_hook_callback_timer)(void *); + +struct t_hook_timer +{ + t_hook_callback_timer *callback; /* timer callback */ + long interval; /* timer interval (milliseconds) */ + int remaining_calls; /* calls remaining (0 = unlimited) */ + struct timeval last_exec; /* last time hook was executed */ +}; + +typedef int (t_hook_callback_fd)(void *); + +struct t_hook_fd +{ + t_hook_callback_fd *callback; /* fd callback */ + int fd; /* socket or file descriptor */ + int flags; /* fd flags (read,write,..) */ +}; + +/* hook variables */ + +extern struct t_hook *weechat_hooks; +extern struct t_hook *last_weechat_hook; + +/* hook functions */ + +extern int hook_valid_for_plugin (void *, struct t_hook *); +extern struct t_hook *hook_command (void *, char *, char *, char *, char *, + char *, t_hook_callback_command *, void *); +extern int hook_command_exec (void *, char *, char *); +extern struct t_hook *hook_message (void *, char *, t_hook_callback_message *, + void *); +extern struct t_hook *hook_config (void *, char *, char *, + t_hook_callback_config *, void *); +extern void hook_config_exec (char *, char *, char *); +extern struct t_hook *hook_timer (void *, long, int, t_hook_callback_timer *, + void *); +extern void hook_timer_exec (struct timeval *); +extern struct t_hook *hook_fd (void *, int, int, t_hook_callback_fd *,void *); +extern void hook_fd_set (fd_set *, fd_set *, fd_set *); +extern void hook_fd_exec (fd_set *, fd_set *, fd_set *); +extern void unhook (struct t_hook *); +extern void unhook_all_plugin (void *); +extern void unhook_all (); +extern void hook_print_log (); + +#endif /* wee-hook.h */ |