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 ILT |
41 | |
42 | /* Prototype these in case the system headers don't provide them. */ | |
43 | extern char *getpwd (); | |
44 | extern char *getwd (); | |
45 | ||
46 | #include "libiberty.h" | |
47 | ||
48 | /* Virtually every UN*X system now in common use (except for pre-4.3-tahoe | |
49 | BSD systems) now provides getcwd as called for by POSIX. Allow for | |
50 | the few exceptions to the general rule here. */ | |
51 | ||
52 | #if !defined(HAVE_GETCWD) && defined(HAVE_GETWD) | |
53 | #define getcwd(buf,len) getwd(buf) | |
54 | #endif | |
55 | ||
56 | #ifdef MAXPATHLEN | |
57 | #define GUESSPATHLEN (MAXPATHLEN + 1) | |
58 | #else | |
59 | #define GUESSPATHLEN 100 | |
60 | #endif | |
61 | ||
62 | #if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__))) | |
63 | ||
64 | /* Get the working directory. Use the PWD environment variable if it's | |
65 | set correctly, since this is faster and gives more uniform answers | |
66 | to the user. Yield the working directory if successful; otherwise, | |
67 | yield 0 and set errno. */ | |
68 | ||
69 | char * | |
70 | getpwd () | |
71 | { | |
72 | static char *pwd; | |
73 | static int failure_errno; | |
74 | ||
75 | char *p = pwd; | |
76 | size_t s; | |
77 | struct stat dotstat, pwdstat; | |
78 | ||
79 | if (!p && !(errno = failure_errno)) | |
80 | { | |
81 | if (! ((p = getenv ("PWD")) != 0 | |
82 | && *p == '/' | |
83 | && stat (p, &pwdstat) == 0 | |
84 | && stat (".", &dotstat) == 0 | |
85 | && dotstat.st_ino == pwdstat.st_ino | |
86 | && dotstat.st_dev == pwdstat.st_dev)) | |
87 | ||
88 | /* The shortcut didn't work. Try the slow, ``sure'' way. */ | |
89 | for (s = GUESSPATHLEN; ! getcwd (p = xmalloc (s), s); s *= 2) | |
90 | { | |
91 | int e = errno; | |
92 | free (p); | |
93 | #ifdef ERANGE | |
94 | if (e != ERANGE) | |
95 | #endif | |
96 | { | |
97 | errno = failure_errno = e; | |
98 | p = 0; | |
99 | break; | |
100 | } | |
101 | } | |
102 | ||
103 | /* Cache the result. This assumes that the program does | |
104 | not invoke chdir between calls to getpwd. */ | |
105 | pwd = p; | |
106 | } | |
107 | return p; | |
108 | } | |
109 | ||
110 | #else /* VMS || _WIN32 && !__CYGWIN__ */ | |
111 | ||
112 | #ifndef MAXPATHLEN | |
113 | #define MAXPATHLEN 255 | |
114 | #endif | |
115 | ||
116 | char * | |
117 | getpwd () | |
118 | { | |
119 | static char *pwd = 0; | |
120 | ||
121 | if (!pwd) | |
122 | pwd = getcwd (xmalloc (MAXPATHLEN + 1), MAXPATHLEN + 1 | |
123 | #ifdef VMS | |
124 | , 0 | |
125 | #endif | |
126 | ); | |
127 | return pwd; | |
128 | } | |
129 | ||
130 | #endif /* VMS || _WIN32 && !__CYGWIN__ */ |