Annotation of hatari/src/paths.c, revision 1.1.1.10

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.10! root       23: #if defined(__MACOSX__)
        !            24:        #define HATARI_HOME_DIR "Library/Application Support/Hatari"
        !            25: #else
        !            26:        #define HATARI_HOME_DIR ".hatari"
        !            27: #endif
        !            28: 
1.1.1.3   root       29: static char sWorkingDir[FILENAME_MAX];    /* Working directory */
1.1       root       30: static char sDataDir[FILENAME_MAX];       /* Directory where data files of Hatari can be found */
                     31: static char sUserHomeDir[FILENAME_MAX];   /* User's home directory ($HOME) */
                     32: static char sHatariHomeDir[FILENAME_MAX]; /* Hatari's home directory ($HOME/.hatari/) */
                     33: 
                     34: 
                     35: /**
                     36:  * Return pointer to current working directory string
                     37:  */
                     38: const char *Paths_GetWorkingDir(void)
                     39: {
                     40:        return sWorkingDir;
                     41: }
                     42: 
                     43: /**
                     44:  * Return pointer to data directory string
                     45:  */
                     46: const char *Paths_GetDataDir(void)
                     47: {
                     48:        return sDataDir;
                     49: }
                     50: 
                     51: /**
                     52:  * Return pointer to user's home directory string
                     53:  */
                     54: const char *Paths_GetUserHome(void)
                     55: {
                     56:        return sUserHomeDir;
                     57: }
                     58: 
                     59: /**
                     60:  * Return pointer to Hatari's home directory string
                     61:  */
                     62: const char *Paths_GetHatariHome(void)
                     63: {
                     64:        return sHatariHomeDir;
                     65: }
                     66: 
                     67: 
                     68: /**
                     69:  * Explore the PATH environment variable to see where our executable is
                     70:  * installed.
                     71:  */
