Replaced FIFO interface with socket.
authorBarrucadu <mike@barrucadu.co.uk>
Wed, 29 Apr 2009 18:01:48 +0000 (19:01 +0100)
committerBarrucadu <mike@barrucadu.co.uk>
Wed, 29 Apr 2009 18:01:48 +0000 (19:01 +0100)
.gitignore
Makefile
TODO
examples/scripts/load_url_from_bookmarks.sh
examples/scripts/load_url_from_history.sh
uzbl.c
uzblctrl.c [new file with mode: 0644]

index 5dc9796..471b6f4 100644 (file)
@@ -1 +1,2 @@
-uzbl
\ No newline at end of file
+uzbl
+uzblctrl
\ No newline at end of file
index a70ca9a..fa68594 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 CPPFLAGS=$(shell pkg-config --cflags gtk+-2.0 webkit-1.0) -Wall -W
 LDFLAGS=$(shell pkg-config --libs gtk+-2.0 webkit-1.0)
-all: uzbl
+all: uzbl uzblctrl
 
 test:
        ./uzbl --uri http://www.uzbl.org
@@ -13,12 +13,14 @@ test-config-real:
        
 clean:
        rm -f uzbl
+       rm -f uzblctrl
 
 install:
        install -d $(DESTDIR)/usr/bin
        install -d $(DESTDIR)/usr/share/uzbl/docs
        install -d $(DESTDIR)/usr/share/uzbl/examples
        install -D -m755 uzbl $(DESTDIR)/usr/bin/uzbl
+       install -D -m755 uzblctrl $(DESTDIR)/usr/bin/uzblctrl
        cp -ax examples $(DESTDIR)/usr/share/uzbl/
        install -D -m644 CHECKLIST $(DESTDIR)/usr/share/uzbl/docs
        install -D -m644 README $(DESTDIR)/usr/share/uzbl/docs
diff --git a/TODO b/TODO
index 8f5a7f2..fbedb5a 100644 (file)
--- a/TODO
+++ b/TODO
@@ -11,7 +11,7 @@ ASAP
 * implement a vimperator-like link following scheme.  but let user pick his favorite characters to construct the "link identifiers" with.
 * add a keybind to hand the current url to an external scrips, so you can edit it and/or store it in the primary and secondary clipboards
 * use http://library.gnome.org/devel/glib/stable/glib-Hash-Tables.html#g-hash-table-insert for tracking bindings and wherever we use structs and ugly loops
-* fifo -> socket. so you can do question-response. socket is slightly more complicated so we'll need to create a uzblctrl
+* fifo -> socket. so you can do question-response. socket is slightly more complicated so we'll need to create a uzblctrl (half done - commands can't yet send data back)
 * select/fork based instead of the pthread stuff -> drops dependency, more lightweight.
 * on website, see if we can <pre><?php include('..'); ?></pre> the documentation inside the uzbl project itself, so we need to maintain the stuff on only 1 place
 * see if we can use the github bugtracker (anonymous posting allowed?)
index ca512eb..7dffafe 100755 (executable)
@@ -9,4 +9,4 @@ else
 fi
 
 goto=`awk '{print $1}' $file | dmenu` #NOTE: it's the job of the script that inserts bookmarks to make sure there are no dupes.
-[ -n "$goto" ] && echo "uri $goto" > $4
+[ -n "$goto" ] && uzblctrl -s $4 -c "uri $goto"
index 366aedf..08cf413 100755 (executable)
@@ -3,4 +3,4 @@
 history_file=/tmp/uzbl.history
 
 goto=`awk '{print $3}' $history_file | sort | uniq | dmenu`
-[ -n "$goto" ] && echo "uri $goto" > $4
+[ -n "$goto" ] && uzblctrl -s $4 -c "uri $goto"
diff --git a/uzbl.c b/uzbl.c
index dcf5fe5..cf46f25 100644 (file)
--- a/uzbl.c
+++ b/uzbl.c
 #include <sys/types.h>
 #include <unistd.h>
 #include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
 
 /* housekeeping / internal variables */
 static GtkWidget* main_window;
