diff --git a/modules/database/src/std/softIoc/softMain.cpp b/modules/database/src/std/softIoc/softMain.cpp index 8400a6554..01ef19b2f 100644 --- a/modules/database/src/std/softIoc/softMain.cpp +++ b/modules/database/src/std/softIoc/softMain.cpp @@ -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(base_dbd); char *macros = NULL; char xmacro[PVNAME_STRINGSZ + 4]; diff --git a/modules/libcom/src/misc/unixFileName.h b/modules/libcom/src/misc/unixFileName.h index 36e818c8f..9d7af252c 100644 --- a/modules/libcom/src/misc/unixFileName.h +++ b/modules/libcom/src/misc/unixFileName.h @@ -14,7 +14,29 @@ #ifndef unixFileNameH #define unixFileNameH +#include + +#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 */ diff --git a/modules/libcom/src/osi/Makefile b/modules/libcom/src/osi/Makefile index ecbf4c23b..0352e9ffe 100644 --- a/modules/libcom/src/osi/Makefile +++ b/modules/libcom/src/osi/Makefile @@ -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 diff --git a/modules/libcom/src/osi/os/Linux/osdgetexec.c b/modules/libcom/src/osi/os/Linux/osdgetexec.c new file mode 100644 index 000000000..2ea8ca4ae --- /dev/null +++ b/modules/libcom/src/osi/os/Linux/osdgetexec.c @@ -0,0 +1,50 @@ + +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include + +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; +} diff --git a/modules/libcom/src/osi/os/WIN32/osiFileName.h b/modules/libcom/src/osi/os/WIN32/osiFileName.h index 6ff0308b2..ced745f71 100644 --- a/modules/libcom/src/osi/os/WIN32/osiFileName.h +++ b/modules/libcom/src/osi/os/WIN32/osiFileName.h @@ -15,7 +15,29 @@ #ifndef osiFileNameH #define osiFileNameH +#include + +#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 */ diff --git a/modules/libcom/src/osi/os/cygwin32/osiFileName.h b/modules/libcom/src/osi/os/cygwin32/osiFileName.h index 6d7fd6eb9..1e7799098 100644 --- a/modules/libcom/src/osi/os/cygwin32/osiFileName.h +++ b/modules/libcom/src/osi/os/cygwin32/osiFileName.h @@ -14,7 +14,29 @@ #ifndef osiFileNameH #define osiFileNameH +#include + +#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 */ diff --git a/modules/libcom/src/osi/os/default/osdgetexec.c b/modules/libcom/src/osi/os/default/osdgetexec.c new file mode 100644 index 000000000..0bec9ead9 --- /dev/null +++ b/modules/libcom/src/osi/os/default/osdgetexec.c @@ -0,0 +1,14 @@ +#include + +#define epicsExportSharedSymbols +#include + +char *epicsGetExecName(void) +{ + return NULL; +} + +char *epicsGetExecDir(void) +{ + return NULL; +}