2019-08-09 16:12:19 -04:00
|
|
|
#include <sys/param.h>
|
2008-06-30 21:53:51 -04:00
|
|
|
|
2019-08-09 16:12:19 -04:00
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <sys/sysctl.h>
|
2008-06-30 21:53:51 -04:00
|
|
|
|
2019-08-09 16:12:19 -04:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2008-06-30 21:53:51 -04:00
|
|
|
|
2019-08-09 16:12:19 -04:00
|
|
|
#include "fs.h"
|
get_exename() for OpenBSD. (#17)
get_exename() for OpenBSD.
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.
* Resolve relative pathnames to absolute, for OpenBSD get_exename().
2016-11-15 15:12:14 -05:00
|
|
|
|
2013-06-03 21:40:14 -04:00
|
|
|
char *get_exename(char *buf, size_t size)
|
|
|
|
{
|
get_exename() for OpenBSD. (#17)
get_exename() for OpenBSD.
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.
* Resolve relative pathnames to absolute, for OpenBSD get_exename().
2016-11-15 15:12:14 -05:00
|
|
|
int mib[4];
|
|
|
|
pid_t pid;
|
|
|
|
size_t len, plen;
|
2019-08-09 07:02:02 -04:00
|
|
|
char **argv, **argv2;
|
get_exename() for OpenBSD. (#17)
get_exename() for OpenBSD.
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.
* Resolve relative pathnames to absolute, for OpenBSD get_exename().
2016-11-15 15:12:14 -05:00
|
|
|
char *p, *path, *pathcpy, filename[PATH_MAX];
|
|
|
|
struct stat sbuf;
|
|
|
|
|
2019-08-09 13:20:17 -04:00
|
|
|
(void)size;
|
|
|
|
|
get_exename() for OpenBSD. (#17)
get_exename() for OpenBSD.
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.
* Resolve relative pathnames to absolute, for OpenBSD get_exename().
2016-11-15 15:12:14 -05:00
|
|
|
pid = getpid();
|
|
|
|
|
|
|
|
mib[0] = CTL_KERN;
|
|
|
|
mib[1] = KERN_PROC_ARGS;
|
|
|
|
mib[2] = pid;
|
|
|
|
mib[3] = KERN_PROC_ARGV;
|
|
|
|
|
|
|
|
buf = NULL;
|
|
|
|
argv = NULL;
|
|
|
|
len = 128;
|
|
|
|
|
|
|
|
// Now, play The Guessing Game with sysctl(3) as to how big argv
|
|
|
|
// is supposed to be. (It's loads of fun for the whole family!)
|
|
|
|
|
|
|
|
while (len < SIZE_MAX / 2) {
|
|
|
|
len *= 2;
|
|
|
|
if ((argv2 = realloc(argv, len)) == NULL)
|
|
|
|
break;
|
|
|
|
argv = argv2;
|
|
|
|
if (sysctl(mib, 4, argv, &len, NULL, 0) == -1) {
|
|
|
|
if (errno == ENOMEM)
|
2019-08-09 07:02:02 -04:00
|
|
|
continue; // Go back and realloc more memory.
|
|
|
|
break; // Bail for some other error in sysctl(3).
|
get_exename() for OpenBSD. (#17)
get_exename() for OpenBSD.
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.
* Resolve relative pathnames to absolute, for OpenBSD get_exename().
2016-11-15 15:12:14 -05:00
|
|
|
}
|
|
|
|
// If you made it here, congrats! You guessed right!
|
|
|
|
if (*argv != NULL)
|
|
|
|
buf = strdup(*argv);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
free(argv);
|
|
|
|
|
|
|
|
// If no error occurred in the sysctl(3) KERN_PROC_ARGV call
|
|
|
|
// above, then buf at this point contains some kind of pathname.
|
|
|
|
|
|
|
|
if (buf != NULL) {
|
2019-08-09 07:02:02 -04:00
|
|
|
if (strchr(buf, '/') == NULL) {
|
|
|
|
// buf contains a `basename`-style pathname (i.e. "foo",
|
|
|
|
// as opposed to "../foo" or "/usr/bin/foo"); search the
|
|
|
|
// PATH for its location. (BTW the setgid(2), setuid(2)
|
|
|
|
// calls are a pre-condition for the access(2) call
|
|
|
|
// later.)
|
|
|
|
|
|
|
|
if ((path = getenv("PATH")) != NULL && !setgid(getegid()) &&
|
|
|
|
!setuid(geteuid())) {
|
|
|
|
|
|
|
|
// The strdup(3) call below, if successful, will
|
|
|
|
// allocate memory for the PATH string returned by
|
|
|
|
// getenv(3) above. This is necessary because the man
|
|
|
|
// page of getenv(3) says that its return value
|
|
|
|
// "should be considered read-only"; however, the
|
|
|
|
// strsep(3) call below is going to be destructively
|
|
|
|
// modifying that value. ("Hulk smash!")
|
|
|
|
|
|
|
|
if ((path = strdup(path)) != NULL) {
|
|
|
|
pathcpy = path;
|
|
|
|
len = strlen(buf);
|
|
|
|
while ((p = strsep(&pathcpy, ":")) != NULL) {
|
|
|
|
if (*p == '\0')
|
|
|
|
p = ".";
|
|
|
|
plen = strlen(p);
|
|
|
|
|
|
|
|
// strip trailing '/'
|
|
|
|
while (p[plen - 1] == '/')
|
|
|
|
p[--plen] = '\0';
|
|
|
|
|
|
|
|
if (plen + 1 + len < sizeof(filename)) {
|
|
|
|
snprintf(filename, sizeof(filename), "%s/%s", p,
|
|
|
|
buf);
|
|
|
|
if ((stat(filename, &sbuf) == 0) &&
|
|
|
|
S_ISREG(sbuf.st_mode) &&
|
|
|
|
access(filename, X_OK) == 0) {
|
|
|
|
buf = strdup(filename);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
free(path); // free the strdup(3) memory allocation.
|
|
|
|
}
|
|
|
|
} else
|
|
|
|
buf = NULL; // call to getenv(3) or [sg]ete?[ug]id(2) failed.
|
|
|
|
}
|
|
|
|
if (buf != NULL && *buf != '/') {
|
|
|
|
// buf contains a relative pathname (e.g. "../foo");
|
|
|
|
// resolve this to an absolute pathname.
|
|
|
|
if (strlcpy(filename, buf, sizeof(filename)) >=
|
|
|
|
sizeof(filename) ||
|
|
|
|
realpath(filename, buf) == NULL)
|
|
|
|
buf = NULL;
|
|
|
|
}
|
get_exename() for OpenBSD. (#17)
get_exename() for OpenBSD.
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.
* Resolve relative pathnames to absolute, for OpenBSD get_exename().
2016-11-15 15:12:14 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
return buf;
|
2013-06-03 21:40:14 -04:00
|
|
|
}
|