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