Back to index

radiance  4R0+20100331
getpath.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: getpath.c,v 2.17 2004/02/12 18:55:50 greg Exp $";
00003 #endif
00004 /*
00005  *  getpath.c - function to search for file in a list of directories
00006  *
00007  *  External symbols declared in standard.h
00008  */
00009 
00010 #include "copyright.h"
00011 
00012 #include  <string.h>
00013 #include  <ctype.h>
00014 
00015 #include  "rtio.h"
00016 #include  "paths.h"
00017 
00018 
00019 #ifdef _WIN32
00020 static char *
00021 core_getpath  /* wrapped below: expand fname, return full path */
00022 #else
00023 char *
00024 getpath       /* expand fname, return full path */
00025 #endif
00026 (
00027 register char  *fname,
00028 register char  *searchpath,
00029 int  mode
00030 )
00031 {
00032        static char  pname[PATH_MAX];
00033        char uname[512];
00034        register char  *cp;
00035        int i;
00036 
00037        if (fname == NULL) { return(NULL); }
00038 
00039        pname[0] = '\0';            /* check for full specification */
00040 
00041        if (ISABS(fname)) { /* absolute path */
00042               strncpy(pname, fname, sizeof(pname)-1);
00043        } else {
00044               switch (*fname) {
00045                      case '.':                          /* relative to cwd */
00046                             strncpy(pname, fname, sizeof(pname)-1);
00047                             break;
00048                      case '~':                          /* relative to home directory */
00049                             fname++;
00050                             cp = uname;
00051                             for (i=0;i<sizeof(uname)&&*fname!='\0'&&!ISDIRSEP(*fname);i++)
00052                                    *cp++ = *fname++;
00053                             *cp = '\0';
00054                             cp = gethomedir(uname, pname, sizeof(pname));
00055                             if(cp == NULL) return NULL;
00056                             strncat(pname, fname, sizeof(pname)-strlen(pname)-1);
00057                             break;
00058               }
00059        }
00060        if (pname[0])        /* got it, check access if search requested */
00061               return(searchpath==NULL||access(pname,mode)==0 ? pname : NULL);
00062 
00063        if (searchpath == NULL) {                 /* don't search */
00064               strncpy(pname, fname, sizeof(pname)-1);
00065               return(pname);
00066        }
00067        /* check search path */
00068        do {
00069               cp = pname;
00070               while (*searchpath && (*cp = *searchpath++) != PATHSEP) {
00071                      cp++;
00072               }
00073               if (cp > pname && !ISDIRSEP(cp[-1])) {
00074                      *cp++ = DIRSEP;
00075               }
00076               strncpy(cp, fname, sizeof(pname)-strlen(pname)-1);
00077               if (access(pname, mode) == 0)             /* file accessable? */
00078                      return(pname);
00079        } while (*searchpath);
00080        /* not found */
00081        return(NULL);
00082 }
00083 
00084 
00085 #ifdef _WIN32
00086 /* This is a wrapper around the above, "emulating" access mode X_OK,
00087    which is not supported on Windows.
00088    If we see X_OK and the filename has no extension, then we'll remove
00089    the X_OK from the mode, append ".exe" to the file name, and search
00090    with the resulting string. If that fails, we'll try again with ".bat".
00091    Theoretically, we might still not have execute rights on a file we find
00092    like this, but that's rare enough not to be worth checking the ACLs.
00093 */
00094 char *
00095 getpath(      /* expand fname, return full path */
00096 register char  *ffname,
00097 register char  *searchpath,
00098 int  mode
00099 )
00100 {
00101        register char  *cp;
00102        char fname[PATH_MAX];
00103 
00104        if (ffname == NULL)
00105               return(NULL);
00106 
00107        /* if we have a dot in the string, we assume there is a file name
00108           extension present */
00109        /* XXX We'd better test for .exe/.bat/.etc explicitly */
00110        if (!(mode & X_OK) || (strrchr(ffname, '.') != NULL)) {
00111               return core_getpath(ffname, searchpath, mode);
00112        }
00113 
00114        /* We're looking for an executable, Windows doesn't have X_OK. */
00115        mode &= ~X_OK;
00116        /* Append .exe */
00117        strncpy(fname, ffname, sizeof(fname)-5);
00118        strcat(fname, ".exe");
00119        cp = core_getpath(fname, searchpath, mode);
00120        if (cp != NULL) return cp;
00121 
00122        /* Try with .bat this time... */
00123        strncpy(fname, ffname, sizeof(fname)-5);
00124        strcat(fname, ".bat");
00125        cp = core_getpath(fname, searchpath, mode);
00126        return cp;
00127 }
00128 #endif /* _WIN32 */
00129 
00130 
00131 #ifdef TEST_MODULE
00132 int main()
00133 {
00134        char * fp;
00135        char fmt[] = "%15s %-10s %s: %s\n";
00136 
00137        fp = getpath("rayinit.cal", getenv("RAYPATH"), R_OK);
00138        printf(fmt,  "rayinit.cal",        "RAYPATH", "R_OK", fp);
00139        fp = getpath("mkillum", getenv("PATH"), X_OK);
00140        printf(fmt,  "mkillum",        "PATH", "X_OK", fp);
00141        fp = getpath("/", getenv("PATH"), W_OK);
00142        printf(fmt,  "/",        "PATH", "W_OK", fp);
00143        fp = getpath("~", getenv("PATH"), F_OK);
00144        printf(fmt,  "~",        "PATH", "F_OK", fp);
00145        printf("Undefining HOME and HOMEPATH\n");
00146        unsetenv("HOME");
00147        unsetenv("HOMEPATH");
00148        fp = getpath("~", getenv("PATH"), F_OK);
00149        printf(fmt,  "~",        "PATH", "F_OK", fp);
00150        fp = getpath("~lp/blah", getenv("PATH"), F_OK);
00151        printf(fmt, "~lp/blah",         "PATH", "F_OK", fp);
00152 }
00153 #endif
00154