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