source: CMT/v1r19/source/cmt_system.cxx @ 1

Last change on this file since 1 was 1, checked in by arnault, 19 years ago

Import all tags

File size: 46.6 KB
Line 
1//-----------------------------------------------------------
2// Copyright Christian Arnault LAL-Orsay CNRS
3// arnault@lal.in2p3.fr
4// See the complete license in cmt_license.txt "http://www.cecill.info".
5//-----------------------------------------------------------
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <string.h>
10#include <errno.h>
11
12#ifdef WIN32
13#include <direct.h>
14#define chdir _chdir
15#define rmdir _rmdir
16//#define mkdir _mkdir
17#define getcwd _getcwd
18#define popen _popen
19#define pclose _pclose
20#define S_IFDIR _S_IFDIR
21#define USE_GETCWD 1
22
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <time.h>
26#include <io.h>
27#include <windows.h>
28
29#define stat _stat
30
31#else
32#include <unistd.h>
33#include <sys/types.h>
34#include <sys/stat.h>
35#include <time.h>
36#include <dirent.h>
37#endif
38
39#ifdef __hpux__
40#define USE_GETCWD 1
41#endif
42
43#ifdef __linux__
44#define USE_GETCWD 1
45#endif
46
47#ifdef USE_GETCWD
48char* getwd (const char* name)
49{
50  char dir[256];
51  getcwd (dir, sizeof (dir));
52  strcpy ((char*) name, dir);
53  return ((char*) name);
54}
55#endif
56
57#include "cmt_system.h"
58#include "cmt_error.h"
59
60//--------------------------------------------------
61cmt_string CmtSystem::pwd ()
62{
63  char buffer[256] = "";
64  char* ptr = 0;
65  char* pwd_env = 0;
66
67#ifdef USE_PWD
68  pwd_env = ::getenv ("PWD"); 
69#endif
70
71  if (pwd_env != 0)
72    {
73      strcpy (buffer, pwd_env);
74    }
75  else
76    {
77      ptr = getcwd (buffer, sizeof (buffer));
78    }
79
80  const char* t = &buffer[0];
81  return ((cmt_string) t);
82}
83
84//--------------------------------------------------
85bool CmtSystem::cd (const cmt_string& dir)
86{
87  static cmt_string new_dir;
88
89  if ((dir.size () == 2) && (dir[1] == ':'))
90    {
91      new_dir = dir;
92      new_dir += file_separator ();
93      if (chdir (new_dir.c_str ()) == 0) 
94        {
95#ifdef USE_PWD
96          new_dir = "PWD=";
97          new_dir += dir;
98          new_dir += file_separator ();
99          putenv (new_dir);
100#endif
101
102          return (true);
103        }
104      return (false);
105    }
106  else
107    {
108      if (chdir (dir.c_str ()) == 0) 
109        {
110#ifdef USE_PWD
111          new_dir = "PWD=";
112          new_dir += dir;
113          putenv (new_dir);
114#endif
115
116          return (true);
117        }
118      return (false);
119    }
120}
121
122//--------------------------------------------------
123void CmtSystem::basename (const cmt_string& file_name, cmt_string& result)
124{
125  int pos = file_name.find_last_of ('/');
126  if (pos == cmt_string::npos)
127    {
128      pos = file_name.find_last_of ('\\');
129    }
130
131  if (pos == cmt_string::npos)
132    {
133      result = file_name;
134    }
135  else
136    {
137      file_name.substr (pos + 1, result);
138    }
139}
140
141//--------------------------------------------------
142void CmtSystem::basename (const cmt_string& file_name,
143                          const cmt_string& /*suffix*/,
144                          cmt_string& result)
145{
146  basename (file_name, result);
147
148  int pos;
149
150  pos = result.find_last_of ('.');
151
152  if (pos != cmt_string::npos)
153    {
154      result.erase (pos);
155    }
156}
157
158//--------------------------------------------------
159void CmtSystem::dirname (const cmt_string& file_name, cmt_string& result)
160{
161  int pos = file_name.find_last_of ('/');
162  if (pos == cmt_string::npos)
163    {
164      pos = file_name.find_last_of ('\\');
165    }
166
167  if (pos == cmt_string::npos)
168    {
169      result = "";
170    }
171  else
172    {
173      result = file_name;
174      result.erase (pos);
175    }
176}
177
178//--------------------------------------------------
179void CmtSystem::name (const cmt_string& file_name, cmt_string& result)
180{
181  int pos;
182
183  result = file_name;
184
185  // remove the suffix
186
187  pos = result.find_last_of ('.');
188
189  if (pos != cmt_string::npos)
190    {
191      result.erase (pos);
192    }
193
194  // remove the directory name
195
196  pos = result.find_last_of ('/');
197  if (pos == cmt_string::npos)
198    {
199      pos = result.find_last_of ('\\');
200    }
201
202  if (pos != cmt_string::npos)
203    {
204      result.erase (0, pos + 1);
205    }
206}
207
208//-------------------------------------------------
209void CmtSystem::get_suffix (const cmt_string& file, cmt_string& result)
210{
211  int pos = file.find_last_of ('.');
212  int sep = file.find_last_of (file_separator ());
213
214  if ((pos == cmt_string::npos) || (pos < sep))
215    {
216      result = "";
217    }
218  else
219    {
220      file.substr (pos + 1, result);
221    }
222}
223
224//-------------------------------------------------
225void CmtSystem::get_dot_suffix (const cmt_string& file, cmt_string& result)
226{
227  int pos = file.find_last_of ('.');
228  int sep = file.find_last_of (file_separator ());
229
230  if ((pos == cmt_string::npos) || (pos < sep))
231    {
232      result = "";
233    }
234  else
235    {
236      file.substr (pos, result);
237    }
238}
239
240//--------------------------------------------------
241bool CmtSystem::has_prefix (const cmt_string& name)
242{
243  if ((name.find ('/') == cmt_string::npos) &&
244      (name.find ('\\') == cmt_string::npos))
245    {
246      return (false);
247    }
248
249  return (true);
250}
251
252//--------------------------------------------------
253bool CmtSystem::absolute_path (const cmt_string& name)
254{
255  if (name.size () == 0) return (false);
256
257  if ((name[0] == '/') ||
258      (name[0] == '\\')) return (true);
259
260  if (name.size () >= 2)
261    {
262      if (name[1] == ':')
263        {
264          return (true);
265        }
266    }
267  return (false);
268}
269
270//--------------------------------------------------
271bool CmtSystem::has_device (const cmt_string& name)
272{
273#ifdef WIN32
274  if (name.size () == 0) return (false);
275
276  if (name.size () >= 2)
277    {
278      if (name[1] == ':')
279        {
280          return (true);
281        }
282      else if ((name[0] == '\\') && (name[1] == '\\'))
283        {
284          return (true);
285        }
286    }
287#endif
288
289  return (false);
290}
291
292//--------------------------------------------------
293cmt_string CmtSystem::current_branch ()
294{
295  cmt_string result;
296
297  basename (pwd (), result);
298
299  return (result);
300}
301
302//--------------------------------------------------
303bool CmtSystem::test_directory (const cmt_string& name)
304{
305  struct stat file_stat;
306  int status;
307
308  status = stat (name.c_str (), &file_stat);
309
310  //cerr << "status(stat) for " << name << " : " << status << " st_mode=" << file_stat.st_mode << endl;
311
312  if (status == 0)
313    {
314      if ((file_stat.st_mode & S_IFDIR) == 0)
315        {
316          return (false);
317        }
318      else
319        {
320          return (true);
321        }
322    }
323  else
324    {
325      return (false);
326    }
327}
328
329//--------------------------------------------------
330bool CmtSystem::test_file (const cmt_string& name)
331{
332  struct stat file_stat;
333  int status;
334
335  status = stat (name.c_str (), &file_stat);
336
337  if (status == 0)
338    {
339      if ((file_stat.st_mode & S_IFDIR) == 0)
340        {
341          return (true);
342        }
343      else
344        {
345          return (false);
346        }
347    }
348  else
349    {
350      return (false);
351    }
352}
353
354//--------------------------------------------------
355bool CmtSystem::compare_files (const cmt_string& name1,
356                               const cmt_string& name2)
357{
358  struct stat file_stat1;
359  struct stat file_stat2;
360  int status;
361
362  status = stat (name1.c_str (), &file_stat1);
363
364  if (status == 0)
365    {
366      if ((file_stat1.st_mode & S_IFDIR) != 0)
367        {
368          return (false);
369        }
370    }
371  else
372    {
373      return (false);
374    }
375
376  status = stat (name2.c_str (), &file_stat2);
377
378  if (status == 0)
379    {
380      if ((file_stat2.st_mode & S_IFDIR) != 0)
381        {
382          return (false);
383        }
384    }
385  else
386    {
387      return (false);
388    }
389
390  if (((int) file_stat1.st_size) != ((int) file_stat2.st_size))
391    {
392      return (false);
393    }
394
395  static cmt_string s1;
396  static cmt_string s2;
397
398  s1.read (name1);
399  s2.read (name2);
400
401  return ((s1 == s2));
402}
403
404//--------------------------------------------------
405//
406// Check if the file "name1" is identical to "name2"
407// if they are identical, "name1" will be simply deleted
408// otherwise "name1" will be copied to "name2" and deleted afterwards
409//
410//--------------------------------------------------
411bool CmtSystem::compare_and_update_files (const cmt_string& name1,
412                                          const cmt_string& name2)
413{
414  struct stat file_stat1;
415  struct stat file_stat2;
416  static cmt_string s1;
417  static cmt_string s2;
418  int status;
419
420  status = stat (name1.c_str (), &file_stat1);
421
422  if (status == 0)
423    {
424      if ((file_stat1.st_mode & S_IFDIR) != 0)
425        {
426          // name1 is a directory.
427          return (false);
428        }
429    }
430  else
431    {
432      // name1 does not exist
433      return (false);
434    }
435
436  s1.read (name1);
437
438  status = stat (name2.c_str (), &file_stat2);
439
440  if (status == 0)
441    {
442      if ((file_stat2.st_mode & S_IFDIR) != 0)
443        {
444          // name2 is a directory
445          return (false);
446        }
447
448      if (((int) file_stat1.st_size) == ((int) file_stat2.st_size))
449        {
450          s2.read (name2);
451          if (s1 == s2)
452            {
453              unlink (name1);
454              return (true);
455            }
456        }
457    }
458
459  FILE* f = fopen (name2, "wb");
460  if (f != NULL)
461    {
462      s1.write (f);
463      fclose (f);
464
465      unlink (name1);
466
467      return (true);
468    }
469  else
470    {
471      //
472      // keep the new file "name1" since it cannot be
473      // copied to "name2"
474      //
475      return (false);
476    }
477}
478
479//--------------------------------------------------
480int CmtSystem::file_size (const cmt_string& name)
481{
482  struct stat file_stat;
483  int status;
484
485  status = stat (name.c_str (), &file_stat);
486
487  if (status == 0)
488    {
489      return ((int) file_stat.st_size);
490    }
491  else
492    {
493      return (0);
494    }
495}
496
497//--------------------------------------------------
498char CmtSystem::file_separator ()
499{
500#ifdef WIN32
501  return ('\\');
502#else
503  return ('/');
504#endif
505}
506
507/**
508 *  Transform all / or \ characters in the text into the current file_separator
509 *  Reduce all multiple file_separator into single ones.
510 */
511void CmtSystem::reduce_file_separators (cmt_string& text)
512{
513  if (file_separator () == '/')
514    {
515      text.replace_all ("\\", "/");
516      while (text.find ("//") != cmt_string::npos)
517        {
518          text.replace_all ("//", "/");
519        }
520    }
521  else
522    {
523      text.replace_all ("/", "\\");
524      while (text.find ("\\\\") != cmt_string::npos)
525        {
526          text.replace_all ("\\\\", "\\");
527        }
528    }
529}
530
531//--------------------------------------------------
532char CmtSystem::path_separator ()
533{
534#ifdef WIN32
535  return (';');
536#else
537  return (':');
538#endif
539}
540
541//--------------------------------------------------
542char CmtSystem::command_separator ()
543{
544#ifdef WIN32
545  return ('&');
546#else
547  return (';');
548#endif
549}
550
551//--------------------------------------------------
552const cmt_string& CmtSystem::ev_open ()
553{
554#ifdef WIN32
555  static const cmt_string s = "%";
556#else
557  static const cmt_string s = "${";
558#endif
559
560  return (s);
561}
562
563//--------------------------------------------------
564const cmt_string& CmtSystem::ev_close ()
565{
566#ifdef WIN32
567  static const cmt_string s = "%";
568#else
569  static const cmt_string s = "}";
570#endif
571
572  return (s);
573}
574
575//-------------------------------------------------
576bool CmtSystem::create_symlink (const cmt_string& oldname,
577                                const cmt_string& newname)
578{
579  ::unlink (newname.c_str ());
580
581#ifdef WIN32
582  int status = 1;
583#else
584  int status = ::symlink (oldname.c_str (), newname.c_str ());
585#endif
586
587  if (status == 0) return (true);
588  return (false);
589}
590
591//-------------------------------------------------
592bool CmtSystem::remove_file (const cmt_string& name)
593{
594  if (::unlink (name) != 0)
595    {
596      cerr << "#CMT> Cannot remove file " << name << endl;
597      return (false);
598    }
599
600  return (true);
601}
602
603//-------------------------------------------------
604bool CmtSystem::remove_directory (const cmt_string& name)
605{
606  //cout << "Try to remove directory " << name << endl;
607
608  cmt_string_vector files;
609
610  scan_dir (name, files);
611
612  for (int i = 0; i < files.size (); i++)
613    {
614      cmt_string& file = files[i];
615
616      if (test_directory (file))
617        {
618          if (!remove_directory (file)) return (false);
619        }
620      else
621        {
622          if (!remove_file (file)) return (false);
623        }
624    }
625 
626  int status = ::rmdir (name);
627  if (status != 0)
628    {
629      cerr << "#CMT> Cannot remove directory " << name << " errno=" << errno << endl;
630      return (false);
631    }
632
633  return (true);
634}
635
636//-------------------------------------------------
637bool CmtSystem::mkdir (const cmt_string& name)
638{
639  static cmt_string_vector path_vector;
640  int i;
641  static cmt_string full_path;
642  char double_fs[] = "  ";
643
644  double_fs[0] = file_separator ();
645  double_fs[1] = file_separator ();
646
647  full_path = name;
648
649  if (file_separator () == '/')
650    {
651      full_path.replace_all ("\\", file_separator ());
652    }
653  else
654    {
655      full_path.replace_all ("/", file_separator ());
656    }
657
658  full_path.replace_all (double_fs, file_separator ());
659
660  split (full_path, file_separator (), path_vector);
661
662  full_path = "";
663
664  if (absolute_path (name))
665    {
666      if (!has_device (name))
667        {
668          full_path = file_separator ();
669        }
670    }
671
672  for (i = 0; i < path_vector.size (); i++)
673    {
674      const cmt_string& path = path_vector[i];
675
676      if (i > 0) full_path += file_separator ();
677      full_path += path;
678
679      if (has_device (path)) continue;
680
681      if (!test_directory (full_path))
682        {
683#ifdef WIN32
684          if (::_mkdir (full_path.c_str ()) != 0)
685            {
686                // cerr << "CMT> cannot create directory " << full_path << endl;
687              return (false);
688            }
689#else
690          if (::mkdir (full_path.c_str (), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH ) != 0)
691            {
692                // cerr << "CMT> cannot create directory " << full_path << endl;
693              return (false);
694            }
695#endif
696        }
697    }
698
699  return (true);
700}
701
702//----------------------------------------------------------
703void CmtSystem::scan_dir (const cmt_string& dir_name,
704                          cmt_string_vector& list)
705{
706  static cmt_string dir_prefix;
707  static cmt_string name_prefix;
708
709  dir_prefix = dir_name;
710  if (dir_name == "") dir_prefix = ".";
711
712  if (!test_directory (dir_prefix))
713    {
714      dirname (dir_prefix, dir_prefix);
715      basename (dir_name, name_prefix);
716    }
717  else
718    {
719    }
720
721  bool need_filter = false;
722
723  int wild_card;
724
725  wild_card = name_prefix.find ('*');
726  if (wild_card != cmt_string::npos)
727    {
728      name_prefix.erase (wild_card);
729    }
730
731  if (name_prefix.size () > 0)
732    {
733      need_filter = true;
734    }
735
736  list.clear ();
737
738#ifdef WIN32
739
740  long dir;
741  struct _finddata_t entry;
742
743  static cmt_string search;
744
745  search = dir_prefix;
746  search += file_separator ();
747  search += "*";
748
749  dir = _findfirst (search.c_str (), &entry);
750  if (dir > 0)
751    {
752      for (;;)
753        {
754          if ((strcmp ((char*) entry.name, ".") != 0) &&
755              (strcmp ((char*) entry.name, "..") != 0) &&
756              (strncmp ((char*) entry.name, ".nfs", 4) != 0))
757            {
758              const char* name = entry.name;
759
760              if (!need_filter ||
761                  (strncmp (name, name_prefix.c_str (), name_prefix.size ()) == 0))
762                {
763                  cmt_string& name_entry = list.add ();
764
765                  name_entry = dir_prefix;
766                  name_entry += file_separator ();
767                  name_entry += name;
768                }
769            }
770
771          int status = _findnext (dir, &entry);
772          if (status != 0)
773            {
774              break;
775            }
776        }
777
778      _findclose (dir);
779    }
780#else
781
782  //cout << "scan_dir> dir=" << dir_name << endl;
783
784  DIR* dir = opendir (dir_prefix.c_str ());
785
786  struct dirent* entry;
787
788  if (dir != 0)
789    {
790      while ((entry = readdir (dir)) != 0)
791        {
792          //if (entry->d_name[0] == '.') continue;
793          if (!strcmp ((char*) entry->d_name, ".")) continue;
794          if (!strcmp ((char*) entry->d_name, "..")) continue;
795          if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
796
797          const char* name = entry->d_name;
798
799          if (need_filter &&
800              (strncmp (name, name_prefix.c_str (), name_prefix.size ()) != 0)) continue;
801
802          //cout << "scan_dir> name=" << name << endl;
803
804          cmt_string& name_entry = list.add ();
805
806          name_entry = dir_prefix;
807          name_entry += file_separator ();
808          name_entry += name;
809        }
810
811      closedir (dir);
812    }
813#endif
814
815}
816
817//----------------------------------------------------------
818void CmtSystem::scan_dir (const cmt_string& dir_name,
819                          const cmt_regexp& expression,
820                          cmt_string_vector& list)
821{
822  static cmt_string dir_prefix;
823
824  dir_prefix = dir_name;
825  if (dir_name == "") dir_prefix = ".";
826
827  if (!test_directory (dir_prefix))
828    {
829      dirname (dir_prefix, dir_prefix);
830    }
831
832  list.clear ();
833
834#ifdef WIN32
835
836  long dir;
837  struct _finddata_t entry;
838
839  static cmt_string search;
840
841  search = dir_prefix;
842  search += file_separator ();
843  search += "*";
844
845  dir = _findfirst (search.c_str (), &entry);
846  if (dir > 0)
847    {
848      for (;;)
849        {
850          if ((entry.name[0] != '.') &&
851              (strcmp ((char*) entry.name, ".") != 0) &&
852              (strcmp ((char*) entry.name, "..") != 0) &&
853              (strncmp ((char*) entry.name, ".nfs", 4) != 0))
854            {
855              const char* name = entry.name;
856             
857              if (expression.match (name))
858                {
859                  cmt_string& name_entry = list.add ();
860
861                  name_entry = dir_prefix;
862                  name_entry += file_separator ();
863                  name_entry += name;
864                }
865            }
866
867          int status = _findnext (dir, &entry);
868          if (status != 0)
869            {
870              break;
871            }
872        }
873      _findclose (dir);
874    }
875#else
876
877  //cout << "scan_dir> dir=" << dir_name << endl;
878
879  DIR* dir = opendir (dir_prefix.c_str ());
880
881  struct dirent* entry;
882
883  if (dir != 0)
884    {
885      while ((entry = readdir (dir)) != 0)
886        {
887          //if (entry->d_name[0] == '.') continue;
888          if (!strcmp ((char*) entry->d_name, ".")) continue;
889          if (!strcmp ((char*) entry->d_name, "..")) continue;
890          if (!strncmp ((char*) entry->d_name, ".nfs", 4)) continue;
891
892          const char* name = entry->d_name;
893
894          if (!expression.match (name)) continue;
895
896          cmt_string& name_entry = list.add ();
897
898          name_entry = dir_prefix;
899          name_entry += file_separator ();
900          name_entry += name;
901        }
902
903      closedir (dir);
904    }
905#endif
906
907}
908
909//----------------------------------------------------------
910CmtSystem::cmt_string_vector& CmtSystem::scan_dir (const cmt_string& dir_name)
911{
912  static cmt_string_vector result;
913
914  scan_dir (dir_name, result);
915
916  return (result);
917}
918
919//----------------------------------------------------------
920const cmt_string& CmtSystem::get_cmt_root ()
921{
922  static cmt_string root;
923
924  root = "";
925
926  const char* env = ::getenv ("CMTROOT");
927  if (env != 0)
928    {
929      root = env;
930
931      dirname (root, root);
932      dirname (root, root);
933      root.replace_all ("\"", "");
934      return (root);
935    }
936
937#ifdef WIN32
938  LONG status;
939  HKEY key = 0;
940
941  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
942                         0, KEY_READ, &key);
943  if (status == ERROR_SUCCESS)
944    {
945      char temp[256];
946      DWORD length = sizeof (temp) - 1;
947      DWORD type;
948
949      status = RegQueryValueEx (key, "root", 0, &type, (LPBYTE) temp, &length);
950      if (status == ERROR_SUCCESS)
951        {
952          root = temp;
953          return (root);
954        }
955    }
956#endif
957
958  return (root);
959}
960
961//----------------------------------------------------------
962void CmtSystem::get_cmt_version (cmt_string& version)
963{
964  version = "";
965
966  const char* env = ::getenv ("CMTROOT");
967  if (env != 0)
968    {
969      cmt_string s = env;
970      basename (s, version);
971      version.replace_all ("\"", "");
972    }
973  else
974    {
975#ifdef WIN32
976      LONG status;
977      HKEY key = 0;
978
979      status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
980                             0, KEY_READ, &key);
981      if (status == ERROR_SUCCESS)
982        {
983          char temp[256];
984          DWORD length = sizeof (temp) - 1;
985          DWORD type;
986         
987          status = RegQueryValueEx (key, "version", 0, &type, 
988                                    (LPBYTE) temp, &length);
989          if (status == ERROR_SUCCESS)
990            {
991              version = temp;
992            }
993        }
994#endif
995    }
996}
997
998//----------------------------------------------------------
999cmt_string CmtSystem::get_cmt_config ()
1000{
1001  const char* env = ::getenv ("CMTCONFIG");
1002  if (env != 0)
1003    {
1004      return (cmt_string (env));
1005    }
1006
1007  env = ::getenv ("CMTBIN");
1008  if (env != 0)
1009    {
1010      return (cmt_string (env));
1011    }
1012
1013#ifdef WIN32
1014  LONG status;
1015  HKEY key = 0;
1016
1017  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
1018                         0, KEY_READ, &key);
1019  if (status == ERROR_SUCCESS)
1020    {
1021      char temp[256];
1022      DWORD length = sizeof (temp) - 1;
1023      DWORD type;
1024
1025      status = RegQueryValueEx (key, "config", 0, &type, 
1026                                (LPBYTE) temp, &length);
1027      if (status == ERROR_SUCCESS)
1028        {
1029          cmt_string config (temp);
1030          return (config);
1031        }
1032    }
1033
1034  return ("VisualC");
1035#endif
1036
1037  return ("");
1038
1039}
1040
1041//----------------------------------------------------------
1042cmt_string CmtSystem::get_cmt_site ()
1043{
1044  const char* env = ::getenv ("CMTSITE");
1045  if (env != 0)
1046    {
1047      return (cmt_string (env));
1048    }
1049
1050#ifdef WIN32
1051  LONG status;
1052  HKEY key = 0;
1053
1054  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
1055                         0, KEY_READ, &key);
1056  if (status == ERROR_SUCCESS)
1057    {
1058      char temp[256];
1059      DWORD length = sizeof (temp) - 1;
1060      DWORD type;
1061
1062      status = RegQueryValueEx (key, "site", 0, &type, (LPBYTE) temp, &length);
1063      if (status == ERROR_SUCCESS)
1064        {
1065          cmt_string site (temp);
1066          return (site);
1067        }
1068    }
1069#endif
1070
1071  return ("");
1072}
1073
1074//----------------------------------------------------------
1075void CmtSystem::get_uname (cmt_string& uname)
1076{
1077#ifdef WIN32
1078  uname = "WIN32";
1079#else
1080
1081  uname = "";
1082
1083  FILE* file;
1084
1085  file = popen ("uname", "r");
1086
1087  if (file != 0)
1088    {
1089      char line[1024];
1090      char* ptr;
1091      char* nl;
1092
1093      line[0] = 0;
1094      ptr = fgets (line, sizeof (line), file);
1095      if (ptr != 0)
1096        {
1097          nl = strrchr (ptr, '\n');
1098          if (nl != 0) *nl = 0;
1099
1100          uname = ptr;
1101        }
1102      pclose (file);
1103    }
1104#endif
1105}
1106
1107//----------------------------------------------------------
1108void CmtSystem::get_hosttype (cmt_string& hosttype)
1109{
1110  hosttype = "";
1111
1112  char* ptr;
1113
1114  ptr = ::getenv ("HOSTTYPE");
1115  if (ptr != 0)
1116    {
1117      hosttype = ptr;
1118    }
1119}
1120
1121//----------------------------------------------------------
1122cmt_string CmtSystem::get_temporary_name ()
1123{
1124  cmt_string name;
1125
1126  name = ::tmpnam (NULL);
1127
1128  return (name);
1129}
1130
1131//----------------------------------------------------------
1132cmt_string CmtSystem::get_home_package ()
1133{
1134  cmt_string name = "CMTHOME";
1135
1136  return (name);
1137}
1138
1139//----------------------------------------------------------
1140bool CmtSystem::is_home_package (const cmt_string& name,
1141                                 const cmt_string& version)
1142{
1143  if (name == "CMTHOME") return (true);
1144
1145  return (false);
1146}
1147
1148//----------------------------------------------------------
1149cmt_string CmtSystem::get_user_context_package ()
1150{
1151  cmt_string name = "CMTUSERCONTEXT";
1152
1153  return (name);
1154}
1155
1156//----------------------------------------------------------
1157bool CmtSystem::is_user_context_package (const cmt_string& name,
1158                                         const cmt_string& version)
1159{
1160  if (name == "CMTUSERCONTEXT") return (true);
1161
1162  return (false);
1163}
1164
1165//----------------------------------------------------------
1166cmt_string CmtSystem::get_project_package ()
1167{
1168  cmt_string name = "PROJECT";
1169
1170  return (name);
1171}
1172
1173//----------------------------------------------------------
1174bool CmtSystem::is_project_package (const cmt_string& name,
1175                                    const cmt_string& version)
1176{
1177  if (name == "PROJECT") return (true);
1178
1179  return (false);
1180}
1181
1182//----------------------------------------------------------
1183bool CmtSystem::testenv (const cmt_string& name)
1184{
1185  const char* env = ::getenv (name);
1186  if (env == 0) return (false);
1187  return (true);
1188}
1189
1190//----------------------------------------------------------
1191cmt_string CmtSystem::getenv (const cmt_string& name)
1192{
1193  cmt_string result;
1194
1195  const char* env = ::getenv (name);
1196  if (env != 0)
1197    {
1198      result = env;
1199    }
1200
1201  if (name == "CMTCONFIG")
1202  {
1203    return (get_cmt_config ());
1204  }
1205
1206  /*
1207  if (name == "CMTROOT")
1208  {
1209          return (get_cmt_root ());
1210  }
1211
1212  if (name == "CMTSITE")
1213  {
1214          return (get_cmt_site ());
1215  }
1216  */
1217
1218  return (result);
1219}
1220
1221//----------------------------------------------------------
1222bool CmtSystem::putenv (const cmt_string& name_value)
1223{
1224  int status = ::putenv ((char*) name_value.c_str ());
1225
1226  if (status == 0) return (true);
1227  else return (false);
1228}
1229
1230//----------------------------------------------------------
1231void CmtSystem::add_cmt_path (const cmt_string& path,
1232                              const cmt_string& path_source,
1233                              IProjectFactory& factory)
1234{
1235  cmt_string npath = path;
1236
1237  if (npath == "") return;
1238
1239#ifdef WIN32
1240  if (npath.size () == 2)
1241    {
1242      if (npath[1] == ':')
1243        {
1244          npath += file_separator ();
1245        }
1246    }
1247#endif
1248
1249  npath.replace_all ("\\", file_separator ());
1250  npath.replace_all ("/", file_separator ());
1251
1252  if (!absolute_path (npath))
1253    {
1254      cmt_string h = pwd ();
1255      h += file_separator ();
1256      h += npath;
1257      npath = h;
1258    }
1259
1260  compress_path (npath);
1261
1262  //cerr << "adding npath=" << npath << endl;
1263
1264  while (npath[npath.size ()-1] == file_separator ())
1265    {
1266      npath.erase (npath.size ()-1);
1267    }
1268
1269  //cerr << "adding npath=[" << npath << "]" << endl;
1270
1271  if (npath != "")
1272    {
1273      if (!test_directory (npath))
1274        {
1275          CmtError::set (CmtError::path_not_found, npath);
1276          return;
1277        }
1278
1279      factory.create_project (npath, path_source);
1280    }
1281}
1282
1283//----------------------------------------------------------
1284static void add_cmt_paths_from_text (const cmt_string& text,
1285                                     const cmt_string& context,
1286                                     IProjectFactory& factory)
1287{
1288  static CmtSystem::cmt_string_vector path_vector;
1289  int i;
1290
1291  CmtSystem::split (text, CmtSystem::path_separator (), path_vector);
1292
1293  for (i = 0; i < path_vector.size (); i++)
1294    {
1295      const cmt_string& path = path_vector[i];
1296
1297      CmtSystem::add_cmt_path (path, context, factory);
1298    }
1299}
1300
1301//----------------------------------------------------------
1302static void add_cmt_paths (const cmt_string& file_name, IProjectFactory& factory)
1303{
1304  if (!CmtSystem::test_file (file_name)) return;
1305
1306  static cmt_string text;
1307
1308  text.read (file_name);
1309
1310  int pos = text.find ("CMTPATH");
1311  if (pos == cmt_string::npos) return;
1312  pos += strlen ("CMTPATH");
1313  pos = text.find (pos, "=");
1314  if (pos == cmt_string::npos) return;
1315  pos++;
1316
1317  text.erase (0, pos);
1318
1319  int nl = text.find (pos, "\n");
1320  if (nl != cmt_string::npos) text.erase (nl);
1321
1322  add_cmt_paths_from_text (text, file_name, factory);
1323}
1324
1325//----------------------------------------------------------
1326void CmtSystem::get_cmt_paths (IProjectFactory& factory, const cmt_string& init_text)
1327{
1328  if (init_text != "")
1329    {
1330      add_cmt_paths_from_text (init_text, "initialization", factory);
1331    }
1332
1333#ifdef WIN32
1334  LONG status;
1335  HKEY key = 0;
1336
1337  status = RegOpenKeyEx (HKEY_CURRENT_USER, "Software\\CMT\\path",
1338                         0, KEY_READ, &key);
1339  if (status == ERROR_SUCCESS)
1340    {
1341      DWORD index = 0;
1342      char name[256];
1343      char temp[256];
1344
1345      for (;;)
1346        {
1347          DWORD name_length = sizeof (name) - 1;
1348          DWORD length = sizeof (temp) - 1;
1349          DWORD type;
1350          status = RegEnumValue (key, index,
1351                                 name, &name_length, 0, &type,
1352                                 (LPBYTE) temp, &length);
1353          if ((status == ERROR_SUCCESS) ||
1354              (status == 234))
1355            {
1356              const cmt_string path = temp;
1357              add_cmt_path (path, "HKEY_CURRENT_USER", factory);
1358            }
1359
1360          if (status == 259)
1361            {
1362              break;
1363            }
1364
1365          index++;
1366        }
1367    }
1368
1369  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT\\path",
1370                         0, KEY_READ, &key);
1371  if (status == ERROR_SUCCESS)
1372    {
1373      DWORD index = 0;
1374      char name[256];
1375      char temp[256];
1376
1377      for (;;)
1378        {
1379          DWORD type;
1380          DWORD name_length = sizeof (name) - 1;
1381          DWORD length = sizeof (temp) - 1;
1382
1383
1384          status = RegEnumValue (key, index,
1385                                 name, &name_length, 0, &type,
1386                                 (LPBYTE) temp, &length);
1387          if (status != ERROR_NO_MORE_ITEMS)
1388            {
1389              const cmt_string path = temp;
1390              add_cmt_path (path, "HKEY_LOCAL_MACHINE", factory);
1391            }
1392          else
1393            {
1394              break;
1395            }
1396          index++;
1397        }
1398    }
1399
1400#endif
1401
1402  //-----------------------------------------
1403  // look for .cmtrc files :
1404  //  first look in ./
1405  //  then in "~/"
1406  //  then in ${CMTROOT}/mgr
1407  //-----------------------------------------
1408  cmt_string rc_name;
1409
1410  const cmt_string env = CmtSystem::getenv ("CMTPATH");
1411
1412  if (env != "")
1413    {
1414      static cmt_string_vector path_vector;
1415      int i;
1416
1417      split (env, path_separator (), path_vector);
1418
1419      for (i = 0; i < path_vector.size (); i++)
1420        {
1421          const cmt_string& path = path_vector[i];
1422
1423          add_cmt_path (path, "${CMTPATH}", factory);
1424        }
1425    }
1426
1427  add_cmt_paths (".cmtrc", factory);
1428
1429  if (get_home_directory (rc_name))
1430    {
1431      rc_name += file_separator ();
1432      rc_name += ".cmtrc";
1433      add_cmt_paths (rc_name, factory);
1434    }
1435
1436  rc_name = get_cmt_root ();
1437  rc_name += file_separator ();
1438  rc_name += "CMT";
1439  rc_name += file_separator ();
1440  cmt_string version;
1441  get_cmt_version (version);
1442  rc_name += version;
1443  rc_name += file_separator ();
1444  rc_name += "mgr";
1445  rc_name += file_separator ();
1446  rc_name += ".cmtrc";
1447
1448  add_cmt_paths (rc_name, factory);
1449
1450  //add_cmt_path (get_cmt_root (), "default path", factory);
1451}
1452
1453//----------------------------------------------------------
1454int CmtSystem::execute (const cmt_string& command)
1455{
1456  //cout << "CmtSystem::execute1> [" << command << "]" << endl;
1457
1458  return (system (command.c_str ()));
1459}
1460
1461//----------------------------------------------------------
1462int CmtSystem::execute (const cmt_string& command, cmt_string& output)
1463{
1464  output = "";
1465
1466  //cout << "CmtSystem::execute2> [" << command << "]" << endl;
1467
1468  FILE* f = popen (command.c_str (), "r"); 
1469 
1470  if (f != 0) 
1471    { 
1472      char line[256]; 
1473      char* ptr;
1474
1475      while ((ptr = fgets (line, sizeof (line), f)) != NULL) 
1476        {
1477          output += ptr;
1478        } 
1479      pclose (f);
1480
1481      return (0);
1482    }
1483
1484  return (1);
1485}
1486
1487//----------------------------------------------------------
1488bool CmtSystem::is_package_directory (const cmt_string& name)
1489{
1490  cmt_string_vector dirs;
1491
1492  cmt_regexp exp ("^[a-zA-Z.][0-9]+([a-zA-Z.][0-9]+([a-zA-Z.][0-9]+)?)?");
1493
1494  scan_dir (name, exp, dirs);
1495
1496  cmt_string req;
1497
1498  req = name;
1499  req += file_separator ();
1500  req += "cmt";
1501  req += file_separator ();
1502  req += "requirements";
1503
1504  if (test_file (req)) return (true);
1505
1506  if (dirs.size () == 0) 
1507    {
1508      return (false);
1509    }
1510
1511  for (int i = 0; i < dirs.size (); i++)
1512      {
1513        const cmt_string& d = dirs[i];
1514
1515        req = d;
1516        req += file_separator ();
1517        req += "mgr";
1518        req += file_separator ();
1519        req += "requirements";
1520
1521        if (test_file (req)) return (true);
1522
1523      req = d;
1524      req += file_separator ();
1525      req += "cmt";
1526      req += file_separator ();
1527      req += "requirements";
1528     
1529      if (test_file (req)) return (true);
1530    }
1531
1532  return (false);
1533}
1534
1535//----------------------------------------------------------
1536bool CmtSystem::is_version_directory (const cmt_string& name)
1537{
1538  int v;
1539  int r;
1540  int p;
1541
1542  return (is_version_directory (name, v, r, p));
1543}
1544
1545//----------------------------------------------------------
1546bool CmtSystem::is_version_directory (const cmt_string& name,
1547                                      int& v,
1548                                      int& r,
1549                                      int& p)
1550{
1551  static const cmt_string numbers = "0123456789";
1552
1553  static const int id_version = 0;
1554  static const int id_release = 1;
1555  static const int id_patch   = 2;
1556
1557  cmt_string buffer;
1558
1559  enum 
1560  {
1561    starting,
1562    at_key,
1563    at_number
1564  } state;
1565
1566  int id;
1567  int pos;
1568  int value;
1569
1570  v = 0;
1571  r = 0;
1572  p = 0;
1573
1574  //
1575  // version : v-field
1576  //         | v-field r-field
1577  //         | v-field r-field p-field
1578  //
1579  // v-field : field
1580  // r-field : field
1581  // p-field : field
1582  //
1583  // field   : key '*'
1584  //         | key number
1585  //
1586  // key     : letters
1587  //
1588
1589  state = starting;
1590  id    = id_version;
1591
1592  for (pos = 0; pos < name.size (); pos++)
1593    {
1594      char c = name[pos];
1595
1596      if (c == '*')
1597        {
1598          // A wild card
1599          switch (state)
1600            {
1601            case starting:
1602              // cannot start with a wild card ??
1603              v = -1;
1604              r = -1;
1605              p = -1;
1606              return (false);
1607            case at_key:
1608              // the numeric field is valued with a wild card
1609              switch (id)
1610                {
1611                case id_version:
1612                  v = -1;
1613                case id_release:
1614                  r = -1;
1615                case id_patch:
1616                  p = -1;
1617                  break;
1618                }
1619              return (true);
1620            case at_number:
1621              // question:
1622              // a number followed by a wild-card is considered as:
1623              //   1) a wild card on the number itself (1* comp with 1, 10, 12, 120, etc)
1624              //   2) a wild card on the next fields (1* comp with 1r1, 1-12 etc)
1625              //
1626
1627              //  Here we select option 1)
1628
1629              sscanf (buffer.c_str (), "%d", &value);
1630              switch (id)
1631                {
1632                case id_version:
1633                  //
1634                  // lazy option 1 implies v = -1;
1635                  // strict option 1 would imply v = -value;
1636                  // option 2 implies v = value;
1637                  //
1638
1639                  v = -1;
1640                  r = -1;
1641                  p = -1;
1642                  break;
1643                case id_release:
1644                  r = value;
1645                  p = -1;
1646                  break;
1647                case id_patch:
1648                  p = value;
1649                  break;
1650                }
1651
1652              return (true);
1653            }
1654        }
1655      else if (numbers.find (c) == cmt_string::npos)
1656        {
1657          // A letter
1658          switch (state)
1659            {
1660            case starting:
1661              state = at_key;
1662              break;
1663            case at_key:
1664              // Multiple letter key (is it permitted??)
1665              break;
1666            case at_number:
1667              sscanf (buffer.c_str (), "%d", &value);
1668              switch (id)
1669                {
1670                case id_version:
1671                  v = value;
1672                  break;
1673                case id_release:
1674                  r = value;
1675                  break;
1676                case id_patch:
1677                  p = value;
1678                  break;
1679                }
1680              buffer = "";
1681              id++;
1682              state = at_key;
1683              break;
1684            }
1685        }
1686      else
1687        {
1688          // a number
1689          switch (state)
1690            {
1691            case starting:
1692              // not starting by a letter (syntax error)
1693              return (false);
1694            case at_key:
1695              // the numeric field for the current id is starting now
1696              buffer += c;
1697              state = at_number;
1698              break;
1699            case at_number:
1700              // continuing the current numeric field
1701              buffer += c;
1702              break;
1703            }
1704        }
1705    }
1706
1707  switch (state)
1708    {
1709    case starting:
1710      // Empty version string
1711      return (false);
1712    case at_key:
1713      // Syntax error (when only letters. Ending letters is not an error)
1714      if (id == id_version) return (false);
1715      else return (true);
1716    case at_number:
1717      sscanf (buffer.c_str (), "%d", &value);
1718      switch (id)
1719        {
1720        case id_version:
1721          v = value;
1722          break;
1723        case id_release:
1724          r = value;
1725          break;
1726        case id_patch:
1727          p = value;
1728          break;
1729        }
1730      id++;
1731      state = at_key;
1732      return (true);
1733    }
1734
1735  return (false);
1736}
1737
1738//----------------------------------------------------------
1739//  Split a line into words. Separators are spaces and tabs
1740//  Text enclosed in double quotes is one word.
1741//----------------------------------------------------------
1742void CmtSystem::split (const cmt_string& text,
1743                       const cmt_string& separators,
1744                       cmt_string_vector& strings)
1745{
1746  static char* buffer = 0;
1747  static int allocated = 0;
1748
1749  bool finished = false;
1750
1751  strings.clear ();
1752
1753  if (text.size () == 0) return;
1754
1755  /*
1756    We are going to work in a copy of the text, since
1757    \0 will be inserted right after each found word.
1758
1759    Then the vector of strings is iteratively filled by each found word.
1760  */
1761
1762  if (buffer == 0)
1763    {
1764      allocated = text.size ();
1765      buffer = (char*) malloc (allocated + 1);
1766    }
1767  else
1768    {
1769      if (text.size () > allocated)
1770        {
1771          allocated = text.size ();
1772          buffer = (char*) realloc (buffer, allocated + 1);
1773        }
1774    }
1775
1776  strcpy (buffer, text.c_str ());
1777
1778  /*
1779    Algorithm :
1780
1781    We look for words separated by <separators> which may be
1782    o spaces (' ' or '\t')
1783    o other characters such as ':'
1784
1785    A word is a character string not containing any separator. A substring in
1786    this word my be enclosed between quotes (" or ') which permits separator
1787    inclusion within words.
1788  */
1789
1790  char* current_word = buffer;
1791
1792  while (*current_word != 0)
1793    {
1794      size_t prefix_length;
1795      size_t word_length;
1796
1797      /*
1798        while ((*current_word == ' ') ||
1799        (*current_word == '\t'))
1800        {
1801        current_word++;
1802        }
1803      */
1804
1805      // first skip all starting separators.
1806
1807      prefix_length = strspn (current_word, separators.c_str ());
1808      if (prefix_length > 0)
1809        {
1810          // Move to the first non-separator character
1811
1812          current_word += prefix_length;
1813        }
1814
1815      /*
1816        Parse the next word.
1817
1818        It may contain enclosures in quote characters or not.
1819        Quotes must be identical on both sides of each enclosure.
1820      */
1821
1822      char* running_char = current_word;
1823
1824      word_length = 0;
1825
1826      for (;;)
1827        {
1828          size_t unquoted_length;
1829          size_t separator_offset;
1830
1831          for (int p = 0;;)
1832            {
1833              unquoted_length = strcspn (running_char + p, "\"\'") + p;
1834              if ((unquoted_length > 0) && (running_char[unquoted_length-1] == '\\'))
1835                {
1836                  p = unquoted_length + 1;
1837                }
1838              else
1839                {
1840                  break;
1841                }
1842            }
1843
1844          separator_offset = strcspn (running_char, separators.c_str ());
1845
1846          if (separator_offset <= unquoted_length)
1847            {
1848              // no quote in this word -> we are finished for this one.
1849              running_char += separator_offset;
1850              break;
1851            }
1852
1853          // We have found a quoted enclosure. Move to it.
1854
1855          running_char += unquoted_length;
1856
1857          char quote = running_char[0];
1858
1859          // Remove it.
1860          {
1861            char* p = running_char;
1862            while (p[1] != 0)
1863              {
1864                *p = p[1];
1865                p++;
1866              }
1867            *p = 0;
1868          }
1869
1870          // Look for the next occurence of this quote.
1871          {
1872            char* p = strchr (running_char, quote);
1873            if (p == 0)
1874              {
1875                // Unmatched quote : the rest of the line will be taken as a word...
1876                running_char += strlen (running_char);
1877                finished = true;
1878                break;
1879              }
1880            else
1881              {
1882                running_char = p;
1883              }
1884          }
1885
1886          // Now we remove the ending quote from the word
1887          // (by shifting all remaining characters by one place to the left)
1888
1889          {
1890            char* p = running_char;
1891            while (p[1] != 0)
1892              {
1893                *p = p[1];
1894                p++;
1895              }
1896            *p = 0;
1897          }
1898        }
1899
1900      word_length = running_char - current_word;
1901
1902      if (current_word[word_length] == 0)
1903        {
1904          finished = true;
1905        }
1906      else
1907        {
1908          current_word[word_length] = 0;
1909        }
1910
1911      /*
1912        if ((t[0] == '"') ||
1913        (t[0] == '\'') ||
1914        (t[0] == ':'))
1915        {
1916        char* quote;
1917
1918        t++;
1919        quote = strchr (t, sep);
1920        if (quote != 0) *quote = 0;
1921        else finished = true;
1922        }
1923        else
1924        {
1925        int offset;
1926
1927        offset = strcspn (t, " \t:");
1928        if ((offset < 0) || (t[offset] == 0)) finished = true;
1929        if (!finished)
1930        {
1931        space = t + offset;
1932        *space = 0;
1933        }
1934        }
1935      */
1936
1937      // Store the current word into the vector of strings
1938
1939      {
1940        cmt_string& s = strings.add ();
1941        s = current_word;
1942      }
1943
1944      if (finished) break;
1945
1946      // Move to the next possible word.
1947      current_word += word_length + 1;
1948    }
1949}
1950
1951//----------------------------------------------------------
1952void CmtSystem::compress_path (const cmt_string& dir, cmt_string& new_dir)
1953{
1954  new_dir = dir;
1955
1956  compress_path (new_dir);
1957}
1958
1959//----------------------------------------------------------
1960//
1961//  We try to detect the aaaa/xxxx/../bbbb patterns which should be
1962// equivalent to aaaa/bbbb
1963//  this therefore consists in removing all /xxxx/../ when
1964//     xxxx is different from ".."
1965//     xxxx is different from "."
1966//     xxxx does not contain any macro reference
1967//
1968//----------------------------------------------------------
1969void CmtSystem::compress_path (cmt_string& dir)
1970{
1971#ifdef WIN32
1972  static const char pattern[] = "\\..";
1973  static const char fs[] = "\\\\";
1974#else
1975  static const char pattern[] = "/..";
1976  static const char fs[] = "//";
1977#endif
1978
1979  if (dir.size () == 0) return;
1980
1981  //
1982  // We first synchronize to using file_separator() in any case.
1983  //
1984
1985  if (file_separator () == '/')
1986    {
1987      dir.replace_all ("\\", file_separator ());
1988    }
1989  else
1990    {
1991      dir.replace_all ("/", file_separator ());
1992    }
1993
1994  // Suppress all duplicated file separators
1995  dir.replace_all (fs, file_separator ());
1996
1997  for (;;)
1998    {
1999      int pos1;
2000      int pos2;
2001      int pos3;
2002
2003      pos1 = dir.find (pattern);
2004      if (pos1 == cmt_string::npos) break;
2005
2006        //
2007        // extract "aaaa/xxxx" from "aaaa/xxxx/../bbbb"
2008        //
2009      cmt_string p = dir.substr (0, pos1);
2010
2011      cmt_string dn;
2012      basename (p, dn);
2013      if (dn == "..") break;
2014      if (dn == ".") break;
2015      if (dn == "") break;
2016     
2017        //
2018        // Is "aaaa/xxxx" only made of "xxxx" ?
2019        //
2020      pos2 = p.find_last_of (file_separator ());
2021     
2022      if (pos2 == cmt_string::npos) 
2023        {
2024          // the pattern was xxxx/..
2025          //
2026          // so xxxx is [0:pos1-1]
2027          //
2028          pos3 = p.find ("$");
2029          if (pos3 == cmt_string::npos)
2030            {
2031              dir.erase (0, pos1 + 3);
2032            }
2033          else
2034            {
2035              break;
2036            }
2037        }
2038      else
2039        {
2040          //    01234567890123456
2041          //    aaaa/xxxx/../bbbb
2042          //        2    1   3
2043          //
2044          // erase the "/xxxx/.." pattern
2045          // result will be "aaaa/bbbb"
2046          //
2047          // Here xxxx is [pos2+1:pos1-1]
2048          //
2049
2050          pos3 = p.find (pos2, "$");
2051          if (pos3 == cmt_string::npos)
2052            {
2053              dir.erase (pos2, pos1 + 3 - pos2);
2054            }
2055          else
2056            {
2057              break;
2058            }
2059        }
2060    }
2061
2062    //if (dir[dir.size () - 1] == file_separator ()) dir.erase (dir.size () - 1);
2063}
2064
2065//----------------------------------------------------------
2066cmt_string CmtSystem::now ()
2067{
2068  cmt_string result;
2069
2070  time_t ltime;
2071  time (&ltime);
2072  result = ctime (&ltime);
2073
2074  result.replace_all ("\n", "");
2075
2076  return (result);
2077}
2078
2079//----------------------------------------------------------
2080cmt_string CmtSystem::user ()
2081{
2082#ifdef _WIN32
2083  cmt_string result = getenv ("USERNAME");
2084#else
2085  cmt_string result = getenv ("USER");
2086#endif
2087
2088  return (result);
2089}
2090
2091//----------------------------------------------------------
2092void CmtSystem::get_cvsroot (cmt_string& cvsroot)
2093{
2094  cvsroot = "";
2095
2096  const char* env = ::getenv ("CVSROOT");
2097  if (env != 0)
2098    {
2099      cvsroot = env;
2100      return;
2101    }
2102
2103#ifdef WIN32
2104  LONG status;
2105  HKEY key = 0;
2106
2107  status = RegOpenKeyEx (HKEY_LOCAL_MACHINE, "Software\\CMT", 
2108                         0, KEY_READ, &key);
2109  if (status == ERROR_SUCCESS)
2110    {
2111      char temp[256];
2112      DWORD length = sizeof (temp) - 1;
2113      DWORD type;
2114
2115      status = RegQueryValueEx (key, "CVSROOT", 0, &type, 
2116                                (LPBYTE) temp, &length);
2117      if (status == ERROR_SUCCESS)
2118        {
2119          cvsroot = temp;
2120          return;
2121        }
2122    }
2123#endif
2124}
2125
2126//----------------------------------------------------------
2127bool CmtSystem::get_home_directory (cmt_string& dir)
2128{
2129  bool status = false;
2130
2131#ifdef WIN32
2132  const char* homedrive = ::getenv ("HOMEDRIVE");
2133  const char* homepath = ::getenv ("HOMEPATH");
2134
2135  if ((homedrive != 0) && (homepath != 0))
2136    {
2137      dir = homedrive;
2138      dir += homepath;
2139      status = true;
2140    }
2141
2142#else
2143  const char* home_env = ::getenv ("HOME");
2144  if (home_env != 0)
2145    {
2146      dir = home_env;
2147      status = true;
2148    }
2149#endif
2150
2151  return (status);
2152}
2153
Note: See TracBrowser for help on using the repository browser.