ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/getpath.c
Revision: 2.20
Committed: Sun Jul 21 16:48:34 2019 UTC (5 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.19: +16 -16 lines
Log Message:
Replaced strncpy() and strncat() with strlcpy() and strlcat() and other fixes

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: getpath.c,v 2.19 2016/03/06 01:13:17 schorsch Exp $";
3 #endif
4 /*
5 * getpath.c - function to search for file in a list of directories
6 *
7 * External symbols declared in rtio.h
8 */
9
10 #include "copyright.h"
11
12 #include <string.h>
13 #include <ctype.h>
14
15 #include "rtio.h"
16 #include "paths.h"
17
18
19 #if defined(_WIN32) || defined(_WIN64)
20 static char *
21 core_getpath /* wrapped below: expand fname, return full path */
22 #else
23 char *
24 getpath /* expand fname, return full path */
25 #endif
26 (
27 char *fname,
28 char *searchpath,
29 int mode
30 )
31 {
32 static char pname[PATH_MAX];
33 char uname[512];
34 char *cp;
35 int i;
36
37 if (fname == NULL) { return(NULL); }
38
39 pname[0] = '\0'; /* check for full specification */
40
41 if (ISABS(fname)) { /* absolute path */
42 strlcpy(pname, fname, sizeof(pname));
43 } else {
44 switch (*fname) {
45 case '.': /* relative to cwd */
46 strlcpy(pname, fname, sizeof(pname));
47 break;
48 case '~': /* relative to home directory */
49 fname++;
50 cp = uname;
51 for (i = 0; i < sizeof(uname) && *fname
52 && !ISDIRSEP(*fname); i++)
53 *cp++ = *fname++;
54 *cp = '\0';
55 cp = gethomedir(uname, pname, sizeof(pname));
56 if(cp == NULL) return NULL;
57 strlcat(pname, fname, sizeof(pname));
58 break;
59 }
60 }
61 if (pname[0]) /* got it, check access if search requested */
62 return(!searchpath || access(pname,mode)==0 ? pname : NULL);
63
64 if (!searchpath) { /* no search */
65 strlcpy(pname, fname, sizeof(pname));
66 return(pname);
67 }
68 /* check search path */
69 do {
70 cp = pname;
71 while (*searchpath && (*cp = *searchpath++) != PATHSEP)
72 cp += (cp-pname < sizeof(pname)-2);
73 if (cp > pname && !ISDIRSEP(cp[-1]))
74 *cp++ = DIRSEP;
75 *cp = '\0';
76 strlcat(pname, fname, sizeof(pname));
77 if (access(pname, mode) == 0) /* file accessable? */
78 return(pname);
79 } while (*searchpath);
80 /* not found */
81 return(NULL);
82 }
83
84
85 #if defined(_WIN32) || defined(_WIN64)
86 /* 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 char *ffname,
97 char *searchpath,
98 int mode
99 )
100 {
101 char *cp;
102 char fname[PATH_MAX];
103
104 if (ffname == NULL)
105 return(NULL);
106
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 if (!(mode & X_OK) || (strrchr(ffname, '.') != NULL)) {
111 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 printf("Undefining HOME and HOMEPATH\n");
146 unsetenv("HOME");
147 unsetenv("HOMEPATH");
148 fp = getpath("~", getenv("PATH"), F_OK);
149 printf(fmt, "~", "PATH", "F_OK", fp);
150 fp = getpath("~lp/blah", getenv("PATH"), F_OK);
151 printf(fmt, "~lp/blah", "PATH", "F_OK", fp);
152 }
153 #endif
154