Hello OpenBSD developers! I have a suggestion on how to get the current executable path in OpenBSD that might be reliable enough and not too costly that it might be accepted for a future OpenBSD version.
Even if it won't be accepted, I need a little help completing the solution I have in mind. The current solution relies on $PWD, $PATH, and argv[0] to guess the most-likely executable path if $PWD, $PATH, or arv[0] were not modified from their original values. The code that does this i originally wrote in C++, I found someone else wrote a C solution which does the same thing, and I helped them by adding the $PWD code logic as a replacement for the cwd. The code is here: https://github.com/time-killer-games/getexecname/blob/patch-1/getexecname.c Due to the use of realpath() if the exe is not found, an empty string or NULL can be returned. However, I want to take it a step further in terms of error codes if an existing executable is in fact found, though it does not point to the same executable that actually spawned the current process. For example: Running firefox but argv[0] was modified to look like it was actually chromium that was running when it isn't chromium. Just an example of that. This doesn't solve the issue of multiple hard links to the executable, which is unlikely to happen enough I'm not worried about it all that much. Maybe an error code could be done in the case of multiple executable hard links which the number of hard links could be retrieved from the stat structure. Which leads to how my other error codes will be returned: Here's my thoughts on the matter as discussed on implementing this feature for the OpenBSD version of the fish shell: The issue: linking errors and not knowing what libraries to link (documentation on the function I use seem incomplete): https://github.com/fish-shell/fish-shell/issues/9086#issuecomment-1194464329 "I've come up with a means to get a proper error code if the executable path returns a path to the wrong file. Basically if meams getting the vnode from the current process id, get the stat struct from the vnode, the compare a few stat structure members with the stat structure returned by opening the path the function guessed points to the current executable. It involves working with a lot of kernel functions which do have documentation but for one reason or another I can't get any of it to compile because linking errors, and the docs don't say anything about what libraries I should be linking to. It will take a while, but this is a lot better." The implementation I am using explained, which is currently incomplete: https://github.com/fish-shell/fish-shell/issues/9086#issuecomment-1194504685 Note: This code won't be implemented in fish shell as the idea was rejected by them, however I'd like to use this code for my own libraries once it is finished. "To expand on my previous comment, here's some general notes from my research yesterday. <snip> To get the vnode from a process id, you must get the struct process * from the process id using the function struct process *prfind(pid_t) declared in sys/proc.h. Then from that struct process * there is the member of the struct called struct vnode *ps_textvp which according to the code comment and other research is in fact the struct vnode * of the process's executable file. The struct process * structure is defined in sys/proc.h. The _KERNEL and __need_process macros need to be defined before including the sys/proc.h header otherwise the struct process * will not be defined. Defining _KERNEL before including sys/proc.h must be done, however it breaks my code if I define that macro before including sys/vnode.h, which is required for the int VOP_GETATTR(struct vnode *, struct vattr *, struct ucred *, struct proc *) function among other things we need, like the struct vattr * structure, which holds the information necessary to get a proper struct stat * from the struct vnode *. To actually get the struct stat * from the struct vnode *, we call int vn_stat(struct vnode *, struct stat *, struct proc *) which also relies on another structure we need to magically get from the current process id, struct proc *. I'm not sure if that parameter can be null or not, or if that would cause issues. MAXCPUS is a macro which needs to be defined, and I'm not sure what header is the right one to include for it, but it depends on the architecture when done incorrectly because each architecture of binary has its own definition of its macro in a different folder in the source tree named after the architecture. For example, if you are building for amd64, it will be in a folder named amd64, etc. Despute having all the right includes and defining that MAXCPUS macro on my own as 64, it still gives me undefined references when building. According to the multiple sources I've found, comparing the ino_t, dev_t, (and possible filesize, modified timestamp) members of struct stat is good enough to know it is the correct file on the file system, the only issue one would run into is hard links of the executable, which have wrong locations, though it would be very unlikely to return them from the current argv[0]." My question is, what linker flags for which libraries do I need, and how do I get the struct proc * structure from the current process id? Are these things even needed to do what I'm after, or is does the issue lie elsewhere? Thank you so very much!! Samuel