4#include "Stroika/Foundation/StroikaPreComp.h"
8#if qStroika_Foundation_Common_Platform_MacOS
9#include <crt_externs.h>
11#include <mach-o/dyld.h>
13#if qStroika_Foundation_Common_Platform_POSIX && qSupport_Proc_Filesystem
16#if qStroika_Foundation_Common_Platform_Windows
21#include "Stroika/Foundation/Containers/Sequence.h"
23#include "Stroika/Foundation/Execution/Exceptions.h"
25#include "Stroika/Foundation/Execution/Throw.h"
63#if qStroika_Foundation_Common_Platform_MacOS
65 Verify (_NSGetExecutablePath (
nullptr, &bufSize) == -1);
68 Verify (_NSGetExecutablePath (buf.begin (), &bufSize) == 0);
69 Assert (buf[bufSize - 1] ==
'\0');
71#elif qStroika_Foundation_Common_Platform_POSIX && qSupport_Proc_Filesystem
77 while ((n = ::readlink (
"/proc/self/exe", buf.data (), buf.GetSize ())) == buf.GetSize ()) {
83 Assert (n <= buf.GetSize ());
84 return SDKString{buf.begin (), buf.begin () + n};
85#elif qStroika_Foundation_Common_Platform_Windows
87 Verify (::GetModuleFileName (
nullptr, buf,
static_cast<DWORD
> (Memory::NEltsOf (buf))));
88 buf[Memory::NEltsOf (buf) - 1] =
'\0';
92 return filesystem::path{};
103#if qStroika_Foundation_Common_Platform_MacOS
104 char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
105 int ret = ::proc_pidpath (processID, pathbuf,
sizeof (pathbuf));
112#elif qStroika_Foundation_Common_Platform_POSIX && qSupport_Proc_Filesystem
118 char linkNameBuf[1024];
119 (void)std::snprintf (linkNameBuf,
sizeof (linkNameBuf),
"/proc/%ld/exe",
static_cast<long> (processID));
120 while ((n = ::readlink (linkNameBuf, buf.data (), buf.GetSize ())) == buf.GetSize ()) {
126 Assert (n <= buf.GetSize ());
127 return SDKString{buf.begin (), buf.begin () + n};
128#elif qStroika_Foundation_Common_Platform_Windows
132 return filesystem::path{};
135 return filesystem::path{};
146 if (
const char* env_p = std::getenv (
"PATH")) {
147 String pathVar = String::FromNarrowSDKString (env_p);
148#if qStroika_Foundation_Common_Platform_POSIX
150#elif qStroika_Foundation_Common_Platform_Windows
154 DISABLE_COMPILER_MSC_WARNING_END (4996)
158#if qStroika_Foundation_Common_Platform_Windows
166 if (const
char* env_p =
std::getenv ("PATHEXT")) {
167 String pathVar = String::FromNarrowSDKString (env_p);
170 DISABLE_COMPILER_MSC_WARNING_END (4996)
182 const SDKChar*
const* envHead =
nullptr;
183#if qStroika_Foundation_Common_Platform_Windows
186 if constexpr (same_as<SDKChar, wchar_t>) {
187 if (_wenviron ==
nullptr) {
188 [[maybe_unused]]
auto ignored = ::_wgetenv (L
"PATH");
192 if (environ ==
nullptr) {
193 [[maybe_unused]]
auto ignored = ::getenv (
"PATH");
196 DISABLE_COMPILER_MSC_WARNING_END (4996)
198#if qStroika_Foundation_Common_Platform_Windows
199 if constexpr (same_as<SDKChar, wchar_t>) {
205#if qStroika_Foundation_Common_Platform_MacOS
206 envHead = (*_NSGetEnviron ());
213 for (
const SDKChar*
const* p = envHead; *p; ++p) {
215 size_t i = eltStr.find (
'=');
216 if (i == SDKString::npos) {
217 DbgTrace (
"bad env elt: {}"_f, String::FromSDKString (eltStr));
221 r.
Add (eltStr.substr (0, i), eltStr.substr (i + 1));
235 r.
Add (String::FromSDKString (i.fKey), String::FromSDKString (i.fValue));
247 auto checkExists = [] (
const filesystem::path& exe) {
249 return filesystem::exists (exe) and filesystem::is_regular_file (exe) and
250 static_cast<bool> (filesystem::status (exe).permissions () & filesystem::perms::owner_exec);
252 if (fn.is_absolute ()) {
253 if (checkExists (fn)) {
256#if qStroika_Foundation_Common_Platform_Windows
257 if (fn.extension ().empty ()) {
258 filesystem::path exe = fn;
259 for (
auto exeExt : kPathEXT ()) {
260 exe.replace_extension (exeExt);
261 if (checkExists (exe)) {
270 for (filesystem::path d :
kPath ()) {
271 filesystem::path exe = d / fn;
272 if (checkExists (exe)) {
275#if qStroika_Foundation_Common_Platform_Windows
276 if (fn.extension ().empty ()) {
277 for (
auto exeExt : kPathEXT ()) {
278 exe.replace_extension (exeExt);
279 if (checkExists (exe)) {
#define WeakAssertNotReached()
#define AssertNotImplemented()
String is like std::u32string, except it is much easier to use, often much more space efficient,...
nonvirtual Containers::Sequence< String > Tokenize() const
nonvirtual bool Add(ArgByValueType< key_type > key, ArgByValueType< mapped_type > newElt, AddReplaceMode addReplaceMode=AddReplaceMode::eAddReplaces)
A generalization of a vector: a container whose elements are keyed by the natural numbers.
Exception<> is a replacement (subclass) for any std c++ exception class (e.g. the default 'std::excep...
value-object, where the value construction is delayed until first needed (can be handy to avoid c++ i...
Logically halfway between std::array and std::vector; Smart 'direct memory array' - which when needed...
nonvirtual void GrowToSize_uninitialized(size_t nElements)
same as GrowToSize (), except leaves newly created elements uninitialized (requires is_trivially_copy...
conditional_t< qTargetPlatformSDKUseswchar_t, wchar_t, char > SDKChar
basic_string< SDKChar > SDKString
DISABLE_COMPILER_MSC_WARNING_START(4996)
void Throw(T &&e2Throw)
identical to builtin C++ 'throw' except that it does helpful, type dependent DbgTrace() messages firs...
const LazyInitialized< Containers::Mapping< Characters::String, Characters::String > > kEnvironment
convert getenv() to a Mapping of Strings for easier access
const LazyInitialized< Containers::Sequence< filesystem::path > > kPath
void ThrowPOSIXErrNo(errno_t errNo=errno)
treats errNo as a POSIX errno value, and throws a SystemError (subclass of @std::system_error) except...
const LazyInitialized< Containers::Mapping< Characters::SDKString, Characters::SDKString > > kRawEnvironment
convert getenv() to a Mapping of SDKString (in case some issue with charactor set conversion)
filesystem::path GetEXEDir()
optional< filesystem::path > FindExecutableInPath(const filesystem::path &fn)
If fn refers to an executable - return it (using kPATH, and kPathEXT as appropriate)
int pid_t
TODO - maybe move this to configuraiotn module???
filesystem::path GetEXEPath()