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