getpwd.c revision 89857
11558Srgrimes/* getpwd.c - get the working directory */
21558Srgrimes
31558Srgrimes/*
41558Srgrimes
51558Srgrimes@deftypefn Supplemental char* getpwd (void)
61558Srgrimes
71558SrgrimesReturns the current working directory.  This implementation caches the
81558Srgrimesresult on the assumption that the process will not call @code{chdir}
91558Srgrimesbetween calls to @code{getpwd}.
101558Srgrimes
111558Srgrimes@end deftypefn
121558Srgrimes
131558Srgrimes*/
141558Srgrimes
151558Srgrimes#ifdef HAVE_CONFIG_H
161558Srgrimes#include "config.h"
171558Srgrimes#endif
181558Srgrimes
191558Srgrimes#include <sys/types.h>
201558Srgrimes
211558Srgrimes#include <errno.h>
221558Srgrimes#ifndef errno
231558Srgrimesextern int errno;
241558Srgrimes#endif
251558Srgrimes
261558Srgrimes#ifdef HAVE_STDLIB_H
271558Srgrimes#include <stdlib.h>
281558Srgrimes#endif
291558Srgrimes#ifdef HAVE_UNISTD_H
301558Srgrimes#include <unistd.h>
311558Srgrimes#endif
321558Srgrimes#ifdef HAVE_SYS_PARAM_H
331558Srgrimes#include <sys/param.h>
341558Srgrimes#endif
3537906Scharnier#if HAVE_SYS_STAT_H
3623685Speter#include <sys/stat.h>
3737906Scharnier#endif
3837906Scharnier
3950476Speter/* Prototype these in case the system headers don't provide them. */
401558Srgrimesextern char *getpwd ();
411558Srgrimesextern char *getwd ();
421558Srgrimes
431558Srgrimes#include "libiberty.h"
441558Srgrimes
451558Srgrimes/* Virtually every UN*X system now in common use (except for pre-4.3-tahoe
461558Srgrimes   BSD systems) now provides getcwd as called for by POSIX.  Allow for
471558Srgrimes   the few exceptions to the general rule here.  */
481558Srgrimes
491558Srgrimes#if !defined(HAVE_GETCWD) && defined(HAVE_GETWD)
501558Srgrimes#define getcwd(buf,len) getwd(buf)
511558Srgrimes#endif
521558Srgrimes
531558Srgrimes#ifdef MAXPATHLEN
541558Srgrimes#define GUESSPATHLEN (MAXPATHLEN + 1)
551558Srgrimes#else
561558Srgrimes#define GUESSPATHLEN 100
571558Srgrimes#endif
581558Srgrimes
591558Srgrimes#if !(defined (VMS) || (defined(_WIN32) && !defined(__CYGWIN__)))
601558Srgrimes
611558Srgrimes/* Get the working directory.  Use the PWD environment variable if it's
621558Srgrimes   set correctly, since this is faster and gives more uniform answers
631558Srgrimes   to the user.  Yield the working directory if successful; otherwise,
641558Srgrimes   yield 0 and set errno.  */
651558Srgrimes
661558Srgrimeschar *
671558Srgrimesgetpwd ()
681558Srgrimes{
691558Srgrimes  static char *pwd;
701558Srgrimes  static int failure_errno;
711558Srgrimes
721558Srgrimes  char *p = pwd;
731558Srgrimes  size_t s;
741558Srgrimes  struct stat dotstat, pwdstat;
751558Srgrimes
761558Srgrimes  if (!p && !(errno = failure_errno))
771558Srgrimes    {
781558Srgrimes      if (! ((p = getenv ("PWD")) != 0
791558Srgrimes	     && *p == '/'
801558Srgrimes	     && stat (p, &pwdstat) == 0
811558Srgrimes	     && stat (".", &dotstat) == 0
821558Srgrimes	     && dotstat.st_ino == pwdstat.st_ino
831558Srgrimes	     && dotstat.st_dev == pwdstat.st_dev))
841558Srgrimes
851558Srgrimes	/* The shortcut didn't work.  Try the slow, ``sure'' way.  */
861558Srgrimes	for (s = GUESSPATHLEN;  ! getcwd (p = xmalloc (s), s);  s *= 2)
8721997Simp	  {
881558Srgrimes	    int e = errno;
891558Srgrimes	    free (p);
9023685Speter#ifdef ERANGE
911558Srgrimes	    if (e != ERANGE)
921558Srgrimes#endif
931558Srgrimes	      {
941558Srgrimes		errno = failure_errno = e;
951558Srgrimes		p = 0;
961558Srgrimes		break;
971558Srgrimes	      }
981558Srgrimes	  }
9992806Sobrien
1001558Srgrimes      /* Cache the result.  This assumes that the program does
1011558Srgrimes	 not invoke chdir between calls to getpwd.  */
1021558Srgrimes      pwd = p;
1031558Srgrimes    }
1041558Srgrimes  return p;
1051558Srgrimes}
1061558Srgrimes
1071558Srgrimes#else	/* VMS || _WIN32 && !__CYGWIN__ */
1081558Srgrimes
1091558Srgrimes#ifndef MAXPATHLEN
1101558Srgrimes#define MAXPATHLEN 255
1111558Srgrimes#endif
1121558Srgrimes
1131558Srgrimeschar *
11421174Sguidogetpwd ()
1151558Srgrimes{
1161558Srgrimes  static char *pwd = 0;
1171558Srgrimes
1181558Srgrimes  if (!pwd)
1191558Srgrimes    pwd = getcwd (xmalloc (MAXPATHLEN + 1), MAXPATHLEN + 1
1201558Srgrimes#ifdef VMS
1211558Srgrimes		  , 0
1221558Srgrimes#endif
1231558Srgrimes		  );
1241558Srgrimes  return pwd;
1251558Srgrimes}
12621997Simp
1271558Srgrimes#endif	/* VMS || _WIN32 && !__CYGWIN__ */
1281558Srgrimes