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