%% 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