|
|
1.1 ! root 1: /* ! 2: Hatari - paths.c ! 3: ! 4: This file is distributed under the GNU Public License, version 2 or at ! 5: your option any later version. Read the file gpl.txt for details. ! 6: ! 7: Set up the various path strings. ! 8: */ ! 9: ! 10: #include <unistd.h> ! 11: #include <sys/stat.h> ! 12: #include <sys/types.h> ! 13: ! 14: #include "config.h" ! 15: #include "main.h" ! 16: #include "file.h" ! 17: #include "paths.h" ! 18: ! 19: char sWorkingDir[FILENAME_MAX]; /* Working directory */ ! 20: static char sDataDir[FILENAME_MAX]; /* Directory where data files of Hatari can be found */ ! 21: static char sUserHomeDir[FILENAME_MAX]; /* User's home directory ($HOME) */ ! 22: static char sHatariHomeDir[FILENAME_MAX]; /* Hatari's home directory ($HOME/.hatari/) */ ! 23: ! 24: ! 25: /** ! 26: * Return pointer to current working directory string ! 27: */ ! 28: const char *Paths_GetWorkingDir(void) ! 29: { ! 30: return sWorkingDir; ! 31: } ! 32: ! 33: /** ! 34: * Return pointer to data directory string ! 35: */ ! 36: const char *Paths_GetDataDir(void) ! 37: { ! 38: return sDataDir; ! 39: } ! 40: ! 41: /** ! 42: * Return pointer to user's home directory string ! 43: */ ! 44: const char *Paths_GetUserHome(void) ! 45: { ! 46: return sUserHomeDir; ! 47: } ! 48: ! 49: /** ! 50: * Return pointer to Hatari's home directory string ! 51: */ ! 52: const char *Paths_GetHatariHome(void) ! 53: { ! 54: return sHatariHomeDir; ! 55: } ! 56: ! 57: ! 58: /** ! 59: * Explore the PATH environment variable to see where our executable is ! 60: * installed. ! 61: */ ! 62: static void Paths_GetExecDirFromPATH(char *argv0, char *pExecDir, int nMaxLen) ! 63: { ! 64: char *pPathEnv; ! 65: char *pAct; ! 66: char *pTmpName; ! 67: const char *pToken; ! 68: ! 69: /* Get the PATH environment string */ ! 70: pPathEnv = getenv("PATH"); ! 71: if (!pPathEnv) ! 72: return; ! 73: /* Duplicate the string because strtok destroys it later */ ! 74: pPathEnv = strdup(pPathEnv); ! 75: if (!pPathEnv) ! 76: return; ! 77: ! 78: pTmpName = malloc(FILENAME_MAX); ! 79: if (!pTmpName) ! 80: return; ! 81: ! 82: /* If there is a semicolon in the PATH, we assume it is the PATH ! 83: * separator token (like on Windows), otherwise we use a colon. */ ! 84: if (strchr((pPathEnv), ';')) ! 85: pToken = ";"; ! 86: else ! 87: pToken = ":"; ! 88: ! 89: pAct = strtok (pPathEnv, pToken); ! 90: while (pAct) ! 91: { ! 92: snprintf(pTmpName, FILENAME_MAX, "%s%c%s", ! 93: pAct, PATHSEP, argv0); ! 94: if (File_Exists(pTmpName)) ! 95: { ! 96: /* Found the executable - so use the corresponding path: */ ! 97: strncpy(pExecDir, pAct, nMaxLen); ! 98: pExecDir[nMaxLen-1] = 0; ! 99: break; ! 100: } ! 101: pAct = strtok (0, pToken); ! 102: } ! 103: ! 104: free(pPathEnv); ! 105: free(pTmpName); ! 106: } ! 107: ! 108: ! 109: /** ! 110: * Locate the directory where the hatari executable resides ! 111: */ ! 112: static char *Paths_InitExecDir(char *argv0) ! 113: { ! 114: char *psExecDir; /* Path string where the hatari executable can be found */ ! 115: ! 116: /* Allocate memory for storing the path string of the executable */ ! 117: psExecDir = malloc(FILENAME_MAX); ! 118: if (!psExecDir) ! 119: { ! 120: fprintf(stderr, "Out of memory (Paths_Init)\n"); ! 121: exit(-1); ! 122: } ! 123: ! 124: /* Determine the bindir... ! 125: * Start with empty string, then try to use OS specific functions, ! 126: * and finally analyze the PATH variable if it has not been found yet. */ ! 127: psExecDir[0] = '\0'; ! 128: ! 129: #if defined(__linux__) ! 130: { ! 131: int i; ! 132: /* On Linux, we can analyze the symlink /proc/self/exe */ ! 133: i = readlink("/proc/self/exe", psExecDir, FILENAME_MAX); ! 134: if (i > 0) ! 135: { ! 136: char *p; ! 137: psExecDir[i] = '\0'; ! 138: p = strrchr(psExecDir, '/'); /* Search last slash */ ! 139: if (p) ! 140: *p = 0; /* Strip file name from path */ ! 141: } ! 142: } ! 143: //#elif defined(WIN32) || defined(__CEGCC__) ! 144: // /* On Windows we can use GetModuleFileName for getting the exe path */ ! 145: // GetModuleFileName(NULL, psExecDir, FILENAME_MAX); ! 146: #endif ! 147: ! 148: /* If we do not have the execdir yet, analyze argv[0] and the PATH: */ ! 149: if (psExecDir[0] == 0) ! 150: { ! 151: if (strchr(argv0, PATHSEP) == 0) ! 152: { ! 153: /* No separator in argv[0], we have to explore PATH... */ ! 154: Paths_GetExecDirFromPATH(argv0, psExecDir, FILENAME_MAX); ! 155: } ! 156: else ! 157: { ! 158: /* There was a path separator in argv[0], so let's assume a ! 159: * relative or absolute path to the current directory in argv[0] */ ! 160: char *p; ! 161: strncpy(psExecDir, argv0, FILENAME_MAX); ! 162: psExecDir[FILENAME_MAX-1] = 0; ! 163: p = strrchr(psExecDir, PATHSEP); /* Search last slash */ ! 164: if (p) ! 165: *p = 0; /* Strip file name from path */ ! 166: } ! 167: } ! 168: ! 169: return psExecDir; ! 170: } ! 171: ! 172: ! 173: /** ! 174: * Initialize the users home directory string ! 175: * and Hatari's home directory (~/.hatari) ! 176: */ ! 177: static void Paths_InitHomeDirs(void) ! 178: { ! 179: char *psHome; ! 180: ! 181: psHome = getenv("HOME"); ! 182: if (!psHome) ! 183: { ! 184: /* $HOME not set, so let's use current working dir as home */ ! 185: strcpy(sUserHomeDir, sWorkingDir); ! 186: strcpy(sHatariHomeDir, sWorkingDir); ! 187: } ! 188: else ! 189: { ! 190: strncpy(sUserHomeDir, psHome, FILENAME_MAX); ! 191: sUserHomeDir[FILENAME_MAX-1] = 0; ! 192: ! 193: /* Try to use a .hatari directory in the users home directory */ ! 194: snprintf(sHatariHomeDir, FILENAME_MAX, "%s%c.hatari", ! 195: sUserHomeDir, PATHSEP); ! 196: if (!File_DirectoryExists(sHatariHomeDir)) ! 197: { ! 198: /* Hatari home directory does not exists yet... ! 199: * ...so let's try to create it: */ ! 200: if (mkdir(sHatariHomeDir, 0755) != 0) ! 201: { ! 202: /* Failed to create, so use user's home dir instead */ ! 203: strcpy(sHatariHomeDir, sUserHomeDir); ! 204: } ! 205: } ! 206: } ! 207: } ! 208: ! 209: ! 210: /** ! 211: * Initialize directory names ! 212: * ! 213: * The datadir will be initialized relative to the bindir (where the executable ! 214: * has been installed to). This means a lot of additional effort since we first ! 215: * have to find out where the executable is. But thanks to this effort, we get ! 216: * a relocatable package (we don't have any absolute path names in the program)! ! 217: */ ! 218: void Paths_Init(char *argv0) ! 219: { ! 220: char *psExecDir; /* Path string where the hatari executable can be found */ ! 221: ! 222: /* Init working directory string */ ! 223: getcwd(sWorkingDir, FILENAME_MAX); ! 224: ! 225: /* Init the user's home directory string */ ! 226: Paths_InitHomeDirs(); ! 227: ! 228: /* Get the directory where the executable resides */ ! 229: psExecDir = Paths_InitExecDir(argv0); ! 230: ! 231: /* Now create the datadir path name from the bindir path name: */ ! 232: if (psExecDir && strlen(psExecDir) > 0) ! 233: { ! 234: snprintf(sDataDir, sizeof(sDataDir), "%s%c%s", ! 235: psExecDir, PATHSEP, BIN2DATADIR); ! 236: } ! 237: else ! 238: { ! 239: /* bindir could not be determined, let's assume datadir is relative ! 240: * to current working directory... */ ! 241: strcpy(sDataDir, BIN2DATADIR); ! 242: } ! 243: ! 244: /* And finally make a proper absolute path out of datadir: */ ! 245: File_MakeAbsoluteName(sDataDir); ! 246: ! 247: free(psExecDir); ! 248: ! 249: /* fprintf(stderr, " WorkingDir = %s\n DataDir = %s\n UserHomeDir = %s\n HatariHomeDir = %s\n", ! 250: sWorkingDir, sDataDir, sUserHomeDir, sHatariHomeDir); */ ! 251: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.