ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/getpath.c
Revision: 2.23
Committed: Sun Dec 5 15:44:15 2021 UTC (2 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.22: +3 -3 lines
Log Message:
fix: repaired regression introduced to Windows version

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.23 static const char RCSid[] = "$Id: getpath.c,v 2.22 2021/11/22 18:23:56 greg Exp $";
3 greg 1.1 #endif
4     /*
5     * getpath.c - function to search for file in a list of directories
6 greg 2.9 *
7 greg 2.18 * External symbols declared in rtio.h
8 greg 2.9 */
9    
10 greg 2.10 #include "copyright.h"
11 greg 1.1
12 schorsch 2.11 #include <ctype.h>
13 greg 2.7
14 schorsch 2.14 #include "rtio.h"
15 greg 2.17 #include "paths.h"
16 greg 1.1
17    
18 schorsch 2.19 #if defined(_WIN32) || defined(_WIN64)
19 schorsch 2.11 static char *
20     core_getpath /* wrapped below: expand fname, return full path */
21     #else
22 greg 1.1 char *
23 schorsch 2.11 getpath /* expand fname, return full path */
24     #endif
25     (
26 greg 2.18 char *fname,
27     char *searchpath,
28     int mode
29 schorsch 2.11 )
30 greg 1.1 {
31 schorsch 2.11 static char pname[PATH_MAX];
32 schorsch 2.15 char uname[512];
33 greg 2.18 char *cp;
34 schorsch 2.15 int i;
35 greg 1.1
36 greg 2.22 if (!fname | (fname == pname))
37     return(fname);
38 greg 1.1
39 greg 2.8 pname[0] = '\0'; /* check for full specification */
40 schorsch 2.11
41 greg 2.22 if (ISABS(fname)) { /* absolute path */
42 greg 2.20 strlcpy(pname, fname, sizeof(pname));
43 schorsch 2.11 } else {
44     switch (*fname) {
45 greg 2.22 case '.': /* relative to cwd */
46 greg 2.20 strlcpy(pname, fname, sizeof(pname));
47 schorsch 2.11 break;
48 greg 2.22 case '~': /* relative to home directory */
49 schorsch 2.11 fname++;
50 schorsch 2.15 cp = uname;
51 greg 2.20 for (i = 0; i < sizeof(uname) && *fname
52     && !ISDIRSEP(*fname); i++)
53 schorsch 2.11 *cp++ = *fname++;
54     *cp = '\0';
55 schorsch 2.15 cp = gethomedir(uname, pname, sizeof(pname));
56     if(cp == NULL) return NULL;
57 greg 2.20 strlcat(pname, fname, sizeof(pname));
58 schorsch 2.11 break;
59 greg 1.1 }
60     }
61 greg 2.8 if (pname[0]) /* got it, check access if search requested */
62 greg 2.20 return(!searchpath || access(pname,mode)==0 ? pname : NULL);
63 greg 1.1
64 greg 2.22 if (!searchpath) { /* no search? */
65 greg 2.20 strlcpy(pname, fname, sizeof(pname));
66 greg 1.1 return(pname);
67     }
68 schorsch 2.11 /* check search path */
69 greg 1.1 do {
70     cp = pname;
71 greg 2.20 while (*searchpath && (*cp = *searchpath++) != PATHSEP)
72     cp += (cp-pname < sizeof(pname)-2);
73     if (cp > pname && !ISDIRSEP(cp[-1]))
74 greg 2.3 *cp++ = DIRSEP;
75 greg 2.20 *cp = '\0';
76     strlcat(pname, fname, sizeof(pname));
77 greg 1.1 if (access(pname, mode) == 0) /* file accessable? */
78     return(pname);
79     } while (*searchpath);
80 schorsch 2.11 /* not found */
81 greg 1.1 return(NULL);
82     }
83 schorsch 2.11
84    
85 schorsch 2.19 #if defined(_WIN32) || defined(_WIN64)
86 schorsch 2.11 /* This is a wrapper around the above, "emulating" access mode X_OK,
87     which is not supported on Windows.
88     If we see X_OK and the filename has no extension, then we'll remove
89     the X_OK from the mode, append ".exe" to the file name, and search
90     with the resulting string. If that fails, we'll try again with ".bat".
91     Theoretically, we might still not have execute rights on a file we find
92     like this, but that's rare enough not to be worth checking the ACLs.
93     */
94     char *
95     getpath( /* expand fname, return full path */
96 greg 2.18 char *ffname,
97     char *searchpath,
98     int mode
99 schorsch 2.11 )
100     {
101 greg 2.18 char *cp;
102 schorsch 2.11 char fname[PATH_MAX];
103    
104 greg 2.23 if (!ffname | (ffname == fname))
105     return(ffname);
106 schorsch 2.11
107     /* if we have a dot in the string, we assume there is a file name
108     extension present */
109     /* XXX We'd better test for .exe/.bat/.etc explicitly */
110 greg 2.22 if (!(mode & X_OK) || strchr(ffname, '.') > ffname) {
111 schorsch 2.11 return core_getpath(ffname, searchpath, mode);
112     }
113    
114     /* We're looking for an executable, Windows doesn't have X_OK. */
115     mode &= ~X_OK;
116     /* Append .exe */
117     strncpy(fname, ffname, sizeof(fname)-5);
118     strcat(fname, ".exe");
119     cp = core_getpath(fname, searchpath, mode);
120     if (cp != NULL) return cp;
121    
122     /* Try with .bat this time... */
123     strncpy(fname, ffname, sizeof(fname)-5);
124     strcat(fname, ".bat");
125     cp = core_getpath(fname, searchpath, mode);
126     return cp;
127     }
128     #endif /* _WIN32 */
129    
130    
131     #ifdef TEST_MODULE
132     int main()
133     {
134     char * fp;
135     char fmt[] = "%15s %-10s %s: %s\n";
136    
137     fp = getpath("rayinit.cal", getenv("RAYPATH"), R_OK);
138     printf(fmt, "rayinit.cal", "RAYPATH", "R_OK", fp);
139     fp = getpath("mkillum", getenv("PATH"), X_OK);
140     printf(fmt, "mkillum", "PATH", "X_OK", fp);
141     fp = getpath("/", getenv("PATH"), W_OK);
142     printf(fmt, "/", "PATH", "W_OK", fp);
143     fp = getpath("~", getenv("PATH"), F_OK);
144     printf(fmt, "~", "PATH", "F_OK", fp);
145 schorsch 2.15 printf("Undefining HOME and HOMEPATH\n");
146 schorsch 2.11 unsetenv("HOME");
147 schorsch 2.15 unsetenv("HOMEPATH");
148 schorsch 2.11 fp = getpath("~", getenv("PATH"), F_OK);
149     printf(fmt, "~", "PATH", "F_OK", fp);
150 schorsch 2.15 fp = getpath("~lp/blah", getenv("PATH"), F_OK);
151     printf(fmt, "~lp/blah", "PATH", "F_OK", fp);
152 schorsch 2.11 }
153     #endif
154