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