Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

get_exename() for OpenBSD. #17

Merged
merged 2 commits into from Nov 15, 2016

Conversation

cryptorick
Copy link
Contributor

Issue

get_exename() gets the pathname of the current process. In femtolisp, this is used to set the top-level *install-dir* which in turn is used as the location of the system image, flisp.boot.

There is only a trivial implementation of get_exename() for OpenBSD that simply returns NULL. A minor consequence is that the unit test will fail for the default build (make) because the system image cannot be found.

Fix

This commit provides an implementation of get_exename() for OpenBSD, so that the system image can be found.

Unlike, say, Linux or FreeBSD, OpenBSD doesn't have a system call to get the path of the current (or any, for that matter) process. The present code contains some logic that was put together to emulate the behavior of the Linux and FreeBSD variants of get_exename() as best as possible. It works as described by the following.

(1) Call sysctl(3) (with CTL_KERN -> KERN_PROC_ARGS -> KERN_PROC_ARGV) to get the "argv[0]" of the current process. If the program (flisp) was called in "basename form" (i.e. as "flisp"), then go to (2). Otherwise, return the value from sysctl(3) which will be an absolute or relative pathname, e.g. "/usr/local/bin/flisp" or "../flisp".

The code for (1) was adapted from old OpenBSD-specific tmux code that has since been abandoned by the author only because he deemed it "too expensive". For that code, see

http://sourceforge.net/p/tmux/tmux-code/ci/8c259f562be24570a19fd94b223034ae8c6e4277/tree/osdep-openbsd.c

(2) Since we now only have "flisp", we need to find out where it is located on the system. We assume that a program like the shell had to crawl PATH to find "flisp"; hence we do the same.

The code for (2) was adapted from the which utility in OpenBSD. See

http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/which/which.c?rev=1.20&content-type=text/plain

Finally, any error condition returns NULL, which is the same behavior of the other get_exename() variants.

Issue

`get_exename()` gets the pathname of the current process.  In
femtolisp, this is used to set the top-level `*install-dir*` which in
turn is used as the location of the system image, `flisp.boot`.

There is only a trivial implementation of `get_exename()` for OpenBSD
that simply returns `NULL`.  A minor consequence is that the unit test
will fail for the default build (make) because the system image cannot
be found.

Fix

This commit provides an implementation of `get_exename()` for OpenBSD,
so that the system image can be found.

Unlike, say, Linux or FreeBSD, OpenBSD doesn't have a system call to
get the path of the current (or any, for that matter) process.  The
present code contains some logic that was put together to emulate the
behavior of the Linux and FreeBSD variants of `get_exename()` as best
as possible.  It works as described by the following.

(1) Call `sysctl(3)` (with `CTL_KERN` -> `KERN_PROC_ARGS` ->
    `KERN_PROC_ARGV`) to get the "`argv[0]`" of the current process.
    If the program (flisp) was called in "`basename` form" (i.e. as
    "flisp"), then go to (2).  Otherwise, return the value from
    `sysctl(3)` which will be an absolute or relative pathname,
    e.g. "/usr/local/bin/flisp" or  "../flisp".

    The code for (1) was adapted from old OpenBSD-specific `tmux` code
    that has since been abandoned by the author only because he deemed
    it "too expensive".  For that code, see

    http://sourceforge.net/p/tmux/tmux-code/ci/8c259f562be24570a19fd94b223034ae8c6e4277/tree/osdep-openbsd.c

(2) Since we now only have "flisp", we need to find out where it is
    located on the system.  We assume that a program like the shell
    had to crawl `PATH` to find "flisp"; hence we do the same.

    The code for (2) was adapted from the `which` utility in OpenBSD.
    See

    http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/which/which.c?rev=1.20&content-type=text/plain

Finally, any error condition returns `NULL`, which is the same
behavior of the other `get_exename()` variants.
@cryptorick
Copy link
Contributor Author

I thought of another thing. The whole idea for this commit is to make the behavior of get_exename() in OpenBSD be like that of Linux or of FreeBSD. But here is a difference between, say, FreeBSD and OpenBSD with this commit implemented. (I elided the banners).

$ uname -rsm
FreeBSD 9.3-RELEASE-p2 amd64
$ ./flisp
> *install-dir*
"/home/rick/dev/femtolisp"
$ uname -rsm
OpenBSD 5.6 amd64
$ ./flisp
> *install-dir*
"."

