From: Daniel Carl Date: Tue, 30 Dec 2014 23:31:16 +0000 (+0100) Subject: Replaced the fifo by socket to remote control vimb (#144). X-Git-Url: https://git.owens.tech///git?a=commitdiff_plain;h=9778ce4d078aa7f658f54156a36d12140c038a59;p=vimb.git Replaced the fifo by socket to remote control vimb (#144). --- diff --git a/doc/vimb.1 b/doc/vimb.1 index ad351e7..8064877 100644 --- a/doc/vimb.1 +++ b/doc/vimb.1 @@ -35,7 +35,10 @@ If the flag is used more than one time, the ordering is preserved when \fICMD\fP are executed. You could also pass several ex commands in one \fICMD\fP, if there are separated by "|". -Example: vimb --cmd "set cookie-accept=origin|set header=Referer,DNT=1" +Example: +.EX +vimb --cmd "set cookie-accept=origin|set header=Referer,DNT=1" +.EE .TP .BI "\-c, \-\-config " "CONFIG-FILE" Use custom configuration given as \fICONFIG-FILE\fP. This will also be applied @@ -46,14 +49,14 @@ on new spawned instances. of an XEmbed-aware application, that vimb will use as its parent. .TP .B \-d, \-\-dump -Dump the current used fifo path to stdout in case vimb is started with \-f -option. If vimb is started with `$(vimb -df > ~/vimb.fifo)' the full fifo -path can be picked up from somewhere by `echo ":o github.com" > $(< -~/vimb.fifo)' -.TP -.B \-f, \-\-fifo -If given vimb will create a control fifo in vimb's config directory -named 'vimb-fifo-{pid}'. +Dump the current used socket path to stdout in case vimb is started with \-s +option. + +Example: +.EX +sh -c "./vimb -s -d > ~/vimb.socket" & +echo ":o github.com" | socat - unix-connect:$(< ~/vimb.socket) +.EE .TP .B "\-h, \-\-help" Show help options. @@ -62,6 +65,9 @@ Show help options. Run vimb in kiosk mode with nearly no keybindings, not inputbox and no context menu. .TP +.B \-s, \-\-socket +If given vimb will create a control socket. +.TP .B "\-v, \-\-version" Print build and version information. .SH MODES @@ -390,7 +396,7 @@ the rhs (right hand side) if this is available depends on the command. At the moment the count parts [N] of commands is parsed, but actual there does not exists any command that uses the count. .br -Commands that are typed interactive (from inputbox or from fifo) are normally +Commands that are typed interactive (from inputbox or from socket) are normally recorded into command history and register. To avoid this, the commands can be prefixed by one or more additional `:' or whitespace. .SS Command Line Editing @@ -1447,14 +1453,14 @@ Contains the title of the current opened page. .B VIMB_PID Contains the pid of the running vimb instance. .TP +.B VIMB_SOCKET +Holds the full path to the control socket, if vimb is compiled with SOCKET +feature and started with `--socket' option. +.TP .B VIMB_XID Holds the X-Window id of the vim window or of the embedding window if vimb is started with -e option. .TP -.B VIMB_FILE -Holds the full path to the control fifo, if vimb is compiled with FIFO feature -and started with `--fifo' option. -.TP .B http_proxy If this variable is set to an none empty value, and the configuration option `proxy' is enabled, this will be used as http proxy. If the proxy URL has no diff --git a/examples/formfiller/formfiller b/examples/formfiller/formfiller index 2f9a455..e0d5f99 100755 --- a/examples/formfiller/formfiller +++ b/examples/formfiller/formfiller @@ -41,16 +41,16 @@ fillform() { # make sure we are in normal mode and fill in the form data # use :: to not save the secrets into vimb command history or into the # last ex command register ": - echo "::e! _vbform.fill($data);" > $VIMB_FIFO + echo "::e! _vbform.fill($data);" | socat - UNIX-CONNECT:$VIMB_SOCKET } # check if uri is given if [ -z "$uri" ]; then die 'No URI given' fi -# check if the script is run from vimb with fifo support enabled -if [ -z "$VIMB_FIFO" ] || [ ! -p "$VIMB_FIFO" ]; then - die 'This script must be run from vimb with fifo support' +# check if the script is run from vimb with socket support enabled +if [ -z "$VIMB_SOCKET" ] || [ ! -S "$VIMB_SOCKET" ]; then + die 'This script must be run from vimb with socket support' fi # extract the domain part without ports from given uri diff --git a/src/config.def.h b/src/config.def.h index ce0e5cb..4690534 100644 --- a/src/config.def.h +++ b/src/config.def.h @@ -52,8 +52,8 @@ #define FEATURE_AUTOCMD /* enable the :auto-response-header feature */ #define FEATURE_ARH -/* allow to use fifo to remote control vimb */ -#define FEATURE_FIFO +/* allow to use socket to remote control vimb */ +#define FEATURE_SOCKET /* time in seconds after that message will be removed from inputbox if the * message where only temporary */ diff --git a/src/io.c b/src/io.c index 3603c0d..c67764b 100644 --- a/src/io.c +++ b/src/io.c @@ -18,25 +18,31 @@ */ #include "config.h" -#ifdef FEATURE_FIFO +#ifdef FEATURE_SOCKET #include "io.h" #include "main.h" #include "map.h" #include #include #include +#include +#include +#include extern VbCore vb; -static gboolean fifo_watch(GIOChannel *gio, GIOCondition condition); +static gboolean socket_accept(GIOChannel *chan); +static gboolean socket_watch(GIOChannel *chan); -gboolean io_init_fifo(const char *name) +gboolean io_init_socket(const char *name) { char *fname, *path; + int sock; + struct sockaddr_un local; - /* create fifo in directory as vimb-fifo-$PID */ - fname = g_strdup_printf(PROJECT "-fifo-%s", name); + /* create socket in directory as vimb-socket-$PID */ + fname = g_strdup_printf(PROJECT "-socket-%s", name); path = g_build_filename(g_get_user_config_dir(), PROJECT, fname, NULL); g_free(fname); @@ -45,26 +51,35 @@ gboolean io_init_fifo(const char *name) unlink(path); } - if (mkfifo(path, 0666) == 0) { - GError *error = NULL; - /* use r+ to avoid blocking caused by wait of a writer */ - GIOChannel *chan = g_io_channel_new_file(path, "r+", &error); + sock = socket(AF_UNIX, SOCK_STREAM, 0); + if (sock < 0) { + g_warning("Can't create socket %s", path); + } + + /* prepare socket address */ + local.sun_family = AF_UNIX; + strcpy(local.sun_path, path); + + if (bind(sock, (struct sockaddr*)&local, sizeof(local)) != -1 + && listen(sock, 5) >= 0 + ) { + GIOChannel *chan = g_io_channel_unix_new(sock); if (chan) { - if (g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc)fifo_watch, NULL)) { - /* don't free path - because we want to keep the value in - * vb.state.fifo_path still accessible */ - vb.state.fifo_path = path; - g_setenv("VIMB_FIFO", path, TRUE); - - return true; - } - } else { - g_warning ("Can't open fifo: %s", error->message); - g_error_free(error); + g_io_channel_set_encoding(chan, NULL, NULL); + g_io_channel_set_buffered(chan, false); + g_io_add_watch(chan, G_IO_IN|G_IO_HUP, (GIOFunc)socket_accept, chan); + /* don't free path - because we want to keep the value in + * vb.state.socket_path still accessible */ + vb.state.socket_path = path; + g_setenv("VIMB_SOCKET", path, true); + + return true; } } else { - g_warning("Can't create fifo %s", path); + g_warning("no bind"); } + + g_warning("Could not listen on %s: %s", path, strerror(errno)); g_free(path); return false; @@ -72,44 +87,81 @@ gboolean io_init_fifo(const char *name) void io_cleanup(void) { - if (vb.state.fifo_path) { - if (unlink(vb.state.fifo_path) == -1) { - g_warning("Can't remove fifo %s", vb.state.fifo_path); + if (vb.state.socket_path) { + if (unlink(vb.state.socket_path) == -1) { + g_warning("Can't remove socket %s", vb.state.socket_path); } - g_free(vb.state.fifo_path); - vb.state.fifo_path = NULL; + g_free(vb.state.socket_path); + vb.state.socket_path = NULL; } } -static gboolean fifo_watch(GIOChannel *gio, GIOCondition condition) +static gboolean socket_accept(GIOChannel *chan) { - char *line; - GIOStatus ret; - GError *err = NULL; + struct sockaddr_un remote; + guint size = sizeof(remote); + GIOChannel *iochan; + int clientsock; - if (condition & G_IO_HUP) { - g_error("fifo: read end of pipe died"); - } + clientsock = accept(g_io_channel_unix_get_fd(chan), (struct sockaddr *)&remote, &size); - if (!gio) { - g_error("fifo: GIOChannel broken"); + if ((iochan = g_io_channel_unix_new(clientsock))) { + g_io_channel_set_encoding(iochan, NULL, NULL); + g_io_add_watch(iochan, G_IO_IN|G_IO_HUP, (GIOFunc)socket_watch, iochan); } + return true; +} - ret = g_io_channel_read_line(gio, &line, NULL, NULL, &err); - if (ret == G_IO_STATUS_ERROR) { - g_error("fifo: error reading from fifo: %s", err->message); - g_error_free(err); +static gboolean socket_watch(GIOChannel *chan) +{ + GIOStatus ret; + GError *error = NULL; + char *line, *inputtext; + gsize len; + + ret = g_io_channel_read_line(chan, &line, &len, NULL, &error); + if (ret == G_IO_STATUS_ERROR || ret == G_IO_STATUS_EOF) { + if (ret == G_IO_STATUS_ERROR) { + g_warning("Error reading: %s", error->message); + g_error_free(&error); + } + + /* shutdown and remove the client channel */ + ret = g_io_channel_shutdown(chan, true, &error); + g_io_channel_unref(chan); + + if (ret == G_IO_STATUS_ERROR) { + g_warning("Error closing: %s", error->message); + g_error_free(&error); + } + return false; } /* simulate the typed flag to allow to record the commands in history */ vb.state.typed = true; + /* run the commands */ map_handle_string(line, true); g_free(line); /* unset typed flag */ vb.state.typed = false; + /* We assume that the commands result is still available in the inputbox, + * so the whole inputbox content is written to the socket. */ + inputtext = vb_get_input_text(); + ret = g_io_channel_write_chars(chan, inputtext, -1, &len, &error); + if (ret == G_IO_STATUS_ERROR) { + g_warning("Error writing: %s", error->message); + g_error_free(&error); + } + if (g_io_channel_flush(chan, &error) == G_IO_STATUS_ERROR) { + g_warning("Error flushing: %s", error->message); + g_error_free(&error); + } + + g_free(inputtext); + return true; } diff --git a/src/io.h b/src/io.h index fdddbf5..fa131ac 100644 --- a/src/io.h +++ b/src/io.h @@ -18,14 +18,14 @@ */ #include "config.h" -#ifdef FEATURE_FIFO +#ifdef FEATURE_SOCKET #ifndef _IO_H #define _IO_H #include -gboolean io_init_fifo(const char *dir); +gboolean io_init_socket(const char *name); void io_cleanup(void); #endif /* end of include guard: _IO_H */ diff --git a/src/main.c b/src/main.c index 509d214..2c3c8e3 100644 --- a/src/main.c +++ b/src/main.c @@ -232,8 +232,8 @@ gboolean vb_load_uri(const Arg *arg) + (vb.embed ? 2 : 0) + (vb.config.file ? 2 : 0) + (vb.config.kioskmode ? 1 : 0) -#ifdef FEATURE_FIFO - + (vb.config.fifo ? 1 : 0) +#ifdef FEATURE_SOCKET + + (vb.config.socket ? 1 : 0) #endif + g_slist_length(vb.config.cmdargs) * 2, sizeof(char *) @@ -258,9 +258,9 @@ gboolean vb_load_uri(const Arg *arg) if (vb.config.kioskmode) { cmd[i++] = "-k"; } -#ifdef FEATURE_FIFO - if (vb.config.fifo) { - cmd[i++] = "-f"; +#ifdef FEATURE_SOCKET + if (vb.config.socket) { + cmd[i++] = "-s"; } #endif cmd[i++] = uri; @@ -1558,7 +1558,7 @@ static void vb_cleanup(void) #ifdef FEATURE_ARH arh_free(vb.config.autoresponseheader); #endif -#ifdef FEATURE_FIFO +#ifdef FEATURE_SOCKET io_cleanup(); #endif g_free(vb.state.pid_str); @@ -1582,7 +1582,7 @@ int main(int argc, char *argv[]) { static char *winid = NULL; static gboolean ver = false; -#ifdef FEATURE_FIFO +#ifdef FEATURE_SOCKET static gboolean dump = false; #endif static GError *err; @@ -1591,9 +1591,9 @@ int main(int argc, char *argv[]) {"cmd", 'C', 0, G_OPTION_ARG_CALLBACK, autocmdOptionArgFunc, "Ex command run before first page is loaded", NULL}, {"config", 'c', 0, G_OPTION_ARG_FILENAME, &vb.config.file, "Custom configuration file", NULL}, {"embed", 'e', 0, G_OPTION_ARG_STRING, &winid, "Reparents to window specified by xid", NULL}, -#ifdef FEATURE_FIFO - {"dump", 'd', 0, G_OPTION_ARG_NONE, &dump, "Dump the fifo path to stdout", NULL}, - {"fifo", 'f', 0, G_OPTION_ARG_NONE, &vb.config.fifo, "Create control fifo", NULL}, +#ifdef FEATURE_SOCKET + {"dump", 'd', 0, G_OPTION_ARG_NONE, &dump, "Dump the socket path to stdout", NULL}, + {"socket", 's', 0, G_OPTION_ARG_NONE, &vb.config.socket, "Create control socket", NULL}, #endif {"kiosk", 'k', 0, G_OPTION_ARG_NONE, &vb.config.kioskmode, "Run in kiosk mode", NULL}, {"version", 'v', 0, G_OPTION_ARG_NONE, &ver, "Print version", NULL}, @@ -1647,15 +1647,15 @@ int main(int argc, char *argv[]) vb_load_uri(&(Arg){VB_TARGET_CURRENT, argv[argc - 1]}); } -#ifdef FEATURE_FIFO - /* setup the control fifo - quit vimb if this failed */ - if (vb.config.fifo && !io_init_fifo(vb.state.pid_str)) { +#ifdef FEATURE_SOCKET + /* setup the control socket - quit vimb if this failed */ + if (vb.config.socket && !io_init_socket(vb.state.pid_str)) { /* cleanup memory */ vb_cleanup(); return EXIT_FAILURE; } - if (dump && vb.state.fifo_path) { - printf("%s\n", vb.state.fifo_path); + if (dump && vb.state.socket_path) { + printf("%s\n", vb.state.socket_path); fflush(NULL); } #endif diff --git a/src/main.h b/src/main.h index 4c4349d..6a71b3d 100644 --- a/src/main.h +++ b/src/main.h @@ -313,6 +313,7 @@ typedef struct { int search_matches; /* number of matches search results */ #endif char *fifo_path; /* holds the path to the control fifo */ + char *socket_path; /* holds the path to the control socket */ char *pid_str; /* holds the pid as string */ } State; @@ -339,8 +340,8 @@ typedef struct { float default_zoom; /* default zoomlevel that is applied on zz zoom reset */ gboolean kioskmode; gboolean input_autohide; /* indicates if the inputbox should be hidden if it's empty */ -#ifdef FEATURE_FIFO - gboolean fifo; /* indicates if the fifo is used */ +#ifdef FEATURE_SOCKET + gboolean socket; /* indicates if the socket is used */ #endif #ifdef FEATURE_HSTS HSTSProvider *hsts_provider; /* the hsts session feature that is added to soup session */