+ (let ((client (assq proc server-clients)))
+ ;; Remove PROC from the list of clients.
+ (when client
+ (setq server-clients (delq client server-clients))
+ (dolist (buf (cdr client))
+ (with-current-buffer buf
+ ;; Remove PROC from the clients of each buffer.
+ (setq server-buffer-clients (delq proc server-buffer-clients))
+ ;; Kill the buffer if necessary.
+ (when (and (null server-buffer-clients)
+ (or (and server-kill-new-buffers
+ (not server-existing-buffer))
+ (server-temp-file-p)))
+ (kill-buffer (current-buffer)))))))
+ ;; If this is a new client process, set the query-on-exit flag to nil
+ ;; for this process (it isn't inherited from the server process).
+ (when (and (eq (process-status proc) 'open)
+ (process-query-on-exit-flag proc))
+ (set-process-query-on-exit-flag proc nil))
+ ;; Delete the associated connection file, if applicable.
+ ;; This is actually problematic: the file may have been overwritten by
+ ;; another Emacs server in the mean time, so it's not ours any more.
+ ;; (and (process-contact proc :server)
+ ;; (eq (process-status proc) 'closed)
+ ;; (ignore-errors (delete-file (process-get proc :server-file))))
+ (server-log (format "Status changed to %s" (process-status proc)) proc))
+
+(defun server-select-display (display)
+ ;; If the current frame is on `display' we're all set.
+ (unless (equal (frame-parameter (selected-frame) 'display) display)
+ ;; Otherwise, look for an existing frame there and select it.
+ (dolist (frame (frame-list))
+ (when (equal (frame-parameter frame 'display) display)
+ (select-frame frame)))
+ ;; If there's no frame on that display yet, create and select one.
+ (unless (equal (frame-parameter (selected-frame) 'display) display)
+ (let* ((buffer (generate-new-buffer " *server-dummy*"))
+ (frame (make-frame-on-display
+ display
+ ;; Make it display (and remember) some dummy buffer, so
+ ;; we can detect later if the frame is in use or not.
+ `((server-dummmy-buffer . ,buffer)
+ ;; This frame may be deleted later (see
+ ;; server-unselect-display) so we want it to be as
+ ;; unobtrusive as possible.
+ (visibility . nil)))))
+ (select-frame frame)
+ (set-window-buffer (selected-window) buffer)))))
+
+(defun server-unselect-display (frame)
+ ;; If the temporary frame is in use (displays something real), make it
+ ;; visible. If not (which can happen if the user's customizations call
+ ;; pop-to-buffer etc.), delete it to avoid preserving the connection after
+ ;; the last real frame is deleted.
+ (if (and (eq (frame-first-window frame)
+ (next-window (frame-first-window frame) 'nomini))
+ (eq (window-buffer (frame-first-window frame))
+ (frame-parameter frame 'server-dummy-buffer)))
+ ;; The temp frame still only shows one buffer, and that is the
+ ;; internal temp buffer.
+ (delete-frame frame)
+ (set-frame-parameter frame 'visibility t))
+ (kill-buffer (frame-parameter frame 'server-dummy-buffer))
+ (set-frame-parameter frame 'server-dummy-buffer nil))
+
+(defun server-unquote-arg (arg)
+ (replace-regexp-in-string
+ "&." (lambda (s)
+ (case (aref s 1)
+ (?& "&")
+ (?- "-")
+ (?n "\n")
+ (t " ")))
+ arg t t))
+
+(defun server-ensure-safe-dir (dir)
+ "Make sure DIR is a directory with no race-condition issues.
+Creates the directory if necessary and makes sure:
+- there's no symlink involved
+- it's owned by us
+- it's not readable/writable by anybody else."
+ (setq dir (directory-file-name dir))
+ (let ((attrs (file-attributes dir)))
+ (unless attrs
+ (letf (((default-file-modes) ?\700)) (make-directory dir t))
+ (setq attrs (file-attributes dir)))
+ ;; Check that it's safe for use.
+ (unless (and (eq t (car attrs)) (eq (nth 2 attrs) (user-uid))
+ (or (eq system-type 'windows-nt)
+ (zerop (logand ?\077 (file-modes dir)))))
+ (error "The directory %s is unsafe" dir))))