[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Cocoa Emacs 23 and Tramp problem

From: Lars Wessman
Subject: Re: Cocoa Emacs 23 and Tramp problem
Date: Fri, 6 Mar 2009 14:57:28 -0800 (PST)
User-agent: G2/1.0

On Mar 6, 10:15 pm, Ted Zlatanov <address@hidden> wrote:
> On Fri, 6 Mar 2009 13:08:53 -0800 (PST) Lars Wessman <address@hidden> wrote:
> LW> On Mar 6, 8:46 pm, "address@hidden" <address@hidden>
> LW> wrote:
> >> On Mar 6, 6:35 pm, Lars Wessman <address@hidden> wrote:
> >> (setq exec-path (cons "C:/path/to/ssh/dir" exec-path))
> LW> No dice, unfortunately.
> Do you have SSH installed?  Where?  Use that path, not c:/... as the
> example suggested.  If you need to install it, use Mac Ports.
> If it still doesn't work, post the result of
> M-: (executable-find "ssh") RET
> For me, it says "/usr/bin/ssh" but on MacOS X it may be elsewhere.
> Ted

Yes, that is where ssh is located in OS X. The solution you suggested
turned out to be on the right track though. I solved the problem by
fishing some functions out of Aquamacs, a distribution which I knew
had a functioning Tramp, for setting the path. Dave Reitter, the
distribution's maintainer, explains in the comments that getting
environment variables from the shell is not straightforward. Here is
the code that did the trick, which I loaded from a separate file
from .emacs:


(defvar environment-temp-file nil)

;; (setq shell-file-name "/bin/bash")
;; (let ((debug-on-error)) (mac-read-environment-vars-from-shell))

;; Reading the environment variables is complex, primarily due to
;; bugs in OS X.  On some systems, starting the login shell and
;; printing all variables takes an hour, so we need to have a
;; timeout.  However, starting the process asynchronuously using
;; `start-process' fails as well on some other systems.  Hence the
;; need to run it with `call-process' and "&", storing the output in
;; a temporary file.
;; dr. 07/2008

(defun mac-read-environment-vars-from-shell ()
  "Import the environment from the system's default login shell
specified in `shell-file-name'."

  (setq environment-temp-file (make-temp-file "envvar-"))
  ;; running the shell with -l (to load the environment)
  (setq default-directory "~/") ; ensure it can be executed

  (message "Shell: %s" shell-file-name)

  (let* ((shell (or shell-file-name "/bin/bash"))   ;; can shell-file-
name be nil?
         (command (format "printenv >%s.tmp; mv %s.tmp %s"

    (if (string-match ".*/\\(ba\\|z\\)sh" shell)
        (call-process shell nil
                      0 nil
                      "-l" "-c" command)
      (if (or (string-match ".*/\\tcsh" shell)
              (string-match ".*/ksh" shell))
          (call-process shell nil
                        0 nil
                        ;; we can't start tcsh as a login shell
                        ;; because it doesn't accept -l in combination
                        ;; with a command.
                        ;; call-process-region wouldn't work because it's
                        ;; not interactive.
                        "-c" command)
        (message "Could not retrieve login shell environment with login
shell: %s" shell)
        ;; won't work for csh, because it doesn't take -l -c ...
;; we call the process asynchronuously
;; using start-process does not work for unknown reasons:
;; sometimes it doesn't get the environment.

;; (mac-read-environment-vars-from-shell)
;; (sit-for 1)
;; (mac-read-environment-vars-from-shell-2)

(defun mac-read-environment-vars-from-shell-2 ()
  "Reads temporary file if it exists."
  (if (file-readable-p environment-temp-file)
            (condition-case nil
                  (insert-file-contents-literally environment-temp-file nil)
                  (delete-file environment-temp-file))
              (error nil))
            (let ((num 0))
             (if (eq (buffer-size) 0)
                 (message "Warning: Login shell did not return environment.")
               (goto-char (point-min))
               (while (re-search-forward "^[A-Za-z_0-9]+=()\s*[^\x]*?
\s*}\s*$" nil t)
                 (replace-match "..." nil nil))
               (goto-char (point-min))
               (while (search-forward-regexp "^\\([A-Za-z_0-9]+\\)=\\(.*\\)$"
nil t)
                 (setq num (1+ num))
                  (match-string 1)
                  (if (equal (match-string 1) "PATH")
                      (concat (match-string 2) ":" (getenv "PATH"))
                    (match-string 2)))))
          (message "%d environment variables imported from login shell
                   num shell-file-name)

(defun mac-post-environment-vars-function ()

  (mac-add-local-directory-to-exec-path) ;; needed for CocoAspell

  ;; inferior workaround, until mac.c is fixed not to set INFOPATH any
  (if (equal (concat (mac-resources-path)
             (getenv "INFOPATH"))
      (setenv "INFOPATH"))

;; when INFOPATH is set from outside, it will only load INFOPATH

  (let ((extra-dirs (list
                     "~/Library/Application Support/Emacs/info"
                     "/Library/Application Support/Emacs/info"
                     (concat (mac-resources-path)
                     (concat (mac-resources-path)

    (setq Info-default-directory-list (append extra-dirs
    (when (getenv "INFOPATH")
      (setenv "INFOPATH" (apply 'concat (getenv "INFOPATH")
                                (mapcar (lambda (x) (concat ":" x))

(defun mac-add-path-to-exec-path ()
  "Add elements from environment variable `PATH' to `exec-path'."
  (let ((l (split-string (getenv "PATH") ":")))
   (lambda (p)
     (unless (member p l)
       (nconc l (list p))))
  (setq exec-path l)))

(defun mac-add-local-directory-to-exec-path ()
  "Add /usr/locaL/bin to `exec-path'"
  (add-to-list 'exec-path "/usr/local/bin"))


And then I added this to my .emacs:

(sit-for 1)

Three cheers for open source!

reply via email to

[Prev in Thread] Current Thread [Next in Thread]