|
|
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.