1.1.1.3   root       72: static void Paths_GetExecDirFromPATH(const char *argv0, char *pExecDir, int nMaxLen)
1.1       root       73: {
                     74:        char *pPathEnv;
                     75:        char *pAct;
                     76:        char *pTmpName;
                     77:        const char *pToken;
                     78: 
                     79:        /* Get the PATH environment string */
                     80:        pPathEnv = getenv("PATH");
                     81:        if (!pPathEnv)
                     82:                return;
                     83:        /* Duplicate the string because strtok destroys it later */
                     84:        pPathEnv = strdup(pPathEnv);
                     85:        if (!pPathEnv)
                     86:                return;
                     87: 
                     88:        pTmpName = malloc(FILENAME_MAX);
                     89:        if (!pTmpName)
1.1.1.10! root       90:        {
        !            91:                perror("Paths_GetExecDirFromPATH");
        !            92:                free(pPathEnv);
1.1       root       93:                return;
1.1.1.10! root       94:        }
1.1       root       95: 
                     96:        /* If there is a semicolon in the PATH, we assume it is the PATH
                     97:         * separator token (like on Windows), otherwise we use a colon. */
                     98:        if (strchr((pPathEnv), ';'))
                     99:                pToken = ";";
                    100:        else
                    101:                pToken = ":";
                    102: 
                    103:        pAct = strtok (pPathEnv, pToken);
                    104:        while (pAct)
                    105:        {
                    106:                snprintf(pTmpName, FILENAME_MAX, "%s%c%s",
                    107:                         pAct, PATHSEP, argv0);
                    108:                if (File_Exists(pTmpName))
                    109:                {
                    110:                        /* Found the executable - so use the corresponding path: */
                    111:                        strncpy(pExecDir, pAct, nMaxLen);
                    112:                        pExecDir[nMaxLen-1] = 0;
                    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 */
                    147:                i = readlink("/proc/self/exe", psExecDir, FILENAME_MAX);
                    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;
                    175:                        strncpy(psExecDir, argv0, FILENAME_MAX);
                    176:                        psExecDir[FILENAME_MAX-1] = 0;
                    177:                        p = strrchr(psExecDir, PATHSEP);  /* Search last slash */
                    178:                        if (p)
                    179:                                *p = 0;                       /* Strip file name from path */
                    180:                }
                    181:        }
                    182: 
                    183:        return psExecDir;
                    184: }
                    185: 
                    186: 
                    187: /**
                    188:  * Initialize the users home directory string
                    189:  * and Hatari's home directory (~/.hatari)
                    190:  */
                    191: static void Paths_InitHomeDirs(void)
                    192: {
                    193:        char *psHome;
                    194: 
                    195:        psHome = getenv("HOME");
1.1.1.8   root      196:        if (psHome)
                    197:                strncpy(sUserHomeDir, psHome, FILENAME_MAX);
                    198: #if defined(WIN32)
                    199:        else
1.1       root      200:        {
1.1.1.8   root      201:                char *psDrive;
                    202:                int len = 0;
1.1.1.6   root      203:                /* Windows home path? */
                    204:                psHome = getenv("HOMEPATH");
1.1.1.8   root      205:                psDrive = getenv("HOMEDRIVE");
                    206:                if (psDrive)
                    207:                {
                    208:                        len = strlen(psDrive);
                    209:                        len = len < FILENAME_MAX ? len : FILENAME_MAX;
                    210:                        strncpy(sUserHomeDir, psDrive, len);
                    211:                }
                    212:                if (psHome)
                    213:                        strncpy(sUserHomeDir+len, psHome, FILENAME_MAX-len);
1.1.1.6   root      214:        }
1.1.1.8   root      215: #endif
1.1.1.6   root      216:        if (!psHome)
                    217:        {
1.1       root      218:                /* $HOME not set, so let's use current working dir as home */
                    219:                strcpy(sUserHomeDir, sWorkingDir);
                    220:                strcpy(sHatariHomeDir, sWorkingDir);
                    221:        }
                    222:        else
                    223:        {
                    224:                sUserHomeDir[FILENAME_MAX-1] = 0;
                    225: 
                    226:                /* Try to use a .hatari directory in the users home directory */
1.1.1.10! root      227:                snprintf(sHatariHomeDir, FILENAME_MAX, "%s%c%s", sUserHomeDir,
        !           228:                         PATHSEP, HATARI_HOME_DIR);
1.1.1.7   root      229:                if (!File_DirExists(sHatariHomeDir))
1.1       root      230:                {
                    231:                        /* Hatari home directory does not exists yet...
                    232:                         * ...so let's try to create it: */
                    233:                        if (mkdir(sHatariHomeDir, 0755) != 0)
                    234:                        {
                    235:                                /* Failed to create, so use user's home dir instead */
                    236:                                strcpy(sHatariHomeDir, sUserHomeDir);
                    237:                        }
                    238:                }
                    239:        }
                    240: }
                    241: 
                    242: 
                    243: /**
                    244:  * Initialize directory names
                    245:  *
                    246:  * The datadir will be initialized relative to the bindir (where the executable
                    247:  * has been installed to). This means a lot of additional effort since we first
                    248:  * have to find out where the executable is. But thanks to this effort, we get
                    249:  * a relocatable package (we don't have any absolute path names in the program)!
                    250:  */
1.1.1.3   root      251: void Paths_Init(const char *argv0)
1.1       root      252: {
                    253:        char *psExecDir;  /* Path string where the hatari executable can be found */
                    254: 
                    255:        /* Init working directory string */
1.1.1.5   root      256:        if (getcwd(sWorkingDir, FILENAME_MAX) == NULL)
                    257:        {
                    258:                /* This should never happen... just in case... */
                    259:                strcpy(sWorkingDir, ".");
                    260:        }
1.1       root      261: 
                    262:        /* Init the user's home directory string */
                    263:        Paths_InitHomeDirs();
                    264: 
                    265:        /* Get the directory where the executable resides */
                    266:        psExecDir = Paths_InitExecDir(argv0);
                    267: 
                    268:        /* Now create the datadir path name from the bindir path name: */
                    269:        if (psExecDir && strlen(psExecDir) > 0)
                    270:        {
                    271:                snprintf(sDataDir, sizeof(sDataDir), "%s%c%s",
                    272:                         psExecDir, PATHSEP, BIN2DATADIR);
                    273:        }
                    274:        else
                    275:        {
                    276:                /* bindir could not be determined, let's assume datadir is relative
                    277:                 * to current working directory... */
                    278:                strcpy(sDataDir, BIN2DATADIR);
                    279:        }
                    280: 
                    281:        /* And finally make a proper absolute path out of datadir: */
                    282:        File_MakeAbsoluteName(sDataDir);
                    283: 
                    284:        free(psExecDir);
                    285: 
                    286:        /* fprintf(stderr, " WorkingDir = %s\n DataDir = %s\n UserHomeDir = %s\n HatariHomeDir = %s\n",
                    287:                sWorkingDir, sDataDir, sUserHomeDir, sHatariHomeDir); */
                    288: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.