1
0
mirror of https://github.com/irssi/irssi.git synced 2024-12-04 14:46:39 -05:00

/EXEC -interactive: Creates a query-like window item. Text written to

it is sent to executed process, like /EXEC -in.


git-svn-id: http://svn.irssi.org/repos/irssi/trunk@1205 dbcabf3a-b0e7-0310-adc4-f8d773084564
This commit is contained in:
Timo Sirainen 2001-02-10 09:54:51 +00:00 committed by cras
parent ddf6810b0e
commit 98a73539ae

View File

@ -34,7 +34,23 @@
#include <signal.h>
#include <sys/wait.h>
#define EXEC_WI(query) \
MODULE_CHECK_CAST_MODULE(query, EXEC_WI_REC, type, \
"WINDOW ITEM TYPE", "EXEC")
#define IS_EXEC_WI(query) \
(EXEC_WI(query) ? TRUE : FALSE)
typedef struct PROCESS_REC PROCESS_REC;
#define STRUCT_SERVER_REC void
typedef struct {
#include "window-item-rec.h"
PROCESS_REC *process;
unsigned int destroying:1;
} EXEC_WI_REC;
struct PROCESS_REC {
int id;
char *name;
char *args;
@ -47,15 +63,53 @@ typedef struct {
char *target; /* send text with /msg <target> ... */
WINDOW_REC *target_win; /* print text to this window */
EXEC_WI_REC *target_item; /* print text to this exec window item */
unsigned int shell:1; /* start the program via /bin/sh */
unsigned int notice:1; /* send text with /notice, not /msg if target is set */
unsigned int silent:1; /* don't print "process exited with level xx" */
} PROCESS_REC;
};
static GSList *processes; /* processes, sorted by */
static GSList *processes;
static int signal_exec_input;
static EXEC_WI_REC *exec_wi_create(WINDOW_REC *window, PROCESS_REC *rec)
{
EXEC_WI_REC *item;
g_return_val_if_fail(window != NULL, NULL);
g_return_val_if_fail(rec != NULL, NULL);
item = g_new0(EXEC_WI_REC, 1);
item->type = module_get_uniq_id_str("WINDOW ITEM TYPE", "EXEC");
item->name = rec->name != NULL ?
g_strdup_printf("%%%s", rec->name) :
g_strdup_printf("%%%d", rec->id);
item->window = window;
item->createtime = time(NULL);
item->process = rec;
MODULE_DATA_INIT(item);
window_item_add(window, (WI_ITEM_REC *) item, FALSE);
return item;
}
static void exec_wi_destroy(EXEC_WI_REC *rec)
{
g_return_if_fail(rec != NULL);
if (rec->destroying) return;
rec->destroying = TRUE;
if (window_item_window((WI_ITEM_REC *) rec) != NULL)
window_item_destroy((WI_ITEM_REC *) rec);
MODULE_DATA_DEINIT(rec);
g_free(rec->name);
g_free(rec);
}
static int process_get_new_id(void)
{
PROCESS_REC *rec;
@ -149,6 +203,8 @@ static void process_destroy(PROCESS_REC *rec, int status)
if (rec->read_tag != -1)
g_source_remove(rec->read_tag);
if (rec->target_item != NULL)
exec_wi_destroy(rec->target_item);
line_split_free(rec->databuf);
g_io_channel_close(rec->in);
@ -349,7 +405,7 @@ static void handle_exec(const char *args, GHashTable *optlist,
{
PROCESS_REC *rec;
char *target;
int notice, signum;
int notice, signum, interactive;
/* check that there's no unknown options. we allowed them
because signals can be used as options, but there should be
@ -414,6 +470,7 @@ static void handle_exec(const char *args, GHashTable *optlist,
return;
}
interactive = g_hash_table_lookup(optlist, "interactive") != NULL;
if (*args == '%') {
/* do something to already existing process */
char *name;
@ -430,11 +487,22 @@ static void handle_exec(const char *args, GHashTable *optlist,
/* change window name */
g_free_not_null(rec->name);
rec->name = *name == '\0' ? NULL : g_strdup(name);
} else if (target == NULL) {
} else if (target == NULL &&
(rec->target_item == NULL || interactive)) {
/* no parameters given,
redirect output to the active window */
g_free_and_null(rec->target);
rec->target_win = active_win;
if (rec->target_item != NULL) {
exec_wi_destroy(rec->target_item);
rec->target_item = NULL;
}
if (interactive) {
rec->target_item =
exec_wi_create(active_win, rec);
}
}
return;
}
@ -464,6 +532,9 @@ static void handle_exec(const char *args, GHashTable *optlist,
rec);
processes = g_slist_append(processes, rec);
if (rec->target == NULL && interactive)
rec->target_item = exec_wi_create(active_win, rec);
signal_emit("exec new", 4, GINT_TO_POINTER(rec->id), rec->name,
GINT_TO_POINTER(rec->pid), rec->args);
}
@ -533,6 +604,9 @@ static void sig_exec_input(PROCESS_REC *rec, const char *text)
signal_emit(rec->notice ? "command notice" : "command msg",
3, str, server, item);
g_free(str);
} else if (rec->target_item != NULL) {
printtext(NULL, rec->target_item->name, MSGLEVEL_CLIENTCRAP,
"%s", text);
} else {
printtext_window(rec->target_win, MSGLEVEL_CLIENTCRAP,
"%s", text);
@ -553,15 +627,34 @@ static void sig_window_destroyed(WINDOW_REC *window)
}
}
static void sig_window_item_destroyed(WINDOW_REC *window, EXEC_WI_REC *item)
{
if (IS_EXEC_WI(item)) {
item->process->target_item = NULL;
exec_wi_destroy(item);
}
}
static void event_text(const char *data, SERVER_REC *server, EXEC_WI_REC *item)
{
if (!IS_EXEC_WI(item)) return;
net_sendbuffer_send(item->process->out, data, strlen(data));
net_sendbuffer_send(item->process->out, "\n", 1);
signal_stop();
}
void fe_exec_init(void)
{
command_bind("exec", NULL, (SIGNAL_FUNC) cmd_exec);
command_set_options("exec", "!- nosh +name out +msg +notice +in window close");
command_set_options("exec", "!- interactive nosh +name out +msg +notice +in window close");
signal_exec_input = signal_get_uniq_id("exec input");
signal_add("pidwait", (SIGNAL_FUNC) sig_pidwait);
signal_add("exec input", (SIGNAL_FUNC) sig_exec_input);
signal_add("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
signal_add("window item destroy", (SIGNAL_FUNC) sig_window_item_destroyed);
signal_add_first("send text", (SIGNAL_FUNC) event_text);
}
void fe_exec_deinit(void)
@ -580,4 +673,6 @@ void fe_exec_deinit(void)
signal_remove("pidwait", (SIGNAL_FUNC) sig_pidwait);
signal_remove("exec input", (SIGNAL_FUNC) sig_exec_input);
signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed);
signal_remove("window item destroy", (SIGNAL_FUNC) sig_window_item_destroyed);
signal_remove("send text", (SIGNAL_FUNC) event_text);
}