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