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