Verify the version of Emacsclient.

lib-src/emacsclient.c (main): Send the version number of emacsclient
to the Emacs process, and exit with error if Emacs does not accept it.

lisp/server.el (server-with-errors-reported): Removed.
(server-process-filter): Cleaned up error handling.
Compare the version of emacsclient with emacs-version; 
signal an error if they do not match.

git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-84
This commit is contained in:
Karoly Lorentey 2004-02-20 01:22:10 +00:00
parent 77134727c9
commit a9298135d8
2 changed files with 148 additions and 120 deletions

View file

@ -562,6 +562,9 @@ To start the server in Emacs, type \"M-x server-start\".\n",
fail (); fail ();
} }
/* First of all, send our version number for verification. */
fprintf (out, "-version %s ", VERSION);
if (nowait) if (nowait)
fprintf (out, "-nowait "); fprintf (out, "-nowait ");
@ -650,7 +653,20 @@ To start the server in Emacs, type \"M-x server-start\".\n",
/* Now, wait for an answer and print any messages. */ /* Now, wait for an answer and print any messages. */
while ((str = fgets (string, BUFSIZ, in))) while ((str = fgets (string, BUFSIZ, in)))
{ {
if (strprefix ("-emacs-pid ", str)) if (strprefix ("-good-version ", str))
{
/* OK, we got the green light. */
}
else if (strprefix ("-bad-version ", str))
{
if (str[strlen (str) - 1] == '\n')
str[strlen (str) - 1] = 0;
fprintf (stderr, "%s: Version mismatch: Emacs is %s, but we are %s\n",
argv[0], str + strlen ("-bad-version "), VERSION);
fail ();
}
else if (strprefix ("-emacs-pid ", str))
{ {
emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10); emacs_pid = strtol (string + strlen ("-emacs-pid"), NULL, 10);
} }

View file

@ -349,17 +349,6 @@ Server mode runs a process that accepts commands from the
;; nothing if there is one (for multiple Emacs sessions)? ;; nothing if there is one (for multiple Emacs sessions)?
(server-start (not server-mode))) (server-start (not server-mode)))
(defmacro server-with-errors-reported (&rest forms)
"Evaluate FORMS; if an error occurs, report it to the client
and return nil. Otherwise, return the result of the last form.
For use in server-process-filter only."
`(condition-case err
(progn ,@forms)
(error (ignore-errors
(process-send-string
proc (concat "-error " (error-message-string err)))
(setq request "")))))
(defun server-process-filter (proc string) (defun server-process-filter (proc string)
"Process a request from the server to edit some files. "Process a request from the server to edit some files.
PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"." PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
@ -368,6 +357,7 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
(when prev (when prev
(setq string (concat prev string)) (setq string (concat prev string))
(process-put proc 'previous-string nil))) (process-put proc 'previous-string nil)))
(condition-case err
;; If the input is multiple lines, ;; If the input is multiple lines,
;; process each line individually. ;; process each line individually.
(while (string-match "\n" string) (while (string-match "\n" string)
@ -375,7 +365,7 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
(coding-system (and default-enable-multibyte-characters (coding-system (and default-enable-multibyte-characters
(or file-name-coding-system (or file-name-coding-system
default-file-name-coding-system))) default-file-name-coding-system)))
client nowait eval newframe display client nowait eval newframe display version-checked
registered ; t if the client is already added to server-clients. registered ; t if the client is already added to server-clients.
(files nil) (files nil)
(lineno 1) (lineno 1)
@ -387,6 +377,17 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
(let ((arg (substring request (match-beginning 0) (1- (match-end 0))))) (let ((arg (substring request (match-beginning 0) (1- (match-end 0)))))
(setq request (substring request (match-end 0))) (setq request (substring request (match-end 0)))
(cond (cond
;; Check version numbers.
((and (equal "-version" arg) (string-match "\\([0-9.]+\\) " request))
(let* ((client-version (match-string 1 request))
(truncated-emacs-version (substring emacs-version 0 (length client-version))))
(setq request (substring request (match-end 0)))
(if (equal client-version truncated-emacs-version)
(progn
(process-send-string proc "-good-version \n")
(setq version-checked t))
(error (concat "Version mismatch: Emacs is " truncated-emacs-version ", emacsclient is " client-version)))))
((equal "-nowait" arg) (setq nowait t)) ((equal "-nowait" arg) (setq nowait t))
((equal "-eval" arg) (setq eval t)) ((equal "-eval" arg) (setq eval t))
@ -396,7 +397,8 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
;; Open a new X frame. ;; Open a new X frame.
((equal "-window-system" arg) ((equal "-window-system" arg)
(server-with-errors-reported (unless version-checked
(error "Protocol error; make sure to use the correct version of emacsclient"))
(let ((frame (make-frame-on-display (let ((frame (make-frame-on-display
(or display (or display
(frame-parameter nil 'display) (frame-parameter nil 'display)
@ -407,14 +409,15 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right. ;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right.
(push client server-clients) (push client server-clients)
(setq registered t (setq registered t
newframe t)))) newframe t)))
;; Open a new tty frame at the client. ARG is the name of the pseudo tty. ;; Open a new tty frame at the client. ARG is the name of the pseudo tty.
((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request)) ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
(let ((tty (server-unquote-arg (match-string 1 request))) (let ((tty (server-unquote-arg (match-string 1 request)))
(type (server-unquote-arg (match-string 2 request)))) (type (server-unquote-arg (match-string 2 request))))
(setq request (substring request (match-end 0))) (setq request (substring request (match-end 0)))
(server-with-errors-reported (unless version-checked
(error "Protocol error; make sure to use the correct version of emacsclient"))
(let ((frame (make-frame-on-tty tty type))) (let ((frame (make-frame-on-tty tty type)))
(push (list (car client) (frame-tty-name frame)) server-ttys) (push (list (car client) (frame-tty-name frame)) server-ttys)
(process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) (process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n"))
@ -422,7 +425,7 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right. ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right.
(push client server-clients) (push client server-clients)
(setq registered t (setq registered t
newframe t))))) newframe t))))
;; ARG is a line number option. ;; ARG is a line number option.
((string-match "\\`\\+[0-9]+\\'" arg) ((string-match "\\`\\+[0-9]+\\'" arg)
@ -435,23 +438,23 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
;; ARG is a filename or a Lisp expression. ;; ARG is a filename or a Lisp expression.
(t (t
;; Undo the quoting that emacsclient does ;; Undo the quoting that emacsclient does
;; for certain special characters. ;; for certain special characters.
(setq arg (server-unquote-arg arg)) (setq arg (server-unquote-arg arg))
;; Now decode the file name if necessary. ;; Now decode the file name if necessary.
(if coding-system (if coding-system
(setq arg (decode-coding-string arg coding-system))) (setq arg (decode-coding-string arg coding-system)))
(unless version-checked
(error "Protocol error; make sure to use the correct version of emacsclient"))
(if eval (if eval
(server-with-errors-reported ;; ARG is a Lisp expression.
(let ((v (eval (car (read-from-string arg))))) (let ((v (eval (car (read-from-string arg)))))
(when (and (not newframe) v) (when (and (not newframe) v)
(with-temp-buffer (with-temp-buffer
(let ((standard-output (current-buffer))) (let ((standard-output (current-buffer)))
(pp v) (pp v)
(process-send-string proc "-print ") (process-send-string proc "-print ")
(process-send-region proc (point-min) (point-max))))))) (process-send-region proc (point-min) (point-max))))))
;; ARG is a file name. ;; ARG is a file name.
;; Collapse multiple slashes to single slashes. ;; Collapse multiple slashes to single slashes.
(setq arg (command-line-normalize-file-name arg)) (setq arg (command-line-normalize-file-name arg))
@ -459,6 +462,8 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
(setq lineno 1) (setq lineno 1)
(setq columnno 0))))) (setq columnno 0)))))
(if (not version-checked)
(error "Protocol error; make sure to use the correct version of emacsclient")
(when files (when files
(run-hooks 'pre-command-hook) (run-hooks 'pre-command-hook)
(server-visit-files files client nowait) (server-visit-files files client nowait)
@ -483,6 +488,13 @@ PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
;; Save for later any partial line that remains. ;; Save for later any partial line that remains.
(when (> (length string) 0) (when (> (length string) 0)
(process-put proc 'previous-string string))) (process-put proc 'previous-string string)))
;; condition-case
(error (ignore-errors
(process-send-string
proc (concat "-error " (error-message-string err)))
(setq string "")
(server-log (error-message-string err) proc)
(delete-process proc)))))
(defun server-goto-line-column (file-line-col) (defun server-goto-line-column (file-line-col)
(goto-line (nth 1 file-line-col)) (goto-line (nth 1 file-line-col))