home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21fs.zip / octave / kpathsea / xgetcwd.c < prev    next >
C/C++ Source or Header  |  2000-01-15  |  5KB  |  154 lines

  1. /* xgetcwd.c: a from-scratch version of getwd.  Ideas from the tcsh 5.20
  2.    source, apparently uncopyrighted.
  3.  
  4. Copyright (C) 1992, 94, 96 Free Software Foundation, Inc.
  5.  
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
  19.  
  20. #include <kpathsea/config.h>
  21.  
  22. #if defined (HAVE_GETCWD) || defined (HAVE_GETWD)
  23. #include <kpathsea/c-pathmx.h>
  24. #else /* not HAVE_GETCWD && not HAVE_GETWD*/
  25. #include <kpathsea/c-dir.h>
  26. #include <kpathsea/xopendir.h>
  27. #include <kpathsea/xstat.h>
  28.  
  29.  
  30. static void
  31. xchdir P1C(string, dirname)
  32. {
  33.   if (chdir (dirname) != 0)
  34.     FATAL_PERROR (dirname);
  35. }
  36.  
  37. #endif /* not HAVE_GETCWD && not HAVE_GETWD */
  38.  
  39.  
  40. /* Return the pathname of the current directory, or give a fatal error.  */
  41.  
  42. string
  43. xgetcwd P1H(void)
  44. {
  45.   /* If the system provides getcwd, use it.  If not, use getwd if
  46.      available.  But provide a way not to use getcwd: on some systems
  47.      getcwd forks, which is expensive and may in fact be impossible for
  48.      large programs like tex.  If your system needs this define and it
  49.      is not detected by configure, let me know.
  50.                                        -- Olaf Weber <infovore@xs4all.nl */
  51. #if defined (HAVE_GETCWD) && !defined (GETCWD_FORKS)
  52.   string path = xmalloc (PATH_MAX + 1);
  53.   
  54.   if (getcwd (path, PATH_MAX + 1) == 0)
  55.     {
  56.       fprintf (stderr, "getcwd: %s", path);
  57.       exit (1);
  58.     }
  59.   
  60.   return path;
  61. #elif defined (HAVE_GETWD)
  62.   string path = xmalloc (PATH_MAX + 1);
  63.   
  64.   if (getwd (path) == 0)
  65.     {
  66.       fprintf (stderr, "getwd: %s", path);
  67.       exit (1);
  68.     }
  69.   
  70.   return path;
  71. #else /* not HAVE_GETCWD && not HAVE_GETWD */
  72.   struct stat root_stat, cwd_stat;
  73.   string cwd_path = xmalloc (2); /* In case we assign "/" below.  */
  74.   
  75.   *cwd_path = 0;
  76.   
  77.   /* Find the inodes of the root and current directories.  */
  78.   root_stat = xstat ("/");
  79.   cwd_stat = xstat (".");
  80.  
  81.   /* Go up the directory hierarchy until we get to root, prepending each
  82.      directory we pass through to `cwd_path'.  */
  83.   while (!SAME_FILE_P (root_stat, cwd_stat))
  84.     {
  85.       struct dirent *e;
  86.       DIR *parent_dir;
  87.       boolean found = false;
  88.       
  89.       xchdir ("..");
  90.       parent_dir = xopendir (".");
  91.  
  92.       /* Look through the parent directory for the entry with the same
  93.          inode, so we can get its name.  */
  94.       while ((e = readdir (parent_dir)) != NULL && !found)
  95.         {
  96.           struct stat test_stat;
  97.           test_stat = xlstat (e->d_name);
  98.           
  99.           if (SAME_FILE_P (test_stat, cwd_stat))
  100.             {
  101.               /* We've found it.  Prepend the pathname.  */
  102.               string temp = cwd_path;
  103.               cwd_path = concat3 ("/", e->d_name, cwd_path);
  104.               free (temp);
  105.               
  106.               /* Set up to test the next parent.  */
  107.               cwd_stat = xstat (".");
  108.               
  109.               /* Stop reading this directory.  */
  110.               found = true;
  111.             }
  112.         }
  113.       if (!found)
  114.         FATAL2 ("No inode %d/device %d in parent directory",
  115.                 cwd_stat.st_ino, cwd_stat.st_dev);
  116.       
  117.       xclosedir (parent_dir);
  118.     }
  119.   
  120.   /* If the current directory is the root, cwd_path will be the empty
  121.      string, and we will have not gone through the loop.  */
  122.   if (*cwd_path == 0)
  123.     strcpy (cwd_path, "/");
  124.   else
  125.     /* Go back to where we were.  */
  126.     xchdir (cwd_path);
  127.  
  128. #ifdef DOSISH
  129.   /* Prepend the drive letter to CWD_PATH, since this technique
  130.      never tells us what the drive is.
  131.  
  132.      Note that on MS-DOS/MS-Windows, the branch that works around
  133.      missing `getwd' will probably only work for DJGPP (which does
  134.      have `getwd'), because only DJGPP reports meaningful
  135.      st_ino numbers.  But someday, somebody might need this...  */
  136.   {
  137.     char drive[3];
  138.     string temp = cwd_path;
  139.  
  140.     /* Make the drive letter lower-case, unless it is beyond Z: (yes,
  141.        there ARE such drives, in case of Novell Netware on MS-DOS).  */
  142.     drive[0] = root_stat.st_dev + (root_stat.st_dev < 26 ? 'a' : 'A');
  143.     drive[1] = ':';
  144.     drive[2] = '\0';
  145.  
  146.     cwd_path = concat (drive, cwd_path);
  147.     free (temp);
  148.   }
  149. #endif
  150.  
  151.   return cwd_path;
  152. #endif /* not HAVE_GETCWD && not HAVE_GETWD */
  153. }
  154.