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