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