\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
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<CR>" > $(<
-~/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<CR>" | socat - unix-connect:$(< ~/vimb.socket)
+.EE
.TP
.B "\-h, \-\-help"
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
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
.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
# 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 "<Esc>::e! _vbform.fill($data);<CR>" > $VIMB_FIFO
+ echo "<Esc>::e! _vbform.fill($data);<CR>" | 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
#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 */
*/
#include "config.h"
-#ifdef FEATURE_FIFO
+#ifdef FEATURE_SOCKET
#include "io.h"
#include "main.h"
#include "map.h"
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <errno.h>
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);
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;
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;
}
*/
#include "config.h"
-#ifdef FEATURE_FIFO
+#ifdef FEATURE_SOCKET
#ifndef _IO_H
#define _IO_H
#include <glib.h>
-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 */
+ (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 *)
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;
#ifdef FEATURE_ARH
arh_free(vb.config.autoresponseheader);
#endif
-#ifdef FEATURE_FIFO
+#ifdef FEATURE_SOCKET
io_cleanup();
#endif
g_free(vb.state.pid_str);
{
static char *winid = NULL;
static gboolean ver = false;
-#ifdef FEATURE_FIFO
+#ifdef FEATURE_SOCKET
static gboolean dump = false;
#endif
static GError *err;
{"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},
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
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;
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 */