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