1 | /* getpwd.c - get the working directory */ |
2 | |
3 | /* |
4 | |
5 | @deftypefn Supplemental char* getpwd (void) |
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 | |
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 |
38 | #if HAVE_LIMITS_H |
39 | #include <limits.h> |
40 | #endif |
41 | |
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) |
49 | /* Prototype in case the system headers doesn't provide it. */ |
50 | extern char *getwd (); |
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 * |
68 | getpwd (void) |
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 (name: "PWD" )) != 0 |
80 | && *p == '/' |
81 | && stat (file: p, buf: &pwdstat) == 0 |
82 | && stat (file: "." , buf: &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. */ |
87 | for (s = GUESSPATHLEN; !getcwd (buf: p = XNEWVEC (char, s), size: s); s *= 2) |
88 | { |
89 | int e = errno; |
90 | free (ptr: 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 * |
115 | getpwd (void) |
116 | { |
117 | static char *pwd = 0; |
118 | |
119 | if (!pwd) |
120 | pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1 |
121 | #ifdef VMS |
122 | , 0 |
123 | #endif |
124 | ); |
125 | return pwd; |
126 | } |
127 | |
128 | #endif /* VMS || _WIN32 && !__CYGWIN__ */ |
129 | |