/*
Copyright (C) 1996, 1997 John W. Eaton
This file is part of Octave.
Octave is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
Octave is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with Octave; see the file COPYING. If not, write to the Free
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301, USA.
*/
/*
The functions listed below were adapted from a similar functions
from GNU Bash, the Bourne Again SHell, copyright (C) 1987, 1989, 1991
Free Software Foundation, Inc.
octave_env::do_absolute_pathname
octave_env::do_base_pathname
octave_env::do_chdir
octave_env::do_getcwd
octave_env::do_make_absolute
octave_env::do_polite_directory_format
octave_env::pathname_backup
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <cctype>
#include <cstdlib>
#include <string>
#ifdef HAVE_UNISTD_H
#ifdef HAVE_SYS_TYPES_H
#include <sys/types.h>
#endif
#include <unistd.h>
#endif
#include "file-ops.h"
#include "lo-error.h"
#include "lo-sysdep.h"
#include "lo-utils.h"
#include "oct-env.h"
#include "oct-passwd.h"
#include "oct-syscalls.h"
octave_env::octave_env (void)
: follow_symbolic_links (true), verbatim_pwd (true),
current_directory (), program_name (), program_invocation_name (),
user_name (), host_name ()
{
// Get a real value for the current directory.
do_getcwd ();
// Etc.
do_get_user_name ();
do_get_host_name ();
}
octave_env *octave_env::instance = 0;
bool
octave_env::instance_ok (void)
{
bool retval = true;
if (! instance)
instance = new octave_env ();
if (! instance)
{
(*current_liboctave_error_handler)
("unable to create current working directoy object!");
retval = false;
}
return retval;
}
std::string
octave_env::polite_directory_format (const std::string& name)
{
return (instance_ok ())
? instance->do_polite_directory_format (name) : std::string ();
}
bool
octave_env::absolute_pathname (const std::string& s)
{
return (instance_ok ())
? instance->do_absolute_pathname (s) : false;
}
std::string
octave_env::base_pathname (const std::string& s)
{
return (instance_ok ())
? instance->do_base_pathname (s) : std::string ();
}
std::string
octave_env::make_absolute (const std::string& s, const std::string& dot_path)
{
return (instance_ok ())
? instance->do_make_absolute (s, dot_path) : std::string ();
}
std::string
octave_env::getcwd ()
{
return (instance_ok ())
? instance->do_getcwd () : std::string ();
}
std::string
octave_env::get_home_directory ()
{
return (instance_ok ())
? instance->do_get_home_directory () : std::string ();
}
std::string
octave_env::get_program_name (void)
{
return (instance_ok ())
? instance->program_name : std::string ();
}
std::string
octave_env::get_program_invocation_name (void)
{
return (instance_ok ())
? instance->program_invocation_name : std::string ();
}
void
octave_env::set_program_name (const std::string& s)
{
if (instance_ok ())
instance->do_set_program_name (s);
}
std::string
octave_env::get_user_name (void)
{
return (instance_ok ())
? instance->do_get_user_name () : std::string ();
}
std::string
octave_env::get_host_name (void)
{
return (instance_ok ())
? instance->do_get_host_name () : std::string ();
}
// XXX FIXME XXX -- this leaves no way to distinguish between a
// variable that is not set and one that is set to the empty string.
// Is this a problem?
std::string
octave_env::getenv (const std::string& name)
{
return (instance_ok ())
? instance->do_getenv (name) : std::string ();
}
void
octave_env::putenv (const std::string& name, const std::string& value)
{
octave_putenv (name, value);
}
bool
octave_env::chdir (const std::string& newdir)
{
return (instance_ok ())
? instance->do_chdir (newdir) : false;
}
void
octave_env::do_set_program_name (const std::string& s) const
{
program_invocation_name = s;
size_t pos = program_invocation_name.find_last_of (file_ops::dir_sep_chars);
program_name = (pos == NPOS)
? program_invocation_name : program_invocation_name.substr (pos+1);
}
// Return a pretty pathname. If the first part of the pathname is the
// same as $HOME, then replace that with `~'.
std::string
octave_env::do_polite_directory_format (const std::string& name) const
{
std::string retval;
std::string home_dir = do_get_home_directory ();
size_t len = home_dir.length ();
if (len > 1 && home_dir == name.substr (0, len)
&& (name.length () == len || file_ops::is_dir_sep (name[len])))
{
retval = "~";
retval.append (name.substr (len));
}
else
retval = name;
return retval;
}
bool
octave_env::do_absolute_pathname (const std::string& s) const
{
size_t len = s.length ();
if (len == 0)
return false;
if (file_ops::is_dir_sep (s[0]))
return true;
#if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
if ((len == 2 && isalpha (s[0]) && s[1] == ':')
|| (len > 2 && isalpha (s[0]) && s[1] == ':'
&& file_ops::is_dir_sep (s[2])))
return true;
#endif
return false;
}
// Return the `basename' of the pathname in STRING (the stuff after
// the last directory separator). If STRING is not a full pathname,
// simply return it.
std::string
octave_env::do_base_pathname (const std::string& s) const
{
if (! do_absolute_pathname (s))
return s;
size_t pos = s.find_last_of (file_ops::dir_sep_chars);
if (pos == NPOS)
return s;
else
return s.substr (pos+1);
}
// Turn STRING (a pathname) into an absolute pathname, assuming that
// DOT_PATH contains the symbolic location of the current directory.
std::string
octave_env::do_make_absolute (const std::string& s,
const std::string& dot_path) const
{
#if defined (__EMX__)
if (s.length () > 1 && s[1] == ':')
return s;
#endif
if (dot_path.empty () || s.empty () || do_absolute_pathname (s))
return s;
std::string current_dir = dot_path;
if (current_dir.empty ())
current_dir = do_getcwd ();
size_t pos = current_dir.length () - 1;
if (! file_ops::is_dir_sep (current_dir[pos]))
current_dir.append (file_ops::dir_sep_str);
// XXX FIXME XXX -- this is probably not correct for all systems.
size_t i = 0;
size_t slen = s.length ();
while (i < slen)
{
if (s[i] == '.')
{
if (i + 1 == slen)
return current_dir;
if (file_ops::is_dir_sep (s[i+1]))
{
i += 2;
continue;
}
if (s[i+1] == '.'
&& (i + 2 == slen || file_ops::is_dir_sep (s[i+2])))
{
i += 2;
if (i != slen)
i++;
pathname_backup (current_dir, 1);
continue;
}
}
size_t tmp = s.find_first_of (file_ops::dir_sep_chars, i);
if (tmp == NPOS)
{
current_dir.append (s, i, tmp-i);
break;
}
else
{
current_dir.append (s, i, tmp-i+1);
i = tmp + 1;
}
}
return current_dir;
}
// Return a string which is the current working directory.
std::string
octave_env::do_getcwd () const
{
if (! follow_symbolic_links)
current_directory = "";
if (verbatim_pwd || current_directory.empty ())
current_directory = ::octave_getcwd ();
return current_directory;
}
// This value is not cached because it can change while Octave is
// running.
std::string
octave_env::do_get_home_directory (void) const
{
std::string hd = do_getenv ("HOME");
if (hd.empty ())
{
octave_passwd pw = octave_passwd::getpwuid (octave_syscalls::getuid ());
hd = pw ? pw.dir () : std::string (file_ops::dir_sep_str);
}
return hd;
}
std::string
octave_env::do_get_user_name (void) const
{
// XXX FIXME XXX -- is it possible for this to change while Octave
// is running?
if (user_name.empty ())
{
octave_passwd pw = octave_passwd::getpwuid (octave_syscalls::getuid ());
user_name = pw ? pw.name () : std::string ("unknown");
}
return user_name;
}
std::string
octave_env::do_get_host_name (void) const
{
// XXX FIXME XXX -- is it possible for this to change while Octave
// is running?
if (host_name.empty ())
{
char hostname[256];
int status = octave_gethostname (hostname, 255);
host_name = (status < 0) ? "unknown" : hostname;
}
return host_name;
}
std::string
octave_env::do_getenv (const std::string& name) const
{
char *value = ::getenv (name.c_str ());
return value ? value : "";
}
// Do the work of changing to the directory NEWDIR. Handle symbolic
// link following, etc.
bool
octave_env::do_chdir (const std::string& newdir)
{
bool retval = false;
std::string tmp;
if (follow_symbolic_links)
{
if (current_directory.empty ())
do_getcwd ();
if (current_directory.empty ())
tmp = newdir;
else
tmp = do_make_absolute (newdir, current_directory);
// Get rid of trailing directory separator.
size_t len = tmp.length ();
if (len > 1)
{
if (file_ops::is_dir_sep (tmp[--len]))
tmp.resize (len);
}
if (! ::octave_chdir (tmp))
{
current_directory = tmp;
retval = true;
}
}
else
retval = (! ::octave_chdir (newdir));
return retval;
}
// Remove the last N directories from PATH.
void
octave_env::pathname_backup (std::string& path, int n) const
{
if (path.empty ())
return;
size_t i = path.length () - 1;
while (n--)
{
while (file_ops::is_dir_sep (path[i]) && i > 0)
i--;
while (! file_ops::is_dir_sep (path[i]) && i > 0)
i--;
i++;
}
path.resize (i);
}
void
octave_env::error (int err_num) const
{
(*current_liboctave_error_handler) ("%s", strerror (err_num));
}
void
octave_env::error (const std::string& s) const
{
(*current_liboctave_error_handler) ("%s", s.c_str ());
}
/*
;;; Local Variables: ***
;;; mode: C++ ***
;;; End: ***
*/
syntax highlighted by Code2HTML, v. 0.9.1