exec: add exec plugin
This commit is contained in:
parent
4f48c7a566
commit
97254780d6
@ -71,6 +71,7 @@ OPTION(ENABLE_ALIAS "Enable Alias plugin" ON)
|
||||
OPTION(ENABLE_ASPELL "Enable Aspell plugin" ON)
|
||||
OPTION(ENABLE_ENCHANT "Enable Enchant lib for Aspell plugin" OFF)
|
||||
OPTION(ENABLE_CHARSET "Enable Charset plugin" ON)
|
||||
OPTION(ENABLE_EXEC "Enable Exec plugin" ON)
|
||||
OPTION(ENABLE_FIFO "Enable FIFO plugin" ON)
|
||||
OPTION(ENABLE_IRC "Enable IRC plugin" ON)
|
||||
OPTION(ENABLE_LOGGER "Enable Logger plugin" ON)
|
||||
|
19
configure.ac
19
configure.ac
@ -104,6 +104,7 @@ AH_VERBATIM([HAVE_ASPELL_VERSION_STRING], [#undef HAVE_ASPELL_VERSION_STRING])
|
||||
AH_VERBATIM([PLUGIN_ALIAS], [#undef PLUGIN_ALIAS])
|
||||
AH_VERBATIM([PLUGIN_ASPELL], [#undef PLUGIN_ASPELL])
|
||||
AH_VERBATIM([PLUGIN_CHARSET], [#undef PLUGIN_CHARSET])
|
||||
AH_VERBATIM([PLUGIN_EXEC], [#undef PLUGIN_EXEC])
|
||||
AH_VERBATIM([PLUGIN_FIFO], [#undef PLUGIN_FIFO])
|
||||
AH_VERBATIM([PLUGIN_IRC], [#undef PLUGIN_IRC])
|
||||
AH_VERBATIM([PLUGIN_LOGGER], [#undef PLUGIN_LOGGER])
|
||||
@ -131,6 +132,7 @@ AC_ARG_ENABLE(alias, [ --disable-alias turn off Alias plugin (de
|
||||
AC_ARG_ENABLE(aspell, [ --disable-aspell turn off Aspell plugin (default=compiled)],enable_aspell=$enableval,enable_aspell=yes)
|
||||
AC_ARG_ENABLE(enchant, [ --enable-enchant turn on Enchant lib for Aspell plugin (default=off)],enable_enchant=$enableval,enable_enchant=no)
|
||||
AC_ARG_ENABLE(charset, [ --disable-charset turn off Charset plugin (default=compiled if found)],enable_charset=$enableval,enable_charset=yes)
|
||||
AC_ARG_ENABLE(exec, [ --disable-exec turn off Exec plugin (default=compiled)],enable_exec=$enableval,enable_exec=yes)
|
||||
AC_ARG_ENABLE(fifo, [ --disable-fifo turn off Fifo plugin (default=compiled)],enable_fifo=$enableval,enable_fifo=yes)
|
||||
AC_ARG_ENABLE(irc, [ --disable-irc turn off IRC plugin (default=compiled)],enable_irc=$enableval,enable_irc=yes)
|
||||
AC_ARG_ENABLE(logger, [ --disable-logger turn off Logger plugin (default=compiled)],enable_logger=$enableval,enable_logger=yes)
|
||||
@ -358,6 +360,18 @@ else
|
||||
not_asked="$not_asked charset"
|
||||
fi
|
||||
|
||||
# ---------------------------------- exec --------------------------------------
|
||||
|
||||
if test "x$enable_exec" = "xyes" ; then
|
||||
EXEC_CFLAGS=""
|
||||
EXEC_LFLAGS=""
|
||||
AC_SUBST(EXEC_CFLAGS)
|
||||
AC_SUBST(EXEC_LFLAGS)
|
||||
AC_DEFINE(PLUGIN_EXEC)
|
||||
else
|
||||
not_asked="$not_asked exec"
|
||||
fi
|
||||
|
||||
# ---------------------------------- fifo --------------------------------------
|
||||
|
||||
if test "x$enable_fifo" = "xyes" ; then
|
||||
@ -1117,6 +1131,7 @@ AM_CONDITIONAL(GUI_NCURSES, test "$enable_ncurses" = "yes")
|
||||
AM_CONDITIONAL(PLUGIN_ALIAS, test "$enable_alias" = "yes")
|
||||
AM_CONDITIONAL(PLUGIN_ASPELL, test "$enable_aspell" = "yes")
|
||||
AM_CONDITIONAL(PLUGIN_CHARSET, test "$enable_charset" = "yes")
|
||||
AM_CONDITIONAL(PLUGIN_EXEC, test "$enable_exec" = "yes")
|
||||
AM_CONDITIONAL(PLUGIN_FIFO, test "$enable_fifo" = "yes")
|
||||
AM_CONDITIONAL(PLUGIN_IRC, test "$enable_irc" = "yes")
|
||||
AM_CONDITIONAL(PLUGIN_LOGGER, test "$enable_logger" = "yes")
|
||||
@ -1149,6 +1164,7 @@ AC_OUTPUT([Makefile
|
||||
src/plugins/alias/Makefile
|
||||
src/plugins/aspell/Makefile
|
||||
src/plugins/charset/Makefile
|
||||
src/plugins/exec/Makefile
|
||||
src/plugins/fifo/Makefile
|
||||
src/plugins/irc/Makefile
|
||||
src/plugins/logger/Makefile
|
||||
@ -1192,6 +1208,9 @@ fi
|
||||
if test "x$enable_charset" = "xyes"; then
|
||||
listplugins="$listplugins charset"
|
||||
fi
|
||||
if test "x$enable_exec" = "xyes"; then
|
||||
listplugins="$listplugins exec"
|
||||
fi
|
||||
if test "x$enable_fifo" = "xyes"; then
|
||||
listplugins="$listplugins fifo"
|
||||
fi
|
||||
|
1
debian/weechat-plugins.install
vendored
1
debian/weechat-plugins.install
vendored
@ -1,4 +1,5 @@
|
||||
usr/lib/weechat/plugins/aspell.so
|
||||
usr/lib/weechat/plugins/exec.so
|
||||
usr/lib/weechat/plugins/fifo.so
|
||||
usr/lib/weechat/plugins/guile.so
|
||||
usr/lib/weechat/plugins/perl.so
|
||||
|
@ -88,6 +88,7 @@ plugin_list = {
|
||||
'alias': '',
|
||||
'aspell': 'o',
|
||||
'charset': 'o',
|
||||
'exec': 'o',
|
||||
'fifo': 'o',
|
||||
'irc': 'co',
|
||||
'logger': 'o',
|
||||
|
@ -113,6 +113,14 @@
|
||||
./src/plugins/aspell/weechat-aspell-speller.c
|
||||
./src/plugins/aspell/weechat-aspell-speller.h
|
||||
./src/plugins/charset/charset.c
|
||||
./src/plugins/exec/exec.c
|
||||
./src/plugins/exec/exec-command.c
|
||||
./src/plugins/exec/exec-command.h
|
||||
./src/plugins/exec/exec-completion.c
|
||||
./src/plugins/exec/exec-completion.h
|
||||
./src/plugins/exec/exec-config.c
|
||||
./src/plugins/exec/exec-config.h
|
||||
./src/plugins/exec/exec.h
|
||||
./src/plugins/fifo/fifo.c
|
||||
./src/plugins/fifo/fifo.h
|
||||
./src/plugins/fifo/fifo-info.c
|
||||
|
@ -114,6 +114,14 @@ SET(WEECHAT_SOURCES
|
||||
./src/plugins/aspell/weechat-aspell-speller.c
|
||||
./src/plugins/aspell/weechat-aspell-speller.h
|
||||
./src/plugins/charset/charset.c
|
||||
./src/plugins/exec/exec.c
|
||||
./src/plugins/exec/exec-command.c
|
||||
./src/plugins/exec/exec-command.h
|
||||
./src/plugins/exec/exec-completion.c
|
||||
./src/plugins/exec/exec-completion.h
|
||||
./src/plugins/exec/exec-config.c
|
||||
./src/plugins/exec/exec-config.h
|
||||
./src/plugins/exec/exec.h
|
||||
./src/plugins/fifo/fifo.c
|
||||
./src/plugins/fifo/fifo.h
|
||||
./src/plugins/fifo/fifo-info.c
|
||||
|
@ -72,6 +72,10 @@ IF(ENABLE_CHARSET)
|
||||
ENDIF(ICONV_FOUND)
|
||||
ENDIF(ENABLE_CHARSET)
|
||||
|
||||
IF(ENABLE_EXEC)
|
||||
ADD_SUBDIRECTORY( exec )
|
||||
ENDIF(ENABLE_EXEC)
|
||||
|
||||
IF(ENABLE_FIFO)
|
||||
ADD_SUBDIRECTORY( fifo )
|
||||
ENDIF(ENABLE_FIFO)
|
||||
|
@ -51,6 +51,10 @@ if PLUGIN_CHARSET
|
||||
charset_dir = charset
|
||||
endif
|
||||
|
||||
if PLUGIN_EXEC
|
||||
exec_dir = exec
|
||||
endif
|
||||
|
||||
if PLUGIN_FIFO
|
||||
fifo_dir = fifo
|
||||
endif
|
||||
@ -103,10 +107,10 @@ if PLUGIN_XFER
|
||||
xfer_dir = xfer
|
||||
endif
|
||||
|
||||
SUBDIRS = . $(alias_dir) $(aspell_dir) $(charset_dir) $(fifo_dir) $(irc_dir) \
|
||||
$(logger_dir) $(relay_dir) $(script_dir) $(perl_dir) $(python_dir) \
|
||||
$(ruby_dir) $(lua_dir) $(tcl_dir) $(guile_dir) $(trigger_dir) \
|
||||
$(xfer_dir)
|
||||
SUBDIRS = . $(alias_dir) $(aspell_dir) $(charset_dir) $(exec_dir) $(fifo_dir) \
|
||||
$(irc_dir) $(logger_dir) $(relay_dir) $(script_dir) $(perl_dir) \
|
||||
$(python_dir) $(ruby_dir) $(lua_dir) $(tcl_dir) $(guile_dir) \
|
||||
$(trigger_dir) $(xfer_dir)
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt
|
||||
|
||||
|
29
src/plugins/exec/CMakeLists.txt
Normal file
29
src/plugins/exec/CMakeLists.txt
Normal file
@ -0,0 +1,29 @@
|
||||
#
|
||||
# Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
#
|
||||
# This file is part of WeeChat, the extensible chat client.
|
||||
#
|
||||
# WeeChat 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.
|
||||
#
|
||||
# WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
ADD_LIBRARY(exec MODULE
|
||||
exec.c exec.h
|
||||
exec-command.c exec-command.h
|
||||
exec-completion.c exec-completion.h
|
||||
exec-config.c exec-config.h)
|
||||
SET_TARGET_PROPERTIES(exec PROPERTIES PREFIX "")
|
||||
|
||||
TARGET_LINK_LIBRARIES(exec)
|
||||
|
||||
INSTALL(TARGETS exec LIBRARY DESTINATION ${LIBDIR}/plugins)
|
38
src/plugins/exec/Makefile.am
Normal file
38
src/plugins/exec/Makefile.am
Normal file
@ -0,0 +1,38 @@
|
||||
#
|
||||
# Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
#
|
||||
# This file is part of WeeChat, the extensible chat client.
|
||||
#
|
||||
# WeeChat 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.
|
||||
#
|
||||
# WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
AM_CPPFLAGS = -DLOCALEDIR=\"$(datadir)/locale\" $(EXEC_CFLAGS)
|
||||
|
||||
libdir = ${weechat_libdir}/plugins
|
||||
|
||||
lib_LTLIBRARIES = exec.la
|
||||
|
||||
exec_la_SOURCES = exec.c \
|
||||
exec.h \
|
||||
exec-command.c \
|
||||
exec-command.h \
|
||||
exec-completion.c \
|
||||
exec-completion.h \
|
||||
exec-config.c \
|
||||
exec-config.h
|
||||
|
||||
exec_la_LDFLAGS = -module -no-undefined
|
||||
exec_la_LIBADD = $(EXEC_LFLAGS)
|
||||
|
||||
EXTRA_DIST = CMakeLists.txt
|
409
src/plugins/exec/exec-command.c
Normal file
409
src/plugins/exec/exec-command.c
Normal file
@ -0,0 +1,409 @@
|
||||
/*
|
||||
* exec-command.c - exec command
|
||||
*
|
||||
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat 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.
|
||||
*
|
||||
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "exec.h"
|
||||
#include "exec-config.h"
|
||||
|
||||
|
||||
/*
|
||||
* Displays a list of executed commands.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_command_list ()
|
||||
{
|
||||
struct t_exec_cmd *ptr_exec_cmd;
|
||||
char str_elapsed[32], str_time1[256], str_time2[256];
|
||||
time_t elapsed_time;
|
||||
struct tm *local_time;
|
||||
|
||||
weechat_printf (NULL, "");
|
||||
|
||||
if (!exec_cmds)
|
||||
{
|
||||
weechat_printf (NULL, _("No command is running"));
|
||||
return;
|
||||
}
|
||||
|
||||
weechat_printf (NULL, _("Commands:"));
|
||||
|
||||
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
|
||||
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
|
||||
{
|
||||
elapsed_time = (ptr_exec_cmd->end_time == 0) ?
|
||||
time (NULL) - ptr_exec_cmd->start_time :
|
||||
ptr_exec_cmd->end_time - ptr_exec_cmd->start_time;
|
||||
if (elapsed_time >= 3600)
|
||||
{
|
||||
snprintf (str_elapsed, sizeof (str_elapsed),
|
||||
/* TRANSLATORS: format: hours + minutes, for example: 3h59 */
|
||||
_("%dh%02d"),
|
||||
elapsed_time / 3600,
|
||||
elapsed_time % 3600);
|
||||
}
|
||||
else if (elapsed_time >= 60)
|
||||
{
|
||||
snprintf (str_elapsed, sizeof (str_elapsed),
|
||||
/* TRANSLATORS: format: minutes + seconds, for example: 3m59 */
|
||||
_("%dm%02d"),
|
||||
elapsed_time / 60,
|
||||
elapsed_time % 60);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf (str_elapsed, sizeof (str_elapsed),
|
||||
/* TRANSLATORS: format: seconds, for example: 59s */
|
||||
_("%ds"),
|
||||
elapsed_time);
|
||||
}
|
||||
if (ptr_exec_cmd->end_time == 0)
|
||||
{
|
||||
/* running command */
|
||||
weechat_printf (NULL,
|
||||
/* TRANSLATORS: %s before "ago" is elapsed time, for example: "3m59" */
|
||||
_(" %s%s%s %d%s%s%s: %s\"%s%s%s\"%s (pid: %d, "
|
||||
"started %s ago)"),
|
||||
weechat_color (weechat_config_string (exec_config_color_flag_running)),
|
||||
">>",
|
||||
weechat_color ("reset"),
|
||||
ptr_exec_cmd->number,
|
||||
(ptr_exec_cmd->name) ? " (" : "",
|
||||
(ptr_exec_cmd->name) ? ptr_exec_cmd->name : "",
|
||||
(ptr_exec_cmd->name) ? ")" : "",
|
||||
weechat_color ("chat_delimiters"),
|
||||
weechat_color ("reset"),
|
||||
ptr_exec_cmd->command,
|
||||
weechat_color ("chat_delimiters"),
|
||||
weechat_color ("reset"),
|
||||
ptr_exec_cmd->pid,
|
||||
str_elapsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* process has ended */
|
||||
local_time = localtime (&ptr_exec_cmd->start_time);
|
||||
strftime (str_time1, sizeof (str_time1),
|
||||
"%Y-%m-%d %H:%M:%S", local_time);
|
||||
local_time = localtime (&ptr_exec_cmd->end_time);
|
||||
strftime (str_time2, sizeof (str_time2),
|
||||
"%Y-%m-%d %H:%M:%S", local_time);
|
||||
weechat_printf (NULL,
|
||||
" %s%s%s %d%s%s%s: %s\"%s%s%s\"%s (%s -> %s, %s)",
|
||||
weechat_color (weechat_config_string (exec_config_color_flag_finished)),
|
||||
"[]",
|
||||
weechat_color ("reset"),
|
||||
ptr_exec_cmd->number,
|
||||
(ptr_exec_cmd->name) ? " (" : "",
|
||||
(ptr_exec_cmd->name) ? ptr_exec_cmd->name : "",
|
||||
(ptr_exec_cmd->name) ? ")" : "",
|
||||
weechat_color ("chat_delimiters"),
|
||||
weechat_color ("reset"),
|
||||
ptr_exec_cmd->command,
|
||||
weechat_color ("chat_delimiters"),
|
||||
weechat_color ("reset"),
|
||||
str_time1,
|
||||
str_time2,
|
||||
str_elapsed);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Searches a running command by id, and displays an error if command is not
|
||||
* found or not running any more.
|
||||
*
|
||||
* Returns the command found, or NULL if not found or not running.
|
||||
*/
|
||||
|
||||
struct t_exec_cmd *
|
||||
exec_command_search_running_id (const char *id)
|
||||
{
|
||||
struct t_exec_cmd *ptr_exec_cmd;
|
||||
|
||||
ptr_exec_cmd = exec_search_by_id (id);
|
||||
if (!ptr_exec_cmd)
|
||||
{
|
||||
weechat_printf (NULL, _("%s%s: command id \"%s\" not found"),
|
||||
weechat_prefix ("error"), EXEC_PLUGIN_NAME, id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!ptr_exec_cmd->hook)
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
_("%s%s: command with id \"%s\" is not running any "
|
||||
"more"),
|
||||
weechat_prefix ("error"), EXEC_PLUGIN_NAME, id);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ptr_exec_cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for command "/exec": manage executed commands.
|
||||
*/
|
||||
|
||||
int
|
||||
exec_command_exec (void *data, struct t_gui_buffer *buffer, int argc,
|
||||
char **argv, char **argv_eol)
|
||||
{
|
||||
int i, command_index, use_shell, pipe_stdin, output_to_buffer, length;
|
||||
long timeout;
|
||||
char *error, *ptr_name, *text;
|
||||
struct t_exec_cmd *ptr_exec_cmd, *new_exec_cmd;
|
||||
struct t_hashtable *options_cmd;
|
||||
struct t_infolist *ptr_infolist;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
(void) buffer;
|
||||
|
||||
/* list running commands */
|
||||
if ((argc == 1)
|
||||
|| ((argc == 2) && (weechat_strcasecmp (argv[1], "-list") == 0)))
|
||||
{
|
||||
exec_command_list ();
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/* send text to a running process */
|
||||
if (weechat_strcasecmp (argv[1], "-in") == 0)
|
||||
{
|
||||
if (argc < 4)
|
||||
return WEECHAT_RC_ERROR;
|
||||
ptr_exec_cmd = exec_command_search_running_id (argv[2]);
|
||||
if (ptr_exec_cmd->hook)
|
||||
{
|
||||
length = strlen (argv_eol[3]) + 1 + 1;
|
||||
text = malloc (length);
|
||||
if (text)
|
||||
{
|
||||
snprintf (text, length, "%s\n", argv_eol[3]);
|
||||
weechat_hook_set (ptr_exec_cmd->hook, "stdin", text);
|
||||
free (text);
|
||||
}
|
||||
}
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/* send a signal to a running process */
|
||||
if (weechat_strcasecmp (argv[1], "-signal") == 0)
|
||||
{
|
||||
if (argc < 4)
|
||||
return WEECHAT_RC_ERROR;
|
||||
ptr_exec_cmd = exec_command_search_running_id (argv[2]);
|
||||
if (ptr_exec_cmd)
|
||||
{
|
||||
/* TODO: send signal to the process */
|
||||
}
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/* send a KILL signal to a running process */
|
||||
if (weechat_strcasecmp (argv[1], "-kill") == 0)
|
||||
{
|
||||
if (argc < 3)
|
||||
return WEECHAT_RC_ERROR;
|
||||
ptr_exec_cmd = exec_command_search_running_id (argv[2]);
|
||||
if (ptr_exec_cmd)
|
||||
{
|
||||
/* TODO: send KILL signal to the process */
|
||||
}
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/* send a KILL signal to all running processes */
|
||||
if (weechat_strcasecmp (argv[1], "-killall") == 0)
|
||||
{
|
||||
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
|
||||
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
|
||||
{
|
||||
/* TODO: send KILL signal to the process */
|
||||
}
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/* parse command options */
|
||||
command_index = -1;
|
||||
use_shell = 1;
|
||||
pipe_stdin = 0;
|
||||
timeout = 0;
|
||||
output_to_buffer = 0;
|
||||
ptr_name = NULL;
|
||||
|
||||
for (i = 1; i < argc; i++)
|
||||
{
|
||||
if (weechat_strcasecmp (argv[i], "-nosh") == 0)
|
||||
{
|
||||
use_shell = 0;
|
||||
}
|
||||
else if (weechat_strcasecmp (argv[i], "-stdin") == 0)
|
||||
{
|
||||
pipe_stdin = 1;
|
||||
}
|
||||
else if (weechat_strcasecmp (argv[i], "-o") == 0)
|
||||
{
|
||||
output_to_buffer = 1;
|
||||
}
|
||||
else if (weechat_strcasecmp (argv[i], "-timeout") == 0)
|
||||
{
|
||||
if (i + 1 >= argc)
|
||||
return WEECHAT_RC_ERROR;
|
||||
i++;
|
||||
error = NULL;
|
||||
timeout = strtol (argv[i], &error, 10);
|
||||
if (!error || error[0])
|
||||
return WEECHAT_RC_ERROR;
|
||||
}
|
||||
else if (weechat_strcasecmp (argv[i], "-name") == 0)
|
||||
{
|
||||
if (i + 1 >= argc)
|
||||
return WEECHAT_RC_ERROR;
|
||||
i++;
|
||||
ptr_name = argv[i];
|
||||
}
|
||||
else
|
||||
{
|
||||
command_index = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (command_index < 0)
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
new_exec_cmd = exec_add ();
|
||||
if (!new_exec_cmd)
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
/* create hashtable for weechat_hook_process_hashtable() */
|
||||
options_cmd = weechat_hashtable_new (32,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
WEECHAT_HASHTABLE_STRING,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!options_cmd)
|
||||
{
|
||||
exec_free (new_exec_cmd);
|
||||
return WEECHAT_RC_ERROR;
|
||||
}
|
||||
|
||||
/* run the command in background */
|
||||
if (use_shell)
|
||||
{
|
||||
/* command will be: sh -c "command arguments..." */
|
||||
weechat_hashtable_set (options_cmd, "arg1", "-c");
|
||||
weechat_hashtable_set (options_cmd, "arg2", argv_eol[command_index]);
|
||||
}
|
||||
if (weechat_exec_plugin->debug >= 1)
|
||||
{
|
||||
weechat_printf (NULL, "%s: executing command: \"%s%s%s\"",
|
||||
EXEC_PLUGIN_NAME,
|
||||
(use_shell) ? "" : "sh -c '",
|
||||
argv_eol[command_index],
|
||||
(use_shell) ? "" : "'");
|
||||
}
|
||||
if (pipe_stdin)
|
||||
weechat_hashtable_set (options_cmd, "stdin", "1");
|
||||
new_exec_cmd->hook = weechat_hook_process_hashtable (
|
||||
(use_shell) ? "sh" : argv_eol[command_index],
|
||||
options_cmd,
|
||||
(int)(timeout * 1000),
|
||||
&exec_process_cb,
|
||||
new_exec_cmd);
|
||||
|
||||
weechat_hashtable_free (options_cmd);
|
||||
|
||||
if (!new_exec_cmd->hook)
|
||||
{
|
||||
exec_free (new_exec_cmd);
|
||||
weechat_printf (NULL,
|
||||
_("%s%s: failed to run command \"%s\""),
|
||||
weechat_prefix ("error"), EXEC_PLUGIN_NAME,
|
||||
argv_eol[command_index]);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
new_exec_cmd->name = (ptr_name) ? strdup (ptr_name) : NULL;
|
||||
new_exec_cmd->command = strdup (argv_eol[command_index]);
|
||||
new_exec_cmd->buffer_plugin = strdup (weechat_buffer_get_string (buffer,
|
||||
"plugin"));
|
||||
new_exec_cmd->buffer_name = strdup (weechat_buffer_get_string (buffer,
|
||||
"name"));
|
||||
new_exec_cmd->output_to_buffer = output_to_buffer;
|
||||
ptr_infolist = weechat_infolist_get ("hook", new_exec_cmd->hook, NULL);
|
||||
if (ptr_infolist)
|
||||
{
|
||||
if (weechat_infolist_next (ptr_infolist))
|
||||
{
|
||||
new_exec_cmd->pid = weechat_infolist_integer (ptr_infolist,
|
||||
"child_pid");
|
||||
}
|
||||
weechat_infolist_free (ptr_infolist);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hooks exec commands.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_command_init ()
|
||||
{
|
||||
weechat_hook_command (
|
||||
"exec",
|
||||
N_("execute external commands"),
|
||||
N_("-list"
|
||||
" || [-nosh] [-stdin] [-o] [-timeout <timeout>] [-name <name>] <id>"
|
||||
" || -in <id> <text>"
|
||||
" || -signal <id> <signal>"
|
||||
" || -kill <id>"
|
||||
" || -killall"),
|
||||
N_(" -list: list commands\n"
|
||||
" -nosh: do not use the shell to execute the command (required if "
|
||||
"the command has some unsafe data, for example the content of a "
|
||||
"message from another user)\n"
|
||||
" -stdin: create a pipe for sending data to the process (with "
|
||||
"/exec -in)\n"
|
||||
" -o: send output of command to the current buffer\n"
|
||||
"-timeout: set a timeout for the command (in seconds)\n"
|
||||
" -name: set a name for the command (to name it later with /exec)\n"
|
||||
" command: the command to execute\n"
|
||||
" -in: send text on standard input of process\n"
|
||||
" -signal: send a signal (integer or name) to the process (example: "
|
||||
"kill, 9, ...)\n"
|
||||
" -kill: alias of \"-signal <id> 9\"\n"
|
||||
"-killall: kill all running processes\n"
|
||||
" number: command number"),
|
||||
"-list"
|
||||
" || -nosh|-stdin|-o|-timeout|-name|%*"
|
||||
" || -in|-signal|-kill %(exec_commands_ids)"
|
||||
" || -killall",
|
||||
&exec_command_exec, NULL);
|
||||
}
|
25
src/plugins/exec/exec-command.h
Normal file
25
src/plugins/exec/exec-command.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat 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.
|
||||
*
|
||||
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __WEECHAT_EXEC_COMMAND_H
|
||||
#define __WEECHAT_EXEC_COMMAND_H 1
|
||||
|
||||
extern void exec_command_init ();
|
||||
|
||||
#endif /* __WEECHAT_EXEC_COMMAND_H */
|
73
src/plugins/exec/exec-completion.c
Normal file
73
src/plugins/exec/exec-completion.c
Normal file
@ -0,0 +1,73 @@
|
||||
/*
|
||||
* exec-completion.c - completion for exec commands
|
||||
*
|
||||
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat 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.
|
||||
*
|
||||
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "exec.h"
|
||||
|
||||
|
||||
/*
|
||||
* Adds executed commands ids to completion list.
|
||||
*/
|
||||
|
||||
int
|
||||
exec_completion_commands_ids_cb (void *data, const char *completion_item,
|
||||
struct t_gui_buffer *buffer,
|
||||
struct t_gui_completion *completion)
|
||||
{
|
||||
struct t_exec_cmd *ptr_exec_cmd;
|
||||
char str_number[32];
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
(void) completion_item;
|
||||
(void) buffer;
|
||||
|
||||
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
|
||||
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
|
||||
{
|
||||
snprintf (str_number, sizeof (str_number), "%d", ptr_exec_cmd->number);
|
||||
weechat_hook_completion_list_add (completion, str_number,
|
||||
0, WEECHAT_LIST_POS_SORT);
|
||||
if (ptr_exec_cmd->name)
|
||||
{
|
||||
weechat_hook_completion_list_add (completion, ptr_exec_cmd->name,
|
||||
0, WEECHAT_LIST_POS_SORT);
|
||||
}
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Hooks completions.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_completion_init ()
|
||||
{
|
||||
weechat_hook_completion ("exec_commands_ids",
|
||||
N_("ids (numbers and names) of executed commands"),
|
||||
&exec_completion_commands_ids_cb, NULL);
|
||||
}
|
25
src/plugins/exec/exec-completion.h
Normal file
25
src/plugins/exec/exec-completion.h
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat 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.
|
||||
*
|
||||
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __WEECHAT_EXEC_COMPLETION_H
|
||||
#define __WEECHAT_EXEC_COMPLETION_H 1
|
||||
|
||||
extern void exec_completion_init ();
|
||||
|
||||
#endif /* __WEECHAT_EXEC_COMPLETION_H */
|
151
src/plugins/exec/exec-config.c
Normal file
151
src/plugins/exec/exec-config.c
Normal file
@ -0,0 +1,151 @@
|
||||
/*
|
||||
* exec-config.c - exec configuration options (file exec.conf)
|
||||
*
|
||||
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat 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.
|
||||
*
|
||||
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "exec.h"
|
||||
#include "exec-config.h"
|
||||
|
||||
|
||||
struct t_config_file *exec_config_file = NULL;
|
||||
|
||||
/* exec config, command section */
|
||||
|
||||
struct t_config_option *exec_config_command_purge_delay;
|
||||
|
||||
/* exec config, color section */
|
||||
|
||||
struct t_config_option *exec_config_color_flag_running;
|
||||
struct t_config_option *exec_config_color_flag_finished;
|
||||
|
||||
/*
|
||||
* Reloads exec configuration file.
|
||||
*/
|
||||
|
||||
int
|
||||
exec_config_reload_cb (void *data, struct t_config_file *config_file)
|
||||
{
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
|
||||
return weechat_config_reload (config_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes exec configuration file.
|
||||
*
|
||||
* Returns:
|
||||
* 1: OK
|
||||
* 0: error
|
||||
*/
|
||||
|
||||
int
|
||||
exec_config_init ()
|
||||
{
|
||||
struct t_config_section *ptr_section;
|
||||
|
||||
exec_config_file = weechat_config_new (EXEC_CONFIG_NAME,
|
||||
&exec_config_reload_cb, NULL);
|
||||
if (!exec_config_file)
|
||||
return 0;
|
||||
|
||||
/* command */
|
||||
ptr_section = weechat_config_new_section (exec_config_file, "command",
|
||||
0, 0,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (!ptr_section)
|
||||
{
|
||||
weechat_config_free (exec_config_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
exec_config_command_purge_delay = weechat_config_new_option (
|
||||
exec_config_file, ptr_section,
|
||||
"purge_delay", "integer",
|
||||
N_("delay for purging finished commands (in seconds, 0 = purge "
|
||||
"commands immediately, -1 = never purge)"),
|
||||
NULL, -1, 36000 * 24 * 30, "0", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
/* color */
|
||||
ptr_section = weechat_config_new_section (exec_config_file, "color",
|
||||
0, 0,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL, NULL, NULL,
|
||||
NULL, NULL);
|
||||
if (!ptr_section)
|
||||
{
|
||||
weechat_config_free (exec_config_file);
|
||||
return 0;
|
||||
}
|
||||
|
||||
exec_config_color_flag_running = weechat_config_new_option (
|
||||
exec_config_file, ptr_section,
|
||||
"flag_running", "color",
|
||||
N_("text color for a running command flag (in exec buffer and "
|
||||
"/exec -list)"),
|
||||
NULL, 0, 0, "lightgreen", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
exec_config_color_flag_finished = weechat_config_new_option (
|
||||
exec_config_file, ptr_section,
|
||||
"flag_finished", "color",
|
||||
N_("text color for a finished command flag (in exec buffer and "
|
||||
"/exec -list)"),
|
||||
NULL, 0, 0, "lightred", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Reads exec configuration file.
|
||||
*/
|
||||
|
||||
int
|
||||
exec_config_read ()
|
||||
{
|
||||
return weechat_config_read (exec_config_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes exec configuration file.
|
||||
*/
|
||||
|
||||
int
|
||||
exec_config_write ()
|
||||
{
|
||||
return weechat_config_write (exec_config_file);
|
||||
}
|
||||
|
||||
/*
|
||||
* Frees exec configuration.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_config_free ()
|
||||
{
|
||||
weechat_config_free (exec_config_file);
|
||||
}
|
38
src/plugins/exec/exec-config.h
Normal file
38
src/plugins/exec/exec-config.h
Normal file
@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat 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.
|
||||
*
|
||||
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __WEECHAT_EXEC_CONFIG_H
|
||||
#define __WEECHAT_EXEC_CONFIG_H 1
|
||||
|
||||
#define EXEC_CONFIG_NAME "exec"
|
||||
#define EXEC_CONFIG_SECTION_EXEC "exec"
|
||||
|
||||
extern struct t_config_file *exec_config_file;
|
||||
|
||||
extern struct t_config_option *exec_config_command_purge_delay;
|
||||
|
||||
extern struct t_config_option *exec_config_color_flag_running;
|
||||
extern struct t_config_option *exec_config_color_flag_finished;
|
||||
|
||||
extern int exec_config_init ();
|
||||
extern int exec_config_read ();
|
||||
extern int exec_config_write ();
|
||||
extern void exec_config_free ();
|
||||
|
||||
#endif /* __WEECHAT_EXEC_CONFIG_H */
|
500
src/plugins/exec/exec.c
Normal file
500
src/plugins/exec/exec.c
Normal file
@ -0,0 +1,500 @@
|
||||
/*
|
||||
* exec.c - execution of external commands in WeeChat
|
||||
*
|
||||
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat 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.
|
||||
*
|
||||
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "../weechat-plugin.h"
|
||||
#include "exec.h"
|
||||
#include "exec-command.h"
|
||||
#include "exec-completion.h"
|
||||
#include "exec-config.h"
|
||||
|
||||
|
||||
WEECHAT_PLUGIN_NAME(EXEC_PLUGIN_NAME);
|
||||
WEECHAT_PLUGIN_DESCRIPTION(N_("Execution of external commands in WeeChat"));
|
||||
WEECHAT_PLUGIN_AUTHOR("Sébastien Helleu <flashcode@flashtux.org>");
|
||||
WEECHAT_PLUGIN_VERSION(WEECHAT_VERSION);
|
||||
WEECHAT_PLUGIN_LICENSE(WEECHAT_LICENSE);
|
||||
|
||||
struct t_weechat_plugin *weechat_exec_plugin = NULL;
|
||||
|
||||
struct t_exec_cmd *exec_cmds = NULL; /* first executed command */
|
||||
struct t_exec_cmd *last_exec_cmd = NULL; /* last executed command */
|
||||
int exec_cmds_count = 0; /* number of executed commands */
|
||||
|
||||
|
||||
/*
|
||||
* Searches for an executed command by id, which can be a number or a name.
|
||||
*
|
||||
* Returns pointer to executed command found, NULL if not found.
|
||||
*/
|
||||
|
||||
struct t_exec_cmd *
|
||||
exec_search_by_id (const char *id)
|
||||
{
|
||||
struct t_exec_cmd* ptr_exec_cmd;
|
||||
char *error;
|
||||
long number;
|
||||
|
||||
error = NULL;
|
||||
number = strtol (id, &error, 10);
|
||||
if (!error || error[0])
|
||||
number = -1;
|
||||
|
||||
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
|
||||
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
|
||||
{
|
||||
/* check if number is matching */
|
||||
if ((number >= 0) && (ptr_exec_cmd->number == (int)number))
|
||||
return ptr_exec_cmd;
|
||||
|
||||
/* check if name is matching */
|
||||
if (ptr_exec_cmd->name && (strcmp (ptr_exec_cmd->name, id) == 0))
|
||||
return ptr_exec_cmd;
|
||||
}
|
||||
|
||||
/* executed command not found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Adds a command in list of executed commands.
|
||||
*/
|
||||
|
||||
struct t_exec_cmd *
|
||||
exec_add ()
|
||||
{
|
||||
struct t_exec_cmd *new_exec_cmd, *ptr_exec_cmd;
|
||||
int number;
|
||||
|
||||
/* find first available number */
|
||||
number = (last_exec_cmd) ? last_exec_cmd->number + 1 : 0;
|
||||
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
|
||||
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
|
||||
{
|
||||
if (ptr_exec_cmd->prev_cmd
|
||||
&& (ptr_exec_cmd->number > ptr_exec_cmd->prev_cmd->number + 1))
|
||||
{
|
||||
number = ptr_exec_cmd->prev_cmd->number + 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
new_exec_cmd = malloc (sizeof (*new_exec_cmd));
|
||||
if (!new_exec_cmd)
|
||||
return NULL;
|
||||
|
||||
new_exec_cmd->prev_cmd = last_exec_cmd;
|
||||
new_exec_cmd->next_cmd = NULL;
|
||||
if (!exec_cmds)
|
||||
exec_cmds = new_exec_cmd;
|
||||
else
|
||||
last_exec_cmd->next_cmd = new_exec_cmd;
|
||||
last_exec_cmd = new_exec_cmd;
|
||||
|
||||
new_exec_cmd->number = number;
|
||||
new_exec_cmd->name = NULL;
|
||||
new_exec_cmd->hook = NULL;
|
||||
new_exec_cmd->command = NULL;
|
||||
new_exec_cmd->pid = 0;
|
||||
new_exec_cmd->start_time = time (NULL);
|
||||
new_exec_cmd->end_time = 0;
|
||||
new_exec_cmd->buffer_plugin = NULL;
|
||||
new_exec_cmd->buffer_name = NULL;
|
||||
new_exec_cmd->output_to_buffer = 0;
|
||||
new_exec_cmd->stdout_size = 0;
|
||||
new_exec_cmd->stdout = NULL;
|
||||
new_exec_cmd->stderr_size = 0;
|
||||
new_exec_cmd->stderr = NULL;
|
||||
new_exec_cmd->return_code = -1;
|
||||
|
||||
exec_cmds_count++;
|
||||
|
||||
return new_exec_cmd;
|
||||
}
|
||||
|
||||
/*
|
||||
* Timer callback to delete a command.
|
||||
*/
|
||||
|
||||
int
|
||||
exec_timer_delete_cb (void *data, int remaining_calls)
|
||||
{
|
||||
struct t_exec_cmd *exec_cmd, *ptr_exec_cmd;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) remaining_calls;
|
||||
|
||||
exec_cmd = (struct t_exec_cmd *)data;
|
||||
if (!exec_cmd)
|
||||
return WEECHAT_RC_OK;
|
||||
|
||||
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
|
||||
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
|
||||
{
|
||||
if (ptr_exec_cmd == exec_cmd)
|
||||
{
|
||||
exec_free (ptr_exec_cmd);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Concatenates some text to stdout/stderr of a command.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_command_concat_output (int *size, char **output, const char *text)
|
||||
{
|
||||
int length, new_size;
|
||||
char *new_output;
|
||||
|
||||
length = strlen (text);
|
||||
new_size = *size + length;
|
||||
new_output = realloc (*output, new_size + 1);
|
||||
if (!new_output)
|
||||
return;
|
||||
|
||||
*output = new_output;
|
||||
memcpy (*output + *size, text, length + 1);
|
||||
*size = new_size;
|
||||
}
|
||||
|
||||
/*
|
||||
* Displays output of a command.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_command_display_output (struct t_exec_cmd *exec_cmd,
|
||||
struct t_gui_buffer *buffer, int stdout)
|
||||
{
|
||||
char *ptr_output, **lines, str_number[32], str_tags[1024];
|
||||
int i, num_lines;
|
||||
|
||||
ptr_output = (stdout) ? exec_cmd->stdout : exec_cmd->stderr;
|
||||
if (!ptr_output)
|
||||
return;
|
||||
|
||||
/*
|
||||
* if output is sent to the buffer, the buffer must exist
|
||||
* (we don't send output by default to core buffer)
|
||||
*/
|
||||
if (exec_cmd->output_to_buffer && !buffer)
|
||||
return;
|
||||
|
||||
lines = weechat_string_split (ptr_output, "\n", 0, 0, &num_lines);
|
||||
if (!lines)
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_lines; i++)
|
||||
{
|
||||
if (exec_cmd->output_to_buffer)
|
||||
weechat_command (buffer, lines[i]);
|
||||
else
|
||||
{
|
||||
snprintf (str_number, sizeof (str_number), "%d", exec_cmd->number);
|
||||
snprintf (str_tags, sizeof (str_tags),
|
||||
"exec_%s,exec_cmd_%s",
|
||||
(stdout) ? "stdout" : "stderr",
|
||||
(exec_cmd->name) ? exec_cmd->name : str_number);
|
||||
weechat_printf_tags (buffer, str_tags,
|
||||
"%s%s",
|
||||
(stdout) ? " \t" : weechat_prefix ("error"),
|
||||
lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
weechat_string_free_split (lines);
|
||||
}
|
||||
|
||||
/*
|
||||
* Ends a command.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_end_command (struct t_exec_cmd *exec_cmd, int return_code)
|
||||
{
|
||||
struct t_gui_buffer *ptr_buffer;
|
||||
|
||||
ptr_buffer = weechat_buffer_search (exec_cmd->buffer_plugin,
|
||||
exec_cmd->buffer_name);
|
||||
|
||||
/* display return code (only if output is NOT sent to buffer) */
|
||||
if (!exec_cmd->output_to_buffer)
|
||||
{
|
||||
weechat_printf (ptr_buffer, "");
|
||||
if (return_code >= 0)
|
||||
{
|
||||
weechat_printf (ptr_buffer, "%s: end of command \"%s\" (rc=%d)",
|
||||
EXEC_PLUGIN_NAME, exec_cmd->command,
|
||||
return_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
weechat_printf (ptr_buffer,
|
||||
_("%s%s: unexpected end of command \"%s\""),
|
||||
weechat_prefix ("error"), EXEC_PLUGIN_NAME,
|
||||
exec_cmd->command);
|
||||
}
|
||||
}
|
||||
|
||||
/* display stdout/stderr (if output to buffer, the buffer must exist) */
|
||||
exec_command_display_output (exec_cmd, ptr_buffer, 1);
|
||||
exec_command_display_output (exec_cmd, ptr_buffer, 0);
|
||||
|
||||
/* (re)set some variables after the end of command */
|
||||
exec_cmd->hook = NULL;
|
||||
exec_cmd->pid = 0;
|
||||
exec_cmd->end_time = time (NULL);
|
||||
exec_cmd->return_code = return_code;
|
||||
|
||||
/* schedule a timer to remove the executed command */
|
||||
if (weechat_config_integer (exec_config_command_purge_delay) >= 0)
|
||||
{
|
||||
weechat_hook_timer (1 + (1000 * weechat_config_integer (exec_config_command_purge_delay)),
|
||||
0, 1,
|
||||
&exec_timer_delete_cb, exec_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for hook process.
|
||||
*/
|
||||
|
||||
int
|
||||
exec_process_cb (void *data, const char *command, int return_code,
|
||||
const char *out, const char *err)
|
||||
{
|
||||
struct t_exec_cmd *ptr_exec_cmd;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) command;
|
||||
|
||||
ptr_exec_cmd = (struct t_exec_cmd *)data;
|
||||
if (!ptr_exec_cmd)
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
if (weechat_exec_plugin->debug >= 2)
|
||||
{
|
||||
weechat_printf (NULL,
|
||||
"%s: process_cb: command=\"%s\", rc=%d, "
|
||||
"out: %d bytes, err: %d bytes",
|
||||
EXEC_PLUGIN_NAME,
|
||||
ptr_exec_cmd->command,
|
||||
return_code,
|
||||
(out) ? strlen (out) : 0,
|
||||
(err) ? strlen (err) : 0);
|
||||
}
|
||||
|
||||
if (return_code == WEECHAT_HOOK_PROCESS_ERROR)
|
||||
{
|
||||
exec_end_command (ptr_exec_cmd, -1);
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
if (out)
|
||||
{
|
||||
exec_command_concat_output (&ptr_exec_cmd->stdout_size,
|
||||
&ptr_exec_cmd->stdout,
|
||||
out);
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
exec_command_concat_output (&ptr_exec_cmd->stderr_size,
|
||||
&ptr_exec_cmd->stderr,
|
||||
err);
|
||||
}
|
||||
|
||||
if (return_code >= 0)
|
||||
exec_end_command (ptr_exec_cmd, return_code);
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes a command.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_free (struct t_exec_cmd *exec_cmd)
|
||||
{
|
||||
if (!exec_cmd)
|
||||
return;
|
||||
|
||||
/* remove command from commands list */
|
||||
if (exec_cmd->prev_cmd)
|
||||
(exec_cmd->prev_cmd)->next_cmd = exec_cmd->next_cmd;
|
||||
if (exec_cmd->next_cmd)
|
||||
(exec_cmd->next_cmd)->prev_cmd = exec_cmd->prev_cmd;
|
||||
if (exec_cmds == exec_cmd)
|
||||
exec_cmds = exec_cmd->next_cmd;
|
||||
if (last_exec_cmd == exec_cmd)
|
||||
last_exec_cmd = exec_cmd->prev_cmd;
|
||||
|
||||
/* free data */
|
||||
if (exec_cmd->hook)
|
||||
weechat_unhook (exec_cmd->hook);
|
||||
if (exec_cmd->name)
|
||||
free (exec_cmd->name);
|
||||
if (exec_cmd->command)
|
||||
free (exec_cmd->command);
|
||||
if (exec_cmd->buffer_plugin)
|
||||
free (exec_cmd->buffer_plugin);
|
||||
if (exec_cmd->buffer_name)
|
||||
free (exec_cmd->buffer_name);
|
||||
if (exec_cmd->stdout)
|
||||
free (exec_cmd->stdout);
|
||||
if (exec_cmd->stderr)
|
||||
free (exec_cmd->stderr);
|
||||
|
||||
free (exec_cmd);
|
||||
|
||||
exec_cmds_count--;
|
||||
}
|
||||
|
||||
/*
|
||||
* Deletes all commands.
|
||||
*/
|
||||
|
||||
void
|
||||
exec_free_all ()
|
||||
{
|
||||
while (exec_cmds)
|
||||
{
|
||||
exec_free (exec_cmds);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Prints exec infos in WeeChat log file (usually for crash dump).
|
||||
*/
|
||||
|
||||
void
|
||||
exec_print_log ()
|
||||
{
|
||||
struct t_exec_cmd *ptr_exec_cmd;
|
||||
|
||||
for (ptr_exec_cmd = exec_cmds; ptr_exec_cmd;
|
||||
ptr_exec_cmd = ptr_exec_cmd->next_cmd)
|
||||
{
|
||||
weechat_log_printf ("");
|
||||
weechat_log_printf ("[exec command (addr:0x%lx)]", ptr_exec_cmd);
|
||||
weechat_log_printf (" number. . . . . . . . . : %d", ptr_exec_cmd->number);
|
||||
weechat_log_printf (" name. . . . . . . . . . : '%s'", ptr_exec_cmd->name);
|
||||
weechat_log_printf (" hook. . . . . . . . . . : 0x%lx", ptr_exec_cmd->hook);
|
||||
weechat_log_printf (" command . . . . . . . . : '%s'", ptr_exec_cmd->command);
|
||||
weechat_log_printf (" pid . . . . . . . . . . : %d", ptr_exec_cmd->pid);
|
||||
weechat_log_printf (" start_time. . . . . . . : %ld", ptr_exec_cmd->start_time);
|
||||
weechat_log_printf (" end_time. . . . . . . . : %ld", ptr_exec_cmd->end_time);
|
||||
weechat_log_printf (" buffer_plugin . . . . . : '%s'", ptr_exec_cmd->buffer_plugin);
|
||||
weechat_log_printf (" buffer_name . . . . . . : '%s'", ptr_exec_cmd->buffer_name);
|
||||
weechat_log_printf (" output_to_buffer. . . . : %d", ptr_exec_cmd->output_to_buffer);
|
||||
weechat_log_printf (" stdout_size . . . . . . : %d", ptr_exec_cmd->stdout_size);
|
||||
weechat_log_printf (" stdout. . . . . . . . . : '%s'", ptr_exec_cmd->stdout);
|
||||
weechat_log_printf (" stderr_size . . . . . . : %d", ptr_exec_cmd->stderr_size);
|
||||
weechat_log_printf (" stderr. . . . . . . . . : '%s'", ptr_exec_cmd->stderr);
|
||||
weechat_log_printf (" return_code . . . . . . : %d", ptr_exec_cmd->return_code);
|
||||
weechat_log_printf (" prev_cmd. . . . . . . . : 0x%lx", ptr_exec_cmd->prev_cmd);
|
||||
weechat_log_printf (" next_cmd. . . . . . . . : 0x%lx", ptr_exec_cmd->next_cmd);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Callback for signal "debug_dump".
|
||||
*/
|
||||
|
||||
int
|
||||
exec_debug_dump_cb (void *data, const char *signal, const char *type_data,
|
||||
void *signal_data)
|
||||
{
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
(void) signal;
|
||||
(void) type_data;
|
||||
|
||||
if (!signal_data
|
||||
|| (weechat_strcasecmp ((char *)signal_data, EXEC_PLUGIN_NAME) == 0))
|
||||
{
|
||||
weechat_log_printf ("");
|
||||
weechat_log_printf ("***** \"%s\" plugin dump *****",
|
||||
weechat_plugin->name);
|
||||
|
||||
exec_print_log ();
|
||||
|
||||
weechat_log_printf ("");
|
||||
weechat_log_printf ("***** End of \"%s\" plugin dump *****",
|
||||
weechat_plugin->name);
|
||||
}
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes exec plugin.
|
||||
*/
|
||||
|
||||
int
|
||||
weechat_plugin_init (struct t_weechat_plugin *plugin, int argc, char *argv[])
|
||||
{
|
||||
/* make C compiler happy */
|
||||
(void) argc;
|
||||
(void) argv;
|
||||
|
||||
weechat_plugin = plugin;
|
||||
|
||||
exec_command_init ();
|
||||
|
||||
if (!exec_config_init ())
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
exec_config_read ();
|
||||
|
||||
/* hook some signals */
|
||||
weechat_hook_signal ("debug_dump", &exec_debug_dump_cb, NULL);
|
||||
|
||||
/* hook completions */
|
||||
exec_completion_init ();
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ends exec plugin.
|
||||
*/
|
||||
|
||||
int
|
||||
weechat_plugin_end (struct t_weechat_plugin *plugin)
|
||||
{
|
||||
/* make C compiler happy */
|
||||
(void) plugin;
|
||||
|
||||
exec_config_write ();
|
||||
exec_free_all ();
|
||||
exec_config_free ();
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
67
src/plugins/exec/exec.h
Normal file
67
src/plugins/exec/exec.h
Normal file
@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Sébastien Helleu <flashcode@flashtux.org>
|
||||
*
|
||||
* This file is part of WeeChat, the extensible chat client.
|
||||
*
|
||||
* WeeChat 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.
|
||||
*
|
||||
* WeeChat 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 WeeChat. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __WEECHAT_EXEC_H
|
||||
#define __WEECHAT_EXEC_H 1
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#define weechat_plugin weechat_exec_plugin
|
||||
#define EXEC_PLUGIN_NAME "exec"
|
||||
|
||||
struct t_exec_cmd
|
||||
{
|
||||
/* command/process */
|
||||
int number; /* command number */
|
||||
char *name; /* name of command */
|
||||
struct t_hook *hook; /* pointer to process hook */
|
||||
char *command; /* command (with arguments) */
|
||||
pid_t pid; /* process id */
|
||||
time_t start_time; /* start time */
|
||||
time_t end_time; /* end time */
|
||||
|
||||
/* buffer */
|
||||
char *buffer_plugin; /* buffer plugin (where cmd is exec) */
|
||||
char *buffer_name; /* buffer name (where cmd is exec) */
|
||||
int output_to_buffer; /* 1 if output is sent to buffer */
|
||||
|
||||
/* command output */
|
||||
int stdout_size; /* number of bytes in stdout */
|
||||
char *stdout; /* stdout of command */
|
||||
int stderr_size; /* number of bytes in stderr */
|
||||
char *stderr; /* stderr of command */
|
||||
int return_code; /* command return code */
|
||||
|
||||
struct t_exec_cmd *prev_cmd; /* link to previous command */
|
||||
struct t_exec_cmd *next_cmd; /* link to next command */
|
||||
};
|
||||
|
||||
extern struct t_weechat_plugin *weechat_exec_plugin;
|
||||
extern struct t_exec_cmd *exec_cmds;
|
||||
extern struct t_exec_cmd *last_exec_cmd;
|
||||
extern int exec_cmds_count;
|
||||
|
||||
extern struct t_exec_cmd *exec_search_by_id (const char *id);
|
||||
extern struct t_exec_cmd *exec_add ();
|
||||
extern int exec_process_cb (void *data, const char *command, int return_code,
|
||||
const char *out, const char *err);
|
||||
extern void exec_free (struct t_exec_cmd *exec_cmd);
|
||||
extern void exec_free_all ();
|
||||
|
||||
#endif /* __WEECHAT_EXEC_H */
|
@ -87,6 +87,7 @@ weechat_CONTENTS="
|
||||
usr/lib/weechat/plugins/alias.dll
|
||||
usr/lib/weechat/plugins/aspell.dll
|
||||
usr/lib/weechat/plugins/charset.dll
|
||||
usr/lib/weechat/plugins/exec.dll
|
||||
usr/lib/weechat/plugins/fifo.dll
|
||||
usr/lib/weechat/plugins/irc.dll
|
||||
usr/lib/weechat/plugins/logger.dll
|
||||
|
Loading…
x
Reference in New Issue
Block a user