From b01390785ede54e5f178094924b30bb33e290123 Mon Sep 17 00:00:00 2001 From: djcb Date: Sat, 28 Apr 2012 09:05:05 +0300 Subject: [PATCH] * mu4e-proc, mu-cmd-server: update server output protocol - this unbreaks running mu server on non-utf8 locales - should also be a bit faster - configure.ac: bump version --- configure.ac | 2 +- emacs/mu4e-proc.el | 38 ++++++++++++++++++++++++++++---------- src/mu-cmd-server.c | 27 ++++++++++++++++++++++----- 3 files changed, 51 insertions(+), 16 deletions(-) diff --git a/configure.ac b/configure.ac index 85ab8438..0d83c88c 100644 --- a/configure.ac +++ b/configure.ac @@ -14,7 +14,7 @@ ## along with this program; if not, write to the Free Software Foundation, ## Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. -AC_INIT([mu],[0.9.8.4-dev2],[http://code.google.com/p/mu0/issues/list],[mu]) +AC_INIT([mu],[0.9.8.4-dev3],[http://code.google.com/p/mu0/issues/list],[mu]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_SRCDIR([src/mu.cc]) # libtoolize wants to put some stuff in here; if you have an old diff --git a/emacs/mu4e-proc.el b/emacs/mu4e-proc.el index 2da8ca4f..fd727c27 100644 --- a/emacs/mu4e-proc.el +++ b/emacs/mu4e-proc.el @@ -34,9 +34,23 @@ (defvar mu4e~proc-buf nil "Buffer for results data.") (defconst mu4e~proc-name "*mu4e-proc*" "Name of the server process, buffer.") (defvar mu4e~proc-process nil "The mu-server process") -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; dealing with the length cookie that precedes expressions +(defconst mu4e~cookie-pre "\376" + "Each expression we get from the backend (mu server) starts with + a length cookie: + <`mu4e~cookie-pre'><`mu4e~cookie-post'>.") +(defconst mu4e~cookie-post "\377" + "Each expression we get from the backend (mu server) starts with + a length cookie: + <`mu4e~cookie-pre'><`mu4e~cookie-post'>.") +(defconst mu4e~cookie-matcher-rx + (concat mu4e~cookie-pre "\\([[:xdigit:]]+\\)" mu4e~cookie-post) + "Regular expression matching the length cookie. Match 1 will be +the length (in hex).") +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + (defun mu4e~proc-start () "Start the mu server process." @@ -78,16 +92,20 @@ (defun mu4e~proc-eat-sexp-from-buf () - "'Eat' the next s-expression from `mu4e~proc-buf'. `mu4e~proc-buf gets its - contents from the mu-servers in the following form: - \376\376 -Function returns this sexp, or nil if there was none. `mu4e~proc-buf' is -updated as well, with all processed sexp data removed." + "'Eat' the next s-expression from `mu4e~proc-buf'. Note: this is a string, +not an emacs-buffer. `mu4e~proc-buf gets its contents from the +mu-servers in the following form: + <`mu4e~cookie-pre'><`mu4e~cookie-post'> + +Function returns this sexp, or nil if there was +none. `mu4e~proc-buf' is updated as well, with all processed sexp +data removed." (when mu4e~proc-buf - ;; TODO: maybe try a non-regexp solution? - (let* ((b (string-match "\376\\([0-9]+\\)\376" mu4e~proc-buf)) + ;; mu4e~cookie-matcher-rx: + ;; (concat mu4e~cookie-pre "\\([[:xdigit:]]+\\)]" mu4e~cookie-post) + (let* ((b (string-match mu4e~cookie-matcher-rx mu4e~proc-buf)) (sexp-len - (when b (string-to-number (match-string 1 mu4e~proc-buf))))) + (when b (string-to-number (match-string 1 mu4e~proc-buf) 16)))) ;; does mu4e~proc-buf contain the full sexp? (when (and b (>= (length mu4e~proc-buf) (+ sexp-len (match-end 0)))) ;; clear-up start @@ -96,7 +114,7 @@ updated as well, with all processed sexp data removed." ;; is the sexp, and convert that to utf-8, before we interpret it. (let ((objcons (ignore-errors ;; note: this may fail if we killed the process - ;; in the middle + ;; in the middle (read-from-string (decode-coding-string (substring mu4e~proc-buf 0 sexp-len) 'utf-8))))) (when objcons diff --git a/src/mu-cmd-server.c b/src/mu-cmd-server.c index 3b12c4f2..c55f291f 100644 --- a/src/mu-cmd-server.c +++ b/src/mu-cmd-server.c @@ -82,17 +82,26 @@ install_sig_handler (void) /************************************************************************/ +/* + * Markers for/after the lenght cookie that precedes the expression we + * write to output. We use octal 376, 377 (ie, 0xfe, 0xff) as they + * will never occur in utf8 */ -/* BOX - beginning-of-expression */ -#define BOX "\376" +#define COOKIE_PRE '\376' +#define COOKIE_POST '\377' static void G_GNUC_PRINTF(1, 2) print_expr (const char* frm, ...) { char *expr; va_list ap; - size_t exprlen; + size_t exprlen, lenlen; + char cookie[16]; + static int outfd = 0; + + if (outfd == 0) + outfd = fileno (stdout); expr = NULL; @@ -100,8 +109,16 @@ print_expr (const char* frm, ...) exprlen = g_vasprintf (&expr, frm, ap); va_end (ap); - g_print (BOX "%u" BOX "%s\n", (unsigned)exprlen + 1, - expr); + /* this cookie tells the frontend where to expect the next + * expression */ + + cookie[0] = COOKIE_PRE; + lenlen = sprintf(cookie + 1, "%x", exprlen + 1); /* + 1 for \n */ + cookie[lenlen + 1] = COOKIE_POST; + + write (outfd, cookie, lenlen + 2); /* + 2 for the 2 BOX */ + write (outfd, expr, exprlen); + write (outfd, "\n", 1); g_free (expr); }