@@ -52,18 +57,17 @@ static gchar* main_title;
 static gchar selected_url[500] = "\0";
 static gint load_progress;
 static Window xwin = 0;
-static char fifopath[64];
+static char socket_path[108];
 
 /* state variables (initial values coming from command line arguments but may be changed later) */
 static gchar*   uri         = NULL;
 static gchar*   config_file = NULL;
 static gchar    config_file_path[500];
-
 static gboolean verbose     = FALSE;
 
 /* settings from config: group behaviour */
 static gchar*   history_handler    = NULL;
-static gchar*   fifodir            = NULL;
+static gchar*   socket_dir         = NULL;
 static gchar*   download_handler   = NULL;
 static gboolean always_insert_mode = FALSE;
 static gboolean show_status        = FALSE;
@@ -331,10 +335,10 @@ close_uzbl (WebKitWebView * web_view) {
 // make sure to put '' around args, so that if there is whitespace we can still keep arguments together.
 static gboolean
 run_command(const char *command, const char *args) {
-   //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl fifo file> [args]
+   //command <uzbl conf> <uzbl pid> <uzbl win id> <uzbl socket file> [args]
     GString* to_execute = g_string_new ("");
     gboolean result;
-    g_string_printf (to_execute, "%s '%s' '%i' '%i' '%s'", command, config_file, (int) getpid() , (int) xwin, fifopath);
+    g_string_printf (to_execute, "%s '%s' '%i' '%i' '%s'", command, config_file, (int) getpid() , (int) xwin, socket_path);
     if(args) {
         g_string_append_printf (to_execute, " %s", args);
     }
@@ -383,34 +387,60 @@ parse_command(const char *cmd) {
 }
  
 static void
-*control_fifo() {
-    if (fifodir) {
-        sprintf (fifopath, "%s/uzbl_%d", fifodir, (int) xwin);
+*control_socket() {
+    if (socket_dir) {
+        sprintf (socket_path, "%s/uzbl_%d", socket_dir, (int) xwin);
     } else {
-        sprintf (fifopath, "/tmp/uzbl_%d", (int) xwin);
+        sprintf (socket_path, "/tmp/uzbl_%d", (int) xwin);
     }
  
-    if (mkfifo (fifopath, 0666) == -1) {
-        printf ("Possible error creating fifo\n");
+    int sock, clientsock, len;
+    unsigned int t;
+    struct sockaddr_un local, remote;
+
+    sock = socket (AF_UNIX, SOCK_STREAM, 0);
+
+    local.sun_family = AF_UNIX;
+    strcpy (local.sun_path, socket_path);
+    unlink (local.sun_path);
+
+    len = strlen (local.sun_path) + sizeof (local.sun_family);
+    bind (sock, (struct sockaddr *) &local, len);
+
+    if (errno == -1) {
+        printf ("A problem occurred when opening a socket in %s\n", socket_path);
+    } else {
+        printf ("Control socket opened in %s\n", socket_path);
     }
+
+    listen (sock, 5);
  
-    printf ("Control fifo opened in %s\n", fifopath);
-    while (true) {
-        FILE *fifo = fopen (fifopath, "r");
-        if (!fifo) {
-            printf ("Could not open %s for reading\n", fifopath);
-            return NULL;
-        }
-        
-        char buffer[256];
+    for(;;) {
+        int done, n;
+        char buffer[512];
+        char temp[128];
+
         memset (buffer, 0, sizeof (buffer));
-        while (!feof (fifo) && fgets (buffer, sizeof (buffer), fifo)) {
-            if (strcmp (buffer, "\n")) {
-                buffer[strlen (buffer) - 1] = '\0'; // Remove newline
-                parse_command (buffer);
-            }
+
+        t          = sizeof (remote);
+        clientsock = accept (sock, (struct sockaddr *) &remote, &t);
+        printf ("Connected to client\n");
+
+        done = 0;
+        do {
+            n = recv (clientsock, temp, 128, 0);
+            if (n == 0)
+                done = 1;
+
+            if (!done)
+                strcat (buffer, temp);
+        } while (!done);
+
+        if (strcmp (buffer, "\n")) {
+            buffer[strlen (buffer) - 1] = '\0';
+            parse_command (buffer);
         }
+        close(clientsock);
     }
     
     return NULL;
@@ -419,7 +449,7 @@ static void
 static void
 setup_threading () {
     pthread_t control_thread;
-    pthread_create(&control_thread, NULL, control_fifo, NULL);
+    pthread_create(&control_thread, NULL, control_socket, NULL);
 }
 
 static void
@@ -613,13 +643,13 @@ settings_init () {
         keyse              = g_key_file_get_keys    (config, "bindings_external",        NULL, NULL);
         status_top         = g_key_file_get_boolean (config, "behavior", "status_top",         NULL);
         home_page          = g_key_file_get_value   (config, "behavior", "home_page",          NULL);
-        if (! fifodir)
-            fifodir        = g_key_file_get_value   (config, "behavior", "fifodir",            NULL);
+        if (! socket_dir)
+            socket_dir     = g_key_file_get_value   (config, "behavior", "socket_dir",            NULL);
     }
        
     printf ("History handler: %s\n",    (history_handler    ? history_handler  : "disabled"));
     printf ("Download manager: %s\n",   (download_handler   ? download_handler : "disabled"));
-    printf ("FIFO directory: %s\n",     (fifodir            ? fifodir          : "/tmp"));
+    printf ("Socket directory: %s\n",   (socket_dir         ? socket_dir       : "/tmp"));
     printf ("Always insert mode: %s\n", (always_insert_mode ? "TRUE"           : "FALSE"));
     printf ("Show status: %s\n",        (show_status        ? "TRUE"           : "FALSE"));
     printf ("Status top: %s\n",         (status_top         ? "TRUE"           : "FALSE"));
@@ -713,7 +743,7 @@ main (int argc, char* argv[]) {
 
     gtk_main ();
 
-    unlink (fifopath);
+    unlink (socket_path);
     return 0;
 }
 
diff --git a/uzblctrl.c b/uzblctrl.c
new file mode 100644 (file)
index 0000000..5415247
--- /dev/null
@@ -0,0 +1,63 @@
+/* Socket code more or less completely copied from here: http://www.ecst.csuchico.edu/~beej/guide/ipc/usock.html */
+
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <gdk/gdkkeysyms.h>
+#include <webkit/webkit.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+
+static gchar* sockpath;
+static gchar* command;
+
+static GOptionEntry entries[] =
+{
+    { "socket",  's', 0, G_OPTION_ARG_STRING, &sockpath, "Socket path of the client uzbl", NULL },
+    { "command", 'c', 0, G_OPTION_ARG_STRING, &command,  "The uzbl command to execute",    NULL },
+    { NULL,       0,  0, 0,                    NULL,      NULL,                            NULL }
+};
+
+int
+main(int argc, char* argv[]) {
+    GError *error = NULL;
+    GOptionContext* context = g_option_context_new ("- some stuff here maybe someday");
+    g_option_context_add_main_entries (context, entries, NULL);
+    g_option_context_add_group        (context, gtk_get_option_group (TRUE));
+    g_option_context_parse            (context, &argc, &argv, &error);
+    
+    int s, len;
+    struct sockaddr_un remote;
+    
+    if ((s = socket (AF_UNIX, SOCK_STREAM, 0)) == -1) {
+        perror ("socket");
+        exit (1);
+    }
+    
+    remote.sun_family = AF_UNIX;
+    strcpy (remote.sun_path, (char *) sockpath);
+    len = strlen (remote.sun_path) + sizeof (remote.sun_family);
+
+    if (connect (s, (struct sockaddr *) &remote, len) == -1) {
+        perror ("connect");
+        exit (1);
+    }
+    
+    if (send (s, command, strlen (command), 0) == -1) {
+        perror ("send");
+        exit (1);
+    }
+    
+    close(s);
+    
+    return 0;
+}