Drew Adams <drew.adams at oracle.com>
[bpt/emacs.git] / lisp / server.el
CommitLineData
55535639 1;;; server.el --- Lisp code for GNU Emacs running as server process
c88ab9ce 2
0d30b337 3;; Copyright (C) 1986, 1987, 1992, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
da6657b7 4;; 2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
6d74b528 5
630cc463 6;; Author: William Sommerfeld <wesommer@athena.mit.edu>
e4874521 7;; Maintainer: FSF
d7b4d18f 8;; Keywords: processes
630cc463 9
9ae0f972 10;; Changes by peck@sun.com and by rms.
35dfa9b6 11;; Overhaul by Karoly Lorentey <lorentey@elte.hu> for multi-tty support.
9ae0f972 12
13;; This file is part of GNU Emacs.
14
15;; GNU Emacs is free software; you can redistribute it and/or modify
16;; it under the terms of the GNU General Public License as published by
b4aa6026 17;; the Free Software Foundation; either version 3, or (at your option)
9ae0f972 18;; any later version.
19
20;; GNU Emacs is distributed in the hope that it will be useful,
21;; but WITHOUT ANY WARRANTY; without even the implied warranty of
22;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23;; GNU General Public License for more details.
24
25;; You should have received a copy of the GNU General Public License
b578f267 26;; along with GNU Emacs; see the file COPYING. If not, write to the
086add15
LK
27;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
28;; Boston, MA 02110-1301, USA.
9ae0f972 29
630cc463 30;;; Commentary:
9ae0f972 31
b578f267
EN
32;; This Lisp code is run in Emacs when it is to operate as
33;; a server for other processes.
9ae0f972 34
b578f267 35;; Load this library and do M-x server-edit to enable Emacs as a server.
44a56b29
SM
36;; Emacs opens up a socket for communication with clients. If there are no
37;; client buffers to edit, server-edit acts like (switch-to-buffer
38;; (other-buffer))
9ae0f972 39
b578f267
EN
40;; When some other program runs "the editor" to edit a file,
41;; "the editor" can be the Emacs client program ../lib-src/emacsclient.
42;; This program transmits the file names to Emacs through
43;; the server subprocess, and Emacs visits them and lets you edit them.
9ae0f972 44
6d3a46f7 45;; Note that any number of clients may dispatch files to Emacs to be edited.
9ae0f972 46
b578f267 47;; When you finish editing a Server buffer, again call server-edit
64f51134
JPW
48;; to mark that buffer as done for the client and switch to the next
49;; Server buffer. When all the buffers for a client have been edited
b578f267 50;; and exited with server-edit, the client "editor" will return
64f51134 51;; to the program that invoked it.
9ae0f972 52
b578f267
EN
53;; Your editing commands and Emacs's display output go to and from
54;; the terminal in the usual way. Thus, server operation is possible
55;; only when Emacs can talk to the terminal at the time you invoke
56;; the client. This is possible in four cases:
9ae0f972 57
b578f267
EN
58;; 1. On a window system, where Emacs runs in one window and the
59;; program that wants to use "the editor" runs in another.
9ae0f972 60
b578f267
EN
61;; 2. On a multi-terminal system, where Emacs runs on one terminal and the
62;; program that wants to use "the editor" runs on another.
9ae0f972 63
b578f267
EN
64;; 3. When the program that wants to use "the editor" is running
65;; as a subprocess of Emacs.
9ae0f972 66
b578f267
EN
67;; 4. On a system with job control, when Emacs is suspended, the program
68;; that wants to use "the editor" will stop and display
69;; "Waiting for Emacs...". It can then be suspended, and Emacs can be
70;; brought into the foreground for editing. When done editing, Emacs is
71;; suspended again, and the client program is brought into the foreground.
9ae0f972 72
64f51134
JPW
73;; The buffer local variable "server-buffer-clients" lists
74;; the clients who are waiting for this buffer to be edited.
b578f267
EN
75;; The global variable "server-clients" lists all the waiting clients,
76;; and which files are yet to be edited for each.
630cc463 77
0acb1916
SM
78;; Todo:
79
80;; - handle command-line-args-left.
81;; - move most of the args processing and decision making from emacsclient.c
82;; to here.
83;; - fix up handling of the client's environment (place it in the terminal?).
84
630cc463 85;;; Code:
8b3e840e
SM
86
87(eval-when-compile (require 'cl))
88
ab1c7f35
RS
89(defgroup server nil
90 "Emacs running as a server process."
91 :group 'external)
92
337e3c70
JB
93(defcustom server-use-tcp nil
94 "If non-nil, use TCP sockets instead of local sockets."
95 :set #'(lambda (sym val)
96 (unless (featurep 'make-network-process '(:family local))
97 (setq val t)
98 (unless load-in-progress
99 (message "Local sockets unsupported, using TCP sockets")))
100 (when val (random t))
101 (set-default sym val))
102 :group 'server
103 :type 'boolean
104 :version "22.1")
105
106(defcustom server-host nil
107 "The name or IP address to use as host address of the server process.
108If set, the server accepts remote connections; otherwise it is local."
109 :group 'server
110 :type '(choice
111 (string :tag "Name or IP address")
112 (const :tag "Local" nil))
113 :version "22.1")
114(put 'server-host 'risky-local-variable t)
115
0eee7a1d 116(defcustom server-auth-dir (concat user-emacs-directory "server/")
337e3c70
JB
117 "Directory for server authentication files."
118 :group 'server
119 :type 'directory
120 :version "22.1")
121(put 'server-auth-dir 'risky-local-variable t)
122
90caccca 123(defcustom server-raise-frame t
ff348fba 124 "If non-nil, raise frame when switching to a buffer."
90caccca
JB
125 :group 'server
126 :type 'boolean
127 :version "22.1")
128
ab1c7f35 129(defcustom server-visit-hook nil
ff348fba 130 "Hook run when visiting a file for the Emacs server."
ab1c7f35 131 :group 'server
0c851d78 132 :type 'hook)
ab1c7f35
RS
133
134(defcustom server-switch-hook nil
ff348fba 135 "Hook run when switching to a buffer for the Emacs server."
ab1c7f35 136 :group 'server
0c851d78 137 :type 'hook)
ab1c7f35
RS
138
139(defcustom server-done-hook nil
ff348fba 140 "Hook run when done editing a buffer for the Emacs server."
ab1c7f35 141 :group 'server
0c851d78 142 :type 'hook)
f9b3ef88 143
64f51134
JPW
144(defvar server-process nil
145 "The current server process.")
9ae0f972 146
147(defvar server-clients nil
148 "List of current server clients.
448f754f 149Each element is a process.")
0a125897 150
9ae0f972 151(defvar server-buffer-clients nil
5f3c1a63 152 "List of client processes requesting editing of current buffer.")
faf931a8 153(make-variable-buffer-local 'server-buffer-clients)
9ae0f972 154;; Changing major modes should not erase this local.
155(put 'server-buffer-clients 'permanent-local t)
156
33186f32 157(defcustom server-window nil
ff348fba 158 "Specification of the window to use for selecting Emacs server buffers.
ec40ed9f 159If nil, use the selected window.
408784a7 160If it is a function, it should take one argument (a buffer) and
33186f32
DL
161display and select it. A common value is `pop-to-buffer'.
162If it is a window, use that.
163If it is a frame, use the frame's selected window.
164
165It is not meaningful to set this to a specific frame or window with Custom.
166Only programs can do so."
167 :group 'server
bf247b6e 168 :version "22.1"
33186f32
DL
169 :type '(choice (const :tag "Use selected window"
170 :match (lambda (widget value)
171 (not (functionp value)))
172 nil)
ee9272ff 173 (function-item :tag "Display in new frame" switch-to-buffer-other-frame)
33186f32
DL
174 (function-item :tag "Use pop-to-buffer" pop-to-buffer)
175 (function :tag "Other function")))
ec40ed9f 176
ab1c7f35 177(defcustom server-temp-file-regexp "^/tmp/Re\\|/draft$"
ff348fba 178 "Regexp matching names of temporary files.
33186f32
DL
179These are deleted and reused after each edit by the programs that
180invoke the Emacs server."
ab1c7f35
RS
181 :group 'server
182 :type 'regexp)
9ae0f972 183
c6a117f0 184(defcustom server-kill-new-buffers t
ff348fba 185 "Whether to kill buffers when done with them.
c6a117f0 186If non-nil, kill a buffer unless it already existed before editing
f258b525 187it with the Emacs server. If nil, kill only buffers as specified by
c6a117f0 188`server-temp-file-regexp'.
f258b525
GM
189Please note that only buffers that still have a client are killed,
190i.e. buffers visited with \"emacsclient --no-wait\" are never killed in
c6a117f0
GM
191this way."
192 :group 'server
193 :type 'boolean
194 :version "21.1")
195
9ae0f972 196(or (assq 'server-buffer-clients minor-mode-alist)
b7621225 197 (push '(server-buffer-clients " Server") minor-mode-alist))
9ae0f972 198
c6a117f0 199(defvar server-existing-buffer nil
ca0c7250 200 "Non-nil means the buffer existed before the server was asked to visit it.
4dd04714 201This means that the server should not kill the buffer when you say you
ca0c7250 202are done with it in the server.")
c6a117f0
GM
203(make-variable-buffer-local 'server-existing-buffer)
204
03ae35cf
SM
205(defvar server-name "server")
206
fc0dcdef
KL
207(defvar server-socket-dir nil
208 "The directory in which to place the server socket.
209Initialized by `server-start'.")
0c851d78 210
9002956f
KL
211(defun server-clients-with (property value)
212 "Return a list of clients with PROPERTY set to VALUE."
213 (let (result)
448f754f
SM
214 (dolist (proc server-clients result)
215 (when (equal value (process-get proc property))
216 (push proc result)))))
9002956f
KL
217
218(defun server-add-client (proc)
219 "Create a client for process PROC, if it doesn't already have one.
220New clients have no properties."
448f754f 221 (add-to-list 'server-clients proc))
9002956f 222
59e085e0
KL
223(defmacro server-with-environment (env vars &rest body)
224 "Evaluate BODY with environment variables VARS set to those in ENV.
65f64034
KL
225The environment variables are then restored to their previous values.
226
59e085e0
KL
227VARS should be a list of strings.
228ENV should be in the same format as `process-environment'."
65f64034 229 (declare (indent 2))
13ba3740
SM
230 (let ((var (make-symbol "var"))
231 (value (make-symbol "value")))
232 `(let ((process-environment process-environment))
59e085e0 233 (dolist (,var ,vars)
e159b869 234 (let ((,value (getenv-internal ,var ,env)))
13ba3740
SM
235 (push (if (null ,value)
236 ,var
237 (concat ,var "=" ,value))
238 process-environment)))
239 (progn ,@body))))
65f64034 240
448f754f 241(defun server-delete-client (proc &optional noframe)
6ed8eeff 242 "Delete CLIENT, including its buffers, terminals and frames.
de93c791 243If NOFRAME is non-nil, let the frames live. (To be used from
5f3c1a63
KL
244`delete-frame-functions'.)"
245 (server-log (concat "server-delete-client" (if noframe " noframe"))
448f754f 246 proc)
9002956f 247 ;; Force a new lookup of client (prevents infinite recursion).
448f754f
SM
248 (when (memq proc server-clients)
249 (let ((buffers (process-get proc 'buffers)))
9002956f 250
5f3c1a63 251 ;; Kill the client's buffers.
9002956f 252 (dolist (buf buffers)
6ed9e43a
KL
253 (when (buffer-live-p buf)
254 (with-current-buffer buf
6ed9e43a 255 ;; Kill the buffer if necessary.
5f3c1a63
KL
256 (when (and (equal server-buffer-clients
257 (list proc))
6ed9e43a
KL
258 (or (and server-kill-new-buffers
259 (not server-existing-buffer))
5f3c1a63
KL
260 (server-temp-file-p))
261 (not (buffer-modified-p)))
262 (let (flag)
263 (unwind-protect
264 (progn (setq server-buffer-clients nil)
265 (kill-buffer (current-buffer))
266 (setq flag t))
267 (unless flag
268 ;; Restore clients if user pressed C-g in `kill-buffer'.
269 (setq server-buffer-clients (list proc)))))))))
9002956f 270
160f0817
KL
271 ;; Delete the client's frames.
272 (unless noframe
273 (dolist (frame (frame-list))
274 (when (and (frame-live-p frame)
275 (equal proc (frame-parameter frame 'client)))
276 ;; Prevent `server-handle-delete-frame' from calling us
277 ;; recursively.
278 (set-frame-parameter frame 'client nil)
279 (delete-frame frame))))
280
448f754f 281 (setq server-clients (delq proc server-clients))
5f3c1a63 282
9002956f 283 ;; Delete the client's tty.
448f754f 284 (let ((terminal (process-get proc 'terminal)))
977ede64
DN
285 ;; Only delete the terminal if it is non-nil.
286 (when (and terminal (eq (terminal-live-p terminal) t))
6ed8eeff 287 (delete-terminal terminal)))
9002956f 288
9002956f 289 ;; Delete the client's process.
448f754f
SM
290 (if (eq (process-status proc) 'open)
291 (delete-process proc))
9002956f
KL
292
293 (server-log "Deleted" proc))))
294
8b3e840e 295(defun server-log (string &optional client)
6d3a46f7
KL
296 "If a *server* buffer exists, write STRING to it for logging purposes.
297If CLIENT is non-nil, add a description of it to the logged
298message."
337e3c70
JB
299 (when (get-buffer "*server*")
300 (with-current-buffer "*server*"
301 (goto-char (point-max))
302 (insert (current-time-string)
974b73e8
KL
303 (cond
304 ((null client) " ")
305 ((listp client) (format " %s: " (car client)))
306 (t (format " %s: " client)))
337e3c70
JB
307 string)
308 (or (bolp) (newline)))))
9ae0f972 309
310(defun server-sentinel (proc msg)
9002956f 311 "The process sentinel for Emacs server connections."
cbfc02e4
RF
312 ;; If this is a new client process, set the query-on-exit flag to nil
313 ;; for this process (it isn't inherited from the server process).
314 (when (and (eq (process-status proc) 'open)
315 (process-query-on-exit-flag proc))
316 (set-process-query-on-exit-flag proc nil))
757e1681
SM
317 ;; Delete the associated connection file, if applicable.
318 ;; This is actually problematic: the file may have been overwritten by
319 ;; another Emacs server in the mean time, so it's not ours any more.
320 ;; (and (process-contact proc :server)
321 ;; (eq (process-status proc) 'closed)
322 ;; (ignore-errors (delete-file (process-get proc :server-file))))
9002956f
KL
323 (server-log (format "Status changed to %s: %s" (process-status proc) msg) proc)
324 (server-delete-client proc))
0c851d78 325
13ba3740
SM
326(defun server-select-display (display)
327 ;; If the current frame is on `display' we're all set.
1a4a884c
SM
328 ;; Similarly if we are unable to open a frames on other displays, there's
329 ;; nothing more we can do.
330 (unless (or (not (fboundp 'make-frame-on-display))
331 (equal (frame-parameter (selected-frame) 'display) display))
13ba3740
SM
332 ;; Otherwise, look for an existing frame there and select it.
333 (dolist (frame (frame-list))
334 (when (equal (frame-parameter frame 'display) display)
335 (select-frame frame)))
336 ;; If there's no frame on that display yet, create and select one.
337 (unless (equal (frame-parameter (selected-frame) 'display) display)
338 (let* ((buffer (generate-new-buffer " *server-dummy*"))
339 (frame (make-frame-on-display
340 display
341 ;; Make it display (and remember) some dummy buffer, so
342 ;; we can detect later if the frame is in use or not.
343 `((server-dummmy-buffer . ,buffer)
344 ;; This frame may be deleted later (see
345 ;; server-unselect-display) so we want it to be as
346 ;; unobtrusive as possible.
347 (visibility . nil)))))
348 (select-frame frame)
349 (set-window-buffer (selected-window) buffer)
350 frame))))
351
352(defun server-unselect-display (frame)
353 (when (frame-live-p frame)
354 ;; If the temporary frame is in use (displays something real), make it
355 ;; visible. If not (which can happen if the user's customizations call
356 ;; pop-to-buffer etc.), delete it to avoid preserving the connection after
357 ;; the last real frame is deleted.
358 (if (and (eq (frame-first-window frame)
359 (next-window (frame-first-window frame) 'nomini))
360 (eq (window-buffer (frame-first-window frame))
361 (frame-parameter frame 'server-dummy-buffer)))
362 ;; The temp frame still only shows one buffer, and that is the
363 ;; internal temp buffer.
364 (delete-frame frame)
365 (set-frame-parameter frame 'visibility t))
366 (kill-buffer (frame-parameter frame 'server-dummy-buffer))
367 (set-frame-parameter frame 'server-dummy-buffer nil)))
368
77134727
KL
369(defun server-handle-delete-frame (frame)
370 "Delete the client connection when the emacsclient frame is deleted."
9002956f 371 (let ((proc (frame-parameter frame 'client)))
e519a50b
KL
372 (when (and (frame-live-p frame)
373 proc
160f0817 374 ;; See if this is the last frame for this client.
d5381da2 375 (>= 1 (let ((frame-num 0))
aabf0cb9 376 (dolist (f (frame-list))
160f0817
KL
377 (when (eq proc (frame-parameter f 'client))
378 (setq frame-num (1+ frame-num))))
379 frame-num)))
9002956f 380 (server-log (format "server-handle-delete-frame, frame %s" frame) proc)
de93c791 381 (server-delete-client proc 'noframe)))) ; Let delete-frame delete the frame later.
9002956f 382
6ed8eeff 383(defun server-handle-suspend-tty (terminal)
9002956f 384 "Notify the emacsclient process to suspend itself when its tty device is suspended."
6ed8eeff
KL
385 (dolist (proc (server-clients-with 'terminal terminal))
386 (server-log (format "server-handle-suspend-tty, terminal %s" terminal) proc)
6d3a46f7 387 (condition-case err
6afdd335 388 (server-send-string proc "-suspend \n")
44954c2f
SM
389 (file-error ;The pipe/socket was closed.
390 (ignore-errors (server-delete-client proc))))))
44a56b29 391
0c851d78 392(defun server-unquote-arg (arg)
6afdd335
KL
393 "Remove &-quotation from ARG.
394See `server-quote-arg' and `server-process-filter'."
0c851d78
SM
395 (replace-regexp-in-string
396 "&." (lambda (s)
397 (case (aref s 1)
398 (?& "&")
399 (?- "-")
400 (?n "\n")
401 (t " ")))
402 arg t t))
9ae0f972 403
0b0d3e0b 404(defun server-quote-arg (arg)
9002956f 405 "In ARG, insert a & before each &, each space, each newline, and -.
0b0d3e0b 406Change spaces to underscores, too, so that the return value never
6afdd335
KL
407contains a space.
408
409See `server-unquote-arg' and `server-process-filter'."
0b0d3e0b
KL
410 (replace-regexp-in-string
411 "[-&\n ]" (lambda (s)
412 (case (aref s 0)
413 (?& "&&")
414 (?- "&-")
415 (?\n "&n")
416 (?\s "&_")))
417 arg t t))
418
6afdd335
KL
419(defun server-send-string (proc string)
420 "A wrapper around `proc-send-string' for logging."
421 (server-log (concat "Sent " string) proc)
422 (process-send-string proc string))
423
724629d2
SM
424(defun server-ensure-safe-dir (dir)
425 "Make sure DIR is a directory with no race-condition issues.
426Creates the directory if necessary and makes sure:
427- there's no symlink involved
428- it's owned by us
429- it's not readable/writable by anybody else."
430 (setq dir (directory-file-name dir))
431 (let ((attrs (file-attributes dir)))
432 (unless attrs
337e3c70 433 (letf (((default-file-modes) ?\700)) (make-directory dir t))
724629d2
SM
434 (setq attrs (file-attributes dir)))
435 ;; Check that it's safe for use.
da6657b7 436 (unless (and (eq t (car attrs)) (eql (nth 2 attrs) (user-uid))
337e3c70
JB
437 (or (eq system-type 'windows-nt)
438 (zerop (logand ?\077 (file-modes dir)))))
724629d2
SM
439 (error "The directory %s is unsafe" dir))))
440
7229064d 441;;;###autoload
9ae0f972 442(defun server-start (&optional leave-dead)
443 "Allow this Emacs process to be a server for client processes.
444This starts a server communications subprocess through which
6d3a46f7
KL
445client \"editors\" can send your editing commands to this Emacs
446job. To use the server, set up the program `emacsclient' in the
9ae0f972 447Emacs distribution as your standard \"editor\".
448
bd410bb0
EZ
449Optional argument LEAVE-DEAD (interactively, a prefix arg) means just
450kill any existing server communications subprocess."
9ae0f972 451 (interactive "P")
d6b4b3cf
KL
452 (when (or
453 (not server-clients)
454 (yes-or-no-p
455 "The current server still has clients; delete them? "))
456 ;; It is safe to get the user id now.
457 (setq server-socket-dir (or server-socket-dir
458 (format "/tmp/emacs%d" (user-uid))))
974b73e8
KL
459 (when server-process
460 ;; kill it dead!
461 (ignore-errors (delete-process server-process)))
d6b4b3cf
KL
462 ;; Delete the socket files made by previous server invocations.
463 (condition-case ()
464 (delete-file (expand-file-name server-name server-socket-dir))
465 (error nil))
466 ;; If this Emacs already had a server, clear out associated status.
467 (while server-clients
468 (server-delete-client (car server-clients)))
9f97e26d 469 ;; Now any previous server is properly stopped.
d6b4b3cf
KL
470 (if leave-dead
471 (progn
472 (server-log (message "Server stopped"))
473 (setq server-process nil))
974b73e8
KL
474 (let* ((server-dir (if server-use-tcp server-auth-dir server-socket-dir))
475 (server-file (expand-file-name server-name server-dir)))
476 ;; Make sure there is a safe directory in which to place the socket.
477 (server-ensure-safe-dir server-dir)
478 ;; Remove any leftover socket or authentication file.
479 (ignore-errors (delete-file server-file))
480 (when server-process
481 (server-log (message "Restarting server")))
482 (letf (((default-file-modes) ?\700))
e4019195 483 (add-hook 'suspend-tty-functions 'server-handle-suspend-tty)
974b73e8
KL
484 (add-hook 'delete-frame-functions 'server-handle-delete-frame)
485 (add-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function)
486 (add-hook 'kill-emacs-query-functions 'server-kill-emacs-query-function)
487 (setq server-process
488 (apply #'make-network-process
489 :name server-name
490 :server t
491 :noquery t
492 :sentinel 'server-sentinel
493 :filter 'server-process-filter
494 ;; We must receive file names without being decoded.
495 ;; Those are decoded by server-process-filter according
496 ;; to file-name-coding-system.
497 :coding 'raw-text
498 ;; The rest of the args depends on the kind of socket used.
499 (if server-use-tcp
500 (list :family nil
501 :service t
502 :host (or server-host 'local)
503 :plist '(:authenticated nil))
504 (list :family 'local
505 :service server-file
506 :plist '(:authenticated t)))))
507 (unless server-process (error "Could not start server process"))
508 (when server-use-tcp
509 (let ((auth-key
510 (loop
d76e2046
JB
511 ;; The auth key is a 64-byte string of random chars in the
512 ;; range `!'..`~'.
513 for i below 64
514 collect (+ 33 (random 94)) into auth
515 finally return (concat auth))))
974b73e8
KL
516 (process-put server-process :auth-key auth-key)
517 (with-temp-file server-file
518 (set-buffer-multibyte nil)
519 (setq buffer-file-coding-system 'no-conversion)
520 (insert (format-network-address
521 (process-contact server-process :local))
522 " " (int-to-string (emacs-pid))
523 "\n" auth-key)))))))))
33186f32 524
44954c2f
SM
525(defun server-running-p (&optional name)
526 "Test whether server NAME is running."
527 (interactive
528 (list (if current-prefix-arg
529 (read-string "Server name: " nil nil server-name))))
530 (unless name (setq name server-name))
531 (condition-case nil
532 (progn
533 (delete-process
534 (make-network-process
535 :name "server-client-test" :family 'local :server nil :noquery t
536 :service (expand-file-name name server-socket-dir)))
537 t)
538 (file-error nil)))
539
33186f32
DL
540;;;###autoload
541(define-minor-mode server-mode
542 "Toggle Server mode.
543With ARG, turn Server mode on if ARG is positive, off otherwise.
544Server mode runs a process that accepts commands from the
545`emacsclient' program. See `server-start' and Info node `Emacs server'."
546 :global t
547 :group 'server
bf247b6e 548 :version "22.1"
33186f32
DL
549 ;; Fixme: Should this check for an existing server socket and do
550 ;; nothing if there is one (for multiple Emacs sessions)?
551 (server-start (not server-mode)))
9ae0f972 552\f
13ba3740
SM
553(defun server-eval-and-print (expr proc)
554 "Eval EXPR and send the result back to client PROC."
555 (let ((v (eval (car (read-from-string expr)))))
556 (when (and v proc)
557 (with-temp-buffer
558 (let ((standard-output (current-buffer)))
559 (pp v)
560 (let ((text (buffer-substring-no-properties
561 (point-min) (point-max))))
562 (server-send-string
563 proc (format "-print %s\n"
564 (server-quote-arg text)))))))))
565
566(defun server-create-tty-frame (tty type proc)
4419b755 567 (add-to-list 'frame-inherited-parameters 'client)
13ba3740
SM
568 (let ((frame
569 (server-with-environment (process-get proc 'env)
570 '("LANG" "LC_CTYPE" "LC_ALL"
571 ;; For tgetent(3); list according to ncurses(3).
572 "BAUDRATE" "COLUMNS" "ESCDELAY" "HOME" "LINES"
573 "NCURSES_ASSUMED_COLORS" "NCURSES_NO_PADDING"
574 "NCURSES_NO_SETBUF" "TERM" "TERMCAP" "TERMINFO"
575 "TERMINFO_DIRS" "TERMPATH"
576 ;; rxvt wants these
577 "COLORFGBG" "COLORTERM")
578 (make-frame-on-tty tty type
579 ;; Ignore nowait here; we always need to
580 ;; clean up opened ttys when the client dies.
581 `((client . ,proc)
4419b755
SM
582 ;; This is a leftover from an earlier
583 ;; attempt at making it possible for process
584 ;; run in the server process to use the
585 ;; environment of the client process.
586 ;; It has no effect now and to make it work
587 ;; we'd need to decide how to make
588 ;; process-environment interact with client
589 ;; envvars, and then to change the
590 ;; C functions `child_setup' and
591 ;; `getenv_internal' accordingly.
448f754f 592 (environment . ,(process-get proc 'env)))))))
13ba3740 593
e159b869
SM
594 ;; ttys don't use the `display' parameter, but callproc.c does to set
595 ;; the DISPLAY environment on subprocesses.
596 (set-frame-parameter frame 'display
597 (getenv-internal "DISPLAY" (process-get proc 'env)))
13ba3740 598 (select-frame frame)
448f754f 599 (process-put proc 'frame frame)
448f754f 600 (process-put proc 'terminal (frame-terminal frame))
13ba3740
SM
601
602 ;; Display *scratch* by default.
603 (switch-to-buffer (get-buffer-create "*scratch*") 'norecord)
604
605 ;; Reply with our pid.
606 (server-send-string proc (concat "-emacs-pid "
607 (number-to-string (emacs-pid)) "\n"))
608 frame))
609
610(defun server-create-window-system-frame (display nowait proc)
4419b755 611 (add-to-list 'frame-inherited-parameters 'client)
e159b869 612 (if (not (fboundp 'make-frame-on-display))
13ba3740
SM
613 (progn
614 ;; This emacs does not support X.
615 (server-log "Window system unsupported" proc)
616 (server-send-string proc "-window-system-unsupported \n")
617 nil)
618 ;; Flag frame as client-created, but use a dummy client.
619 ;; This will prevent the frame from being deleted when
620 ;; emacsclient quits while also preventing
621 ;; `server-save-buffers-kill-terminal' from unexpectedly
622 ;; killing emacs on that frame.
623 (let* ((params `((client . ,(if nowait 'nowait proc))
4419b755 624 ;; This is a leftover, see above.
13ba3740
SM
625 (environment . ,(process-get proc 'env))))
626 (frame (make-frame-on-display
627 (or display
628 (frame-parameter nil 'display)
629 (getenv "DISPLAY")
630 (error "Please specify display"))
448f754f 631 params)))
13ba3740 632 (server-log (format "%s created" frame) proc)
4419b755
SM
633 ;; XXX We need to ensure the parameters are really set because Emacs
634 ;; forgets unhandled initialization parameters for X frames at
13ba3740
SM
635 ;; the moment.
636 (modify-frame-parameters frame params)
13ba3740 637 (select-frame frame)
448f754f
SM
638 (process-put proc 'frame frame)
639 (process-put proc 'terminal (frame-terminal frame))
13ba3740
SM
640
641 ;; Display *scratch* by default.
642 (switch-to-buffer (get-buffer-create "*scratch*") 'norecord)
643 frame)))
644
645
646(defun server-goto-toplevel (proc)
647 (condition-case nil
648 ;; If we're running isearch, we must abort it to allow Emacs to
649 ;; display the buffer and switch to it.
650 (dolist (buffer (buffer-list))
651 (with-current-buffer buffer
652 (when (bound-and-true-p isearch-mode)
653 (isearch-cancel))))
654 ;; Signaled by isearch-cancel.
655 (quit (message nil)))
656 (when (> (recursion-depth) 0)
657 ;; We're inside a minibuffer already, so if the emacs-client is trying
658 ;; to open a frame on a new display, we might end up with an unusable
659 ;; frame because input from that display will be blocked (until exiting
660 ;; the minibuffer). Better exit this minibuffer right away.
661 ;; Similarly with recursive-edits such as the splash screen.
662 (run-with-timer 0 nil (lexical-let ((proc proc))
663 (lambda () (server-execute-continuation proc))))
664 (top-level)))
665
666;; We use various special properties on process objects:
667;; - `env' stores the info about the environment of the emacsclient process.
668;; - `continuation' is a no-arg function that we need to execute. It contains
669;; commands we wanted to execute in some earlier invocation of the process
670;; filter but that we somehow were unable to process at that time
671;; (e.g. because we first need to throw to the toplevel).
672
673(defun server-execute-continuation (proc)
674 (let ((continuation (process-get proc 'continuation)))
675 (process-put proc 'continuation nil)
676 (if continuation (ignore-errors (funcall continuation)))))
677
337e3c70 678(defun* server-process-filter (proc string)
33186f32 679 "Process a request from the server to edit some files.
6afdd335
KL
680PROC is the server process. STRING consists of a sequence of
681commands prefixed by a dash. Some commands have arguments; these
682are &-quoted and need to be decoded by `server-unquote-arg'. The
683filter parses and executes these commands.
684
685To illustrate the protocol, here is an example command that
686emacsclient sends to create a new X frame (note that the whole
687sequence is sent on a single line):
688
6afdd335
KL
689 -env HOME /home/lorentey
690 -env DISPLAY :0.0
691 ... lots of other -env commands
692 -display :0.0
693 -window-system
694
6afdd335
KL
695The following commands are accepted by the server:
696
974b73e8
KL
697`-auth AUTH-STRING'
698 Authenticate the client using the secret authentication string
a38daa0a 699 AUTH-STRING.
974b73e8 700
59e085e0 701`-env NAME=VALUE'
6afdd335
KL
702 An environment variable on the client side.
703
2828d5f9
KL
704`-dir DIRNAME'
705 The current working directory of the client process.
706
92071250
KL
707`-current-frame'
708 Forbid the creation of new frames.
709
6afdd335
KL
710`-nowait'
711 Request that the next frame created should not be
712 associated with this client.
713
714`-display DISPLAY'
715 Set the display name to open X frames on.
716
717`-position LINE[:COLUMN]'
718 Go to the given line and column number
719 in the next file opened.
720
721`-file FILENAME'
722 Load the given file in the current frame.
723
724`-eval EXPR'
725 Evaluate EXPR as a Lisp expression and return the
726 result in -print commands.
727
728`-window-system'
729 Open a new X frame.
730
731`-tty DEVICENAME TYPE'
732 Open a new tty frame at the client.
733
6afdd335
KL
734`-suspend'
735 Suspend this tty frame. The client sends this string in
736 response to SIGTSTP and SIGTTOU. The server must cease all I/O
737 on this tty until it gets a -resume command.
738
2828d5f9
KL
739`-resume'
740 Resume this tty frame. The client sends this string when it
741 gets the SIGCONT signal and it is the foreground process on its
742 controlling tty.
743
6afdd335
KL
744`-ignore COMMENT'
745 Do nothing, but put the comment in the server
746 log. Useful for debugging.
747
748
749The following commands are accepted by the client:
750
6afdd335
KL
751`-emacs-pid PID'
752 Describes the process id of the Emacs process;
753 used to forward window change signals to it.
754
755`-window-system-unsupported'
756 Signals that the server does not
757 support creating X frames; the client must try again with a tty
758 frame.
759
760`-print STRING'
761 Print STRING on stdout. Used to send values
762 returned by -eval.
763
764`-error DESCRIPTION'
765 Signal an error (but continue processing).
766
767`-suspend'
768 Suspend this terminal, i.e., stop the client process. Sent
769 when the user presses C-z."
770 (server-log (concat "Received " string) proc)
337e3c70
JB
771 ;; First things first: let's check the authentication
772 (unless (process-get proc :authenticated)
773 (if (and (string-match "-auth \\(.*?\\)\n" string)
974b73e8
KL
774 (equal (match-string 1 string) (process-get proc :auth-key)))
775 (progn
776 (setq string (substring string (match-end 0)))
777 (process-put proc :authenticated t)
778 (server-log "Authentication successful" proc))
337e3c70 779 (server-log "Authentication failed" proc)
974b73e8
KL
780 (server-send-string
781 proc (concat "-error " (server-quote-arg "Authentication failed")))
337e3c70
JB
782 (delete-process proc)
783 ;; We return immediately
784 (return-from server-process-filter)))
3f7ef08e
SM
785 (let ((prev (process-get proc 'previous-string)))
786 (when prev
787 (setq string (concat prev string))
788 (process-put proc 'previous-string nil)))
a9298135 789 (condition-case err
0b0d3e0b 790 (progn
9002956f 791 (server-add-client proc)
13ba3740
SM
792 (if (not (string-match "\n" string))
793 ;; Save for later any partial line that remains.
794 (when (> (length string) 0)
795 (process-put proc 'previous-string string))
796
797 ;; In earlier versions of server.el (where we used an `emacsserver'
798 ;; process), there could be multiple lines. Nowadays this is not
799 ;; supported any more.
800 (assert (eq (match-end 0) (length string)))
0b0d3e0b
KL
801 (let ((request (substring string 0 (match-beginning 0)))
802 (coding-system (and default-enable-multibyte-characters
803 (or file-name-coding-system
804 default-file-name-coding-system)))
9002956f
KL
805 nowait ; t if emacsclient does not want to wait for us.
806 frame ; The frame that was opened for the client (if any).
59e085e0 807 display ; Open the frame on this display.
0b0d3e0b 808 dontkill ; t if the client should not be killed.
13ba3740 809 (commands ())
2828d5f9 810 dir
13ba3740
SM
811 (tty-name nil) ;nil, `window-system', or the tty name.
812 tty-type ;string.
0b0d3e0b
KL
813 (files nil)
814 (lineno 1)
815 (columnno 0))
816 ;; Remove this line from STRING.
817 (setq string (substring string (match-end 0)))
9002956f 818 (while (string-match " *[^ ]* " request)
13ba3740
SM
819 (let ((arg (substring request (match-beginning 0)
820 (1- (match-end 0)))))
0b0d3e0b
KL
821 (setq request (substring request (match-end 0)))
822 (cond
13ba3740
SM
823 ;; -version CLIENT-VERSION: obsolete at birth.
824 ((and (equal "-version" arg) (string-match "[^ ]+ " request))
825 (setq request (substring request (match-end 0))))
0b0d3e0b 826
9002956f 827 ;; -nowait: Emacsclient won't wait for a result.
0b0d3e0b
KL
828 ((equal "-nowait" arg) (setq nowait t))
829
92071250 830 ;; -current-frame: Don't create frames.
13ba3740 831 ((equal "-current-frame" arg) (setq tty-name nil))
92071250 832
9002956f 833 ;; -display DISPLAY:
59e085e0 834 ;; Open X frames on the given display instead of the default.
13ba3740
SM
835 ((and (equal "-display" arg)
836 (string-match "\\([^ ]*\\) " request))
1a4a884c 837 (setq display (match-string 1 request))
8a3a4fd3 838 (setq request (substring request (match-end 0))))
0b0d3e0b 839
9002956f 840 ;; -window-system: Open a new X frame.
0b0d3e0b 841 ((equal "-window-system" arg)
13ba3740
SM
842 (setq dontkill t)
843 (setq tty-name 'window-system))
9002956f
KL
844
845 ;; -resume: Resume a suspended tty frame.
0b0d3e0b 846 ((equal "-resume" arg)
448f754f 847 (lexical-let ((terminal (process-get proc 'terminal)))
0b0d3e0b 848 (setq dontkill t)
13ba3740
SM
849 (push (lambda ()
850 (when (eq (terminal-live-p terminal) t)
851 (resume-tty terminal)))
852 commands)))
0b0d3e0b 853
9002956f
KL
854 ;; -suspend: Suspend the client's frame. (In case we
855 ;; get out of sync, and a C-z sends a SIGTSTP to
856 ;; emacsclient.)
0b0d3e0b 857 ((equal "-suspend" arg)
448f754f 858 (lexical-let ((terminal (process-get proc 'terminal)))
0b0d3e0b 859 (setq dontkill t)
13ba3740
SM
860 (push (lambda ()
861 (when (eq (terminal-live-p terminal) t)
862 (suspend-tty terminal)))
863 commands)))
0b0d3e0b 864
9002956f
KL
865 ;; -ignore COMMENT: Noop; useful for debugging emacsclient.
866 ;; (The given comment appears in the server log.)
13ba3740 867 ((and (equal "-ignore" arg) (string-match "[^ ]* " request))
0b0d3e0b
KL
868 (setq dontkill t
869 request (substring request (match-end 0))))
870
9002956f 871 ;; -tty DEVICE-NAME TYPE: Open a new tty frame at the client.
13ba3740
SM
872 ((and (equal "-tty" arg)
873 (string-match "\\([^ ]*\\) \\([^ ]*\\) " request))
874 (setq tty-name (match-string 1 request))
875 (setq tty-type (match-string 2 request))
876 (setq dontkill t)
877 (setq request (substring request (match-end 0))))
878
879 ;; -position LINE[:COLUMN]: Set point to the given
880 ;; position in the next file.
881 ((and (equal "-position" arg)
882 (string-match "\\+\\([0-9]+\\)\\(?::\\([0-9]+\\)\\)? "
883 request))
b4bb3cbc 884 (setq lineno (string-to-number (match-string 1 request))
13ba3740
SM
885 columnno (if (null (match-end 2)) 0
886 (string-to-number (match-string 2 request)))
4e15f072 887 request (substring request (match-end 0))))
0b0d3e0b 888
9002956f 889 ;; -file FILENAME: Load the given file.
13ba3740
SM
890 ((and (equal "-file" arg)
891 (string-match "\\([^ ]+\\) " request))
0b0d3e0b
KL
892 (let ((file (server-unquote-arg (match-string 1 request))))
893 (setq request (substring request (match-end 0)))
894 (if coding-system
895 (setq file (decode-coding-string file coding-system)))
896 (setq file (command-line-normalize-file-name file))
80a426c2 897 (push (list file lineno columnno) files)
13ba3740
SM
898 (server-log (format "New file: %s (%d:%d)"
899 file lineno columnno) proc))
0b0d3e0b
KL
900 (setq lineno 1
901 columnno 0))
902
9002956f 903 ;; -eval EXPR: Evaluate a Lisp expression.
13ba3740
SM
904 ((and (equal "-eval" arg)
905 (string-match "\\([^ ]+\\) " request))
906 (lexical-let ((expr (server-unquote-arg
907 (match-string 1 request))))
0b0d3e0b
KL
908 (setq request (substring request (match-end 0)))
909 (if coding-system
910 (setq expr (decode-coding-string expr coding-system)))
13ba3740
SM
911 (push (lambda () (server-eval-and-print expr proc))
912 commands)
0b0d3e0b
KL
913 (setq lineno 1
914 columnno 0)))
915
59e085e0
KL
916 ;; -env NAME=VALUE: An environment variable.
917 ((and (equal "-env" arg) (string-match "\\([^ ]+\\) " request))
918 (let ((var (server-unquote-arg (match-string 1 request))))
da8e8fc1 919 ;; XXX Variables should be encoded as in getenv/setenv.
9002956f 920 (setq request (substring request (match-end 0)))
13ba3740
SM
921 (process-put proc 'env
922 (cons var (process-get proc 'env)))))
9002956f 923
2828d5f9
KL
924 ;; -dir DIRNAME: The cwd of the emacsclient process.
925 ((and (equal "-dir" arg) (string-match "\\([^ ]+\\) " request))
926 (setq dir (server-unquote-arg (match-string 1 request)))
927 (setq request (substring request (match-end 0)))
928 (if coding-system
929 (setq dir (decode-coding-string dir coding-system)))
930 (setq dir (command-line-normalize-file-name dir)))
931
0b0d3e0b
KL
932 ;; Unknown command.
933 (t (error "Unknown command: %s" arg)))))
13ba3740
SM
934
935 (setq frame
936 (case tty-name
937 ((nil) (if display (server-select-display display)))
938 ((window-system)
939 (server-create-window-system-frame display nowait proc))
940 (t (server-create-tty-frame tty-name tty-type proc))))
941
942 (process-put proc 'continuation
943 (lexical-let ((proc proc)
944 (files files)
945 (nowait nowait)
946 (commands commands)
947 (dontkill dontkill)
948 (frame frame)
949 (tty-name tty-name))
950 (lambda ()
951 (server-execute proc files nowait commands
952 dontkill frame tty-name))))
953
954 (when (or frame files)
955 (server-goto-toplevel proc))
956
957 (server-execute-continuation proc))))
a9298135 958 ;; condition-case
13ba3740
SM
959 (error (server-return-error proc err))))
960
961(defun server-execute (proc files nowait commands dontkill frame tty-name)
962 (condition-case err
448f754f 963 (let* ((buffers
13ba3740
SM
964 (when files
965 (run-hooks 'pre-command-hook)
448f754f 966 (prog1 (server-visit-files files proc nowait)
13ba3740
SM
967 (run-hooks 'post-command-hook)))))
968
969 (mapc 'funcall (nreverse commands))
970
971 ;; Delete the client if necessary.
972 (cond
973 (nowait
974 ;; Client requested nowait; return immediately.
975 (server-log "Close nowait client" proc)
976 (server-delete-client proc))
977 ((and (not dontkill) (null buffers))
978 ;; This client is empty; get rid of it immediately.
979 (server-log "Close empty client" proc)
980 (server-delete-client proc)))
981 (cond
982 ((or isearch-mode (minibufferp))
983 nil)
984 ((and frame (null buffers))
985 (message "%s" (substitute-command-keys
986 "When done with this frame, type \\[delete-frame]")))
987 ((not (null buffers))
988 (server-switch-buffer (car buffers))
989 (run-hooks 'server-switch-hook)
990 (unless nowait
991 (message "%s" (substitute-command-keys
992 "When done with a buffer, type \\[server-edit]")))))
993 (when (and frame (null tty-name))
994 (server-unselect-display frame)))
995 (error (server-return-error proc err))))
996
997(defun server-return-error (proc err)
998 (ignore-errors
999 (server-send-string
1000 proc (concat "-error " (server-quote-arg
1001 (error-message-string err))))
1002 (server-log (error-message-string err) proc)
1003 (delete-process proc)))
9ae0f972 1004
6b98185f 1005(defun server-goto-line-column (file-line-col)
6d3a46f7
KL
1006 "Move point to the position indicated in FILE-LINE-COL.
1007FILE-LINE-COL should be a three-element list as described in
1008`server-visit-files'."
6b98185f
RS
1009 (goto-line (nth 1 file-line-col))
1010 (let ((column-number (nth 2 file-line-col)))
1011 (if (> column-number 0)
1012 (move-to-column (1- column-number)))))
1013
448f754f 1014(defun server-visit-files (files proc &optional nowait)
c5b0a355 1015 "Find FILES and return a list of buffers created.
8c493570 1016FILES is an alist whose elements are (FILENAME LINENUMBER COLUMNNUMBER).
448f754f 1017PROC is the client that requested this operation.
dfa35e6b
RS
1018NOWAIT non-nil means this client is not waiting for the results,
1019so don't mark these buffers specially, just visit them normally."
e82e73c2 1020 ;; Bind last-nonmenu-event to force use of keyboard, not mouse, for queries.
44a56b29 1021 (let ((last-nonmenu-event t) client-record)
3a0ce849
RS
1022 ;; Restore the current buffer afterward, but not using save-excursion,
1023 ;; because we don't want to save point in this buffer
1024 ;; if it happens to be one of those specified by the server.
44a56b29
SM
1025 (save-current-buffer
1026 (dolist (file files)
1027 ;; If there is an existing buffer modified or the file is
1028 ;; modified, revert it. If there is an existing buffer with
1029 ;; deleted file, offer to write it.
cd7320d4 1030 (let* ((minibuffer-auto-raise (or server-raise-frame
974b73e8 1031 minibuffer-auto-raise))
c2d0d432 1032 (filen (car file))
44a56b29 1033 (obuf (get-file-buffer filen)))
c398358a 1034 (add-to-history 'file-name-history filen)
44a56b29
SM
1035 (if (and obuf (set-buffer obuf))
1036 (progn
1037 (cond ((file-exists-p filen)
95eefb35 1038 (when (not (verify-visited-file-modtime obuf))
974b73e8 1039 (revert-buffer t nil)))
44a56b29 1040 (t
95eefb35 1041 (when (y-or-n-p
974b73e8
KL
1042 (concat "File no longer exists: " filen
1043 ", write buffer to file? "))
1044 (write-file filen))))
5f3c1a63
KL
1045 (unless server-buffer-clients
1046 (setq server-existing-buffer t))
44a56b29
SM
1047 (server-goto-line-column file))
1048 (set-buffer (find-file-noselect filen))
1049 (server-goto-line-column file)
1050 (run-hooks 'server-visit-hook)))
1051 (unless nowait
1052 ;; When the buffer is killed, inform the clients.
1053 (add-hook 'kill-buffer-hook 'server-kill-buffer nil t)
448f754f 1054 (push proc server-buffer-clients))
c5b0a355
KL
1055 (push (current-buffer) client-record)))
1056 (unless nowait
448f754f
SM
1057 (process-put proc 'buffers
1058 (nconc (process-get proc 'buffers) client-record)))
c5b0a355 1059 client-record))
9ae0f972 1060\f
b392bac9 1061(defun server-buffer-done (buffer &optional for-killing)
9ae0f972 1062 "Mark BUFFER as \"done\" for its client(s).
9184aafb
RS
1063This buries the buffer, then returns a list of the form (NEXT-BUFFER KILLED).
1064NEXT-BUFFER is another server buffer, as a suggestion for what to select next,
8b3e840e
SM
1065or nil. KILLED is t if we killed BUFFER (typically, because it was visiting
1066a temp file).
1067FOR-KILLING if non-nil indicates that we are called from `kill-buffer'."
0c851d78 1068 (let ((next-buffer nil)
9002956f 1069 (killed nil))
448f754f
SM
1070 (dolist (proc server-clients)
1071 (let ((buffers (process-get proc 'buffers)))
8b3e840e 1072 (or next-buffer
9002956f
KL
1073 (setq next-buffer (nth 1 (memq buffer buffers))))
1074 (when buffers ; Ignore bufferless clients.
1075 (setq buffers (delq buffer buffers))
448f754f 1076 ;; Delete all dead buffers from PROC.
9002956f
KL
1077 (dolist (b buffers)
1078 (and (bufferp b)
1079 (not (buffer-live-p b))
1080 (setq buffers (delq b buffers))))
448f754f 1081 (process-put proc 'buffers buffers)
9002956f
KL
1082 ;; If client now has no pending buffers,
1083 ;; tell it that it is done, and forget it entirely.
1084 (unless buffers
448f754f
SM
1085 (server-log "Close" proc)
1086 (server-delete-client proc)))))
337e3c70
JB
1087 (when (and (bufferp buffer) (buffer-name buffer))
1088 ;; We may or may not kill this buffer;
1089 ;; if we do, do not call server-buffer-done recursively
1090 ;; from kill-buffer-hook.
1091 (let ((server-kill-buffer-running t))
1092 (with-current-buffer buffer
1093 (setq server-buffer-clients nil)
1094 (run-hooks 'server-done-hook))
1095 ;; Notice whether server-done-hook killed the buffer.
1096 (if (null (buffer-name buffer))
1097 (setq killed t)
1098 ;; Don't bother killing or burying the buffer
1099 ;; when we are called from kill-buffer.
1100 (unless for-killing
1101 (when (and (not killed)
1102 server-kill-new-buffers
1103 (with-current-buffer buffer
1104 (not server-existing-buffer)))
599f9a5c 1105 (setq killed t)
337e3c70
JB
1106 (bury-buffer buffer)
1107 (kill-buffer buffer))
1108 (unless killed
1109 (if (server-temp-file-p buffer)
1110 (progn
1111 (kill-buffer buffer)
1112 (setq killed t))
1113 (bury-buffer buffer)))))))
9184aafb 1114 (list next-buffer killed)))
9ae0f972 1115
408784a7 1116(defun server-temp-file-p (&optional buffer)
9ae0f972 1117 "Return non-nil if BUFFER contains a file considered temporary.
1118These are files whose names suggest they are repeatedly
1119reused to pass information to another program.
1120
1121The variable `server-temp-file-regexp' controls which filenames
1122are considered temporary."
1123 (and (buffer-file-name buffer)
1124 (string-match server-temp-file-regexp (buffer-file-name buffer))))
1125
1126(defun server-done ()
cc9875f9 1127 "Offer to save current buffer, mark it as \"done\" for clients.
ed9ae328
RS
1128This kills or buries the buffer, then returns a list
1129of the form (NEXT-BUFFER KILLED). NEXT-BUFFER is another server buffer,
1130as a suggestion for what to select next, or nil.
1131KILLED is t if we killed BUFFER, which happens if it was created
1132specifically for the clients and did not exist before their request for it."
408784a7
SM
1133 (when server-buffer-clients
1134 (if (server-temp-file-p)
1135 ;; For a temp file, save, and do make a non-numeric backup
1136 ;; (unless make-backup-files is nil).
1137 (let ((version-control nil)
1138 (buffer-backed-up nil))
1139 (save-buffer))
337e3c70
JB
1140 (when (and (buffer-modified-p)
1141 buffer-file-name
1142 (y-or-n-p (concat "Save file " buffer-file-name "? ")))
1143 (save-buffer)))
408784a7 1144 (server-buffer-done (current-buffer))))
faf931a8 1145
71207de2
RS
1146;; Ask before killing a server buffer.
1147;; It was suggested to release its client instead,
1148;; but I think that is dangerous--the client would proceed
1149;; using whatever is on disk in that file. -- rms.
03d78665 1150(defun server-kill-buffer-query-function ()
9002956f 1151 "Ask before killing a server buffer."
03d78665 1152 (or (not server-buffer-clients)
114a8b8c
KL
1153 (let ((res t))
1154 (dolist (proc server-buffer-clients res)
448f754f
SM
1155 (when (and (memq proc server-clients)
1156 (eq (process-status proc) 'open))
1157 (setq res nil))))
03d78665
RS
1158 (yes-or-no-p (format "Buffer `%s' still has clients; kill it? "
1159 (buffer-name (current-buffer))))))
1160
03d78665 1161(defun server-kill-emacs-query-function ()
7540c1e0 1162 "Ask before exiting Emacs it has live clients."
9002956f
KL
1163 (or (not server-clients)
1164 (let (live-client)
448f754f
SM
1165 (dolist (proc server-clients live-client)
1166 (when (memq t (mapcar 'buffer-live-p (process-get
1167 proc 'buffers)))
974b73e8 1168 (setq live-client t))))
9002956f 1169 (yes-or-no-p "This Emacs session has clients; exit anyway? ")))
b392bac9 1170
fb873cfc 1171(defvar server-kill-buffer-running nil
599f9a5c 1172 "Non-nil while `server-kill-buffer' or `server-buffer-done' is running.")
fb873cfc 1173
b392bac9 1174(defun server-kill-buffer ()
6d3a46f7
KL
1175 "Remove the current buffer from its clients' buffer list.
1176Designed to be added to `kill-buffer-hook'."
fb873cfc
RS
1177 ;; Prevent infinite recursion if user has made server-done-hook
1178 ;; call kill-buffer.
1179 (or server-kill-buffer-running
599f9a5c
RS
1180 (and server-buffer-clients
1181 (let ((server-kill-buffer-running t))
1182 (when server-process
1183 (server-buffer-done (current-buffer) t))))))
9ae0f972 1184\f
1185(defun server-edit (&optional arg)
1186 "Switch to next server editing buffer; say \"Done\" for current buffer.
1187If a server buffer is current, it is marked \"done\" and optionally saved.
ed9ae328 1188The buffer is also killed if it did not exist before the clients asked for it.
9ae0f972 1189When all of a client's buffers are marked as \"done\", the client is notified.
1190
1191Temporary files such as MH <draft> files are always saved and backed up,
991298c3
RS
1192no questions asked. (The variable `make-backup-files', if nil, still
1193inhibits a backup; you can set it locally in a particular buffer to
1194prevent a backup for it.) The variable `server-temp-file-regexp' controls
9ae0f972 1195which filenames are considered temporary.
1196
64f51134 1197If invoked with a prefix argument, or if there is no server process running,
9ae0f972 1198starts server process and that is all. Invoked by \\[server-edit]."
9ae0f972 1199 (interactive "P")
6b519504 1200 (cond
95eefb35
JB
1201 ((or arg
1202 (not server-process)
1203 (memq (process-status server-process) '(signal exit)))
1204 (server-mode 1))
1205 (server-clients (apply 'server-switch-buffer (server-done)))
1206 (t (message "No server editing buffers exist"))))
9ae0f972 1207
98a4349c 1208(defun server-switch-buffer (&optional next-buffer killed-one)
9ae0f972 1209 "Switch to another buffer, preferably one that has a client.
6d3a46f7
KL
1210Arg NEXT-BUFFER is a suggestion; if it is a live buffer, use it.
1211
1212KILLED-ONE is t in a recursive call if we have already killed one
1213temp-file server buffer. This means we should avoid the final
1214\"switch to some other buffer\" since we've already effectively
1215done that."
ca0c7250 1216 (if (null next-buffer)
9002956f
KL
1217 (progn
1218 (let ((rest server-clients))
1219 (while (and rest (not next-buffer))
448f754f 1220 (let ((proc (car rest)))
9002956f 1221 ;; Only look at frameless clients.
448f754f
SM
1222 (when (not (process-get proc 'frame))
1223 (setq next-buffer (car (process-get proc 'buffers))))
9002956f
KL
1224 (setq rest (cdr rest)))))
1225 (and next-buffer (server-switch-buffer next-buffer killed-one))
1226 (unless (or next-buffer killed-one (window-dedicated-p (selected-window)))
1227 ;; (switch-to-buffer (other-buffer))
90ee5627 1228 (message "No server buffers remain to edit")))
9002956f 1229 (if (not (buffer-live-p next-buffer))
ca0c7250 1230 ;; If NEXT-BUFFER is a dead buffer, remove the server records for it
9ae0f972 1231 ;; and try the next surviving server buffer.
ca0c7250
SM
1232 (apply 'server-switch-buffer (server-buffer-done next-buffer))
1233 ;; OK, we know next-buffer is live, let's display and select it.
408784a7
SM
1234 (if (functionp server-window)
1235 (funcall server-window next-buffer)
1236 (let ((win (get-buffer-window next-buffer 0)))
1237 (if (and win (not server-window))
1238 ;; The buffer is already displayed: just reuse the window.
90caccca
JB
1239 (progn
1240 (select-window win)
1241 (set-buffer next-buffer))
408784a7 1242 ;; Otherwise, let's find an appropriate window.
60b4b298 1243 (cond ((window-live-p server-window)
408784a7
SM
1244 (select-window server-window))
1245 ((framep server-window)
337e3c70
JB
1246 (unless (frame-live-p server-window)
1247 (setq server-window (make-frame)))
408784a7 1248 (select-window (frame-selected-window server-window))))
337e3c70
JB
1249 (when (window-minibuffer-p (selected-window))
1250 (select-window (next-window nil 'nomini 0)))
408784a7
SM
1251 ;; Move to a non-dedicated window, if we have one.
1252 (when (window-dedicated-p (selected-window))
1253 (select-window
1254 (get-window-with-predicate
1255 (lambda (w)
1256 (and (not (window-dedicated-p w))
6ed8eeff
KL
1257 (equal (frame-terminal (window-frame w))
1258 (frame-terminal (selected-frame)))))
408784a7
SM
1259 'nomini 'visible (selected-window))))
1260 (condition-case nil
1261 (switch-to-buffer next-buffer)
1262 ;; After all the above, we might still have ended up with
1263 ;; a minibuffer/dedicated-window (if there's no other).
90caccca
JB
1264 (error (pop-to-buffer next-buffer)))))))
1265 (when server-raise-frame
1266 (select-frame-set-input-focus (window-frame (selected-window))))))
9ae0f972 1267
59e085e0 1268;;;###autoload
6ed8eeff 1269(defun server-save-buffers-kill-terminal (proc &optional arg)
59e085e0 1270 "Offer to save each buffer, then kill PROC.
b4ca0271 1271
7540c1e0
KL
1272With prefix arg, silently save all file-visiting buffers, then kill.
1273
1274If emacsclient was started with a list of filenames to edit, then
1275only these files will be asked to be saved."
448f754f 1276 (let ((buffers (process-get proc 'buffers)))
59e085e0
KL
1277 ;; If client is bufferless, emulate a normal Emacs session
1278 ;; exit and offer to save all buffers. Otherwise, offer to
1279 ;; save only the buffers belonging to the client.
1280 (save-some-buffers arg
1281 (if buffers
1282 (lambda () (memq (current-buffer) buffers))
1283 t))
1284 (server-delete-client proc)))
b4ca0271 1285
772c5eb7 1286(define-key ctl-x-map "#" 'server-edit)
df4e8a11
DL
1287
1288(defun server-unload-hook ()
6d3a46f7 1289 "Unload the server library."
2e8457a0 1290 (server-mode -1)
e4019195 1291 (remove-hook 'suspend-tty-functions 'server-handle-suspend-tty)
9002956f 1292 (remove-hook 'delete-frame-functions 'server-handle-delete-frame)
df4e8a11
DL
1293 (remove-hook 'kill-buffer-query-functions 'server-kill-buffer-query-function)
1294 (remove-hook 'kill-emacs-query-functions 'server-kill-emacs-query-function)
1295 (remove-hook 'kill-buffer-hook 'server-kill-buffer))
3bb38bc2 1296
2e8457a0 1297(add-hook 'kill-emacs-hook (lambda () (server-mode -1))) ;Cleanup upon exit.
3bb38bc2 1298(add-hook 'server-unload-hook 'server-unload-hook)
16c15321
RM
1299\f
1300(provide 'server)
c88ab9ce 1301
2e8457a0 1302;; arch-tag: 1f7ecb42-f00a-49f8-906d-61995d84c8d6
c88ab9ce 1303;;; server.el ends here