152419Sjulian/* getpwd.c - get the working directory */
252419Sjulian
352419Sjulian/*
452419Sjulian
552419Sjulian@deftypefn Supplemental char* getpwd (void)
652419Sjulian
752419SjulianReturns the current working directory.  This implementation caches the
852419Sjulianresult on the assumption that the process will not call @code{chdir}
952419Sjulianbetween calls to @code{getpwd}.
1052419Sjulian
1152419Sjulian@end deftypefn
1252419Sjulian
1352419Sjulian*/
1452419Sjulian
1552419Sjulian#ifdef HAVE_CONFIG_H
1652419Sjulian#include "config.h"
1752419Sjulian#endif
1852419Sjulian
1952419Sjulian#include <sys/types.h>
2052419Sjulian
2152419Sjulian#include <errno.h>
2252419Sjulian#ifndef errno
2352419Sjulianextern int errno;
2452419Sjulian#endif
2552419Sjulian
2652419Sjulian#ifdef HAVE_STDLIB_H
2752419Sjulian#include <stdlib.h>
2852419Sjulian#endif
2952419Sjulian#ifdef HAVE_UNISTD_H
3052419Sjulian#include <unistd.h>
3152419Sjulian#endif
3252419Sjulian#ifdef HAVE_SYS_PARAM_H
3352419Sjulian#include <sys/param.h>
3452419Sjulian#endif
3552419Sjulian#if HAVE_SYS_STAT_H
3652419Sjulian#include <sys/stat.h>
3752419Sjulian#endif
3852419Sjulian#if HAVE_LIMITS_H
3952419Sjulian#include <limits.h>
4052419Sjulian#endif
4152419Sjulian
4252419Sjulian#include "libiberty.h"
4352419Sjulian
4452419Sjulian/* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
4552419Sjulian   BSD systems) now provides getcwd as called for by POSIX.  Allow for
4652419Sjulian   the few exceptions to the general rule here.  */
4752419Sjulian
4852419Sjulian#if !defined(HAVE_GETCWD) && defined(HAVE_GETWD)
4952419Sjulian/* Prototype in case the system headers doesn't provide it. */
5052419Sjulianextern char *getwd ();
5152419Sjulian#define getcwd(buf,len) getwd(buf)
5252419Sjulian#endif
5352419Sjulian
5452419Sjulian#ifdef MAXPATHLEN
5552419Sjulian#define GUESSPATHLEN (MAXPATHLEN + 1)
5652419Sjulian#else
5752419Sjulian#define GUESSPATHLEN 100
5852419Sjulian#endif
5952419Sjulian
6052419Sjulian#if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__)))
6152419Sjulian
6252419Sjulian/* Get the working directory.  Use the PWD environment variable if it's
6352419Sjulian   set correctly, since this is faster and gives more uniform answers
6452419Sjulian   to the user.  Yield the working directory if successful; otherwise,
6552419Sjulian   yield 0 and set errno.  */
6652419Sjulian
6752419Sjulianchar *
6852419Sjuliangetpwd (void)
6952419Sjulian{
7052419Sjulian  static char *pwd;
7152419Sjulian  static int failure_errno;
7252419Sjulian
7352419Sjulian  char *p = pwd;
7452419Sjulian  size_t s;
7552419Sjulian  struct stat dotstat, pwdstat;
7652419Sjulian
7752419Sjulian  if (!p && !(errno = failure_errno))
7852419Sjulian    {
7952419Sjulian      if (! ((p = getenv ("PWD")) != 0
8052419Sjulian	     && *p == '/'
8152419Sjulian	     && stat (p, &pwdstat) == 0
8252419Sjulian	     && stat (".", &dotstat) == 0
8352419Sjulian	     && dotstat.st_ino == pwdstat.st_ino
8452419Sjulian	     && dotstat.st_dev == pwdstat.st_dev))
8552419Sjulian
8652419Sjulian	/* The shortcut didn't work.  Try the slow, ``sure'' way.  */
8752419Sjulian	for (s = GUESSPATHLEN;  !getcwd (p = XNEWVEC (char, s), s);  s *= 2)
8852419Sjulian	  {
8952419Sjulian	    int e = errno;
9052419Sjulian	    free (p);
9152419Sjulian#ifdef ERANGE
9252419Sjulian	    if (e != ERANGE)
9352419Sjulian#endif
9452419Sjulian	      {
9552419Sjulian		errno = failure_errno = e;
9652419Sjulian		p = 0;
9752419Sjulian		break;
9852419Sjulian	      }
9952419Sjulian	  }
10052539Sjulian
10152419Sjulian      /* Cache the result.  This assumes that the program does
10252419Sjulian	 not invoke chdir between calls to getpwd.  */
10352419Sjulian      pwd = p;
10452419Sjulian    }
10552419Sjulian  return p;
10652419Sjulian}
10752419Sjulian
10852419Sjulian#else	/* VMS || _WIN32 && !__CYGWIN__ */
10952419Sjulian
11052419Sjulian#ifndef MAXPATHLEN
11152419Sjulian#define MAXPATHLEN 255
11252419Sjulian#endif
11352419Sjulian
11452419Sjulianchar *
11552419Sjuliangetpwd (void)
11652419Sjulian{
11752419Sjulian  static char *pwd = 0;
11852419Sjulian
11952419Sjulian  if (!pwd)
12052419Sjulian    pwd = getcwd (XNEWVEC (char, MAXPATHLEN + 1), MAXPATHLEN + 1
12152419Sjulian#ifdef VMS
12252419Sjulian		  , 0
12352419Sjulian#endif
12452419Sjulian		  );
12552419Sjulian  return pwd;
12652419Sjulian}
12752419Sjulian
12852419Sjulian#endif	/* VMS || _WIN32 && !__CYGWIN__ */
12952419Sjulian