117721Speter#ifdef HAVE_CONFIG_H
217721Speter# include "config.h"
317721Speter#endif
417721Speter
517721Speter#include <stdio.h>
617721Speter
717721Speter#ifdef STDC_HEADERS
817721Speter# include <stdlib.h>
917721Speter#endif
1017721Speter
1117721Speter#ifdef HAVE_UNISTD_H
1217721Speter# include <unistd.h>
1317721Speter#endif
1417721Speter
1517721Speter#ifdef HAVE_FCNTL_H
1666525Speter# include <sys/types.h>
1717721Speter# include <fcntl.h>
1817721Speter#else
1917721Speter# include <sys/file.h>
2017721Speter#endif
2117721Speter
2217721Speter#ifdef HAVE_DIRECT_H
2317721Speter# include <direct.h>
2417721Speter#endif
2517721Speter
2617721Speter#ifdef HAVE_IO_H
2717721Speter# include <io.h>
2817721Speter#endif
2917721Speter
3017721Speter#include <errno.h>
3117721Speter# ifndef errno
3217721Speterextern int errno;
3317721Speter#endif
3417721Speter
3517721Speter#include "savecwd.h"
3617721Speter#include "error.h"
3717721Speter
3817721Speterchar *xgetwd __PROTO((void));
3917721Speter
4017721Speter/* Record the location of the current working directory in CWD so that
4117721Speter   the program may change to other directories and later use restore_cwd
4217721Speter   to return to the recorded location.  This function may allocate
4317721Speter   space using malloc (via xgetwd) or leave a file descriptor open;
4417721Speter   use free_cwd to perform the necessary free or close.  Upon failure,
4517721Speter   no memory is allocated, any locally opened file descriptors are
4617721Speter   closed;  return non-zero -- in that case, free_cwd need not be
4717721Speter   called, but doing so is ok.  Otherwise, return zero.  */
4817721Speter
4917721Speterint
5017721Spetersave_cwd (cwd)
5117721Speter     struct saved_cwd *cwd;
5217721Speter{
5317721Speter  static int have_working_fchdir = 1;
5417721Speter
5517721Speter  cwd->desc = -1;
5617721Speter  cwd->name = NULL;
5717721Speter
5817721Speter  if (have_working_fchdir)
5917721Speter    {
6017721Speter#ifdef HAVE_FCHDIR
6117721Speter      cwd->desc = open (".", O_RDONLY);
6217721Speter      if (cwd->desc < 0)
6317721Speter	{
6417721Speter	  error (0, errno, "cannot open current directory");
6517721Speter	  return 1;
6617721Speter	}
6717721Speter
6817721Speter# if __sun__ || sun
6917721Speter      /* On SunOS 4, fchdir returns EINVAL if accounting is enabled,
7017721Speter	 so we have to fall back to chdir.  */
7117721Speter      if (fchdir (cwd->desc))
7217721Speter	{
7317721Speter	  if (errno == EINVAL)
7417721Speter	    {
7517721Speter	      close (cwd->desc);
7617721Speter	      cwd->desc = -1;
7717721Speter	      have_working_fchdir = 0;
7817721Speter	    }
7917721Speter	  else
8017721Speter	    {
8117721Speter	      error (0, errno, "current directory");
8217721Speter	      close (cwd->desc);
8317721Speter	      cwd->desc = -1;
8417721Speter	      return 1;
8517721Speter	    }
8617721Speter	}
8717721Speter# endif /* __sun__ || sun */
8817721Speter#else
8917721Speter#define fchdir(x) (abort (), 0)
9017721Speter      have_working_fchdir = 0;
9117721Speter#endif
9217721Speter    }
9317721Speter
9417721Speter  if (!have_working_fchdir)
9517721Speter    {
9617721Speter      cwd->name = xgetwd ();
9717721Speter      if (cwd->name == NULL)
9817721Speter	{
9917721Speter	  error (0, errno, "cannot get current directory");
10017721Speter	  return 1;
10117721Speter	}
10217721Speter    }
10317721Speter  return 0;
10417721Speter}
10517721Speter
10617721Speter/* Change to recorded location, CWD, in directory hierarchy.
10717721Speter   If "saved working directory", NULL))
10817721Speter   */
10917721Speter
11017721Speterint
11117721Speterrestore_cwd (cwd, dest)
11217721Speter     const struct saved_cwd *cwd;
11317721Speter     const char *dest;
11417721Speter{
11517721Speter  int fail = 0;
11617721Speter  if (cwd->desc >= 0)
11717721Speter    {
11817721Speter      if (fchdir (cwd->desc))
11917721Speter	{
12017721Speter	  error (0, errno, "cannot return to %s",
12117721Speter		 (dest ? dest : "saved working directory"));
12217721Speter	  fail = 1;
12317721Speter	}
12417721Speter    }
12517721Speter  else if (chdir (cwd->name) < 0)
12617721Speter    {
12717721Speter      error (0, errno, "%s", cwd->name);
12817721Speter      fail = 1;
12917721Speter    }
13017721Speter  return fail;
13117721Speter}
13217721Speter
13317721Spetervoid
13417721Speterfree_cwd (cwd)
13517721Speter     struct saved_cwd *cwd;
13617721Speter{
13717721Speter  if (cwd->desc >= 0)
13817721Speter    close (cwd->desc);
13917721Speter  if (cwd->name)
14017721Speter    free (cwd->name);
14117721Speter}
14217721Speter
143