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