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