epicsGetExecDir() paths relative to executable

For linux, enable softIoc to find .dbd relative to the executable
location.

The same could be done for other targets

*bsd
  may have symlink /proc/curproc/file
  fallback to sysctl() with KERN_PROC_PATHNAME

solaris
  getexecname()

mac
  _NSGetExecutablePath()

WIN32
  GetModuleFileName(NULL)

others
  out of luck...
This commit is contained in:
Michael Davidsaver
2018-04-25 22:57:03 -07:00
parent 4ee3cbf382
commit 32340584b4
7 changed files with 170 additions and 2 deletions

View File

@@ -62,23 +62,59 @@
#include "epicsThread.h"
#include "epicsExit.h"
#include "epicsStdio.h"
#include "epicsString.h"
#include "dbStaticLib.h"
#include "subRecord.h"
#include "dbAccess.h"
#include "asDbLib.h"
#include "iocInit.h"
#include "iocsh.h"
#include "osiFileName.h"
#include "epicsInstallDir.h"
extern "C" int softIoc_registerRecordDeviceDriver(struct dbBase *pdbbase);
#define DBD_FILE EPICS_BASE "/dbd/softIoc.dbd"
#define EXIT_FILE EPICS_BASE "/db/softIocExit.db"
#define DBD_BASE "dbd/softIoc.dbd"
#define EXIT_BASE "db/softIocExit.db"
#define DBD_FILE_REL "../../" DBD_BASE
#define EXIT_FILE_REL "../../" EXIT_BASE
#define DBD_FILE EPICS_BASE "/" DBD_BASE
#define EXIT_FILE EPICS_BASE "/" EXIT_BASE
const char *arg0;
const char *base_dbd = DBD_FILE;
const char *exit_db = EXIT_FILE;
static void preparePath(void)
{
FILE *fp;
char *prefix = epicsGetExecDir();
char *dbd, *exit;
if(!prefix) return;
dbd = (char*)malloc(strlen(prefix) + strlen(DBD_FILE_REL) + 1);
if(dbd) {
dbd[0] = '\0';
strcat(dbd, prefix);
strcat(dbd, DBD_FILE_REL);
printf("Testing '%s'\n", dbd);
if((fp = fopen(dbd, "rb"))!=NULL) {
fclose(fp);
base_dbd = dbd;
}
}
exit = (char*)malloc(strlen(prefix) + strlen(EXIT_FILE_REL) + 1);
if(exit) {
exit[0] = '\0';
strcat(exit, prefix);
strcat(exit, EXIT_FILE_REL);
if((fp = fopen(exit, "rb"))!=NULL) {
fclose(fp);
exit_db = exit;
}
}
}
static void exitSubroutine(subRecord *precord) {
epicsExitLater((precord->a == 0.0) ? EXIT_SUCCESS : EXIT_FAILURE);
@@ -96,6 +132,7 @@ static void usage(int status) {
int main(int argc, char *argv[])
{
preparePath();
char *dbd_file = const_cast<char*>(base_dbd);
char *macros = NULL;
char xmacro[PVNAME_STRINGSZ + 4];

View File

@@ -14,7 +14,29 @@
#ifndef unixFileNameH
#define unixFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ":"
#define OSI_PATH_SEPARATOR "/"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* unixFileNameH */

View File

@@ -123,6 +123,7 @@ Com_SRCS += osdMonotonic.c
Com_SRCS += osdProcess.c
Com_SRCS += osdNetIntf.c
Com_SRCS += osdMessageQueue.c
Com_SRCS += osdgetexec.c
Com_SRCS += devLibVME.c
Com_SRCS += devLibVMEOSD.c

View File

@@ -0,0 +1,50 @@
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
size_t max = PATH_MAX;
char *ret = NULL;
ssize_t n;
while(1) {
char *temp = realloc(ret, max);
if(!temp) {
/* we treat alloc failure as terminal */
free(ret);
ret = NULL;
break;
}
ret = temp;
n = readlink("/proc/self/exe", ret, max);
if(n < max) {
/* readlink() never adds a nil */
ret[n] = '\0';
break;
}
max += 64;
}
return ret;
}
char *epicsGetExecDir(void)
{
char *ret = epicsGetExecName();
if(ret) {
char *sep = strrchr(ret, '/');
if(sep) {
/* nil the charactor after the / */
sep[1] = '\0';
}
}
return ret;
}

View File

@@ -15,7 +15,29 @@
#ifndef osiFileNameH
#define osiFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ";"
#define OSI_PATH_SEPARATOR "\\"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* osiFileNameH */

View File

@@ -14,7 +14,29 @@
#ifndef osiFileNameH
#define osiFileNameH
#include <shareLib.h>
#ifdef __cplusplus
extern "C" {
#endif
#define OSI_PATH_LIST_SEPARATOR ";"
#define OSI_PATH_SEPARATOR "\\"
/** Return the absolute path of the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecName(void);
/** Return the absolute path of the directory containing the current executable.
@returns NULL or the path. Caller must free()
*/
epicsShareFunc
char *epicsGetExecDir(void);
#ifdef __cplusplus
}
#endif
#endif /* osiFileNameH */

View File

@@ -0,0 +1,14 @@
#include <stdlib.h>
#define epicsExportSharedSymbols
#include <osiFileName.h>
char *epicsGetExecName(void)
{
return NULL;
}
char *epicsGetExecDir(void)
{
return NULL;
}