This works for finding flisp.boot in the build case, but I'm now wondering if on OpenBSD the value of *install-dir* shouldn't be "/home/rick/dev/femtolisp" instead. (That's in fact the absolute pathname of "." on my OpenBSD box too.)

Whether this should be the case (i.e. *install-dir* should always be an absolute (full) pathname) is probably dependent on what other purpose you would use the value of get_exename() for. One thing that comes to mind is that the absolute pathname might be needed if we were to install femtolisp under, say, /usr/local. Just a thought.

What do you think? Am I over-thinking this? Thanks!

@JeffBezanson
Copy link
Owner

Thanks, this is much appreciated!

I think install-dir should be an absolute path; it should still be possible to use it to find flisp's files if the current directory changes at run time.

@cryptorick
Copy link
Contributor Author

Oh, yes, you are right. So, I should put in more logic to resolve the relative pathnames to absolute.

Now, comes my lack of github etiquette/protocol: should I add another commit (the new change) on top of this one, or ditch this commit and resubmit a new commit/issue, being the combination of what I have now plus the new stuff coming (as if I'd known all along what I was doing :)? I suppose, in the end, it's not a big deal, but I thought I'd ask. Thanks, Jeff!

@JeffBezanson
Copy link
Owner

Typically I'd force push to the same branch (then github will update the PR automatically), and squash commits if there are lots of them. With just 2 commits I'd say squashing is optional.

@cryptorick
Copy link
Contributor Author

OK, Jeff, you should see the second commit now. I added a call to realpath() to resolve the relative pathnames. Also, I rearranged the conditional logic slightly to catch a corner case I missed before. I originally assumed that looking down $PATH we'd only be encountering absolute directory pathnames -- I forgot you could put things like . in PATH (mostly because I don't :) -- so now when it searches down $PATH, after it finds the directory (location), it will still check for a relative pathname to resolve.

Sorry for the delay finishing this. Again, thanks for your help.

@cryptorick
Copy link
Contributor Author

Here are some tests (some of which may be overkill, but hey, Overkill's my middle name). I start the whole thing with a clone from scratch. (I omit some output for brevity's sake.)

~/dev $ uname -rsm                                                                                                                                                           
OpenBSD 5.6 amd64
~/dev $ git clone https://github.com/cryptorick/femtolisp.git flisp-test
~/dev $ cd flisp-test
~/dev/flisp-test $ git checkout openbsd-get-exename
~/dev/flisp-test $ gmake
gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt  -DUSE_COMPUTED_GOTO -c flisp.c -o flisp.o
gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt  -DUSE_COMPUTED_GOTO -c builtins.c -o builtins.o
gcc -O2 -DNDEBUG -falign-functions -Wall -Wno-strict-aliasing -Illt  -DUSE_COMPUTED_GOTO -c string.c -o string.o
    .
    .
    .
cd tests && ../flisp unittest.lsp
all tests pass
~/dev/flisp-test $ # ^^ Note "all tests pass"; before: "fatal error:"
~/dev/flisp-test $ #
~/dev/flisp-test $ # Test 1: Call flisp here
~/dev/flisp-test $ #
~/dev/flisp-test $ ./flisp
> *install-dir*
"/home/rick/dev/flisp-test"
> ^D
~/dev/flisp-test $ #
~/dev/flisp-test $ # Test 2: Call flisp via PATH with `.` on PATH
~/dev/flisp-test $ #
~/dev/flisp-test $ echo $PATH
/home/rick/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games:.
~/dev/flisp-test $ flisp
> *install-dir*
"/home/rick/dev/flisp-test"
> ^D
~/dev/flisp-test $ #
~/dev/flisp-test $ # Test 3: Call flisp via PATH with absolute directory pathname
~/dev/flisp-test $ #
~/dev/flisp-test $ PATH=$PATH:~/dev/flisp-test
~/dev/flisp-test $ echo $PATH
/home/rick/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/X11R6/bin:/usr/local/bin:/usr/local/sbin:/usr/games:.:/home/rick/dev/flisp-test
~/dev/flisp-test $ cd
~ $ flisp
> *install-dir*
"/home/rick/dev/flisp-test"
> ^D
~ $ #
~ $ # Test 4: Call flisp with (other) relative pathname
~ $ #
~ $ dev/flisp-test/flisp 
> *install-dir*
"/home/rick/dev/flisp-test"
> ^D
~ $ #
~ $ # Test 5: Call flisp with absolute pathname
~ $ #
~ $ /home/rick/dev/flisp-test/flisp 
> *install-dir*
"/home/rick/dev/flisp-test"
> ^D

@JeffBezanson JeffBezanson merged commit 6bc3fe5 into JeffBezanson:master Nov 15, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants