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