From 98a73539aebf81a5c373ef869ae5af9cb5c857b6 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Sat, 10 Feb 2001 09:54:51 +0000 Subject: [PATCH] /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 --- src/fe-common/core/fe-exec.c | 107 +++++++++++++++++++++++++++++++++-- 1 file changed, 101 insertions(+), 6 deletions(-) diff --git a/src/fe-common/core/fe-exec.c b/src/fe-common/core/fe-exec.c index 346e02f7..520530aa 100644 --- a/src/fe-common/core/fe-exec.c +++ b/src/fe-common/core/fe-exec.c @@ -34,7 +34,23 @@ #include #include +#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 ... */ 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; } @@ -453,7 +521,7 @@ static void handle_exec(const char *args, GHashTable *optlist, rec->id = process_get_new_id(); rec->target = g_strdup(target); - rec->target_win = active_win; + rec->target_win = active_win; rec->args = g_strdup(args); rec->notice = notice; rec->silent = g_hash_table_lookup(optlist, "-") != NULL; @@ -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); }