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