summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTimo Sirainen <cras@irssi.org>2001-02-10 09:54:51 +0000
committercras <cras@dbcabf3a-b0e7-0310-adc4-f8d773084564>2001-02-10 09:54:51 +0000
commit98a73539aebf81a5c373ef869ae5af9cb5c857b6 (patch)
tree7a7ed2e10e653034522bcd92117fe141dddbebc5
parentddf6810b0ea03e144ecdbafed3fb625d7039d832 (diff)
downloadirssi-98a73539aebf81a5c373ef869ae5af9cb5c857b6.zip
/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
-rw-r--r--src/fe-common/core/fe-exec.c107
1 files 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 <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;
}
@@ -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);
}