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 <signal.h>
#include <sys/wait.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 { typedef struct {
#include "window-item-rec.h"
PROCESS_REC *process;
unsigned int destroying:1;
} EXEC_WI_REC;
struct PROCESS_REC {
int id; int id;
char *name; char *name;
char *args; char *args;
@ -47,15 +63,53 @@ typedef struct {
char *target; /* send text with /msg <target> ... */ char *target; /* send text with /msg <target> ... */
WINDOW_REC *target_win; /* print text to this window */ 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 shell:1; /* start the program via /bin/sh */
unsigned int notice:1; /* send text with /notice, not /msg if target is set */ 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" */ 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 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) static int process_get_new_id(void)
{ {
PROCESS_REC *rec; PROCESS_REC *rec;
@ -149,6 +203,8 @@ static void process_destroy(PROCESS_REC *rec, int status)
if (rec->read_tag != -1) if (rec->read_tag != -1)
g_source_remove(rec->read_tag); g_source_remove(rec->read_tag);
if (rec->target_item != NULL)
exec_wi_destroy(rec->target_item);
line_split_free(rec->databuf); line_split_free(rec->databuf);
g_io_channel_close(rec->in); g_io_channel_close(rec->in);
@ -349,7 +405,7 @@ static void handle_exec(const char *args, GHashTable *optlist,
{ {
PROCESS_REC *rec; PROCESS_REC *rec;
char *target; char *target;
int notice, signum; int notice, signum, interactive;
/* check that there's no unknown options. we allowed them /* check that there's no unknown options. we allowed them
because signals can be used as options, but there should be 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; return;
} }
interactive = g_hash_table_lookup(optlist, "interactive") != NULL;
if (*args == '%') { if (*args == '%') {
/* do something to already existing process */ /* do something to already existing process */
char *name; char *name;
@ -430,11 +487,22 @@ static void handle_exec(const char *args, GHashTable *optlist,
/* change window name */ /* change window name */
g_free_not_null(rec->name); g_free_not_null(rec->name);
rec->name = *name == '\0' ? NULL : g_strdup(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, /* no parameters given,
redirect output to the active window */ redirect output to the active window */
g_free_and_null(rec->target); g_free_and_null(rec->target);
rec->target_win = active_win; 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; return;
} }
@ -464,6 +532,9 @@ static void handle_exec(const char *args, GHashTable *optlist,
rec); rec);
processes = g_slist_append(processes, 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, signal_emit("exec new", 4, GINT_TO_POINTER(rec->id), rec->name,
GINT_TO_POINTER(rec->pid), rec->args); 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", signal_emit(rec->notice ? "command notice" : "command msg",
3, str, server, item); 3, str, server, item);
g_free(str); g_free(str);
} else if (rec->target_item != NULL) {
printtext(NULL, rec->target_item->name, MSGLEVEL_CLIENTCRAP,
"%s", text);
} else { } else {
printtext_window(rec->target_win, MSGLEVEL_CLIENTCRAP, printtext_window(rec->target_win, MSGLEVEL_CLIENTCRAP,
"%s", text); "%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) void fe_exec_init(void)
{ {
command_bind("exec", NULL, (SIGNAL_FUNC) cmd_exec); 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_exec_input = signal_get_uniq_id("exec input");
signal_add("pidwait", (SIGNAL_FUNC) sig_pidwait); signal_add("pidwait", (SIGNAL_FUNC) sig_pidwait);
signal_add("exec input", (SIGNAL_FUNC) sig_exec_input); signal_add("exec input", (SIGNAL_FUNC) sig_exec_input);
signal_add("window destroyed", (SIGNAL_FUNC) sig_window_destroyed); 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) void fe_exec_deinit(void)
@ -580,4 +673,6 @@ void fe_exec_deinit(void)
signal_remove("pidwait", (SIGNAL_FUNC) sig_pidwait); signal_remove("pidwait", (SIGNAL_FUNC) sig_pidwait);
signal_remove("exec input", (SIGNAL_FUNC) sig_exec_input); signal_remove("exec input", (SIGNAL_FUNC) sig_exec_input);
signal_remove("window destroyed", (SIGNAL_FUNC) sig_window_destroyed); 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);
} }