ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/getpath.c
Revision: 2.12
Committed: Mon Jun 30 14:59:11 2003 UTC (20 years, 10 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.11: +5 -5 lines
Log Message:
Replaced most outdated BSD function calls with their posix equivalents, and cleaned up a few other platform dependencies.

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: getpath.c,v 2.11 2003/06/26 00:58:09 schorsch Exp $";
3 #endif
4 /*
5 * getpath.c - function to search for file in a list of directories
6 *
7 * External symbols declared in standard.h
8 */
9
10 #include "copyright.h"
11
12 #include <string.h>
13 #include <ctype.h>
14 #ifndef RHAS_GETPWNAM
15 #include <pwd.h>
16 #include <sys/types.h>
17 #endif
18
19 #include "paths.h"
20
21
22
23 #ifdef _WIN32
24 static char *
25 core_getpath /* wrapped below: expand fname, return full path */
26 #else
27 char *
28 getpath /* expand fname, return full path */
29 #endif
30 (
31 register char *fname,
32 register char *searchpath,
33 int mode
34 )
35 {
36 #ifndef RHAS_GETPWNAM
37 struct passwd *pwent;
38 #endif
39 static char pname[PATH_MAX];
40 register char *cp;
41
42 if (fname == NULL) { return(NULL); }
43
44 pname[0] = '\0'; /* check for full specification */
45
46 if (ISABS(fname)) { /* Can't use CASEDIRSEP below on Windows */
47 strncpy(pname, fname, sizeof(pname)-1);
48 } else {
49 switch (*fname) {
50 /* XXX This doesn't work on Windows */
51 /* CASEDIRSEP: */ /* relative to root */
52 case '.': /* relative to cwd */
53 strncpy(pname, fname, sizeof(pname)-1);
54 break;
55 case '~': /* relative to home directory */
56 fname++;
57 if (*fname == '\0' || ISDIRSEP(*fname)) { /* ours */
58 if ((cp = getenv("HOME")) == NULL)
59 #ifdef _WIN32 /* Windows sometimes uses a different var name */
60 if ((cp = getenv("HOMEDIR")) == NULL)
61 #endif
62 return(NULL);
63 strncpy(pname, cp, sizeof(pname)-1);
64 strncat(pname, fname, sizeof(pname)-strlen(pname)-1);
65 break;
66 }
67 #ifndef RHAS_GETPWNAM
68 /* XXX Should we request our own home directory from the
69 XXX system as well if the above fails? */
70 /* XXX In any case, we need do the same thing on Windows... */
71 cp = pname; /* user */
72 do
73 *cp++ = *fname++;
74 while (*fname && !ISDIRSEP(*fname));
75 *cp = '\0';
76 if ((pwent = getpwnam(pname)) == NULL)
77 return(NULL);
78 strncpy(pname, pwent->pw_dir, sizeof(pname)-1);
79 strncat(pname, fname, sizeof(pname)-strlen(pname)-1);
80 break;
81 #endif
82 }
83 }
84 if (pname[0]) /* got it, check access if search requested */
85 return(searchpath==NULL||access(pname,mode)==0 ? pname : NULL);
86
87 if (searchpath == NULL) { /* don't search */
88 strncpy(pname, fname, sizeof(pname)-1);
89 return(pname);
90 }
91 /* check search path */
92 do {
93 cp = pname;
94 while (*searchpath && (*cp = *searchpath++) != PATHSEP) {
95 cp++;
96 }
97 if (cp > pname && !ISDIRSEP(cp[-1])) {
98 *cp++ = DIRSEP;
99 }
100 strncpy(cp, fname, sizeof(pname)-strlen(pname)-1);
101 if (access(pname, mode) == 0) /* file accessable? */
102 return(pname);
103 } while (*searchpath);
104 /* not found */
105 return(NULL);
106 }
107
108
109 #ifdef _WIN32
110 /* This is a wrapper around the above, "emulating" access mode X_OK,
111 which is not supported on Windows.
112 If we see X_OK and the filename has no extension, then we'll remove
113 the X_OK from the mode, append ".exe" to the file name, and search
114 with the resulting string. If that fails, we'll try again with ".bat".
115 Theoretically, we might still not have execute rights on a file we find
116 like this, but that's rare enough not to be worth checking the ACLs.
117 */
118 char *
119 getpath( /* expand fname, return full path */
120 register char *ffname,
121 register char *searchpath,
122 int mode
123 )
124 {
125 register char *cp;
126 char fname[PATH_MAX];
127
128 if (ffname == NULL)
129 return(NULL);
130
131 /* if we have a dot in the string, we assume there is a file name
132 extension present */
133 /* XXX We'd better test for .exe/.bat/.etc explicitly */
134 if (!(mode & X_OK) || (strrchr(ffname, '.') != NULL)) {
135 return core_getpath(ffname, searchpath, mode);
136 }
137
138 /* We're looking for an executable, Windows doesn't have X_OK. */
139 mode &= ~X_OK;
140 /* Append .exe */
141 strncpy(fname, ffname, sizeof(fname)-5);
142 strcat(fname, ".exe");
143 cp = core_getpath(fname, searchpath, mode);
144 if (cp != NULL) return cp;
145
146 /* Try with .bat this time... */
147 strncpy(fname, ffname, sizeof(fname)-5);
148 strcat(fname, ".bat");
149 cp = core_getpath(fname, searchpath, mode);
150 return cp;
151 }
152 #endif /* _WIN32 */
153
154
155 #ifdef TEST_MODULE
156 int main()
157 {
158 char * fp;
159 char fmt[] = "%15s %-10s %s: %s\n";
160
161 fp = getpath("rayinit.cal", getenv("RAYPATH"), R_OK);
162 printf(fmt, "rayinit.cal", "RAYPATH", "R_OK", fp);
163 fp = getpath("mkillum", getenv("PATH"), X_OK);
164 printf(fmt, "mkillum", "PATH", "X_OK", fp);
165 fp = getpath("/", getenv("PATH"), W_OK);
166 printf(fmt, "/", "PATH", "W_OK", fp);
167 fp = getpath("~", getenv("PATH"), F_OK);
168 printf(fmt, "~", "PATH", "F_OK", fp);
169 printf("Undefining HOME and HOMEDIR\n");
170 unsetenv("HOME");
171 unsetenv("HOMEDIR");
172 fp = getpath("~", getenv("PATH"), F_OK);
173 printf(fmt, "~", "PATH", "F_OK", fp);
174 #ifndef RHAS_GETPWNAM
175 fp = getpath("~lp", getenv("PATH"), F_OK);
176 printf(fmt, "~lp", "PATH", "F_OK", fp);
177 #endif
178 }
179 #endif
180