From 9d857698d465ac3c36b70a5083d867f826067bc8 Mon Sep 17 00:00:00 2001 From: Aaron Date: Tue, 28 May 2024 14:30:28 -0600 Subject: [PATCH] Look for input files relative to executable path instead of cwd (#11) * Change default input files location to be relative to executable --- Include/42.h | 3 ++ Kit/Include/iokit.h | 7 +++++ Kit/Source/iokit.c | 69 +++++++++++++++++++++++++++++++++++++++++++++ Makefile | 8 +++++- Source/42init.c | 37 ++++++++++++++++++++++-- 5 files changed, 121 insertions(+), 3 deletions(-) diff --git a/Include/42.h b/Include/42.h index 1876517f..1cb61149 100755 --- a/Include/42.h +++ b/Include/42.h @@ -55,6 +55,9 @@ EXTERN long Nmatl; /* Number of geometric objects */ EXTERN long Ngeom; +#define STRINGIZE(x) #x +#define STRINGIZE_VALUE_OF(x) STRINGIZE(x) + EXTERN char InOutPath[80]; EXTERN char ModelPath[80]; EXTERN char CmdFileName[80]; diff --git a/Kit/Include/iokit.h b/Kit/Include/iokit.h index 9bae5592..d4db9d19 100755 --- a/Kit/Include/iokit.h +++ b/Kit/Include/iokit.h @@ -31,6 +31,8 @@ #include #ifdef _WIN32 #include + extern char *_pgmptr; + #define OS_SEP '\\' #else #include #include @@ -38,6 +40,7 @@ #include /* Finesse winsock SOCKET datatype */ #define SOCKET int + #define OS_SEP '/' #endif /* #include */ @@ -49,6 +52,10 @@ int FileToString(const char *file_name, char **result_string, SOCKET InitSocketServer(int Port, int AllowBlocking); SOCKET InitSocketClient(const char *hostname, int Port, int AllowBlocking); +void SplitPath(char *path_file, char **path, char **file); +void GetExecutablePath(char *path, size_t bufsize); +void AddTrailingSlash(char *path); + /* ** #ifdef __cplusplus ** } diff --git a/Kit/Source/iokit.c b/Kit/Source/iokit.c index 39011694..1d22f49d 100755 --- a/Kit/Source/iokit.c +++ b/Kit/Source/iokit.c @@ -278,6 +278,75 @@ SOCKET InitSocketClient(const char *hostname, int Port,int AllowBlocking) #endif /* _WIN32 */ } +/** + * Splits the `path_file` into a directory part: `path`, and file part: `file` + * If `path_file` is just a filename with no containing folder, `path` will be a 0 length string. +*/ +void SplitPath(char *path_file, char **path, char **file) { + *path = (char *)malloc(strlen(path_file)); + // file = (char *)malloc(strlen(path_file)); + strcpy(*path, path_file); + char *pos = strrchr(*path, OS_SEP); + if (NULL == pos) { + *file = strdup(path_file); + (*path)[0] = '\0'; + } else { + *pos = '\0'; + *file = strdup(pos + 1); + } +} + +/** + * Attempts to retrieve the full path to the currently running executable + * and populates `path` with it. Uses `max_path_len` to avoid overrunning `path` + * `max_path_len` is the total size of `path`, which means it includes the + * null terminating character. +*/ +void GetExecutablePath(char *path, size_t max_path_len) { + ssize_t len; + memset(path, 0, max_path_len); +#if defined(_WIN32) + strncpy(path, _pgmptr, max_path_len); + len = strlen(path); +#else + len = readlink("/proc/self/exe", path, max_path_len); + if (len < 0) { + printf("Error: error when getting executable path. Exiting.\n"); + exit(EXIT_FAILURE); + } +#endif + if (len >= max_path_len) { + printf("Error: executable path received too long for file path buffer. Exiting.\n"); + exit(EXIT_FAILURE); + } +} + +/** + * Looks for a trailing slash in `path`; if one isn't found it appends one to `path` +*/ +void AddTrailingSlash(char *path) { + char *end = strchr(path, '\0'); + if (end == NULL) { + printf( + "Error: path provided contains no null terminating character. " + "Exiting.\n"); + exit(EXIT_FAILURE); + } + + char *slash = strrchr(path, OS_SEP); + if (slash != NULL) { + size_t diff = end - slash; + if (diff == 1) { + return; + } + } + + char *sep = (char *)malloc(3); + sprintf(sep, "%c", OS_SEP); + strcat(path, sep); + free(sep); +} + /* #ifdef __cplusplus ** } ** #endif diff --git a/Makefile b/Makefile index 6ad2f6af..b84ea887 100755 --- a/Makefile +++ b/Makefile @@ -48,6 +48,12 @@ GMSECFLAG = RBTFLAG = #RBTFLAG = -D _ENABLE_RBT_ +DEFAULT_CASE_PATH = +#DEFAULT_CASE_PATH = -D _DEFAULT_CASE_PATH_=./InOut + +DEFAULT_MODEL_PATH = +#DEFAULT_MODEL_PATH = -D _DEFAULT_MODEL_PATH_=./Model + ifeq ($(strip $(GMSECFLAG)),) GMSECDIR = GMSECINC = @@ -243,7 +249,7 @@ $(OBJ)AppWriteToSocket.o $(OBJ)AppReadFromSocket.o $(OBJ)AppWriteToFile.o #ANSIFLAGS = -Wstrict-prototypes -pedantic -ansi -Werror ANSIFLAGS = -CFLAGS = -fpic -Wall -Wshadow -Wno-deprecated $(XWARN) -g $(ANSIFLAGS) $(GLINC) $(CINC) -I $(INC) -I $(KITINC) -I $(KITSRC) -I $(RBTSRC) $(GMSECINC) -O0 $(ARCHFLAG) $(GUIFLAG) $(GUI_LIB) $(SHADERFLAG) $(CFDFLAG) $(FFTBFLAG) $(GSFCFLAG) $(GMSECFLAG) $(STANDALONEFLAG) $(RBTFLAG) +CFLAGS = -fpic -Wall -Wshadow -Wno-deprecated $(XWARN) -g $(ANSIFLAGS) $(GLINC) $(CINC) -I $(INC) -I $(KITINC) -I $(KITSRC) -I $(RBTSRC) $(GMSECINC) -O0 $(ARCHFLAG) $(GUIFLAG) $(GUI_LIB) $(SHADERFLAG) $(CFDFLAG) $(FFTBFLAG) $(GSFCFLAG) $(GMSECFLAG) $(STANDALONEFLAG) $(RBTFLAG) $(DEFAULT_CASE_PATH) $(DEFAULT_MODEL_PATH) ########################## Rules to link 42 ############################# diff --git a/Source/42init.c b/Source/42init.c index 3b101cb1..68ad9c0e 100755 --- a/Source/42init.c +++ b/Source/42init.c @@ -4368,8 +4368,41 @@ void InitSim(int argc, char **argv) if (argc > 1) sprintf(InOutPath,"../../GSFC/RBT/%s/",argv[1]); if (argc > 2) sprintf(ModelPath,"../../GSFC/RBT/%s/",argv[2]); #else - sprintf(InOutPath,"./InOut/"); - sprintf(ModelPath,"./Model/"); + char *exec_name, *exec_dir, *exec_path; + exec_path = (char *)malloc(FILENAME_MAX); + + GetExecutablePath(exec_path, FILENAME_MAX); + SplitPath(exec_path, &exec_dir, &exec_name); + + if (strlen(exec_dir) == 0) { + printf("Error finding executable's containing folder. Exiting."); + exit(EXIT_FAILURE); + } + + AddTrailingSlash(exec_dir); + +#ifndef _DEFAULT_CASE_PATH_ + strcpy(InOutPath, exec_dir); + strcat(InOutPath, "examples/InOut"); +#else + sprintf(InOutPath, STRINGIZE_VALUE_OF(_DEFAULT_CASE_PATH_)); +#endif + + AddTrailingSlash((char *)InOutPath); + +#ifndef _DEFAULT_MODEL_PATH_ + strcpy(ModelPath, exec_dir); + strcat(ModelPath, "Model"); +#else + sprintf(ModelPath, STRINGIZE_VALUE_OF(_DEFAULT_MODEL_PATH_)); +#endif + + AddTrailingSlash((char *)ModelPath); + + free(exec_name); + free(exec_dir); + free(exec_path); + if (argc > 1) sprintf(InOutPath,"./%s/",argv[1]); if (argc > 2) sprintf(ModelPath,"./%s/",argv[2]); #endif