home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / octa21fs.zip / octave / octave-2.1.23 / liboctave / oct-env.cc < prev    next >
C/C++ Source or Header  |  2000-01-15  |  9KB  |  498 lines

  1. /*
  2.  
  3. Copyright (C) 1996, 1997 John W. Eaton
  4.  
  5. This file is part of Octave.
  6.  
  7. Octave is free software; you can redistribute it and/or modify it
  8. under the terms of the GNU General Public License as published by the
  9. Free Software Foundation; either version 2, or (at your option) any
  10. later version.
  11.  
  12. Octave is distributed in the hope that it will be useful, but WITHOUT
  13. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  14. FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  15. for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with Octave; see the file COPYING.  If not, write to the Free
  19. Software Foundation, 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21. */
  22.  
  23. /*
  24.  
  25. The functions listed below were adapted from a similar functions
  26. from GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991
  27. Free Software Foundation, Inc.
  28.  
  29.   octave_env::do_absolute_pathname
  30.   octave_env::do_base_pathname
  31.   octave_env::do_chdir
  32.   octave_env::do_getcwd
  33.   octave_env::do_make_absolute
  34.   octave_env::do_polite_directory_format
  35.   octave_env::pathname_backup
  36.  
  37. */ 
  38.  
  39. #ifdef HAVE_CONFIG_H
  40. #include <config.h>
  41. #endif
  42.  
  43. #include <cstdlib>
  44.  
  45. #ifdef HAVE_UNISTD_H
  46. #ifdef HAVE_SYS_TYPES_H
  47. #include <sys/types.h>
  48. #endif
  49. #include <unistd.h>
  50. #endif
  51.  
  52. #include "lo-error.h"
  53. #include "lo-sysdep.h"
  54. #include "lo-utils.h"
  55. #include "oct-env.h"
  56. #include "oct-passwd.h"
  57. #include "oct-syscalls.h"
  58.  
  59. octave_env::octave_env (void)
  60.   : follow_symbolic_links (true), verbatim_pwd (true),
  61.     current_directory (), program_name (), program_invocation_name (),
  62.     user_name (), host_name ()
  63. {
  64.   // Get a real value for the current directory.
  65.   do_getcwd ();
  66.  
  67.   // Etc.
  68.   do_get_user_name ();
  69.  
  70.   do_get_host_name ();
  71. }
  72.  
  73. octave_env *octave_env::instance = 0;
  74.  
  75. bool
  76. octave_env::instance_ok (void)
  77. {
  78.   bool retval = true;
  79.  
  80.   if (! instance)
  81.     instance = new octave_env ();
  82.  
  83.   if (! instance)
  84.     {
  85.       (*current_liboctave_error_handler)
  86.     ("unable to create current working directoy object!");
  87.  
  88.       retval = false;
  89.     }
  90.  
  91.   return retval;
  92. }
  93.  
  94. string
  95. octave_env::polite_directory_format (const string& name)
  96. {
  97.   return (instance_ok ())
  98.     ? instance->do_polite_directory_format (name) : string ();
  99. }
  100.  
  101. bool
  102. octave_env::absolute_pathname (const string& s)
  103. {
  104.   return (instance_ok ())
  105.     ? instance->do_absolute_pathname (s) : false;
  106. }
  107.  
  108. string
  109. octave_env::base_pathname (const string& s)
  110. {
  111.   return (instance_ok ())
  112.     ? instance->do_base_pathname (s) : string ();
  113. }
  114.  
  115. string
  116. octave_env::make_absolute (const string& s, const string& dot_path)
  117. {
  118.   return (instance_ok ())
  119.     ? instance->do_make_absolute (s, dot_path) : string ();
  120. }
  121.  
  122. string
  123. octave_env::getcwd ()
  124. {
  125.   return (instance_ok ())
  126.     ? instance->do_getcwd () : string ();
  127. }
  128.  
  129. string
  130. octave_env::get_home_directory ()
  131. {
  132.   return (instance_ok ())
  133.     ? instance->do_get_home_directory () : string ();
  134. }
  135.  
  136. string
  137. octave_env::get_program_name (void)
  138. {
  139.   return (instance_ok ())
  140.     ? instance->program_name : string ();
  141. }
  142.  
  143. string
  144. octave_env::get_program_invocation_name (void)
  145. {
  146.   return (instance_ok ())
  147.     ? instance->program_invocation_name : string ();
  148. }
  149.  
  150. void
  151. octave_env::set_program_name (const string& s)
  152. {
  153.   if (instance_ok ())
  154.     instance->do_set_program_name (s);
  155. }
  156.  
  157. string
  158. octave_env::get_user_name (void)
  159. {
  160.   return (instance_ok ())
  161.     ? instance->do_get_user_name () : string ();
  162. }
  163.  
  164. string
  165. octave_env::get_host_name (void)
  166. {
  167.   return (instance_ok ())
  168.     ? instance->do_get_host_name () : string ();
  169. }
  170.  
  171. // XXX FIXME XXX -- this leaves no way to distinguish between a
  172. // variable that is not set and one that is set to the empty string.
  173. // Is this a problem?
  174.  
  175. string
  176. octave_env::getenv (const string& name)
  177. {
  178.   return (instance_ok ())
  179.     ? instance->do_getenv (name) : string ();
  180. }
  181.  
  182. void
  183. octave_env::putenv (const string& name, const string& value)
  184. {
  185.   octave_putenv (name, value);
  186. }
  187.  
  188. bool
  189. octave_env::chdir (const string& newdir)
  190. {
  191.   return (instance_ok ())
  192.     ? instance->do_chdir (newdir) : false;
  193. }
  194.  
  195. void
  196. octave_env::do_set_program_name (const string& s) const
  197. {
  198.   program_invocation_name = s;
  199.  
  200.   size_t pos = program_invocation_name.rfind ('/');
  201.  
  202.   program_name = (pos == NPOS)
  203.     ? program_invocation_name : program_invocation_name.substr (pos+1);
  204. }
  205.  
  206. // Return a pretty pathname.  If the first part of the pathname is the
  207. // same as $HOME, then replace that with `~'.
  208.  
  209. string
  210. octave_env::do_polite_directory_format (const string& name) const
  211. {
  212.   string retval;
  213.  
  214.   string home_dir = do_get_home_directory ();
  215.  
  216.   size_t len = home_dir.length ();
  217.  
  218.   if (len > 1 && home_dir.compare (name, 0, len) == 0
  219.       && (name.length () == len || name[len] == '/'))
  220.     {
  221.       retval = "~";
  222.       retval.append (name.substr (len));
  223.     }
  224.   else
  225.     retval = name;
  226.  
  227.   return retval;
  228. }
  229.  
  230. // Return 1 if STRING contains an absolute pathname, else 0.
  231.  
  232. bool
  233. octave_env::do_absolute_pathname (const string& s) const
  234. {
  235.   if (s.empty ())
  236.     return 0;
  237.  
  238.   if (s[0] == '/')
  239.     return true;
  240.  
  241.   if (s[0] == '.')
  242.     {
  243.       if (s[1] == '\0' || s[1] == '/')
  244.     return true;
  245.  
  246.       if (s[1] == '.')
  247.     if (s[2] == '\0' || s[2] == '/')
  248.       return true;
  249.     }
  250.  
  251.   return false;
  252. }
  253.  
  254. // Return the `basename' of the pathname in STRING (the stuff after
  255. // the last '/').  If STRING is not a full pathname, simply return it.
  256.  
  257. string
  258. octave_env::do_base_pathname (const string& s) const
  259. {
  260.   if (! do_absolute_pathname (s))
  261.     return s;
  262.  
  263.   size_t pos = s.rfind ('/');
  264.  
  265.   if (pos == NPOS)
  266.     return s;
  267.   else
  268.     return s.substr (pos+1);
  269. }
  270.  
  271. // Turn STRING (a pathname) into an absolute pathname, assuming that
  272. // DOT_PATH contains the symbolic location of '.'.
  273.  
  274. string
  275. octave_env::do_make_absolute (const string& s, const string& dot_path) const
  276. {
  277. #if defined (__EMX__)
  278.   if (s.length () > 1 && s[1] == ':')
  279.     return s;
  280. #endif
  281.  
  282.   if (dot_path.empty () || s[0] == '/' || s.empty ())
  283.     return s;
  284.  
  285.   string current_path = dot_path;
  286.  
  287.   if (current_path.empty ())
  288.     current_path = "./";
  289.  
  290.   size_t pos = current_path.length () - 1;
  291.  
  292.   if (current_path[pos] != '/')
  293.     current_path.append ("/");
  294.  
  295.   size_t i = 0;
  296.   size_t slen = s.length ();
  297.  
  298.   while (i < slen)
  299.     {
  300.       if (s[i] == '.')
  301.     {
  302.       if (i + 1 == slen)
  303.         return current_path;
  304.  
  305.       if (s[i+1] == '/')
  306.         {
  307.           i += 2;
  308.           continue;
  309.         }
  310.  
  311.       if (s[i+1] == '.' && (i + 2 == slen || s[i+2] == '/'))
  312.         {
  313.           i += 2;
  314.  
  315.           if (i != slen)
  316.         i++;
  317.  
  318.           pathname_backup (current_path, 1);
  319.  
  320.           continue;
  321.         }
  322.     }
  323.  
  324.       size_t tmp = s.find ('/', i);
  325.  
  326.       if (tmp == NPOS)
  327.     {
  328.       current_path.append (s, i, tmp-i);
  329.       break;
  330.     }
  331.       else
  332.     {
  333.       current_path.append (s, i, tmp-i+1);
  334.       i = tmp + 1;
  335.     }
  336.     }
  337.  
  338.   return current_path;
  339. }
  340.  
  341. // Return a consed string which is the current working directory.
  342.  
  343. string
  344. octave_env::do_getcwd ()
  345. {
  346.   if (! follow_symbolic_links)
  347.     current_directory = "";
  348.  
  349.   if (verbatim_pwd || current_directory.empty ())
  350.     current_directory = ::octave_getcwd ();
  351.  
  352.   return current_directory;
  353. }
  354.  
  355. // This value is not cached because it can change while Octave is
  356. // running.
  357.  
  358. string
  359. octave_env::do_get_home_directory (void) const
  360. {
  361.   string hd = do_getenv ("HOME");
  362.  
  363.   if (hd.empty ())
  364.     {
  365.       octave_passwd pw = octave_passwd::getpwuid (octave_syscalls::getuid ());
  366.  
  367.       hd = pw ? pw.dir () : string ("/");
  368.     }
  369.  
  370.   return hd;
  371. }
  372.  
  373. string
  374. octave_env::do_get_user_name (void) const
  375. {
  376.   // XXX FIXME XXX -- is it possible for this to change while Octave
  377.   // is running?
  378.  
  379.   if (user_name.empty ())
  380.     {
  381.       octave_passwd pw = octave_passwd::getpwuid (octave_syscalls::getuid ());
  382.  
  383.       user_name = pw ? pw.name () : string ("unknown");
  384.     }
  385.  
  386.   return user_name;
  387. }
  388.  
  389. string
  390. octave_env::do_get_host_name (void) const
  391. {
  392.   // XXX FIXME XXX -- is it possible for this to change while Octave
  393.   // is running?
  394.  
  395.   if (host_name.empty ())
  396.     {
  397.       char hostname[256];
  398.  
  399.       int status = gethostname (hostname, 255);
  400.  
  401.       host_name = (status < 0) ? "unknown" : hostname;
  402.     }
  403.  
  404.   return host_name;
  405. }
  406.  
  407. string
  408. octave_env::do_getenv (const string& name) const
  409. {
  410.   char *value = ::getenv (name.c_str ());
  411.  
  412.   return value ? value : "";
  413. }
  414.  
  415. // Do the work of changing to the directory NEWDIR.  Handle symbolic
  416. // link following, etc.
  417.  
  418. bool
  419. octave_env::do_chdir (const string& newdir)
  420. {
  421.   bool retval = false;
  422.  
  423.   string tmp;
  424.  
  425.   if (follow_symbolic_links)
  426.     {
  427.       if (current_directory.empty ())
  428.     do_getcwd ();
  429.  
  430.       if (current_directory.empty ())
  431.     tmp = newdir;
  432.       else
  433.     tmp = do_make_absolute (newdir, current_directory);
  434.  
  435.       // Get rid of trailing `/'.
  436.  
  437.       size_t len = tmp.length ();
  438.  
  439.       if (len > 1)
  440.     {
  441.       if (tmp[--len] == '/')
  442.         tmp.resize (len);
  443.     }
  444.  
  445.       if (! ::octave_chdir (tmp))
  446.     {
  447.       current_directory = tmp;
  448.       retval = true;
  449.     }
  450.     }
  451.   else
  452.     retval = (! ::octave_chdir (newdir));
  453.  
  454.   return retval;
  455. }
  456.  
  457. // Remove the last N directories from PATH.
  458.  
  459. void
  460. octave_env::pathname_backup (string& path, int n) const
  461. {
  462.   if (path.empty ())
  463.     return;
  464.  
  465.   size_t i = path.length () - 1;
  466.  
  467.   while (n--)
  468.     {
  469.       while (path[i] == '/' && i > 0)
  470.     i--;
  471.  
  472.       while (path[i] != '/' && i > 0)
  473.     i--;
  474.  
  475.       i++;
  476.     }
  477.  
  478.   path.resize (i);
  479. }
  480.  
  481. void
  482. octave_env::error (int err_num) const
  483. {
  484.   (*current_liboctave_error_handler) ("%s", strerror (err_num));
  485. }
  486.  
  487. void
  488. octave_env::error (const string& s) const
  489. {
  490.   (*current_liboctave_error_handler) ("%s", s.c_str ());
  491. }
  492.  
  493. /*
  494. ;;; Local Variables: ***
  495. ;;; mode: C++ ***
  496. ;;; End: ***
  497. */
  498.