Commit | Line | Data |
---|---|---|
e2eaf477 ILT |
1 | /* getpwd.c - get the working directory */ |
2 | ||
39423523 DD |
3 | /* |
4 | ||
99b58139 | 5 | @deftypefn Supplemental char* getpwd (void) |
39423523 DD |
6 | |
7 | Returns the current working directory. This implementation caches the | |
8 | result on the assumption that the process will not call @code{chdir} | |
9 | between calls to @code{getpwd}. | |
10 | ||
11 | @end deftypefn | |
12 | ||
13 | */ | |
14 | ||
e2eaf477 ILT |
15 | #ifdef HAVE_CONFIG_H |
16 | #include "config.h" | |
17 | #endif | |
18 | ||
19 | #include <sys/types.h> | |
20 | ||
21 | #include <errno.h> | |
22 | #ifndef errno | |
23 | extern int errno; | |
24 | #endif | |
25 | ||
26 | #ifdef HAVE_STDLIB_H | |
27 | #include <stdlib.h> | |
28 | #endif | |
29 | #ifdef HAVE_UNISTD_H | |
30 | #include <unistd.h> | |
31 | #endif | |
32 | #ifdef HAVE_SYS_PARAM_H | |
33 | #include <sys/param.h> | |
34 | #endif | |
35 | #if HAVE_SYS_STAT_H | |
36 | #include <sys/stat.h> | |
37 | #endif | |
37254c9a DD |
38 | #if HAVE_LIMITS_H |
39 | #include <limits.h> | |
40 | #endif | |
e2eaf477 | 41 | |
e2eaf477 ILT |
42 | #include "libiberty.h" |
43 | ||
44 | /* Virtually every UN*X system now in common use (except for pre-4.3-tahoe | |
45 | BSD systems) now provides getcwd as called for by POSIX. Allow for | |
46 | the few exceptions to the general rule here. */ | |
47 | ||
48 | #if !defined(HAVE_GETCWD) && defined(HAVE_GETWD) | |
2349f557 DD |
49 | /* Prototype in case the system headers doesn't provide it. */ |
50 | extern char *getwd (); | |
e2eaf477 ILT |
51 | #define getcwd(buf,len) getwd(buf) |
52 | #endif | |
53 | ||
54 | #ifdef MAXPATHLEN | |
55 | #define GUESSPATHLEN (MAXPATHLEN + 1) | |
56 | #else | |
57 | #define GUESSPATHLEN 100 | |
58 | #endif | |
59 | ||
60 | #if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__))) | |
61 | ||
62 | /* Get the working directory. Use the PWD environment variable if it's | |
63 | set correctly, since this is faster and gives more uniform answers | |
64 | to the user. Yield the working directory if successful; otherwise, | |
65 | yield 0 and set errno. */ | |
66 | ||
67 | char * | |
49b1fae4 | 68 | getpwd (void) |
e2eaf477 ILT |
69 | { |
70 | static char *pwd; | |
71 | static int failure_errno; | |
72 | ||
73 | char *p = pwd; | |
74 | size_t s; | |
75 | struct stat dotstat, pwdstat; | |
76 | ||
77 | if (!p && !(errno = failure_errno)) | |
78 | { | |
79 | if (! ((p = getenv ("PWD")) != 0 | |
80 | && *p == '/' | |
81 | && stat (p, &pwdstat) == 0 | |
82 | && stat (".", &dotstat) == 0 | |
83 | && dotstat.st_ino == pwdstat.st_ino | |
84 | && dotstat.st_dev == pwdstat.st_dev)) | |
85 | ||
86 | /* The shortcut didn't work. Try the slow, ``sure'' way. */ | |
abf6a75b | 87 | for (s = GUESSPATHLEN; !getcwd (p = XNEWVEC (char, s), s); s *= 2) |
e2eaf477 ILT |
88 | { |
89 | int e = errno; | |
90 | free (p); | |
91 | #ifdef ERANGE | |
92 | if (e != ERANGE) | |
93 | #endif | |
94 | { | |
95 | errno = failure_errno = e; | |
96 | p = 0; | |
97 | break; | |
98 | } | |
99 | } | |
100 | ||
101 | /* Cache the result. This assumes that the program does | |
102 | not invoke chdir between calls to getpwd. */ | |
103 | pwd = p; | |
104 | } | |
105 | return p; | |
106 | } | |
107 | ||
108 | #else /* VMS || _WIN32 && !__CYGWIN__ */ | |
109 | ||
110 | #ifndef MAXPATHLEN | |
111 | #define MAXPATHLEN 255 | |
112 | #endif | |
113 | ||
114 | char * | |
49b1fae4 | 115 | getpwd (void) |
e2eaf477 ILT |
116 | { |
117 | static char *pwd = 0; | |
118 | ||
119 | if (!pwd) | |
abf6a75b | 120 | pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1 |
e2eaf477 ILT |
121 | #ifdef VMS |
122 | , 0 | |
123 | #endif | |
124 | ); | |
125 | return pwd; | |
126 | } | |
127 | ||
128 | #endif /* VMS || _WIN32 && !__CYGWIN__ */ |