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