comparison lisp/server.el @ 83044:52039abab942

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
author Karoly Lorentey <lorentey@elte.hu>
date Fri, 20 Feb 2004 01:22:10 +0000
parents 78a785f205ea
children a871be7b26a5
comparison
equal deleted inserted replaced
83043:78a785f205ea 83044:52039abab942
347 :version "21.4" 347 :version "21.4"
348 ;; Fixme: Should this check for an existing server socket and do 348 ;; Fixme: Should this check for an existing server socket and do
349 ;; nothing if there is one (for multiple Emacs sessions)? 349 ;; nothing if there is one (for multiple Emacs sessions)?
350 (server-start (not server-mode))) 350 (server-start (not server-mode)))
351 351
352 (defmacro server-with-errors-reported (&rest forms)
353 "Evaluate FORMS; if an error occurs, report it to the client
354 and return nil. Otherwise, return the result of the last form.
355 For use in server-process-filter only."
356 `(condition-case err
357 (progn ,@forms)
358 (error (ignore-errors
359 (process-send-string
360 proc (concat "-error " (error-message-string err)))
361 (setq request "")))))
362
363 (defun server-process-filter (proc string) 352 (defun server-process-filter (proc string)
364 "Process a request from the server to edit some files. 353 "Process a request from the server to edit some files.
365 PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"." 354 PROC is the server process. Format of STRING is \"PATH PATH PATH... \\n\"."
366 (server-log string proc) 355 (server-log string proc)
367 (let ((prev (process-get proc 'previous-string))) 356 (let ((prev (process-get proc 'previous-string)))
368 (when prev 357 (when prev
369 (setq string (concat prev string)) 358 (setq string (concat prev string))
370 (process-put proc 'previous-string nil))) 359 (process-put proc 'previous-string nil)))
371 ;; If the input is multiple lines, 360 (condition-case err
372 ;; process each line individually. 361 ;; If the input is multiple lines,
373 (while (string-match "\n" string) 362 ;; process each line individually.
374 (let ((request (substring string 0 (match-beginning 0))) 363 (while (string-match "\n" string)
375 (coding-system (and default-enable-multibyte-characters 364 (let ((request (substring string 0 (match-beginning 0)))
376 (or file-name-coding-system 365 (coding-system (and default-enable-multibyte-characters
377 default-file-name-coding-system))) 366 (or file-name-coding-system
378 client nowait eval newframe display 367 default-file-name-coding-system)))
379 registered ; t if the client is already added to server-clients. 368 client nowait eval newframe display version-checked
380 (files nil) 369 registered ; t if the client is already added to server-clients.
381 (lineno 1) 370 (files nil)
382 (columnno 0)) 371 (lineno 1)
383 ;; Remove this line from STRING. 372 (columnno 0))
384 (setq string (substring string (match-end 0))) 373 ;; Remove this line from STRING.
385 (setq client (cons proc nil)) 374 (setq string (substring string (match-end 0)))
386 (while (string-match "[^ ]* " request) 375 (setq client (cons proc nil))
387 (let ((arg (substring request (match-beginning 0) (1- (match-end 0))))) 376 (while (string-match "[^ ]* " request)
388 (setq request (substring request (match-end 0))) 377 (let ((arg (substring request (match-beginning 0) (1- (match-end 0)))))
389 (cond
390 ((equal "-nowait" arg) (setq nowait t))
391 ((equal "-eval" arg) (setq eval t))
392
393 ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request))
394 (setq display (match-string 1 request)
395 request (substring request (match-end 0))))
396
397 ;; Open a new X frame.
398 ((equal "-window-system" arg)
399 (server-with-errors-reported
400 (let ((frame (make-frame-on-display
401 (or display
402 (frame-parameter nil 'display)
403 (getenv "DISPLAY")
404 (error "Please specify display")))))
405 (push (list proc frame) server-frames)
406 (select-frame frame)
407 ;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right.
408 (push client server-clients)
409 (setq registered t
410 newframe t))))
411
412 ;; Open a new tty frame at the client. ARG is the name of the pseudo tty.
413 ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
414 (let ((tty (server-unquote-arg (match-string 1 request)))
415 (type (server-unquote-arg (match-string 2 request))))
416 (setq request (substring request (match-end 0))) 378 (setq request (substring request (match-end 0)))
417 (server-with-errors-reported 379 (cond
418 (let ((frame (make-frame-on-tty tty type))) 380 ;; Check version numbers.
419 (push (list (car client) (frame-tty-name frame)) server-ttys) 381 ((and (equal "-version" arg) (string-match "\\([0-9.]+\\) " request))
420 (process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n")) 382 (let* ((client-version (match-string 1 request))
421 (select-frame frame) 383 (truncated-emacs-version (substring emacs-version 0 (length client-version))))
422 ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right. 384 (setq request (substring request (match-end 0)))
423 (push client server-clients) 385 (if (equal client-version truncated-emacs-version)
424 (setq registered t 386 (progn
425 newframe t))))) 387 (process-send-string proc "-good-version \n")
426 388 (setq version-checked t))
427 ;; ARG is a line number option. 389 (error (concat "Version mismatch: Emacs is " truncated-emacs-version ", emacsclient is " client-version)))))
428 ((string-match "\\`\\+[0-9]+\\'" arg) 390
429 (setq lineno (string-to-int (substring arg 1)))) 391 ((equal "-nowait" arg) (setq nowait t))
430 392 ((equal "-eval" arg) (setq eval t))
431 ;; ARG is line number:column option. 393
432 ((string-match "\\`\\+\\([0-9]+\\):\\([0-9]+\\)\\'" arg) 394 ((and (equal "-display" arg) (string-match "\\([^ ]*\\) " request))
433 (setq lineno (string-to-int (match-string 1 arg)) 395 (setq display (match-string 1 request)
434 columnno (string-to-int (match-string 2 arg)))) 396 request (substring request (match-end 0))))
435 397
436 ;; ARG is a filename or a Lisp expression. 398 ;; Open a new X frame.
437 (t 399 ((equal "-window-system" arg)
438 400 (unless version-checked
439 ;; Undo the quoting that emacsclient does 401 (error "Protocol error; make sure to use the correct version of emacsclient"))
440 ;; for certain special characters. 402 (let ((frame (make-frame-on-display
441 (setq arg (server-unquote-arg arg)) 403 (or display
442 ;; Now decode the file name if necessary. 404 (frame-parameter nil 'display)
443 (if coding-system 405 (getenv "DISPLAY")
444 (setq arg (decode-coding-string arg coding-system))) 406 (error "Please specify display")))))
445 (if eval 407 (push (list proc frame) server-frames)
446 (server-with-errors-reported 408 (select-frame frame)
447 (let ((v (eval (car (read-from-string arg))))) 409 ;; This makes sure that `emacsclient -w -e '(delete-frame)'' works right.
448 (when (and (not newframe) v) 410 (push client server-clients)
449 (with-temp-buffer 411 (setq registered t
450 (let ((standard-output (current-buffer))) 412 newframe t)))
451 (pp v) 413
452 (process-send-string proc "-print ") 414 ;; Open a new tty frame at the client. ARG is the name of the pseudo tty.
453 (process-send-region proc (point-min) (point-max))))))) 415 ((and (equal "-tty" arg) (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
454 416 (let ((tty (server-unquote-arg (match-string 1 request)))
455 ;; ARG is a file name. 417 (type (server-unquote-arg (match-string 2 request))))
456 ;; Collapse multiple slashes to single slashes. 418 (setq request (substring request (match-end 0)))
457 (setq arg (command-line-normalize-file-name arg)) 419 (unless version-checked
458 (push (list arg lineno columnno) files)) 420 (error "Protocol error; make sure to use the correct version of emacsclient"))
459 (setq lineno 1) 421 (let ((frame (make-frame-on-tty tty type)))
460 (setq columnno 0))))) 422 (push (list (car client) (frame-tty-name frame)) server-ttys)
461 423 (process-send-string proc (concat "-emacs-pid " (number-to-string (emacs-pid)) "\n"))
462 (when files 424 (select-frame frame)
463 (run-hooks 'pre-command-hook) 425 ;; This makes sure that `emacsclient -t -e '(delete-frame)'' works right.
464 (server-visit-files files client nowait) 426 (push client server-clients)
465 (run-hooks 'post-command-hook)) 427 (setq registered t
466 ;; CLIENT is now a list (CLIENTNUM BUFFERS...) 428 newframe t))))
467 (if (and (not newframe) (null (cdr client))) 429
468 ;; This client is empty; get rid of it immediately. 430 ;; ARG is a line number option.
469 (progn 431 ((string-match "\\`\\+[0-9]+\\'" arg)
470 (delete-process proc) 432 (setq lineno (string-to-int (substring arg 1))))
471 (server-log "Close empty client" proc)) 433
472 ;; We visited some buffer for this client. 434 ;; ARG is line number:column option.
473 (or nowait registered (push client server-clients)) 435 ((string-match "\\`\\+\\([0-9]+\\):\\([0-9]+\\)\\'" arg)
474 (unless (or isearch-mode (minibufferp)) 436 (setq lineno (string-to-int (match-string 1 arg))
475 (if (and newframe (null (cdr client))) 437 columnno (string-to-int (match-string 2 arg))))
476 (message (substitute-command-keys 438
477 "When done with this frame, type \\[delete-frame]")) 439 ;; ARG is a filename or a Lisp expression.
478 (server-switch-buffer (nth 1 client)) 440 (t
479 (run-hooks 'server-switch-hook) 441 ;; Undo the quoting that emacsclient does
480 (unless nowait 442 ;; for certain special characters.
481 (message (substitute-command-keys 443 (setq arg (server-unquote-arg arg))
482 "When done with a buffer, type \\[server-edit]")))))))) 444 ;; Now decode the file name if necessary.
483 ;; Save for later any partial line that remains. 445 (if coding-system
484 (when (> (length string) 0) 446 (setq arg (decode-coding-string arg coding-system)))
485 (process-put proc 'previous-string string))) 447 (unless version-checked
448 (error "Protocol error; make sure to use the correct version of emacsclient"))
449 (if eval
450 ;; ARG is a Lisp expression.
451 (let ((v (eval (car (read-from-string arg)))))
452 (when (and (not newframe) v)
453 (with-temp-buffer
454 (let ((standard-output (current-buffer)))
455 (pp v)
456 (process-send-string proc "-print ")
457 (process-send-region proc (point-min) (point-max))))))
458 ;; ARG is a file name.
459 ;; Collapse multiple slashes to single slashes.
460 (setq arg (command-line-normalize-file-name arg))
461 (push (list arg lineno columnno) files))
462 (setq lineno 1)
463 (setq columnno 0)))))
464
465 (if (not version-checked)
466 (error "Protocol error; make sure to use the correct version of emacsclient")
467 (when files
468 (run-hooks 'pre-command-hook)
469 (server-visit-files files client nowait)
470 (run-hooks 'post-command-hook))
471 ;; CLIENT is now a list (CLIENTNUM BUFFERS...)
472 (if (and (not newframe) (null (cdr client)))
473 ;; This client is empty; get rid of it immediately.
474 (progn
475 (delete-process proc)
476 (server-log "Close empty client" proc))
477 ;; We visited some buffer for this client.
478 (or nowait registered (push client server-clients))
479 (unless (or isearch-mode (minibufferp))
480 (if (and newframe (null (cdr client)))
481 (message (substitute-command-keys
482 "When done with this frame, type \\[delete-frame]"))
483 (server-switch-buffer (nth 1 client))
484 (run-hooks 'server-switch-hook)
485 (unless nowait
486 (message (substitute-command-keys
487 "When done with a buffer, type \\[server-edit]"))))))))
488 ;; Save for later any partial line that remains.
489 (when (> (length string) 0)
490 (process-put proc 'previous-string string)))
491 ;; condition-case
492 (error (ignore-errors
493 (process-send-string
494 proc (concat "-error " (error-message-string err)))
495 (setq string "")
496 (server-log (error-message-string err) proc)
497 (delete-process proc)))))
486 498
487 (defun server-goto-line-column (file-line-col) 499 (defun server-goto-line-column (file-line-col)
488 (goto-line (nth 1 file-line-col)) 500 (goto-line (nth 1 file-line-col))
489 (let ((column-number (nth 2 file-line-col))) 501 (let ((column-number (nth 2 file-line-col)))
490 (if (> column-number 0) 502 (if (> column-number 0)