xref: /openbsd-src/gnu/lib/libiberty/src/getpwd.c (revision 20fce977aadac3358da45d5027d7d19cdc03b0fe)
100bf4279Sespie /* getpwd.c - get the working directory */
200bf4279Sespie 
39588ddcfSespie /*
49588ddcfSespie 
59588ddcfSespie @deftypefn Supplemental char* getpwd (void)
69588ddcfSespie 
79588ddcfSespie Returns the current working directory.  This implementation caches the
89588ddcfSespie result on the assumption that the process will not call @code{chdir}
99588ddcfSespie between calls to @code{getpwd}.
109588ddcfSespie 
119588ddcfSespie @end deftypefn
129588ddcfSespie 
139588ddcfSespie */
149588ddcfSespie 
1500bf4279Sespie #ifdef HAVE_CONFIG_H
1600bf4279Sespie #include "config.h"
1700bf4279Sespie #endif
1800bf4279Sespie 
1900bf4279Sespie #include <sys/types.h>
2000bf4279Sespie 
2100bf4279Sespie #include <errno.h>
2200bf4279Sespie #ifndef errno
2300bf4279Sespie extern int errno;
2400bf4279Sespie #endif
2500bf4279Sespie 
2600bf4279Sespie #ifdef HAVE_STDLIB_H
2700bf4279Sespie #include <stdlib.h>
2800bf4279Sespie #endif
2900bf4279Sespie #ifdef HAVE_UNISTD_H
3000bf4279Sespie #include <unistd.h>
3100bf4279Sespie #endif
3200bf4279Sespie #ifdef HAVE_SYS_PARAM_H
3300bf4279Sespie #include <sys/param.h>
3400bf4279Sespie #endif
3500bf4279Sespie #if HAVE_SYS_STAT_H
3600bf4279Sespie #include <sys/stat.h>
3700bf4279Sespie #endif
38*20fce977Smiod #if HAVE_LIMITS_H
39*20fce977Smiod #include <limits.h>
40*20fce977Smiod #endif
4100bf4279Sespie 
4200bf4279Sespie #include "libiberty.h"
4300bf4279Sespie 
4400bf4279Sespie /* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
4500bf4279Sespie    BSD systems) now provides getcwd as called for by POSIX.  Allow for
4600bf4279Sespie    the few exceptions to the general rule here.  */
4700bf4279Sespie 
4800bf4279Sespie #if !defined(HAVE_GETCWD) && defined(HAVE_GETWD)
49*20fce977Smiod /* Prototype in case the system headers doesn't provide it. */
50*20fce977Smiod extern char *getwd ();
5100bf4279Sespie #define getcwd(buf,len) getwd(buf)
5200bf4279Sespie #endif
5300bf4279Sespie 
5400bf4279Sespie #ifdef MAXPATHLEN
5500bf4279Sespie #define GUESSPATHLEN (MAXPATHLEN + 1)
5600bf4279Sespie #else
5700bf4279Sespie #define GUESSPATHLEN 100
5800bf4279Sespie #endif
5900bf4279Sespie 
6000bf4279Sespie #if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__)))
6100bf4279Sespie 
6200bf4279Sespie /* Get the working directory.  Use the PWD environment variable if it's
6300bf4279Sespie    set correctly, since this is faster and gives more uniform answers
6400bf4279Sespie    to the user.  Yield the working directory if successful; otherwise,
6500bf4279Sespie    yield 0 and set errno.  */
6600bf4279Sespie 
6700bf4279Sespie char *
getpwd(void)68*20fce977Smiod getpwd (void)
6900bf4279Sespie {
7000bf4279Sespie   static char *pwd;
7100bf4279Sespie   static int failure_errno;
7200bf4279Sespie 
7300bf4279Sespie   char *p = pwd;
7400bf4279Sespie   size_t s;
7500bf4279Sespie   struct stat dotstat, pwdstat;
7600bf4279Sespie 
7700bf4279Sespie   if (!p && !(errno = failure_errno))
7800bf4279Sespie     {
7900bf4279Sespie       if (! ((p = getenv ("PWD")) != 0
8000bf4279Sespie 	     && *p == '/'
8100bf4279Sespie 	     && stat (p, &pwdstat) == 0
8200bf4279Sespie 	     && stat (".", &dotstat) == 0
8300bf4279Sespie 	     && dotstat.st_ino == pwdstat.st_ino
8400bf4279Sespie 	     && dotstat.st_dev == pwdstat.st_dev))
8500bf4279Sespie 
8600bf4279Sespie 	/* The shortcut didn't work.  Try the slow, ``sure'' way.  */
87*20fce977Smiod 	for (s = GUESSPATHLEN;  !getcwd (p = XNEWVEC (char, s), s);  s *= 2)
8800bf4279Sespie 	  {
8900bf4279Sespie 	    int e = errno;
9000bf4279Sespie 	    free (p);
9100bf4279Sespie #ifdef ERANGE
9200bf4279Sespie 	    if (e != ERANGE)
9300bf4279Sespie #endif
9400bf4279Sespie 	      {
9500bf4279Sespie 		errno = failure_errno = e;
9600bf4279Sespie 		p = 0;
9700bf4279Sespie 		break;
9800bf4279Sespie 	      }
9900bf4279Sespie 	  }
10000bf4279Sespie 
10100bf4279Sespie       /* Cache the result.  This assumes that the program does
10200bf4279Sespie 	 not invoke chdir between calls to getpwd.  */
10300bf4279Sespie       pwd = p;
10400bf4279Sespie     }
10500bf4279Sespie   return p;
10600bf4279Sespie }
10700bf4279Sespie 
10800bf4279Sespie #else	/* VMS || _WIN32 && !__CYGWIN__ */
10900bf4279Sespie 
11000bf4279Sespie #ifndef MAXPATHLEN
11100bf4279Sespie #define MAXPATHLEN 255
11200bf4279Sespie #endif
11300bf4279Sespie 
11400bf4279Sespie char *
getpwd(void)115*20fce977Smiod getpwd (void)
11600bf4279Sespie {
11700bf4279Sespie   static char *pwd = 0;
11800bf4279Sespie 
11900bf4279Sespie   if (!pwd)
120*20fce977Smiod     pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1
12100bf4279Sespie #ifdef VMS
12200bf4279Sespie 		  , 0
12300bf4279Sespie #endif
12400bf4279Sespie 		  );
12500bf4279Sespie   return pwd;
12600bf4279Sespie }
12700bf4279Sespie 
12800bf4279Sespie #endif	/* VMS || _WIN32 && !__CYGWIN__ */
129