1c26070a5Stholo #ifdef HAVE_CONFIG_H
2c26070a5Stholo # include "config.h"
3c26070a5Stholo #endif
4c26070a5Stholo
5c26070a5Stholo #include <stdio.h>
6c26070a5Stholo
7c26070a5Stholo #ifdef STDC_HEADERS
8c26070a5Stholo # include <stdlib.h>
9c26070a5Stholo #endif
10c26070a5Stholo
11c26070a5Stholo #ifdef HAVE_UNISTD_H
12c26070a5Stholo # include <unistd.h>
13c26070a5Stholo #endif
14c26070a5Stholo
15c26070a5Stholo #ifdef HAVE_FCNTL_H
16*e77048c1Stholo # include <sys/types.h>
17c26070a5Stholo # include <fcntl.h>
18c26070a5Stholo #else
19c26070a5Stholo # include <sys/file.h>
20c26070a5Stholo #endif
21c26070a5Stholo
22c26070a5Stholo #ifdef HAVE_DIRECT_H
23c26070a5Stholo # include <direct.h>
24c26070a5Stholo #endif
25c26070a5Stholo
26c26070a5Stholo #ifdef HAVE_IO_H
27c26070a5Stholo # include <io.h>
28c26070a5Stholo #endif
29c26070a5Stholo
30c26070a5Stholo #include <errno.h>
31c26070a5Stholo # ifndef errno
32c26070a5Stholo extern int errno;
33c26070a5Stholo #endif
34c26070a5Stholo
35c26070a5Stholo #include "savecwd.h"
36c26070a5Stholo #include "error.h"
37c26070a5Stholo
38c26070a5Stholo char *xgetwd __PROTO((void));
39c26070a5Stholo
40c26070a5Stholo /* Record the location of the current working directory in CWD so that
41c26070a5Stholo the program may change to other directories and later use restore_cwd
42c26070a5Stholo to return to the recorded location. This function may allocate
43c26070a5Stholo space using malloc (via xgetwd) or leave a file descriptor open;
44c26070a5Stholo use free_cwd to perform the necessary free or close. Upon failure,
45c26070a5Stholo no memory is allocated, any locally opened file descriptors are
46c26070a5Stholo closed; return non-zero -- in that case, free_cwd need not be
47c26070a5Stholo called, but doing so is ok. Otherwise, return zero. */
48c26070a5Stholo
49c26070a5Stholo int
save_cwd(cwd)50c26070a5Stholo save_cwd (cwd)
51c26070a5Stholo struct saved_cwd *cwd;
52c26070a5Stholo {
53c26070a5Stholo static int have_working_fchdir = 1;
54c26070a5Stholo
55c26070a5Stholo cwd->desc = -1;
56c26070a5Stholo cwd->name = NULL;
57c26070a5Stholo
58c26070a5Stholo if (have_working_fchdir)
59c26070a5Stholo {
60c26070a5Stholo #ifdef HAVE_FCHDIR
61c26070a5Stholo cwd->desc = open (".", O_RDONLY);
62c26070a5Stholo if (cwd->desc < 0)
63c26070a5Stholo {
64c26070a5Stholo error (0, errno, "cannot open current directory");
65c26070a5Stholo return 1;
66c26070a5Stholo }
67c26070a5Stholo
68c26070a5Stholo # if __sun__ || sun
69c26070a5Stholo /* On SunOS 4, fchdir returns EINVAL if accounting is enabled,
70c26070a5Stholo so we have to fall back to chdir. */
71c26070a5Stholo if (fchdir (cwd->desc))
72c26070a5Stholo {
73c26070a5Stholo if (errno == EINVAL)
74c26070a5Stholo {
75c26070a5Stholo close (cwd->desc);
76c26070a5Stholo cwd->desc = -1;
77c26070a5Stholo have_working_fchdir = 0;
78c26070a5Stholo }
79c26070a5Stholo else
80c26070a5Stholo {
81c26070a5Stholo error (0, errno, "current directory");
82c26070a5Stholo close (cwd->desc);
83c26070a5Stholo cwd->desc = -1;
84c26070a5Stholo return 1;
85c26070a5Stholo }
86c26070a5Stholo }
87c26070a5Stholo # endif /* __sun__ || sun */
88c26070a5Stholo #else
89c26070a5Stholo #define fchdir(x) (abort (), 0)
90c26070a5Stholo have_working_fchdir = 0;
91c26070a5Stholo #endif
92c26070a5Stholo }
93c26070a5Stholo
94c26070a5Stholo if (!have_working_fchdir)
95c26070a5Stholo {
96c26070a5Stholo cwd->name = xgetwd ();
97c26070a5Stholo if (cwd->name == NULL)
98c26070a5Stholo {
99c26070a5Stholo error (0, errno, "cannot get current directory");
100c26070a5Stholo return 1;
101c26070a5Stholo }
102c26070a5Stholo }
103c26070a5Stholo return 0;
104c26070a5Stholo }
105c26070a5Stholo
106c26070a5Stholo /* Change to recorded location, CWD, in directory hierarchy.
107c26070a5Stholo If "saved working directory", NULL))
108c26070a5Stholo */
109c26070a5Stholo
110c26070a5Stholo int
restore_cwd(cwd,dest)111c26070a5Stholo restore_cwd (cwd, dest)
112c26070a5Stholo const struct saved_cwd *cwd;
113c26070a5Stholo const char *dest;
114c26070a5Stholo {
115c26070a5Stholo int fail = 0;
116c26070a5Stholo if (cwd->desc >= 0)
117c26070a5Stholo {
118c26070a5Stholo if (fchdir (cwd->desc))
119c26070a5Stholo {
120c26070a5Stholo error (0, errno, "cannot return to %s",
121c26070a5Stholo (dest ? dest : "saved working directory"));
122c26070a5Stholo fail = 1;
123c26070a5Stholo }
124c26070a5Stholo }
125c26070a5Stholo else if (chdir (cwd->name) < 0)
126c26070a5Stholo {
127c26070a5Stholo error (0, errno, "%s", cwd->name);
128c26070a5Stholo fail = 1;
129c26070a5Stholo }
130c26070a5Stholo return fail;
131c26070a5Stholo }
132c26070a5Stholo
133c26070a5Stholo void
free_cwd(cwd)134c26070a5Stholo free_cwd (cwd)
135c26070a5Stholo struct saved_cwd *cwd;
136c26070a5Stholo {
137c26070a5Stholo if (cwd->desc >= 0)
138c26070a5Stholo close (cwd->desc);
139c26070a5Stholo if (cwd->name)
140c26070a5Stholo free (cwd->name);
141c26070a5Stholo }
142c26070a5Stholo
143