getpwd.c 2.5 KB

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