00001
00002
00003
00004
00005
00006
00007 #include <stdio.h>
00008 #include <stdlib.h>
00009 #include <string.h>
00010 #include <errno.h>
00011
00012 #ifdef WIN32
00013 #include <direct.h>
00014 #define chdir _chdir
00015 #define rmdir _rmdir
00016
00017 #define getcwd _getcwd
00018 #define popen _popen
00019 #define pclose _pclose
00020 #define S_IFDIR _S_IFDIR
00021 #define USE_GETCWD 1
00022
00023 #include <sys/types.h>
00024 #include <sys/stat.h>
00025 #include <time.h>
00026 #include <io.h>
00027 #include <windows.h>
00028
00029 #define stat _stat
00030
00031 #else
00032 #include <unistd.h>
00033 #include <sys/types.h>
00034 #include <sys/stat.h>
00035 #include <time.h>
00036 #include <dirent.h>
00037 #endif
00038
00039 #ifdef __hpux__
00040 #define USE_GETCWD 1
00041 #endif
00042
00043 #ifdef __linux__
00044 #define USE_GETCWD 1
00045 #endif
00046
00047 #ifdef USE_GETCWD
00048 char* getwd (const char* name)
00049 {
00050 char dir[256];
00051 getcwd (dir, sizeof (dir));
00052 strcpy ((char*) name, dir);
00053 return ((char*) name);
00054 }
00055 #endif
00056
00057 #include "cmt_system.h"
00058 #include "cmt_error.h"
00059
00060
00061 cmt_string CmtSystem::pwd ()
00062 {
00063 char buffer[256] = "";
00064 char* ptr = 0;
00065 char* pwd_env = 0;
00066
00067 #ifdef USE_PWD
00068 pwd_env = ::getenv ("PWD");
00069 #endif
00070
00071 if (pwd_env != 0)
00072 {
00073 strcpy (buffer, pwd_env);
00074 }
00075 else
00076 {
00077 ptr = getcwd (buffer, sizeof (buffer));
00078 }
00079
00080 const char* t = &buffer[0];
00081 return ((cmt_string) t);
00082 }
00083
00084
00085 bool CmtSystem::cd (const cmt_string& dir)
00086 {
00087 static cmt_string new_dir;
00088
00089 if ((dir.size () == 2) && (dir[1] == ':'))
00090 {
00091 new_dir = dir;
00092 new_dir += file_separator ();
00093 if (chdir (new_dir.c_str ()) == 0)
00094 {
00095 #ifdef USE_PWD
00096 new_dir = "PWD=";
00097 new_dir += dir;
00098 new_dir += file_separator ();
00099 putenv (new_dir);
00100 #endif
00101
00102 return (true);
00103 }
00104 return (false);
00105 }
00106 else
00107 {
00108 if (chdir (dir.c_str ()) == 0)
00109 {
00110 #ifdef USE_PWD
00111 new_dir = "PWD=";
00112 new_dir += dir;
00113 putenv (new_dir);
00114 #endif
00115
00116 return (true);
00117 }
00118 return (false);
00119 }
00120 }
00121
00122
00123 void CmtSystem::basename (const cmt_string& file_name, cmt_string& result)
00124 {
00125 int pos = file_name.find_last_of ('/');
00126 if (pos == cmt_string::npos)
00127 {
00128 pos = file_name.find_last_of ('\\');
00129 }
00130
00131 if (pos == cmt_string::npos)
00132 {
00133 result = file_name;
00134 }
00135 else
00136 {
00137 file_name.substr (pos + 1, result);
00138 }
00139 }
00140
00141
00142 void CmtSystem::basename (const cmt_string& file_name,
00143 const cmt_string& ,
00144 cmt_string& result)
00145 {
00146 basename (file_name, result);
00147
00148 int pos;
00149
00150 pos = result.find_last_of ('.');
00151
00152 if (pos != cmt_string::npos)
00153 {
00154 result.erase (pos);
00155 }
00156 }
00157
00158
00159 void CmtSystem::dirname (const cmt_string& file_name, cmt_string& result)
00160 {
00161 int pos = file_name.find_last_of ('/');
00162 if (pos == cmt_string::npos)
00163 {
00164 pos = file_name.find_last_of ('\\');
00165 }
00166
00167 if (pos == cmt_string::npos)
00168 {
00169 result = "";
00170 }
00171 else
00172 {
00173 result = file_name;
00174 result.erase (pos);
00175 }
00176 }
00177
00178
00179 void CmtSystem::name (const cmt_string& file_name, cmt_string& result)
00180 {
00181 int pos;
00182
00183 result = file_name;
00184
00185
00186
00187 pos = result.find_last_of ('.');
00188
00189 if (pos != cmt_string::npos)
00190 {
00191 result.erase (pos);
00192 }
00193
00194
00195
00196 pos = result.find_last_of ('/');
00197 if (pos == cmt_string::npos)
00198 {
00199 pos = result.find_last_of ('\\');
00200 }
00201
00202 if (pos != cmt_string::npos)
00203 {
00204 result.erase (0, pos + 1);
00205 }
00206 }
00207
00208
00209 void CmtSystem::get_suffix (const cmt_string& file, cmt_string& result)
00210 {
00211 int pos = file.find_last_of ('.');
00212 int sep = file.find_last_of (file_separator ());
00213
00214 if ((pos == cmt_string::npos) || (pos < sep))
00215 {
00216 result = "";
00217 }
00218 else
00219 {
00220 file.substr (pos + 1, result);
00221 }
00222 }
00223
00224
00225 void CmtSystem::get_dot_suffix (const cmt_string& file, cmt_string& result)
00226 {
00227 int pos = file.find_last_of ('.');
00228 int sep = file.find_last_of (file_separator ());
00229
00230 if ((pos == cmt_string::npos) || (pos < sep))
00231 {
00232 result = "";
00233 }
00234 else
00235 {
00236 file.substr (pos, result);
00237 }
00238 }
00239
00240
00241 bool CmtSystem::has_prefix (const cmt_string& name)
00242 {
00243 if ((name.find ('/') == cmt_string::npos) &&
00244 (name.find ('\\') == cmt_string::npos))
00245 {
00246 return (false);
00247 }
00248
00249 return (true);
00250 }
00251
00252
00253 bool CmtSystem::absolute_path (const cmt_string& name)
00254 {
00255 if (name.size () == 0) return (false);
00256
00257 if ((name[0] == '/') ||
00258 (name[0] == '\\')) return (true);
00259
00260 if (name.size () >= 2)
00261 {
00262 if (name[1] == ':')
00263 {
00264 return (true);
00265 }
00266 }
00267 return (false);
00268 }
00269
00270
00271 bool CmtSystem::has_device (const cmt_string& name)
00272 {
00273 #ifdef WIN32
00274 if (name.size () == 0) return (false);
00275
00276 if (name.size () >= 2)
00277 {
00278 if (name[1] == ':')
00279 {
00280 return (true);
00281 }
00282 else if ((name[0] == '\\') && (name[1] == '\\'))
00283 {
00284 return (true);
00285 }
00286 }
00287 #endif
00288
00289 return (false);
00290 }
00291
00292
00293 cmt_string CmtSystem::current_branch ()
00294 {
00295 cmt_string result;
00296
00297 basename (pwd (), result);
00298
00299 return (result);
00300 }
00301
00302
00303 bool CmtSystem::test_directory (const cmt_string& name)
00304 {
00305 struct stat file_stat;
00306 int status;
00307
00308 status = stat (name.c_str (), &file_stat);
00309
00310
00311
00312 if (status == 0)
00313 {
00314 if ((file_stat.st_mode & S_IFDIR) == 0)
00315 {
00316 return (false);
00317 }
00318 else
00319 {
00320 return (true);
00321 }
00322 }
00323 else
00324 {
00325 return (false);
00326 }
00327 }
00328
00329
00330 bool CmtSystem::test_file (const cmt_string& name)
00331 {
00332 struct stat file_stat;
00333 int status;
00334
00335 status = stat (name.c_str (), &file_stat);
00336
00337 if (status == 0)
00338 {
00339 if ((file_stat.st_mode & S_IFDIR) == 0)
00340 {
00341 return (true);
00342 }
00343 else
00344 {
00345 return (false);
00346 }
00347 }
00348 else
00349 {
00350 return (false);
00351 }
00352 }
00353
00354
00355 bool CmtSystem::compare_files (const cmt_string& name1,
00356 const cmt_string& name2)
00357 {
00358 struct stat file_stat1;
00359 struct stat file_stat2;
00360 int status;
00361
00362 status = stat (name1.c_str (), &file_stat1);
00363
00364 if (status == 0)
00365 {
00366 if ((file_stat1.st_mode & S_IFDIR) != 0)
00367 {
00368 return (false);
00369 }
00370 }
00371 else
00372 {
00373 return (false);
00374 }
00375
00376 status = stat (name2.c_str (), &file_stat2);
00377
00378 if (status == 0)
00379 {
00380 if ((file_stat2.st_mode & S_IFDIR) != 0)
00381 {
00382 return (false);
00383 }
00384 }
00385 else
00386 {
00387 return (false);
00388 }
00389
00390 if (((int) file_stat1.st_size) != ((int) file_stat2.st_size))
00391 {
00392 return (false);
00393 }
00394
00395 static cmt_string s1;
00396 static cmt_string s2;
00397
00398 s1.read (name1);
00399 s2.read (name2);
00400
00401 return ((s1 == s2));
00402 }
00403
00404
00405
00406
00407
00408
00409
00410
00411 bool CmtSystem::compare_and_update_files (const cmt_string& name1,
00412 const cmt_string& name2)
00413 {
00414 struct stat file_stat1;
00415 struct stat file_stat2;
00416 static cmt_string s1;
00417 static cmt_string s2;
00418 int status;
00419
00420 status = stat (name1.c_str (), &file_stat1);
00421
00422 if (status == 0)
00423 {
00424 if ((file_stat1.st_mode & S_IFDIR) != 0)
00425 {
00426
00427 return (false);
00428 }
00429 }
00430 else
00431 {
00432
00433 return (false);
00434 }
00435
00436 s1.read (name1);
00437
00438 status = stat (name2.c_str (), &file_stat2);
00439
00440 if (status == 0)
00441 {
00442 if ((file_stat2.st_mode & S_IFDIR) != 0)
00443 {
00444
00445 return (false);
00446 }
00447
00448 if (((int) file_stat1.st_size) == ((int) file_stat2.st_size))
00449 {
00450 s2.read (name2);
00451 if (s1 == s2)
00452 {
00453 unlink (name1);
00454 return (true);
00455 }
00456 }
00457 }
00458
00459 FILE* f = fopen (name2, "wb");
00460 if (f != NULL)
00461 {
00462 s1.write (f);
00463 fclose (f);
00464
00465 unlink (name1);
00466
00467 return (true);
00468 }
00469 else
00470 {
00471
00472
00473
00474
00475 return (false);
00476 }
00477 }
00478
00479
00480 int CmtSystem::file_size (const cmt_string& name)
00481 {
00482 struct stat file_stat;
00483 int status;
00484
00485 status = stat (name.c_str (), &file_stat);
00486
00487 if (status == 0)
00488 {
00489 return ((int) file_stat.st_size);
00490 }
00491 else
00492 {
00493 return (0);
00494 }
00495 }
00496
00497
00498 char CmtSystem::file_separator ()
00499 {
00500 #ifdef WIN32
00501 return ('\\');
00502 #else
00503 return ('/');
00504 #endif
00505 }
00506
00511 void CmtSystem::reduce_file_separators (cmt_string& text)
00512 {
00513 if (file_separator () == '/')
00514 {
00515 text.replace_all ("\\", "/");
00516 while (text.find ("//") != cmt_string::npos)
00517 {
00518 text.replace_all ("//", "/");
00519 }
00520 }
00521 else
00522 {
00523 text.replace_all ("/", "\\");
00524 while (text.find ("\\\\") != cmt_string::npos)
00525 {
00526 text.replace_all ("\\\\", "\\");
00527 }
00528 }
00529 }
00530
00531
00532 char CmtSystem::path_separator ()
00533 {
00534 #ifdef WIN32
00535 return (';');
00536 #else
00537 return (':');
00538 #endif
00539 }
00540
00541
00542 char CmtSystem::command_separator ()
00543 {
00544 #ifdef WIN32
00545 return ('&');
00546 #else
00547 return (';');
00548 #endif
00549 }
00550
00551
00552 const cmt_string& CmtSystem::ev_open ()
00553 {
00554 #ifdef WIN32
00555 static const cmt_string s = "%";
00556 #else
00557 static const cmt_string s = "${";
00558 #endif
00559
00560 return (s);
00561 }
00562
00563
00564 const cmt_string& CmtSystem::ev_close ()
00565 {
00566 #ifdef WIN32
00567 static const cmt_string s = "%";
00568 #else
00569 static const cmt_string s = "}";
00570 #endif
00571
00572 return (s);
00573 }
00574
00575
00576 bool CmtSystem::create_symlink (const cmt_string& oldname,
00577 const cmt_string& newname)
00578 {
00579 ::unlink (newname.c_str ());
00580
00581 #ifdef WIN32
00582 int status = 1;
00583 #else
00584 int status = ::symlink (oldname.c_str (), newname.c_str ());
00585 #endif
00586
00587 if (status == 0) return (true);
00588 return (false);
00589 }
00590
00591
00592 bool CmtSystem::remove_file (const cmt_string& name)
00593 {
00594 if (::unlink (name) != 0)
00595 {
00596 cerr << "#CMT> Cannot remove file " << name << endl;
00597 return (false);
00598 }
00599
00600 return (true);
00601 }
00602
00603
00604 bool CmtSystem::remove_directory (const cmt_string& name)
00605 {
00606
00607
00608 cmt_string_vector files;
00609
00610 scan_dir (name, files);
00611
00612 for (int i = 0; i < files.size (); i++)
00613 {
00614 cmt_string& file = files[i];
00615
00616 if (test_directory (file))
00617 {
00618
00619 if (!remove_directory (file)) return (false);
00620 }
00621 else
00622 {
00623
00624 if (!remove_file (file)) return (false);
00625 }
00626 }
00627
00628 int status = ::rmdir (name);
00629 if (status != 0)
00630 {
00631 cerr << "#CMT> Cannot remove directory " << name << " errno=" << errno << endl;
00632 return (false);
00633 }
00634
00635 return (true);
00636 }
00637
00638
00639 bool CmtSystem::mkdir (const cmt_string& name)
00640 {
00641 static cmt_string_vector path_vector;
00642 int i;
00643 static cmt_string full_path;
00644 char double_fs[] = " ";
00645
00646 double_fs[0] = file_separator ();
00647 double_fs[1] = file_separator ();
00648
00649 full_path = name;
00650
00651 if (file_separator () == '/')
00652 {
00653 full_path.replace_all ("\\", file_separator ());
00654 }
00655 else
00656 {
00657 full_path.replace_all ("/", file_separator ());
00658 }
00659
00660 full_path.replace_all (double_fs, file_separator ());
00661
00662 split (full_path, file_separator (), path_vector);
00663
00664 full_path = "";
00665
00666 if (absolute_path (name))
00667 {
00668 if (!has_device (name))
00669 {
00670 full_path = file_separator ();
00671 }
00672 }
00673
00674 for (i = 0; i < path_vector.size (); i++)
00675 {
00676 const cmt_string& path = path_vector[i];
00677
00678 if (i > 0) full_path += file_separator ();
00679 full_path += path;
00680
00681 if (has_device (path)) continue;
00682
00683 if (!test_directory (full_path))
00684 {
00685 #ifdef WIN32
00686 if (::_mkdir (full_path.c_str ()) != 0)
00687 {
00688
00689 return (false);
00690 }
00691 #else
00692 if (::mkdir (full_path.c_str (), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) != 0)
00693 {
00694
00695 return (false);
00696 }
00697 #endif
00698 }
00699 }
00700
00701 return (true);
00702 }
00703
00704
00705 void CmtSystem::scan_dir (const cmt_string& dir_name,
00706 cmt_string_vector& list)
00707 {
00708 static cmt_string dir_prefix;
00709 static cmt_string name_prefix;
00710
00711 dir_prefix = dir_name;
00712 if (dir_name == "") dir_prefix = ".";
00713
00714 if (!test_directory (dir_prefix))
00715 {
00716 dirname (dir_prefix, dir_prefix);
00717 basename (dir_name, name_prefix);
00718 }
00719 else
00720 {
00721 }
00722
00723 bool need_filter = false;
00724
00725 int wild_card;
00726
00727 wild_card = name_prefix.find ('*');
00728 if (wild_card != cmt_string::npos)
00729 {
00730 name_prefix.erase (wild_card);
00731 }
00732
00733 if (name_prefix.size () > 0)
00734 {
00735 need_filter = true;
00736 }
00737
00738 list.clear ();
00739
00740 #ifdef WIN32
00741
00742 long dir;
00743 struct _finddata_t entry;
00744
00745 static cmt_string search;
00746
00747 search = dir_prefix;
00748 search += file_separator ();
00749 search += "*";
00750
00751 dir = _findfirst (search.c_str (), &entry);
00752 if (dir > 0)
00753 {
00754 for (;;)
00755 {
00756 if ((strcmp ((char*) entry.name, ".") != 0) &&
00757 (strcmp ((char*) entry.name, "..") != 0) &&
00758 (strncmp ((char*) entry.name, ".nfs", 4) != 0))
00759 {
00760 const char* name = entry.name;
00761
00762 if (!need_filter ||
00763 (strncmp (name, name_prefix.c_str (), name_prefix.size ()) == 0))
00764 {
00765 cmt_string& name_entry = list.add ();
00766
00767 name_entry = dir_prefix;
00768 name_entry += file_separator ();
00769 name_entry += name;
00770 }
00771 }
00772
00773 int status = _findnext (dir, &entry);
00774 if (status != 0)
00775 {
00776 break;
00777 }
00778 }
00779
00780 _findclose (dir);
00781 }
00782 #else
00783
00784
00785
00786 DIR* dir = opendir (dir_prefix.c_str ());
00787
00788 struct dirent* entry;
00789
00790 if (dir != 0)
00791 {
00792 while ((entry = readdir (dir)) != 0)
00793 {
00794
00795 if (!strcmp ((char*) entry->d_name, ".")) continue;
00796 if (!strcmp ((char*) entry->d_name, "..")) continue;
00797 if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
00798
00799 const char* name = entry->d_name;
00800
00801 if (need_filter &&
00802 (strncmp (name, name_prefix.c_str (), name_prefix.size ()) != 0)) continue;
00803
00804
00805
00806 cmt_string& name_entry = list.add ();
00807
00808 name_entry = dir_prefix;
00809 name_entry += file_separator ();
00810 name_entry += name;
00811 }
00812
00813 closedir (dir);
00814 }
00815 #endif
00816
00817 }
00818
00819
00820 void CmtSystem::scan_dir (const cmt_string& dir_name,
00821 const cmt_regexp& expression,
00822 cmt_string_vector& list)
00823 {
00824 static cmt_string dir_prefix;
00825
00826 dir_prefix = dir_name;
00827 if (dir_name == "") dir_prefix = ".";
00828
00829 if (!test_directory (dir_prefix))
00830 {
00831 dirname (dir_prefix, dir_prefix);
00832 }
00833
00834 list.clear ();
00835
00836 #ifdef WIN32
00837
00838 long dir;
00839 struct _finddata_t entry;
00840
00841 static cmt_string search;
00842
00843 search = dir_prefix;
00844 search += file_separator ();
00845 search += "*";
00846
00847 dir = _findfirst (search.c_str (), &entry);
00848 if (dir > 0)
00849 {
00850 for (;;)
00851 {
00852 if ((entry.name[0] != '.') &&
00853 (strcmp ((char*) entry.name, ".") != 0) &&
00854 (strcmp ((char*) entry.name, "..") != 0) &&
00855 (strncmp ((char*) entry.name, ".nfs", 4) != 0))
00856 {
00857 const char* name = entry.name;
00858
00859 if (expression.match (name))
00860 {
00861 cmt_string& name_entry = list.add ();
00862
00863 name_entry = dir_prefix;
00864 name_entry += file_separator ();
00865 name_entry += name;
00866 }
00867 }
00868
00869 int status = _findnext (dir, &entry);
00870 if (status != 0)
00871 {
00872 break;
00873 }
00874 }
00875 _findclose (dir);
00876 }
00877 #else
00878
00879
00880
00881 DIR* dir = opendir (dir_prefix.c_str ());
00882
00883 struct dirent* entry;
00884
00885 if (dir != 0)
00886 {
00887 while ((entry = readdir (dir)) != 0)
00888 {
00889
00890 if (!strcmp ((char*) entry->d_name, ".")) continue;
00891 if (!strcmp ((char*) entry->d_name, "..")) continue;
00892 if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
00893
00894 const char* name = entry->d_name;
00895
00896 if (!expression.match (name)) continue;
00897
00898 cmt_string& name_entry = list.add ();
00899
00900 name_entry = dir_prefix;
00901 name_entry += file_separator ();
00902 name_entry += name;
00903 }
00904
00905 closedir (dir);
00906 }
00907 #endif
00908
00909 }
00910
00911
00912 CmtSystem::cmt_string_vector& CmtSystem::scan_dir (const cmt_string& dir_name)
00913 {
00914 static cmt_string_vector result;
00915
00916 scan_dir (dir_name, result);
00917
00918 return (result);
00919 }
00920
00921
00922 const cmt_string& CmtSystem::get_cmt_root ()
00923 {
00924 static cmt_string root;
00925
00926 root = "";
00927
00928 const char* env = ::getenv ("CMTROOT");
00929 if (env != 0)
00930 {
00931 root = env;
00932
00933 dirname (root, root);
00934 dirname (root, root);
00935 root.replace_all ("\"", "");
00936 return (root);
00937 }
00938
00939 #ifdef WIN32
00940 LONG status;
00941 HKEY key = 0;
00942
00943 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
00944 0, KEY_READ, &key);
00945 if (status == ERROR_SUCCESS)
00946 {
00947 char temp[256];
00948 DWORD length = sizeof (temp) - 1;
00949 DWORD type;
00950
00951 status = RegQueryValueEx (key, "root", 0, &type, (LPBYTE) temp, &length);
00952 if (status == ERROR_SUCCESS)
00953 {
00954 root = temp;
00955 return (root);
00956 }
00957 }
00958 #endif
00959
00960 return (root);
00961 }
00962
00963
00964 void CmtSystem::get_cmt_version (cmt_string& version)
00965 {
00966 version = "";
00967
00968 const char* env = ::getenv ("CMTROOT");
00969 if (env != 0)
00970 {
00971 cmt_string s = env;
00972 basename (s, version);
00973 version.replace_all ("\"", "");
00974 }
00975 else
00976 {
00977 #ifdef WIN32
00978 LONG status;
00979 HKEY key = 0;
00980
00981 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
00982 0, KEY_READ, &key);
00983 if (status == ERROR_SUCCESS)
00984 {
00985 char temp[256];
00986 DWORD length = sizeof (temp) - 1;
00987 DWORD type;
00988
00989 status = RegQueryValueEx (key, "version", 0, &type,
00990 (LPBYTE) temp, &length);
00991 if (status == ERROR_SUCCESS)
00992 {
00993 version = temp;
00994 }
00995 }
00996 #endif
00997 }
00998 }
00999
01000
01001 cmt_string CmtSystem::get_cmt_config ()
01002 {
01003 const char* env = ::getenv ("CMTCONFIG");
01004 if (env != 0)
01005 {
01006 return (cmt_string (env));
01007 }
01008
01009 env = ::getenv ("CMTBIN");
01010 if (env != 0)
01011 {
01012 return (cmt_string (env));
01013 }
01014
01015 #ifdef WIN32
01016 LONG status;
01017 HKEY key = 0;
01018
01019 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
01020 0, KEY_READ, &key);
01021 if (status == ERROR_SUCCESS)
01022 {
01023 char temp[256];
01024 DWORD length = sizeof (temp) - 1;
01025 DWORD type;
01026
01027 status = RegQueryValueEx (key, "config", 0, &type,
01028 (LPBYTE) temp, &length);
01029 if (status == ERROR_SUCCESS)
01030 {
01031 cmt_string config (temp);
01032 return (config);
01033 }
01034 }
01035
01036 return ("VisualC");
01037 #endif
01038
01039 return ("");
01040
01041 }
01042
01043
01044 cmt_string CmtSystem::get_cmt_site ()
01045 {
01046 const char* env = ::getenv ("CMTSITE");
01047 if (env != 0)
01048 {
01049 return (cmt_string (env));
01050 }
01051
01052 #ifdef WIN32
01053 LONG status;
01054 HKEY key = 0;
01055
01056 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
01057 0, KEY_READ, &key);
01058 if (status == ERROR_SUCCESS)
01059 {
01060 char temp[256];
01061 DWORD length = sizeof (temp) - 1;
01062 DWORD type;
01063
01064 status = RegQueryValueEx (key, "site", 0, &type, (LPBYTE) temp, &length);
01065 if (status == ERROR_SUCCESS)
01066 {
01067 cmt_string site (temp);
01068 return (site);
01069 }
01070 }
01071 #endif
01072
01073 return ("");
01074 }
01075
01076
01077 void CmtSystem::get_uname (cmt_string& uname)
01078 {
01079 #ifdef WIN32
01080 uname = "WIN32";
01081 #else
01082
01083 uname = "";
01084
01085 FILE* file;
01086
01087 file = popen ("uname", "r");
01088
01089 if (file != 0)
01090 {
01091 char line[1024];
01092 char* ptr;
01093 char* nl;
01094
01095 line[0] = 0;
01096 ptr = fgets (line, sizeof (line), file);
01097 if (ptr != 0)
01098 {
01099 nl = strrchr (ptr, '\n');
01100 if (nl != 0) *nl = 0;
01101
01102 uname = ptr;
01103 }
01104 pclose (file);
01105 }
01106 #endif
01107 }
01108
01109
01110 void CmtSystem::get_hosttype (cmt_string& hosttype)
01111 {
01112 hosttype = "";
01113
01114 char* ptr;
01115
01116 ptr = ::getenv ("HOSTTYPE");
01117 if (ptr != 0)
01118 {
01119 hosttype = ptr;
01120 }
01121 }
01122
01123
01124 cmt_string CmtSystem::get_temporary_name ()
01125 {
01126 cmt_string name;
01127
01128 name = ::tmpnam (NULL);
01129
01130 return (name);
01131 }
01132
01133
01134 cmt_string CmtSystem::get_home_package ()
01135 {
01136 cmt_string name = "CMTHOME";
01137
01138 return (name);
01139 }
01140
01141
01142 bool CmtSystem::is_home_package (const cmt_string& name,
01143 const cmt_string& version)
01144 {
01145 if (name == "CMTHOME") return (true);
01146
01147 return (false);
01148 }
01149
01150
01151 cmt_string CmtSystem::get_user_context_package ()
01152 {
01153 cmt_string name = "CMTUSERCONTEXT";
01154
01155 return (name);
01156 }
01157
01158
01159 bool CmtSystem::is_user_context_package (const cmt_string& name,
01160 const cmt_string& version)
01161 {
01162 if (name == "CMTUSERCONTEXT") return (true);
01163
01164 return (false);
01165 }
01166
01167
01168 cmt_string CmtSystem::get_project_package ()
01169 {
01170 cmt_string name = "PROJECT";
01171
01172 return (name);
01173 }
01174
01175
01176 bool CmtSystem::is_project_package (const cmt_string& name,
01177 const cmt_string& version)
01178 {
01179 if (name == "PROJECT") return (true);
01180
01181 return (false);
01182 }
01183
01184
01185 bool CmtSystem::testenv (const cmt_string& name)
01186 {
01187 const char* env = ::getenv (name);
01188 if (env == 0) return (false);
01189 return (true);
01190 }
01191
01192
01193 cmt_string CmtSystem::getenv (const cmt_string& name)
01194 {
01195 cmt_string result;
01196
01197 const char* env = ::getenv (name);
01198 if (env != 0)
01199 {
01200 result = env;
01201 }
01202
01203 if (name == "CMTCONFIG")
01204 {
01205 return (get_cmt_config ());
01206 }
01207
01208
01209
01210
01211
01212
01213
01214
01215
01216
01217
01218
01219
01220 return (result);
01221 }
01222
01223
01224 bool CmtSystem::putenv (const cmt_string& name_value)
01225 {
01226 int status = ::putenv ((char*) name_value.c_str ());
01227
01228 if (status == 0) return (true);
01229 else return (false);
01230 }
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240 class CMTPathManager
01241 {
01242 public:
01243 static CMTPathManager& instance ();
01244 static void reset ();
01245 static void add_cmt_path (const cmt_string& path,
01246 const cmt_string& path_source,
01247 IProjectFactory& factory);
01248
01249 private:
01250 CMTPathManager () : m_project (0)
01251 {
01252 }
01253
01254 void do_reset ()
01255 {
01256 m_project = 0;
01257 }
01258
01259 void do_add_cmt_path (const cmt_string& path,
01260 const cmt_string& path_source,
01261 IProjectFactory& factory)
01262 {
01263 cmt_string npath = path;
01264
01265 if (npath == "") return;
01266
01267 #ifdef WIN32
01268 if (npath.size () == 2)
01269 {
01270 if (npath[1] == ':')
01271 {
01272 npath += CmtSystem::file_separator ();
01273 }
01274 }
01275 #endif
01276
01277 npath.replace_all ("\\", CmtSystem::file_separator ());
01278 npath.replace_all ("/", CmtSystem::file_separator ());
01279
01280 if (!CmtSystem::absolute_path (npath))
01281 {
01282 cmt_string h = CmtSystem::pwd ();
01283 h += CmtSystem::file_separator ();
01284 h += npath;
01285 npath = h;
01286 }
01287
01288 CmtSystem::compress_path (npath);
01289
01290
01291
01292 while (npath[npath.size ()-1] == CmtSystem::file_separator ())
01293 {
01294 npath.erase (npath.size ()-1);
01295 }
01296
01297
01298
01299 if (npath != "")
01300 {
01301 if (!CmtSystem::test_directory (npath))
01302 {
01303 CmtError::set (CmtError::path_not_found, npath);
01304 return;
01305 }
01306
01307 cmt_string project_name;
01308
01309 if ((path_source == "CMTUSERCONTEXT") ||
01310 (path_source == "CMTHOME"))
01311 {
01312 project_name = path_source;
01313 }
01314
01315 m_project = factory.create_project (project_name, npath, path_source, m_project);
01316 }
01317 }
01318
01319 Project* m_project;
01320 };
01321
01322 CMTPathManager& CMTPathManager::instance ()
01323 {
01324 static CMTPathManager me;
01325
01326 return (me);
01327 }
01328
01329 void CMTPathManager::reset ()
01330 {
01331 static CMTPathManager& me = instance ();
01332 me.do_reset ();
01333 }
01334
01335 void CMTPathManager::add_cmt_path (const cmt_string& path,
01336 const cmt_string& path_source,
01337 IProjectFactory& factory)
01338 {
01339 static CMTPathManager& me = instance ();
01340 me.do_add_cmt_path (path, path_source, factory);
01341 }
01342
01343
01344
01345
01346 static void add_cmt_paths_from_text (const cmt_string& text,
01347 const cmt_string& context,
01348 IProjectFactory& factory)
01349 {
01350 static CmtSystem::cmt_string_vector path_vector;
01351 int i;
01352
01353 CmtSystem::split (text, CmtSystem::path_separator (), path_vector);
01354
01355 for (i = 0; i < path_vector.size (); i++)
01356 {
01357 const cmt_string& path = path_vector[i];
01358
01359 CMTPathManager::add_cmt_path (path, context, factory);
01360 }
01361 }
01362
01363
01364 static void add_cmt_paths_from_file (const cmt_string& file_name, IProjectFactory& factory)
01365 {
01366 if (!CmtSystem::test_file (file_name)) return;
01367
01368 static cmt_string text;
01369
01370 text.read (file_name);
01371
01372 int pos = text.find ("CMTPATH");
01373 if (pos == cmt_string::npos) return;
01374 pos += strlen ("CMTPATH");
01375 pos = text.find (pos, "=");
01376 if (pos == cmt_string::npos) return;
01377 pos++;
01378
01379 text.erase (0, pos);
01380
01381 int nl = text.find (pos, "\n");
01382 if (nl != cmt_string::npos) text.erase (nl);
01383
01384 add_cmt_paths_from_text (text, file_name, factory);
01385 }
01386
01387
01388
01389
01390
01391
01392
01393
01394
01395
01396
01397
01398
01399
01400 void CmtSystem::get_cmt_paths (IProjectFactory& factory,
01401 const cmt_string& init_text,
01402 const cmt_string& cmt_user_context,
01403 const cmt_string& cmt_home)
01404 {
01405 CMTPathManager::reset ();
01406
01407 if (init_text != "")
01408 {
01409 add_cmt_paths_from_text (init_text, "initialization", factory);
01410 }
01411
01412 #ifdef WIN32
01413 LONG status;
01414 HKEY key = 0;
01415
01416 status = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\CMT\\path",
01417 0, KEY_READ, &key);
01418 if (status == ERROR_SUCCESS)
01419 {
01420 DWORD index = 0;
01421 char name[256];
01422 char temp[256];
01423
01424 for (;;)
01425 {
01426 DWORD name_length = sizeof (name) - 1;
01427 DWORD length = sizeof (temp) - 1;
01428 DWORD type;
01429 status = RegEnumValue (key, index,
01430 name, &name_length, 0, &type,
01431 (LPBYTE) temp, &length);
01432 if ((status == ERROR_SUCCESS) ||
01433 (status == 234))
01434 {
01435 const cmt_string path = temp;
01436 CMTPathManager::add_cmt_path (path, "HKEY_CURRENT_USER", factory);
01437 }
01438
01439 if (status == 259)
01440 {
01441 break;
01442 }
01443
01444 index++;
01445 }
01446 }
01447
01448 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT\\path",
01449 0, KEY_READ, &key);
01450 if (status == ERROR_SUCCESS)
01451 {
01452 DWORD index = 0;
01453 char name[256];
01454 char temp[256];
01455
01456 for (;;)
01457 {
01458 DWORD type;
01459 DWORD name_length = sizeof (name) - 1;
01460 DWORD length = sizeof (temp) - 1;
01461
01462
01463 status = RegEnumValue (key, index,
01464 name, &name_length, 0, &type,
01465 (LPBYTE) temp, &length);
01466 if (status != ERROR_NO_MORE_ITEMS)
01467 {
01468 const cmt_string path = temp;
01469 CMTPathManager::add_cmt_path (path, "HKEY_LOCAL_MACHINE", factory);
01470 }
01471 else
01472 {
01473 break;
01474 }
01475 index++;
01476 }
01477 }
01478
01479 #endif
01480
01481
01482
01483
01484
01485
01486
01487 cmt_string rc_name;
01488
01489 add_cmt_paths_from_file (".cmtrc", factory);
01490
01491 if (get_home_directory (rc_name))
01492 {
01493 rc_name += file_separator ();
01494 rc_name += ".cmtrc";
01495 add_cmt_paths_from_file (rc_name, factory);
01496 }
01497
01498 rc_name = get_cmt_root ();
01499 rc_name += file_separator ();
01500 rc_name += "CMT";
01501 rc_name += file_separator ();
01502 cmt_string version;
01503 get_cmt_version (version);
01504 rc_name += version;
01505 rc_name += file_separator ();
01506 rc_name += "mgr";
01507 rc_name += file_separator ();
01508 rc_name += ".cmtrc";
01509
01510 add_cmt_paths_from_file (rc_name, factory);
01511
01512 CMTPathManager::add_cmt_path (cmt_user_context, "CMTUSERCONTEXT", factory);
01513 CMTPathManager::add_cmt_path (cmt_home, "CMTHOME", factory);
01514 }
01515
01516
01517 int CmtSystem::execute (const cmt_string& command)
01518 {
01519
01520
01521 return (system (command.c_str ()));
01522 }
01523
01524
01525 int CmtSystem::execute (const cmt_string& command, cmt_string& output)
01526 {
01527 output = "";
01528
01529
01530
01531 FILE* f = popen (command.c_str (), "r");
01532
01533 if (f != 0)
01534 {
01535 char line[256];
01536 char* ptr;
01537
01538 while ((ptr = fgets (line, sizeof (line), f)) != NULL)
01539 {
01540 output += ptr;
01541 }
01542 pclose (f);
01543
01544 return (0);
01545 }
01546
01547 return (1);
01548 }
01549
01550
01551 bool CmtSystem::is_package_directory (const cmt_string& name)
01552 {
01553 cmt_string_vector dirs;
01554
01555 cmt_regexp exp ("^[a-zA-Z.][0-9]+([a-zA-Z.][0-9]+([a-zA-Z.][0-9]+)?)?");
01556
01557 scan_dir (name, exp, dirs);
01558
01559 cmt_string req;
01560
01561 req = name;
01562 req += file_separator ();
01563 req += "cmt";
01564 req += file_separator ();
01565 req += "requirements";
01566
01567 if (test_file (req)) return (true);
01568
01569 if (dirs.size () == 0)
01570 {
01571 return (false);
01572 }
01573
01574 for (int i = 0; i < dirs.size (); i++)
01575 {
01576 const cmt_string& d = dirs[i];
01577
01578 req = d;
01579 req += file_separator ();
01580 req += "mgr";
01581 req += file_separator ();
01582 req += "requirements";
01583
01584 if (test_file (req)) return (true);
01585
01586 req = d;
01587 req += file_separator ();
01588 req += "cmt";
01589 req += file_separator ();
01590 req += "requirements";
01591
01592 if (test_file (req)) return (true);
01593 }
01594
01595 return (false);
01596 }
01597
01598
01599 bool CmtSystem::is_version_directory (const cmt_string& name)
01600 {
01601 int v;
01602 int r;
01603 int p;
01604
01605 return (is_version_directory (name, v, r, p));
01606 }
01607
01608
01609 bool CmtSystem::is_version_directory (const cmt_string& name,
01610 int& v,
01611 int& r,
01612 int& p)
01613 {
01614 if ((name == "HEAD") || (name == "head"))
01615 {
01616 v = 0;
01617 r = 0;
01618 p = 0;
01619
01620 return (true);
01621 }
01622
01623 static const cmt_string numbers = "0123456789";
01624
01625 static const int id_version = 0;
01626 static const int id_release = 1;
01627 static const int id_patch = 2;
01628
01629 cmt_string buffer;
01630
01631 enum
01632 {
01633 starting,
01634 at_key,
01635 at_number
01636 } state;
01637
01638 int id;
01639 int pos;
01640 int value;
01641
01642 v = 0;
01643 r = 0;
01644 p = 0;
01645
01646
01647
01648
01649
01650
01651
01652
01653
01654
01655
01656
01657
01658
01659
01660
01661 state = starting;
01662 id = id_version;
01663
01664 for (pos = 0; pos < name.size (); pos++)
01665 {
01666 char c = name[pos];
01667
01668 if (c == '*')
01669 {
01670
01671 switch (state)
01672 {
01673 case starting:
01674
01675 v = -1;
01676 r = -1;
01677 p = -1;
01678 return (false);
01679 case at_key:
01680
01681 switch (id)
01682 {
01683 case id_version:
01684 v = -1;
01685 case id_release:
01686 r = -1;
01687 case id_patch:
01688 p = -1;
01689 break;
01690 }
01691 return (true);
01692 case at_number:
01693
01694
01695
01696
01697
01698
01699
01700
01701 sscanf (buffer.c_str (), "%d", &value);
01702 switch (id)
01703 {
01704 case id_version:
01705
01706
01707
01708
01709
01710
01711 v = -1;
01712 r = -1;
01713 p = -1;
01714 break;
01715 case id_release:
01716 r = value;
01717 p = -1;
01718 break;
01719 case id_patch:
01720 p = value;
01721 break;
01722 }
01723
01724 return (true);
01725 }
01726 }
01727 else if (numbers.find (c) == cmt_string::npos)
01728 {
01729
01730 switch (state)
01731 {
01732 case starting:
01733 state = at_key;
01734 break;
01735 case at_key:
01736
01737 break;
01738 case at_number:
01739 sscanf (buffer.c_str (), "%d", &value);
01740 switch (id)
01741 {
01742 case id_version:
01743 v = value;
01744 break;
01745 case id_release:
01746 r = value;
01747 break;
01748 case id_patch:
01749 p = value;
01750 break;
01751 }
01752 buffer = "";
01753 id++;
01754 state = at_key;
01755 break;
01756 }
01757 }
01758 else
01759 {
01760
01761 switch (state)
01762 {
01763 case starting:
01764
01765 return (false);
01766 case at_key:
01767
01768 buffer += c;
01769 state = at_number;
01770 break;
01771 case at_number:
01772
01773 buffer += c;
01774 break;
01775 }
01776 }
01777 }
01778
01779 switch (state)
01780 {
01781 case starting:
01782
01783 return (false);
01784 case at_key:
01785
01786 if (id == id_version) return (false);
01787 else return (true);
01788 case at_number:
01789 sscanf (buffer.c_str (), "%d", &value);
01790 switch (id)
01791 {
01792 case id_version:
01793 v = value;
01794 break;
01795 case id_release:
01796 r = value;
01797 break;
01798 case id_patch:
01799 p = value;
01800 break;
01801 }
01802 id++;
01803 state = at_key;
01804 return (true);
01805 }
01806
01807 return (false);
01808 }
01809
01810
01811
01812
01813
01814 void CmtSystem::split (const cmt_string& text,
01815 const cmt_string& separators,
01816 cmt_string_vector& strings)
01817 {
01818 static char* buffer = 0;
01819 static int allocated = 0;
01820
01821 bool finished = false;
01822
01823 strings.clear ();
01824
01825 if (text.size () == 0) return;
01826
01827
01828
01829
01830
01831
01832
01833
01834 if (buffer == 0)
01835 {
01836 allocated = text.size ();
01837 buffer = (char*) malloc (allocated + 1);
01838 }
01839 else
01840 {
01841 if (text.size () > allocated)
01842 {
01843 allocated = text.size ();
01844 buffer = (char*) realloc (buffer, allocated + 1);
01845 }
01846 }
01847
01848 strcpy (buffer, text.c_str ());
01849
01850
01851
01852
01853
01854
01855
01856
01857
01858
01859
01860
01861
01862 char* current_word = buffer;
01863
01864 while (*current_word != 0)
01865 {
01866 size_t prefix_length;
01867 size_t word_length;
01868
01869
01870
01871
01872
01873
01874
01875
01876
01877
01878
01879 prefix_length = strspn (current_word, separators.c_str ());
01880 if (prefix_length > 0)
01881 {
01882
01883
01884 current_word += prefix_length;
01885 }
01886
01887
01888
01889
01890
01891
01892
01893
01894 char* running_char = current_word;
01895
01896 word_length = 0;
01897
01898 for (;;)
01899 {
01900 size_t unquoted_length;
01901 size_t separator_offset;
01902
01903 for (int p = 0;;)
01904 {
01905 unquoted_length = strcspn (running_char + p, "\"\'") + p;
01906 if ((unquoted_length > 0) && (running_char[unquoted_length-1] == '\\'))
01907 {
01908 p = unquoted_length + 1;
01909 }
01910 else
01911 {
01912 break;
01913 }
01914 }
01915
01916 separator_offset = strcspn (running_char, separators.c_str ());
01917
01918 if (separator_offset <= unquoted_length)
01919 {
01920
01921 running_char += separator_offset;
01922 break;
01923 }
01924
01925
01926
01927 running_char += unquoted_length;
01928
01929 char quote = running_char[0];
01930
01931
01932 {
01933 char* p = running_char;
01934 while (p[1] != 0)
01935 {
01936 *p = p[1];
01937 p++;
01938 }
01939 *p = 0;
01940 }
01941
01942
01943 {
01944 char* p = strchr (running_char, quote);
01945 if (p == 0)
01946 {
01947
01948 running_char += strlen (running_char);
01949 finished = true;
01950 break;
01951 }
01952 else
01953 {
01954 running_char = p;
01955 }
01956 }
01957
01958
01959
01960
01961 {
01962 char* p = running_char;
01963 while (p[1] != 0)
01964 {
01965 *p = p[1];
01966 p++;
01967 }
01968 *p = 0;
01969 }
01970 }
01971
01972 word_length = running_char - current_word;
01973
01974 if (current_word[word_length] == 0)
01975 {
01976 finished = true;
01977 }
01978 else
01979 {
01980 current_word[word_length] = 0;
01981 }
01982
01983
01984
01985
01986
01987
01988
01989
01990
01991
01992
01993
01994
01995
01996
01997
01998
01999
02000
02001
02002
02003
02004
02005
02006
02007
02008
02009
02010
02011 {
02012 cmt_string& s = strings.add ();
02013 s = current_word;
02014 }
02015
02016 if (finished) break;
02017
02018
02019 current_word += word_length + 1;
02020 }
02021 }
02022
02023
02024 void CmtSystem::compress_path (const cmt_string& dir, cmt_string& new_dir)
02025 {
02026 new_dir = dir;
02027
02028 compress_path (new_dir);
02029 }
02030
02031
02032
02033
02034
02035
02036
02037
02038
02039
02040
02041 void CmtSystem::compress_path (cmt_string& dir)
02042 {
02043 #ifdef WIN32
02044 static const char pattern[] = "\\..";
02045 static const char fs[] = "\\\\";
02046 #else
02047 static const char pattern[] = "/..";
02048 static const char fs[] = "//";
02049 #endif
02050
02051 if (dir.size () == 0) return;
02052
02053
02054
02055
02056
02057 if (file_separator () == '/')
02058 {
02059 dir.replace_all ("\\", file_separator ());
02060 }
02061 else
02062 {
02063 dir.replace_all ("/", file_separator ());
02064 }
02065
02066
02067 dir.replace_all (fs, file_separator ());
02068
02069 for (;;)
02070 {
02071 int pos1;
02072 int pos2;
02073 int pos3;
02074
02075 pos1 = dir.find (pattern);
02076 if (pos1 == cmt_string::npos) break;
02077
02078
02079
02080
02081 cmt_string p = dir.substr (0, pos1);
02082
02083 cmt_string dn;
02084 basename (p, dn);
02085 if (dn == "..") break;
02086 if (dn == ".") break;
02087 if (dn == "") break;
02088
02089
02090
02091
02092 pos2 = p.find_last_of (file_separator ());
02093
02094 if (pos2 == cmt_string::npos)
02095 {
02096
02097
02098
02099
02100 pos3 = p.find ("$");
02101 if (pos3 == cmt_string::npos)
02102 {
02103 dir.erase (0, pos1 + 3);
02104 }
02105 else
02106 {
02107 break;
02108 }
02109 }
02110 else
02111 {
02112
02113
02114
02115
02116
02117
02118
02119
02120
02121
02122 pos3 = p.find (pos2, "$");
02123 if (pos3 == cmt_string::npos)
02124 {
02125 dir.erase (pos2, pos1 + 3 - pos2);
02126 }
02127 else
02128 {
02129 break;
02130 }
02131 }
02132 }
02133
02134
02135 }
02136
02137
02138 cmt_string CmtSystem::now ()
02139 {
02140 cmt_string result;
02141
02142 time_t ltime;
02143 time (<ime);
02144 result = ctime (<ime);
02145
02146 result.replace_all ("\n", "");
02147
02148 return (result);
02149 }
02150
02151
02152 cmt_string CmtSystem::user ()
02153 {
02154 #ifdef _WIN32
02155 cmt_string result = getenv ("USERNAME");
02156 #else
02157 cmt_string result = getenv ("USER");
02158 #endif
02159
02160 return (result);
02161 }
02162
02163
02164 void CmtSystem::get_cvsroot (cmt_string& cvsroot)
02165 {
02166 cvsroot = "";
02167
02168 const char* env = ::getenv ("CVSROOT");
02169 if (env != 0)
02170 {
02171 cvsroot = env;
02172 return;
02173 }
02174
02175 #ifdef WIN32
02176 LONG status;
02177 HKEY key = 0;
02178
02179 status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT",
02180 0, KEY_READ, &key);
02181 if (status == ERROR_SUCCESS)
02182 {
02183 char temp[256];
02184 DWORD length = sizeof (temp) - 1;
02185 DWORD type;
02186
02187 status = RegQueryValueEx (key, "CVSROOT", 0, &type,
02188 (LPBYTE) temp, &length);
02189 if (status == ERROR_SUCCESS)
02190 {
02191 cvsroot = temp;
02192 return;
02193 }
02194 }
02195 #endif
02196 }
02197
02198
02199 bool CmtSystem::get_home_directory (cmt_string& dir)
02200 {
02201 bool status = false;
02202
02203 #ifdef WIN32
02204 const char* homedrive = ::getenv ("HOMEDRIVE");
02205 const char* homepath = ::getenv ("HOMEPATH");
02206
02207 if ((homedrive != 0) && (homepath != 0))
02208 {
02209 dir = homedrive;
02210 dir += homepath;
02211 status = true;
02212 }
02213
02214 #else
02215 const char* home_env = ::getenv ("HOME");
02216 if (home_env != 0)
02217 {
02218 dir = home_env;
02219 status = true;
02220 }
02221 #endif
02222
02223 return (status);
02224 }
02225