|
|
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"
18:
1.1.1.5 root 19: #if defined(WIN32) && !defined(mkdir)
1.1.1.2 root 20: #define mkdir(name,mode) mkdir(name)
21: #endif /* WIN32 */
22:
1.1.1.3 root 23: static char sWorkingDir[FILENAME_MAX]; /* Working directory */
1.1 root 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: */
1.1.1.3 root 66: static void Paths_GetExecDirFromPATH(const char *argv0, char *pExecDir, int nMaxLen)
1.1 root 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: */
1.1.1.3 root 116: static char *Paths_InitExecDir(const char *argv0)
1.1 root 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");
1.1.1.8 root 186: if (psHome)
187: strncpy(sUserHomeDir, psHome, FILENAME_MAX);
188: #if defined(WIN32)
189: else
1.1 root 190: {
1.1.1.8 root 191: char *psDrive;
192: int len = 0;
1.1.1.6 root 193: /* Windows home path? */
194: psHome = getenv("HOMEPATH");
1.1.1.8 root 195: psDrive = getenv("HOMEDRIVE");
196: if (psDrive)
197: {
198: len = strlen(psDrive);
199: len = len < FILENAME_MAX ? len : FILENAME_MAX;
200: strncpy(sUserHomeDir, psDrive, len);
201: }
202: if (psHome)
203: strncpy(sUserHomeDir+len, psHome, FILENAME_MAX-len);
1.1.1.6 root 204: }
1.1.1.8 root 205: #endif
1.1.1.6 root 206: if (!psHome)
207: {
1.1 root 208: /* $HOME not set, so let's use current working dir as home */
209: strcpy(sUserHomeDir, sWorkingDir);
210: strcpy(sHatariHomeDir, sWorkingDir);
211: }
212: else
213: {
214: sUserHomeDir[FILENAME_MAX-1] = 0;
215:
216: /* Try to use a .hatari directory in the users home directory */
217: snprintf(sHatariHomeDir, FILENAME_MAX, "%s%c.hatari",
218: sUserHomeDir, PATHSEP);
1.1.1.7 root 219: if (!File_DirExists(sHatariHomeDir))
1.1 root 220: {
221: /* Hatari home directory does not exists yet...
222: * ...so let's try to create it: */
223: if (mkdir(sHatariHomeDir, 0755) != 0)
224: {
225: /* Failed to create, so use user's home dir instead */
226: strcpy(sHatariHomeDir, sUserHomeDir);
227: }
228: }
229: }
230: }
231:
232:
233: /**
234: * Initialize directory names
235: *
236: * The datadir will be initialized relative to the bindir (where the executable
237: * has been installed to). This means a lot of additional effort since we first
238: * have to find out where the executable is. But thanks to this effort, we get
239: * a relocatable package (we don't have any absolute path names in the program)!
240: */
1.1.1.3 root 241: void Paths_Init(const char *argv0)
1.1 root 242: {
243: char *psExecDir; /* Path string where the hatari executable can be found */
244:
245: /* Init working directory string */
1.1.1.5 root 246: if (getcwd(sWorkingDir, FILENAME_MAX) == NULL)
247: {
248: /* This should never happen... just in case... */
249: strcpy(sWorkingDir, ".");
250: }
1.1 root 251:
252: /* Init the user's home directory string */
253: Paths_InitHomeDirs();
254:
255: /* Get the directory where the executable resides */
256: psExecDir = Paths_InitExecDir(argv0);
257:
258: /* Now create the datadir path name from the bindir path name: */
259: if (psExecDir && strlen(psExecDir) > 0)
260: {
261: snprintf(sDataDir, sizeof(sDataDir), "%s%c%s",
262: psExecDir, PATHSEP, BIN2DATADIR);
263: }
264: else
265: {
266: /* bindir could not be determined, let's assume datadir is relative
267: * to current working directory... */
268: strcpy(sDataDir, BIN2DATADIR);
269: }
270:
271: /* And finally make a proper absolute path out of datadir: */
272: File_MakeAbsoluteName(sDataDir);
273:
274: free(psExecDir);
275:
276: /* fprintf(stderr, " WorkingDir = %s\n DataDir = %s\n UserHomeDir = %s\n HatariHomeDir = %s\n",
277: sWorkingDir, sDataDir, sUserHomeDir, sHatariHomeDir); */
278: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.