%% options copyright owner = Dirk Krause copyright year = 2015-xxxx license = bsd %% header /** @file Find name of executed file. */ #ifndef DK4CONF_H_INCLUDED #include "dk4conf.h" #endif #ifndef DK4TYPES_H_INCLUDED #include "dk4types.h" #endif #ifndef DK4ERROR_H_INCLUDED #include "dk4error.h" #endif #ifdef __cplusplus extern "C" { #endif /** Retrieve path to executable file. CRT on Windows: Not used. @param buffer Buffer to store the file name. @param sz Buffer size. @param argv0 First command line word. @param erp Error report, may be NULL. @return 1 on success, 0 on error. Error codes: - DK4_E_INVALID_ARGUMENTS
if buffer is NULL or sz is 0, - DK4_E_NOT_FOUND
if the system function(s) failed to find the name, - DK4_E_SYSTEM
if the function failed to find the current working directory, - DK4_E_BUFFER_TOO_SMALL
if the buffer is too small to hold the file name. */ int dk4execpath_c8(char *buffer, size_t sz, const char *argv0, dk4_er_t *erp); #ifdef __cplusplus } #endif %% module #include "dk4exep8.h" #ifndef DK4STR8_H_INCLUDED #include "dk4str8.h" #endif #ifndef DK4MEM_H_INCLUDED #include "dk4mem.h" #endif #ifndef DK4PATH8_H_INCLUDED #include "dk4path8.h" #endif #ifndef DK4STAT8_H_INCLUDED #include "dk4stat8.h" #endif #ifndef DK4STAT_H_INCLUDED #include "dk4stat.h" #endif #ifndef DK4MAO8D_H_INCLUDED #include "dk4mao8d.h" #endif #ifndef DK4MPL_H_INCLUDED #include "dk4mpl.h" #endif #if DK4_ON_WINDOWS #ifndef WINDOWS_H_INCLUDED #include #define WINDOWS_H_INCLUDED 1 #endif #ifndef WINBASE_H_INCLUDED #include #define WINBASE_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SYS_TYPES_H #ifndef SYS_TYPES_H_INCLUDED #include #define SYS_TYPES_H_INCLUDED 1 #endif #endif #if DK4_HAVE_SYS_STAT_H #ifndef SYS_STAT_H_INCLUDED #include #define SYS_STAT_H_INCLUDED 1 #endif #endif #ifndef STDLIB_H_INCLUDED #include #define STDLIB_H_INCLUDED 1 #endif #if DK4_HAVE_ERRNO_H #ifndef ERRNO_H_INCLUDED #include #define ERRNO_H_INCLUDED 1 #endif #endif #if DK4_HAVE_UNISTD_H #ifndef UNISTD_H_INCLUDED #include #define UNISTD_H_INCLUDED 1 #endif #endif #if DK4_HAVE_STRING_H #ifndef STRING_H_INCLUDED #include #define STRING_H_INCLUDED 1 #endif #endif $!trace-include static const char * const dk4execpath_c8_kw[] = { /* 0 */ "PATH", #if DK4_HAVE_BACKSLASH_AS_SEP /* 1 */ "\\", #else /* 1 */ "/", #endif NULL }; #if !DK4_ON_WINDOWS /** Retrieve name of executable file by PATH environment variable inspection. @param buffer Buffer to store result. @param sz Size of buffer. @param argv0 First command line word. @param erp Error report, may be NULL. @return 1 on success, 0 on error. */ static int dk4execpath_c8_inspect_path( char *buffer, size_t sz, const char * argv0, dk4_er_t *erp ) { dk4_stat_t stbuf; char *envpath; char *mycopy; char *p1; char *p2; int back = 0; int cc = 1; envpath = getenv(dk4execpath_c8_kw[0]); if (NULL != envpath) { mycopy = dk4str8_dup(envpath, erp); if (NULL != mycopy) { p1 = mycopy; while ((NULL != p1) && (0 != cc) && (0 == back)) { p2 = dk4str8_chr(p1, ':'); if (NULL != p2) { *(p2++) = '\0'; } if (0 != dk4str8_cpy_s(buffer, sz, p1, erp)) { if (0 != dk4str8_cat_s(buffer, sz, dk4execpath_c8_kw[1], erp)) { if (0 != dk4str8_cat_s(buffer, sz, argv0, erp)) { if (0 != dk4stat_c8(&stbuf, buffer, NULL)) { if (0 != dk4stat_is_regular(&stbuf, NULL)) { back = 1; } } else { $? "! no such file" } } else { cc = 0; } } else { cc = 0; } } else { cc = 0; } p1 = p2; } dk4mem_free(mycopy); } } else { dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } return back; } #endif #if !DK4_ON_WINDOWS #if DK4_HAVE_PROC_PID_EXE static const char * const dk4exep8_kw[] = { /* 0 */ "/proc/", /* 1 */ "/exe" }; #endif #endif #if DK4_ON_WINDOWS #pragma warning (disable:4100) #endif int dk4execpath_c8(char *buffer, size_t sz, const char *argv0, dk4_er_t *erp) { #if DK4_ON_WINDOWS DWORD res; DWORD dwsz; #else #if DK4_HAVE_GETEXECNAME char cwd[DK4_MAX_PATH]; const char *enptr; #endif #if DK4_HAVE_PROC_PID_EXE char numbuf[64]; char fnbuf[sizeof(numbuf)+11]; ssize_t rlres; int res; #endif #endif int back = 0; $? "+ dk4execpath_c8" if ((NULL != buffer) && (0 < sz)) { #if DK4_ON_WINDOWS if ((dk4_um_t)0xFFFFFFFFUL >= (dk4_um_t)sz) { dwsz = (DWORD)sz; } else { dwsz = 0xFFFFFFFFUL; } res = GetModuleFileNameA(GetModuleHandle(NULL), buffer, dwsz); if (0 < res) { if ((dk4_um_t)res < (dk4_um_t)sz) { buffer[res] = '\0'; back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { /* ERROR: Failed to find executable file name */ dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND); } #else #if DK4_HAVE_GETEXECNAME $? ". attempt getexecname" #if 0 /* Prototype is const char *getexecname(void); */ if (0 == getexecname(buffer, sz)) { back = 1; $? ". ok getexecname" } #endif enptr = getexecname(); if (NULL != enptr) { if ('/' == *enptr) { if (strlen(enptr) < sz) { strcpy(buffer, enptr); back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { errno = 0; if (NULL != getcwd(cwd, sizeof(cwd))) { if ((strlen(cwd) + strlen(dk4execpath_c8_kw[1]) + strlen(enptr)) < sz) { strcpy(buffer, cwd); strcat(buffer, dk4execpath_c8_kw[1]); strcat(buffer, enptr); back = 1; } else { dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL); } } else { /* ERROR: Current directory not found */ dk4error_set_idetails(erp, DK4_E_SYSTEM, errno); } } } #endif #if DK4_HAVE_PROC_PID_EXE if (0 == back) { $? ". inspect /proc/pid/exe" res = dk4ma_write_c8_decimal_unsigned( numbuf, sizeof(numbuf), (dk4_um_t)getpid(), 0, NULL ); if (0 != res) { $? ". number" if (0 != dk4str8_cpy_s(fnbuf, sizeof(fnbuf), dk4exep8_kw[0], NULL)) { $? ". cpy ok" if (0 != dk4str8_cat_s(fnbuf, sizeof(fnbuf), numbuf, NULL)) { $? ". cat ok" if (0 != dk4str8_cat_s(fnbuf,sizeof(fnbuf),dk4exep8_kw[1],NULL)) { $? ". cat ok \"%!8s\"", fnbuf rlres = readlink(fnbuf, buffer, sz); $? ". readlink -> %d", (int)rlres if (0 < rlres) { $? ". readlink ok" if (rlres < sz) { $? ". path size ok" buffer[rlres] = '\0'; $? ". ok /proc/pid/exe" back = 1; $? ". file \"%!8s\"", buffer } } } } } } } #endif if (0 == back) { $? ". inspect PATH" if (NULL != argv0) { back = dk4execpath_c8_inspect_path(buffer, sz, argv0, erp); if (0 != back) { $? ". ok PATH" } } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } } #endif } else { dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS); } $? "- dk4execpath_c8 %d", back return back; } #if DK4_ON_WINDOWS #pragma warning (default:4100) #endif