GNU Octave  4.0.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
oct-env.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 1996-2015 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 3 of the License, or (at your
10 option) any 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, see
19 <http://www.gnu.org/licenses/>.
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 <cctype>
44 #include <cstdlib>
45 #include <cstring>
46 
47 #include <string>
48 
49 #include <sys/types.h>
50 #include <unistd.h>
51 
52 #include "progname.h"
53 
54 #include "file-ops.h"
55 #include "lo-error.h"
56 #include "lo-sysdep.h"
57 #include "lo-utils.h"
58 #include "oct-env.h"
59 #include "oct-passwd.h"
60 #include "oct-syscalls.h"
61 #include "singleton-cleanup.h"
62 
64  : follow_symbolic_links (true), verbatim_pwd (true),
65  current_directory (), prog_name (), prog_invocation_name (),
66  user_name (), host_name ()
67 {
68  // Get a real value for the current directory.
69  do_getcwd ();
70 
71  // Etc.
73 
75 }
76 
78 
79 bool
81 {
82  bool retval = true;
83 
84  if (! instance)
85  {
86  instance = new octave_env ();
87 
88  if (instance)
90  }
91 
92  if (! instance)
93  {
94  (*current_liboctave_error_handler)
95  ("unable to create current working directory object!");
96 
97  retval = false;
98  }
99 
100  return retval;
101 }
102 
103 std::string
104 octave_env::polite_directory_format (const std::string& name)
105 {
106  return (instance_ok ())
107  ? instance->do_polite_directory_format (name) : std::string ();
108 }
109 
110 bool
111 octave_env::absolute_pathname (const std::string& s)
112 {
113  return (instance_ok ())
114  ? instance->do_absolute_pathname (s) : false;
115 }
116 
117 bool
119 {
120  return (instance_ok ())
121  ? instance->do_rooted_relative_pathname (s) : false;
122 }
123 
124 std::string
125 octave_env::base_pathname (const std::string& s)
126 {
127  return (instance_ok ())
128  ? instance->do_base_pathname (s) : std::string ();
129 }
130 
131 std::string
132 octave_env::make_absolute (const std::string& s, const std::string& dot_path)
133 {
134  return (instance_ok ())
135  ? instance->do_make_absolute (s, dot_path) : std::string ();
136 }
137 
138 std::string
140 {
141  return (instance_ok ())
142  ? instance->do_getcwd () : std::string ();
143 }
144 
145 std::string
147 {
148  return (instance_ok ())
149  ? instance->do_get_home_directory () : std::string ();
150 }
151 
152 std::string
154 {
155  return (instance_ok ())
156  ? instance->do_get_temp_directory () : std::string ();
157 }
158 
159 std::string
161 {
162  return (instance_ok ())
163  ? instance->prog_name : std::string ();
164 }
165 
166 std::string
168 {
169  return (instance_ok ())
170  ? instance->prog_invocation_name : std::string ();
171 }
172 
173 void
174 octave_env::set_program_name (const std::string& s)
175 {
176  if (instance_ok ())
178 }
179 
180 std::string
182 {
183  return (instance_ok ())
184  ? instance->do_get_user_name () : std::string ();
185 }
186 
187 std::string
189 {
190  return (instance_ok ())
191  ? instance->do_get_host_name () : std::string ();
192 }
193 
194 std::string
196 {
197  std::string tempd;
198 
199 #if defined (__MINGW32__) || defined (_MSC_VER)
200 
201  tempd = do_getenv ("TEMP");
202 
203  if (tempd.empty ())
204  tempd = do_getenv ("TMP");
205 
206  #if defined (P_tmpdir)
207  if (tempd.empty ())
208  tempd = P_tmpdir;
209  #endif
210 
211  // Some versions of MinGW and MSVC either don't define P_tmpdir, or
212  // define it to a single backslash. In such cases just use C:\temp.
213  if (tempd.empty () || tempd == "\\")
214  tempd = "c:\\temp";
215 
216 #else // Unix-like OS
217 
218  tempd = do_getenv ("TMP");
219 
220  #if defined (P_tmpdir)
221  if (tempd.empty ())
222  tempd = P_tmpdir;
223  #else
224  if (tempd.empty ())
225  tempd = "/tmp";
226  #endif
227 
228 #endif
229 
230  return tempd;
231 }
232 
233 // FIXME: this leaves no way to distinguish between a
234 // variable that is not set and one that is set to the empty string.
235 // Is this a problem?
236 
237 std::string
238 octave_env::getenv (const std::string& name)
239 {
240  return (instance_ok ())
241  ? instance->do_getenv (name) : std::string ();
242 }
243 
244 void
245 octave_env::putenv (const std::string& name, const std::string& value)
246 {
247  octave_putenv (name, value);
248 }
249 
250 bool
252 {
253  std::string display = getenv ("DISPLAY");
254 
255  return ! display.empty ();
256 }
257 
258 bool
259 octave_env::chdir (const std::string& newdir)
260 {
261  return (instance_ok ())
262  ? instance->do_chdir (newdir) : false;
263 }
264 
265 void
266 octave_env::do_set_program_name (const std::string& s) const
267 {
268  // For gnulib.
269  ::set_program_name (s.c_str ());
270 
271  // Let gnulib strip off things like the "lt-" prefix from libtool.
272  prog_invocation_name = program_name;
273 
274  size_t pos
275  = prog_invocation_name.find_last_of (file_ops::dir_sep_chars ());
276 
277  // Also keep a shortened version of the program name.
278  prog_name = (pos == std::string::npos)
279  ? prog_invocation_name : prog_invocation_name.substr (pos+1);
280 }
281 
282 // Return a pretty pathname. If the first part of the pathname is the
283 // same as $HOME, then replace that with '~'.
284 
285 std::string
286 octave_env::do_polite_directory_format (const std::string& name) const
287 {
288  std::string retval;
289 
290  std::string home_dir = do_get_home_directory ();
291 
292  size_t len = home_dir.length ();
293 
294  if (len > 1 && home_dir == name.substr (0, len)
295  && (name.length () == len || file_ops::is_dir_sep (name[len])))
296  {
297  retval = "~";
298  retval.append (name.substr (len));
299  }
300  else
301  retval = name;
302 
303  return retval;
304 }
305 
306 bool
307 octave_env::do_absolute_pathname (const std::string& s) const
308 {
309  size_t len = s.length ();
310 
311  if (len == 0)
312  return false;
313 
314  if (file_ops::is_dir_sep (s[0]))
315  return true;
316 
317 #if defined (OCTAVE_HAVE_WINDOWS_FILESYSTEM)
318  if ((len == 2 && isalpha (s[0]) && s[1] == ':')
319  || (len > 2 && isalpha (s[0]) && s[1] == ':'
320  && file_ops::is_dir_sep (s[2])))
321  return true;
322 #endif
323 
324  return false;
325 }
326 
327 bool
328 octave_env::do_rooted_relative_pathname (const std::string& s) const
329 {
330  size_t len = s.length ();
331 
332  if (len == 0)
333  return false;
334 
335  if (len == 1 && s[0] == '.')
336  return true;
337 
338  if (len > 1 && s[0] == '.' && file_ops::is_dir_sep (s[1]))
339  return true;
340 
341  if (len == 2 && s[0] == '.' && s[1] == '.')
342  return true;
343 
344  if (len > 2 && s[0] == '.' && s[1] == '.' && file_ops::is_dir_sep (s[2]))
345  return true;
346 
347  return false;
348 }
349 
350 // Return the 'basename' of the pathname in STRING (the stuff after
351 // the last directory separator). If STRING is not a full pathname,
352 // simply return it.
353 
354 std::string
355 octave_env::do_base_pathname (const std::string& s) const
356 {
358  return s;
359 
360  size_t pos = s.find_last_of (file_ops::dir_sep_chars ());
361 
362  if (pos == std::string::npos)
363  return s;
364  else
365  return s.substr (pos+1);
366 }
367 
368 // Turn STRING (a pathname) into an absolute pathname, assuming that
369 // DOT_PATH contains the symbolic location of the current directory.
370 
371 std::string
372 octave_env::do_make_absolute (const std::string& s,
373  const std::string& dot_path) const
374 {
375  if (dot_path.empty () || s.empty () || do_absolute_pathname (s))
376  return s;
377 
378  std::string current_dir = dot_path;
379 
380  if (current_dir.empty ())
381  current_dir = do_getcwd ();
382 
383  size_t pos = current_dir.length () - 1;
384 
385  if (! file_ops::is_dir_sep (current_dir[pos]))
386  current_dir.append (file_ops::dir_sep_str ());
387 
388  // FIXME: this is probably not correct for all systems.
389 
390  size_t i = 0;
391  size_t slen = s.length ();
392 
393  while (i < slen)
394  {
395  if (s[i] == '.')
396  {
397  if (i + 1 == slen)
398  return current_dir;
399 
400  if (file_ops::is_dir_sep (s[i+1]))
401  {
402  i += 2;
403  continue;
404  }
405 
406  if (s[i+1] == '.'
407  && (i + 2 == slen || file_ops::is_dir_sep (s[i+2])))
408  {
409  i += 2;
410 
411  if (i != slen)
412  i++;
413 
414  pathname_backup (current_dir, 1);
415 
416  continue;
417  }
418  }
419 
420  size_t tmp = s.find_first_of (file_ops::dir_sep_chars (), i);
421 
422  if (tmp == std::string::npos)
423  {
424  current_dir.append (s, i, tmp-i);
425  break;
426  }
427  else
428  {
429  current_dir.append (s, i, tmp-i+1);
430  i = tmp + 1;
431  }
432  }
433 
434  return current_dir;
435 }
436 
437 // Return a string which is the current working directory.
438 
439 std::string
441 {
442  if (! follow_symbolic_links)
443  current_directory = "";
444 
445  if (verbatim_pwd || current_directory.empty ())
447 
448  return current_directory;
449 }
450 
451 // This value is not cached because it can change while Octave is
452 // running.
453 
454 std::string
456 {
457  std::string hd = do_getenv ("HOME");
458 
459 #if defined (__MINGW32__) || defined (_MSC_VER)
460  // Maybe we are started directly from cmd.exe.
461  if (hd.empty ())
462  {
463  std::string drv = do_getenv ("HOMEDRIVE");
464  if (drv.empty ())
465  hd = do_getenv ("HOMEPATH");
466  else
467  hd = drv + do_getenv ("HOMEPATH");
468  }
469 #endif
470 
471  if (hd.empty ())
472  {
474 
475  hd = pw ? pw.dir () : std::string (file_ops::dir_sep_str ());
476  }
477 
478  return hd;
479 }
480 
481 std::string
483 {
484  if (user_name.empty ())
485  {
487 
488  user_name = pw ? pw.name () : std::string ("unknown");
489  }
490 
491  return user_name;
492 }
493 
494 std::string
496 {
497  if (host_name.empty ())
498  {
499  char hostname[1024];
500 
501  int status = gnulib::gethostname (hostname, 1023);
502 
503  host_name = (status < 0) ? "unknown" : hostname;
504  }
505 
506  return host_name;
507 }
508 
509 std::string
510 octave_env::do_getenv (const std::string& name) const
511 {
512  char *value = ::getenv (name.c_str ());
513 
514  return value ? value : "";
515 }
516 
517 // Do the work of changing to the directory NEWDIR. Handle symbolic
518 // link following, etc.
519 
520 bool
521 octave_env::do_chdir (const std::string& newdir)
522 {
523  bool retval = false;
524 
525  std::string tmp;
526 
528  {
529  if (current_directory.empty ())
530  do_getcwd ();
531 
532  if (current_directory.empty ())
533  tmp = newdir;
534  else
535  tmp = do_make_absolute (newdir, current_directory);
536 
537  // Get rid of trailing directory separator.
538 
539  size_t len = tmp.length ();
540 
541  if (len > 1)
542  {
543  if (file_ops::is_dir_sep (tmp[--len]))
544  tmp.resize (len);
545  }
546 
547  if (! ::octave_chdir (tmp))
548  {
549  current_directory = tmp;
550  retval = true;
551  }
552  }
553  else
554  retval = (! ::octave_chdir (newdir));
555 
556  return retval;
557 }
558 
559 // Remove the last N directories from PATH.
560 
561 void
562 octave_env::pathname_backup (std::string& path, int n) const
563 {
564  if (path.empty ())
565  return;
566 
567  size_t i = path.length () - 1;
568 
569  while (n--)
570  {
571  while (file_ops::is_dir_sep (path[i]) && i > 0)
572  i--;
573 
574  while (! file_ops::is_dir_sep (path[i]) && i > 0)
575  i--;
576 
577  i++;
578  }
579 
580  path.resize (i);
581 }
582 
583 void
584 octave_env::error (int err_num) const
585 {
586  (*current_liboctave_error_handler) ("%s", gnulib::strerror (err_num));
587 }
588 
589 void
590 octave_env::error (const std::string& s) const
591 {
592  (*current_liboctave_error_handler) ("%s", s.c_str ());
593 }
static uid_t getuid(void)
bool verbatim_pwd
Definition: oct-env.h:131
void octave_putenv(const std::string &name, const std::string &value)
Definition: lo-utils.cc:96
static std::string get_program_name(void)
Definition: oct-env.cc:160
bool do_chdir(const std::string &newdir)
Definition: oct-env.cc:521
static void putenv(const std::string &name, const std::string &value)
Definition: oct-env.cc:245
void do_set_program_name(const std::string &s) const
Definition: oct-env.cc:266
bool do_rooted_relative_pathname(const std::string &s) const
Definition: oct-env.cc:328
int octave_chdir(const std::string &path_arg)
Definition: lo-sysdep.cc:71
void error(int) const
Definition: oct-env.cc:584
static bool instance_ok(void)
Definition: oct-env.cc:80
static void cleanup_instance(void)
Definition: oct-env.h:123
std::string prog_invocation_name
Definition: oct-env.h:139
bool do_absolute_pathname(const std::string &s) const
Definition: oct-env.cc:307
static void set_program_name(const std::string &s)
Definition: oct-env.cc:174
std::string do_base_pathname(const std::string &s) const
Definition: oct-env.cc:355
std::string dir(void) const
Definition: oct-passwd.cc:85
std::string prog_name
Definition: oct-env.h:137
std::string host_name
Definition: oct-env.h:143
static std::string get_program_invocation_name(void)
Definition: oct-env.cc:167
octave_env(void)
Definition: oct-env.cc:63
static std::string get_current_directory(void)
Definition: oct-env.cc:139
static bool chdir(const std::string &newdir)
Definition: oct-env.cc:259
static void add(fptr f)
static std::string make_absolute(const std::string &s, const std::string &dot_path=get_current_directory())
Definition: oct-env.cc:132
std::string do_get_temp_directory(void) const
Definition: oct-env.cc:195
static std::string getenv(const std::string &name)
Definition: oct-env.cc:238
static bool absolute_pathname(const std::string &s)
Definition: oct-env.cc:111
static bool rooted_relative_pathname(const std::string &s)
Definition: oct-env.cc:118
std::string do_getenv(const std::string &name) const
Definition: oct-env.cc:510
std::string do_polite_directory_format(const std::string &name) const
Definition: oct-env.cc:286
static std::string polite_directory_format(const std::string &name)
Definition: oct-env.cc:104
std::string user_name
Definition: oct-env.h:141
static std::string dir_sep_chars(void)
Definition: file-ops.h:68
static std::string base_pathname(const std::string &s)
Definition: oct-env.cc:125
std::string name(void) const
Definition: oct-passwd.cc:40
bool follow_symbolic_links
Definition: oct-env.h:127
void pathname_backup(std::string &path, int n) const
Definition: oct-env.cc:562
std::string do_get_home_directory(void) const
Definition: oct-env.cc:455
std::string do_getcwd(void) const
Definition: oct-env.cc:440
static std::string get_user_name(void)
Definition: oct-env.cc:181
static bool is_dir_sep(char c)
Definition: file-ops.h:73
std::string do_get_host_name(void) const
Definition: oct-env.cc:495
static octave_passwd getpwuid(uid_t uid)
Definition: oct-passwd.cc:122
static bool have_x11_display(void)
Definition: oct-env.cc:251
static std::string dir_sep_str(void)
Definition: file-ops.h:63
std::string do_get_user_name(void) const
Definition: oct-env.cc:482
std::string do_make_absolute(const std::string &s, const std::string &dot_path) const
Definition: oct-env.cc:372
std::string current_directory
Definition: oct-env.h:134
static std::string get_temp_directory(void)
Definition: oct-env.cc:153
std::string octave_getcwd(void)
Definition: lo-sysdep.cc:49
static std::string get_host_name(void)
Definition: oct-env.cc:188
static std::string get_home_directory(void)
Definition: oct-env.cc:146
static octave_env * instance
Definition: oct-env.h:120