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

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: }

unix.superglobalmegacorp.com

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