Page 1 of 1

CCL init file problem

Posted: Wed Jan 25, 2017 2:31 am
by gekkonier
Disclaimer: I'm on Windows, and I want to set up a programming environment that I don't have to install but be able to start it from lets say dropbox or a stick.

CCL tries to find the ccl-init.lisp file on startup.
After a lot of searching I found out, that CCL tries to do this with the path that ccl's implementation of (USER-HOMEDIR-PATHNAME) spits out.
Normally I would think that it's the same as the HOME environment variable. But CCL constructs the path in an other way it seems.

The problem is, that if i set a HOME environment variable inside a batch file:

Code: Select all

SET HOME=%CD%
this homedir is good to go for emacs, because if i C-x C-f ~/ccl-init.lisp inside Emacs, Emacs finds the file and treats the ~ abbrev correctly.

However, CCL does not recognise the setted HOME env variable as user homedir and therefor cannot find the ccl-init.lisp.
If I do a (user-homedir-pathname) inside the slime repl or ccl's repl it spits out my "original" user's home directory, and not that one I've set as HOME in my batchfile.

So, I think CCL's implementation of (user-homedir-pathname) constructs it's answer in another way than reading out HOME from the environment.
But how?

I would like to use ccl-init.lisp to load lets say quicklisp, but I'm not able to, because I don't know how CCL puts it's own (user-homedir-pathname) together.
In the end I want to do something similar as "Lispstick" but I want to use CCL instead of SBCL.

SBCL seems to load it's init file from the directory the HOME environment variable points to as you can see in lispstick, but CCL does it in an other way. But how?

I don't want to clutter my dev environment into the host os all over the place, I want to use it from a specific directory that I can copy, move, alter, whatever.

Thank you for any input.

Re: CCL init file problem

Posted: Wed Jan 25, 2017 5:24 am
by gekkonier
I went a bit further, but don't understand it exactly.

I tried to find the definition of (USER-HOMEDIR-PATHNAME) with M+, inside slime and found this:

Code: Select all

(defun user-homedir-pathname (&optional host)
  "Return the home directory of the user as a pathname."
  (declare (ignore host))
  (let* ((native (get-user-home-dir (getuid)))
	 (pathname (and native (native-to-directory-pathname native))))
    (if (and pathname (eq :absolute (car (pathname-directory pathname))))
      pathname
      (make-pathname :directory '(:absolute) :defaults nil))))
So far my minimal knowledge of common lisp allows, it uses (get-user-home-dir) to get it...

Then I went to the definition of (get-user-home-dir). There, stands this value comes from the OS user database, not from $HOME, or?
I think thats the problem I have.
What could I do, to fix that?
It seems that it reads it's value out of the registry, or a winapi function _wgetenv?
If it's not possible at all I think I have to try out SBCL. But that on the other side writes it's "fragile" with multithreading. And I want to use multithreading once I've got a grip on common lisp.

Enclosed the code from (get-user-home-dir) which is used in (user-homedir-pathname).


Code: Select all

(defun get-user-home-dir (userid)
  "Look up and return the defined home directory of the user identified
by uid, as a native namestring. This value comes from the OS user database, not from the $HOME
environment variable, unless *TRUST-PATHS-FROM-ENVIRONMENT* is true.
Returns NIL if there is no user with the ID uid."
  #+(or windows-target android-target)
  (declare (ignore userid))
  #+windows-target
  (dolist (k '(#||"HOME"||# "USERPROFILE")) 
    (with-native-utf-16-cstrs ((key k))
      (let* ((p (#__wgetenv key)))
        (unless (%null-ptr-p p)
          (return (get-foreign-namestring p))))))
  #-windows-target
  (or (and *trust-paths-from-environment*
           (let* ((p (getenv "HOME")))
             (and p
                  (eq (nth-value 1 (%probe-file-x p)) :directory)
                  p)))
      #+android-target "/data/local" ; for now
      #-android-target
      (rlet ((pwd :passwd)
             (result :address pwd))
        (do* ((buflen 512 (* 2 buflen)))
             ()
          (%stack-block ((buf buflen))
            (let* ((err
                    #-solaris-target
                     (#_getpwuid_r userid pwd buf buflen result)
                     #+solaris-target
                     (external-call "__posix_getpwuid_r"
                                    :uid_t userid
                                    :address pwd
                                    :address buf
                                    :int buflen
                                    :address result
                                    :int)))
              (if (eql 0 err)
                (let* ((rp (%get-ptr result))
                       (dir (and (not (%null-ptr-p rp))
                                 (get-foreign-namestring (pref rp :passwd.pw_dir)))))
                  (return (if (and dir (eq (%unix-file-kind dir) :directory))
                            dir)))
                (unless (eql err #$ERANGE)
                  (return nil)))))))))

Re: CCL init file problem

Posted: Wed Jan 25, 2017 5:37 am
by gekkonier
Now it get's weird for me....

Code: Select all

"Look up and return the defined home directory of the user identified
by uid, as a native namestring. This value comes from the OS user database, not from the $HOME
environment variable, unless *TRUST-PATHS-FROM-ENVIRONMENT* is true.
Returns NIL if there is no user with the ID uid."

Code: Select all

CL-USER> *TRUST-PATHS-FROM-ENVIRONMENT*
T
Huh? So the ccl implementation should use the environment variable, or not?

Re: CCL init file problem

Posted: Wed Jan 25, 2017 2:06 pm
by edgar-rft
Common Lisp (not only CCL) usually considers the directory stored in the *DEFAULT-PATHNAME-DEFAULTS* variable as "working directory". Try to set this variable in your init file to the desired HOME directory and try if it works for you:

Code: Select all

(setf *default-pathname-defaults* #P"<full-path-to-your-home-directory>"
To expand a relative filename use:

Code: Select all

(merge-pathname #P"my-file.lisp") => #P"<path-from-default-pathname-defaults>/my-file.lisp"
More info in Practical Common Lisp under Filenames and A Portable Pathname Library.

Re: CCL init file problem

Posted: Wed Jan 25, 2017 2:31 pm
by David Mullen
The mailing list had a question about it: [Openmcl-devel] *trust-paths-from-environment* under Windows? I guess CCL has its reasons for not using the HOME variable on Windows—security reasons, maybe?—so some modification would be involved in making that happen.

Re: CCL init file problem

Posted: Thu Jan 26, 2017 1:54 am
by gekkonier
I posted this problem on comp.lang.lisp too, it seems, that in the code above HOME is commented out and USERPROFILE will be read from CCL to find it's init file.
So I will try this later today and see, if I get a portable CCL with this.
Try to set this variable in your init file to the desired HOME directory and try if it works for you: *snip*
That would not work I think, because the init file would not be read. Thats exactly the problem. I need to bend some env Variables, so that CCL finds it's init file in a different location.
But I hope that the USERPROFILE env variable will do the trick. I will try later!

Thank you all for your suggestions!

Re: CCL init file problem

Posted: Fri Jan 27, 2017 7:48 am
by edgar-rft
Have you tried the following:

Code: Select all

ccl --load /full/path/to/ccl-init.lisp
The problem with the windows environment variables is that different Windows versions use different variable names for the HOME directory variable.