getpwd.c revision 60484
16562Sphk/* getpwd.c - get the working directory */
237421Scharnier
36562Sphk#ifdef HAVE_CONFIG_H
46562Sphk#include "config.h"
53995Spst#endif
63995Spst
76562Sphk#include <sys/types.h>
86562Sphk
96562Sphk#include <errno.h>
106562Sphk#ifndef errno
116562Sphkextern int errno;
126562Sphk#endif
136562Sphk
146562Sphk#ifdef HAVE_STDLIB_H
156562Sphk#include <stdlib.h>
166562Sphk#endif
176562Sphk#ifdef HAVE_UNISTD_H
183995Spst#include <unistd.h>
193995Spst#endif
2037421Scharnier#ifdef HAVE_SYS_PARAM_H
2137421Scharnier#include <sys/param.h>
2237421Scharnier#endif
2337421Scharnier#if HAVE_SYS_STAT_H
2437421Scharnier#include <sys/stat.h>
2519168Sbde#endif
2637421Scharnier
2719168Sbde/* Prototype these in case the system headers don't provide them. */
283995Spstextern char *getpwd ();
293995Spstextern char *getwd ();
3032074Ssteve
3119168Sbde#include "libiberty.h"
323995Spst
333995Spst/* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
346562Sphk   BSD systems) now provides getcwd as called for by POSIX.  Allow for
356562Sphk   the few exceptions to the general rule here.  */
363995Spst
373995Spst#if !defined(HAVE_GETCWD) && defined(HAVE_GETWD)
383995Spst#define getcwd(buf,len) getwd(buf)
393995Spst#endif
406562Sphk
416562Sphk#ifdef MAXPATHLEN
426562Sphk#define GUESSPATHLEN (MAXPATHLEN + 1)
436725Sphk#else
4432074Ssteve#define GUESSPATHLEN 100
453995Spst#endif
463995Spst
473995Spst#if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__)))
483995Spst
493995Spst/* Get the working directory.  Use the PWD environment variable if it's
503995Spst   set correctly, since this is faster and gives more uniform answers
513995Spst   to the user.  Yield the working directory if successful; otherwise,
523995Spst   yield 0 and set errno.  */
533995Spst
543995Spstchar *
556562Sphkgetpwd ()
566562Sphk{
576562Sphk  static char *pwd;
586562Sphk  static int failure_errno;
593995Spst
6032086Ssteve  char *p = pwd;
616562Sphk  size_t s;
629489Sphk  struct stat dotstat, pwdstat;
633995Spst
6432074Ssteve  if (!p && !(errno = failure_errno))
6532086Ssteve    {
6632086Ssteve      if (! ((p = getenv ("PWD")) != 0
6732074Ssteve	     && *p == '/'
6832074Ssteve	     && stat (p, &pwdstat) == 0
6932074Ssteve	     && stat (".", &dotstat) == 0
7032074Ssteve	     && dotstat.st_ino == pwdstat.st_ino
7132074Ssteve	     && dotstat.st_dev == pwdstat.st_dev))
7232074Ssteve
7332074Ssteve	/* The shortcut didn't work.  Try the slow, ``sure'' way.  */
746562Sphk	for (s = GUESSPATHLEN;  ! getcwd (p = xmalloc (s), s);  s *= 2)
7532074Ssteve	  {
7632074Ssteve	    int e = errno;
776562Sphk	    free (p);
7832074Ssteve#ifdef ERANGE
7932074Ssteve	    if (e != ERANGE)
8032074Ssteve#endif
816562Sphk	      {
8232074Ssteve		errno = failure_errno = e;
8332074Ssteve		p = 0;
8432074Ssteve		break;
8532074Ssteve	      }
8637421Scharnier	  }
8732074Ssteve
8832074Ssteve      /* Cache the result.  This assumes that the program does
8932074Ssteve	 not invoke chdir between calls to getpwd.  */
9032074Ssteve      pwd = p;
9132074Ssteve    }
926725Sphk  return p;
933995Spst}
946562Sphk
953995Spst#else	/* VMS || _WIN32 && !__CYGWIN__ */
966562Sphk
976562Sphk#ifndef MAXPATHLEN
983995Spst#define MAXPATHLEN 255
996562Sphk#endif
1006562Sphk
1016562Sphkchar *
1023995Spstgetpwd ()
1036562Sphk{
1049489Sphk  static char *pwd = 0;
1053995Spst
1069489Sphk  if (!pwd)
1073995Spst    pwd = getcwd (xmalloc (MAXPATHLEN + 1), MAXPATHLEN + 1
1086562Sphk#ifdef VMS
1096562Sphk		  , 0
1103995Spst#endif
1116562Sphk		  );
1126562Sphk  return pwd;
1133995Spst}
1146562Sphk
1156562Sphk#endif	/* VMS || _WIN32 && !__CYGWIN__ */
1166725Sphk