packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmSystemTools.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #if defined(_MSC_VER) && _MSC_VER < 1300
13 # define _WIN32_WINNT 0x0400 /* for wincrypt.h */
14 #endif
15 #include "cmSystemTools.h"
16 #include <ctype.h>
17 #include <errno.h>
18 #include <time.h>
19 #include <string.h>
20 #include <stdlib.h>
21 #ifdef __QNX__
22 # include <malloc.h> /* for malloc/free on QNX */
23 #endif
24 #include <cmsys/Glob.hxx>
25 #include <cmsys/RegularExpression.hxx>
26 #include <cmsys/Directory.hxx>
27 #include <cmsys/System.h>
28 #if defined(CMAKE_BUILD_WITH_CMAKE)
29 # include "cmArchiveWrite.h"
30 # include <cm_libarchive.h>
31 # include <cmsys/Terminal.h>
32 #endif
33 #include <cmsys/stl/algorithm>
34
35 #if defined(_WIN32)
36 # include <windows.h>
37 # include <wincrypt.h>
38 #else
39 # include <sys/time.h>
40 # include <sys/types.h>
41 # include <unistd.h>
42 # include <utime.h>
43 # include <sys/wait.h>
44 #endif
45
46 #include <sys/stat.h>
47
48 #if defined(_WIN32) && \
49    (defined(_MSC_VER) || defined(__WATCOMC__) || \
50     defined(__BORLANDC__) || defined(__MINGW32__))
51 # include <io.h>
52 #endif
53
54 #if defined(CMAKE_BUILD_WITH_CMAKE)
55 #  include <fcntl.h>
56 #  include "cmCryptoHash.h"
57 #endif
58
59 #if defined(CMAKE_USE_ELF_PARSER)
60 # include "cmELF.h"
61 #endif
62
63 class cmSystemToolsFileTime
64 {
65 public:
66 #if defined(_WIN32) && !defined(__CYGWIN__)
67   FILETIME timeCreation;
68   FILETIME timeLastAccess;
69   FILETIME timeLastWrite;
70 #else
71   struct utimbuf timeBuf;
72 #endif
73 };
74
75 #if defined(__sgi) && !defined(__GNUC__)
76 # pragma set woff 1375 /* base class destructor not virtual */
77 #endif
78
79 #if !defined(HAVE_ENVIRON_NOT_REQUIRE_PROTOTYPE)
80 // For GetEnvironmentVariables
81 # if defined(_WIN32)
82 extern __declspec( dllimport ) char** environ;
83 # else
84 extern char** environ;
85 # endif
86 #endif
87
88 #ifdef _WIN32
89 class cmSystemToolsWindowsHandle
90 {
91 public:
92   cmSystemToolsWindowsHandle(HANDLE h): handle_(h) {}
93   ~cmSystemToolsWindowsHandle()
94     {
95     if(this->handle_ != INVALID_HANDLE_VALUE)
96       {
97       CloseHandle(this->handle_);
98       }
99     }
100   operator bool() const { return this->handle_ != INVALID_HANDLE_VALUE; }
101   bool operator !() const { return this->handle_ == INVALID_HANDLE_VALUE; }
102   operator HANDLE() const { return this->handle_; }
103 private:
104   HANDLE handle_;
105 };
106 #elif defined(__APPLE__)
107 #include <crt_externs.h>
108 #define environ (*_NSGetEnviron())
109 #endif
110
111 bool cmSystemTools::s_RunCommandHideConsole = false;
112 bool cmSystemTools::s_DisableRunCommandOutput = false;
113 bool cmSystemTools::s_ErrorOccured = false;
114 bool cmSystemTools::s_FatalErrorOccured = false;
115 bool cmSystemTools::s_DisableMessages = false;
116 bool cmSystemTools::s_ForceUnixPaths = false;
117
118 std::string cmSystemTools::s_Windows9xComspecSubstitute = "command.com";
119 void cmSystemTools::SetWindows9xComspecSubstitute(const char* str)
120 {
121   if ( str )
122     {
123     cmSystemTools::s_Windows9xComspecSubstitute = str;
124     }
125 }
126 const char* cmSystemTools::GetWindows9xComspecSubstitute()
127 {
128   return cmSystemTools::s_Windows9xComspecSubstitute.c_str();
129 }
130
131 void (*cmSystemTools::s_ErrorCallback)(const char*, const char*,
132                                        bool&, void*);
133 void (*cmSystemTools::s_StdoutCallback)(const char*, int len, void*);
134 void* cmSystemTools::s_ErrorCallbackClientData = 0;
135 void* cmSystemTools::s_StdoutCallbackClientData = 0;
136 bool (*cmSystemTools::s_InterruptCallback)(void*);
137 void* cmSystemTools::s_InterruptCallbackClientData = 0;
138
139 // replace replace with with as many times as it shows up in source.
140 // write the result into source.
141 #if defined(_WIN32) && !defined(__CYGWIN__)
142 void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64 view)
143 {
144   // Regular expression to match anything inside [...] that begins in HKEY.
145   // Note that there is a special rule for regular expressions to match a
146   // close square-bracket inside a list delimited by square brackets.
147   // The "[^]]" part of this expression will match any character except
148   // a close square-bracket.  The ']' character must be the first in the
149   // list of characters inside the [^...] block of the expression.
150   cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
151
152   // check for black line or comment
153   while (regEntry.find(source))
154     {
155     // the arguments are the second match
156     std::string key = regEntry.match(1);
157     std::string val;
158     if (ReadRegistryValue(key.c_str(), val, view))
159       {
160       std::string reg = "[";
161       reg += key + "]";
162       cmSystemTools::ReplaceString(source, reg.c_str(), val.c_str());
163       }
164     else
165       {
166       std::string reg = "[";
167       reg += key + "]";
168       cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
169       }
170     }
171 }
172 #else
173 void cmSystemTools::ExpandRegistryValues(std::string& source, KeyWOW64)
174 {
175   cmsys::RegularExpression regEntry("\\[(HKEY[^]]*)\\]");
176   while (regEntry.find(source))
177     {
178     // the arguments are the second match
179     std::string key = regEntry.match(1);
180     std::string val;
181     std::string reg = "[";
182     reg += key + "]";
183     cmSystemTools::ReplaceString(source, reg.c_str(), "/registry");
184     }
185
186 }
187 #endif
188
189 std::string cmSystemTools::EscapeQuotes(const char* str)
190 {
191   std::string result = "";
192   for(const char* ch = str; *ch != '\0'; ++ch)
193     {
194     if(*ch == '"')
195       {
196       result += '\\';
197       }
198     result += *ch;
199     }
200   return result;
201 }
202
203 std::string cmSystemTools::TrimWhitespace(const std::string& s)
204 {
205   std::string::const_iterator start = s.begin();
206   while(start != s.end() && *start <= ' ')
207     ++start;
208   if (start == s.end())
209     return "";
210
211   std::string::const_iterator stop = s.end()-1;
212   while(*stop <= ' ')
213     --stop;
214   return std::string(start, stop+1);
215 }
216
217 void cmSystemTools::Error(const char* m1, const char* m2,
218                           const char* m3, const char* m4)
219 {
220   std::string message = "CMake Error: ";
221   if(m1)
222     {
223     message += m1;
224     }
225   if(m2)
226     {
227     message += m2;
228     }
229   if(m3)
230     {
231     message += m3;
232     }
233   if(m4)
234     {
235     message += m4;
236     }
237   cmSystemTools::s_ErrorOccured = true;
238   cmSystemTools::Message(message.c_str(),"Error");
239 }
240
241 void cmSystemTools::SetInterruptCallback(InterruptCallback f, void* clientData)
242 {
243   s_InterruptCallback = f;
244   s_InterruptCallbackClientData = clientData;
245 }
246
247 bool cmSystemTools::GetInterruptFlag()
248 {
249   if(s_InterruptCallback)
250     {
251     return (*s_InterruptCallback)(s_InterruptCallbackClientData);
252     }
253   return false;
254 }
255
256 void cmSystemTools::SetErrorCallback(ErrorCallback f, void* clientData)
257 {
258   s_ErrorCallback = f;
259   s_ErrorCallbackClientData = clientData;
260 }
261
262 void cmSystemTools::SetStdoutCallback(StdoutCallback f, void* clientData)
263 {
264   s_StdoutCallback = f;
265   s_StdoutCallbackClientData = clientData;
266 }
267
268 void cmSystemTools::Stdout(const char* s)
269 {
270   if(s_StdoutCallback)
271     {
272     (*s_StdoutCallback)(s, static_cast<int>(strlen(s)),
273                         s_StdoutCallbackClientData);
274     }
275   else
276     {
277     std::cout << s;
278     std::cout.flush();
279     }
280 }
281
282 void cmSystemTools::Stderr(const char* s, int length)
283 {
284     std::cerr.write(s, length);
285     std::cerr.flush();
286 }
287
288 void cmSystemTools::Stdout(const char* s, int length)
289 {
290   if(s_StdoutCallback)
291     {
292     (*s_StdoutCallback)(s, length, s_StdoutCallbackClientData);
293     }
294   else
295     {
296     std::cout.write(s, length);
297     std::cout.flush();
298     }
299 }
300
301 void cmSystemTools::Message(const char* m1, const char *title)
302 {
303   if(s_DisableMessages)
304     {
305     return;
306     }
307   if(s_ErrorCallback)
308     {
309     (*s_ErrorCallback)(m1, title, s_DisableMessages,
310                        s_ErrorCallbackClientData);
311     return;
312     }
313   else
314     {
315     std::cerr << m1 << std::endl << std::flush;
316     }
317
318 }
319
320
321 void cmSystemTools::ReportLastSystemError(const char* msg)
322 {
323   std::string m = msg;
324   m += ": System Error: ";
325   m += Superclass::GetLastSystemError();
326   cmSystemTools::Error(m.c_str());
327 }
328
329 bool cmSystemTools::IsInternallyOn(const char* val)
330 {
331   if (!val)
332     {
333     return false;
334     }
335   std::basic_string<char> v = val;
336
337   for(std::basic_string<char>::iterator c = v.begin();
338       c != v.end(); c++)
339     {
340     *c = static_cast<char>(toupper(*c));
341     }
342   return (v == "I_ON" || v == "i_on");
343 }
344
345 bool cmSystemTools::IsOn(const char* val)
346 {
347   if (!val)
348     {
349     return false;
350     }
351   std::basic_string<char> v = val;
352
353   for(std::basic_string<char>::iterator c = v.begin();
354       c != v.end(); c++)
355     {
356     *c = static_cast<char>(toupper(*c));
357     }
358   return (v == "ON" || v == "1" || v == "YES" || v == "TRUE" || v == "Y");
359 }
360
361 bool cmSystemTools::IsNOTFOUND(const char* val)
362 {
363   size_t len = strlen(val);
364   const char* notfound = "-NOTFOUND";
365   const size_t lenNotFound = 9;
366   if(len < lenNotFound-1)
367     {
368     return false;
369     }
370   if(len == lenNotFound-1)
371     {
372     return ( strcmp(val, "NOTFOUND") == 0);
373     }
374   return ((strncmp((val + (len - lenNotFound)), notfound, lenNotFound) == 0));
375 }
376
377
378 bool cmSystemTools::IsOff(const char* val)
379 {
380   if (!val || strlen(val) == 0)
381     {
382     return true;
383     }
384   std::basic_string<char> v = val;
385
386   for(std::basic_string<char>::iterator c = v.begin();
387       c != v.end(); c++)
388     {
389     *c = static_cast<char>(toupper(*c));
390     }
391   return (v == "OFF" || v == "0" || v == "NO" || v == "FALSE" ||
392           v == "N" || cmSystemTools::IsNOTFOUND(v.c_str()) || v == "IGNORE");
393 }
394
395 //----------------------------------------------------------------------------
396 void cmSystemTools::ParseWindowsCommandLine(const char* command,
397                                             std::vector<std::string>& args)
398 {
399   // See the MSDN document "Parsing C Command-Line Arguments" at
400   // http://msdn2.microsoft.com/en-us/library/a1y7w461.aspx for rules
401   // of parsing the windows command line.
402
403   bool in_argument = false;
404   bool in_quotes = false;
405   int backslashes = 0;
406   std::string arg;
407   for(const char* c = command;*c; ++c)
408     {
409     if(*c == '\\')
410       {
411       ++backslashes;
412       in_argument = true;
413       }
414     else if(*c == '"')
415       {
416       int backslash_pairs  = backslashes >> 1;
417       int backslash_escaped = backslashes & 1;
418       arg.append(backslash_pairs, '\\');
419       backslashes = 0;
420       if(backslash_escaped)
421         {
422         /* An odd number of backslashes precede this quote.
423            It is escaped.  */
424         arg.append(1, '"');
425         }
426       else
427         {
428         /* An even number of backslashes precede this quote.
429            It is not escaped.  */
430         in_quotes = !in_quotes;
431         }
432       in_argument = true;
433       }
434     else
435       {
436       arg.append(backslashes, '\\');
437       backslashes = 0;
438       if(isspace(*c))
439         {
440         if(in_quotes)
441           {
442           arg.append(1, *c);
443           }
444         else if(in_argument)
445           {
446           args.push_back(arg);
447           arg = "";
448           in_argument = false;
449           }
450         }
451       else
452         {
453         in_argument = true;
454         arg.append(1, *c);
455         }
456       }
457     }
458   arg.append(backslashes, '\\');
459   if(in_argument)
460     {
461     args.push_back(arg);
462     }
463 }
464
465 //----------------------------------------------------------------------------
466 class cmSystemToolsArgV
467 {
468   char** ArgV;
469 public:
470   cmSystemToolsArgV(char** argv): ArgV(argv) {}
471   ~cmSystemToolsArgV()
472     {
473     for(char** arg = this->ArgV; arg && *arg; ++arg)
474       {
475       free(*arg);
476       }
477     free(this->ArgV);
478     }
479   void Store(std::vector<std::string>& args) const
480     {
481     for(char** arg = this->ArgV; arg && *arg; ++arg)
482       {
483       args.push_back(*arg);
484       }
485     }
486   void Store(std::vector<cmStdString>& args) const
487     {
488     for(char** arg = this->ArgV; arg && *arg; ++arg)
489       {
490       args.push_back(*arg);
491       }
492     }
493 };
494
495 //----------------------------------------------------------------------------
496 void cmSystemTools::ParseUnixCommandLine(const char* command,
497                                          std::vector<std::string>& args)
498 {
499   // Invoke the underlying parser.
500   cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0);
501   argv.Store(args);
502 }
503
504 //----------------------------------------------------------------------------
505 void cmSystemTools::ParseUnixCommandLine(const char* command,
506                                          std::vector<cmStdString>& args)
507 {
508   // Invoke the underlying parser.
509   cmSystemToolsArgV argv = cmsysSystem_Parse_CommandForUnix(command, 0);
510   argv.Store(args);
511 }
512
513 std::string cmSystemTools::EscapeWindowsShellArgument(const char* arg,
514                                                       int shell_flags)
515 {
516   char local_buffer[1024];
517   char* buffer = local_buffer;
518   int size = cmsysSystem_Shell_GetArgumentSizeForWindows(arg, shell_flags);
519   if(size > 1024)
520     {
521     buffer = new char[size];
522     }
523   cmsysSystem_Shell_GetArgumentForWindows(arg, buffer, shell_flags);
524   std::string result(buffer);
525   if(buffer != local_buffer)
526     {
527     delete [] buffer;
528     }
529   return result;
530 }
531
532 std::vector<cmStdString> cmSystemTools::ParseArguments(const char* command)
533 {
534   std::vector<cmStdString> args;
535   std::string arg;
536
537   bool win_path = false;
538
539   if ((command[0] != '/' && command[1] == ':' && command[2] == '\\') ||
540       (command[0] == '\"' && command[1] != '/' && command[2] == ':'
541        && command[3] == '\\') ||
542       (command[0] == '\'' && command[1] != '/' && command[2] == ':'
543        && command[3] == '\\') ||
544       (command[0] == '\\' && command[1] == '\\'))
545     {
546     win_path = true;
547     }
548   // Split the command into an argv array.
549   for(const char* c = command; *c;)
550     {
551     // Skip over whitespace.
552     while(*c == ' ' || *c == '\t')
553       {
554       ++c;
555       }
556     arg = "";
557     if(*c == '"')
558       {
559       // Parse a quoted argument.
560       ++c;
561       while(*c && *c != '"')
562         {
563         arg.append(1, *c);
564         ++c;
565         }
566       if(*c)
567         {
568         ++c;
569         }
570       args.push_back(arg);
571       }
572     else if(*c == '\'')
573       {
574       // Parse a quoted argument.
575       ++c;
576       while(*c && *c != '\'')
577         {
578         arg.append(1, *c);
579         ++c;
580         }
581       if(*c)
582         {
583         ++c;
584         }
585       args.push_back(arg);
586       }
587     else if(*c)
588       {
589       // Parse an unquoted argument.
590       while(*c && *c != ' ' && *c != '\t')
591         {
592         if(*c == '\\' && !win_path)
593           {
594           ++c;
595           if(*c)
596             {
597             arg.append(1, *c);
598             ++c;
599             }
600           }
601         else
602           {
603           arg.append(1, *c);
604           ++c;
605           }
606         }
607       args.push_back(arg);
608       }
609     }
610
611   return args;
612 }
613
614
615 bool cmSystemTools::RunSingleCommand(std::vector<cmStdString>const& command,
616                                      std::string* output ,
617                                      int* retVal , const char* dir ,
618                                      OutputOption outputflag ,
619                                      double timeout )
620 {
621   std::vector<const char*> argv;
622   for(std::vector<cmStdString>::const_iterator a = command.begin();
623       a != command.end(); ++a)
624     {
625     argv.push_back(a->c_str());
626     }
627   argv.push_back(0);
628   if ( output )
629     {
630     *output = "";
631     }
632
633   cmsysProcess* cp = cmsysProcess_New();
634   cmsysProcess_SetCommand(cp, &*argv.begin());
635   cmsysProcess_SetWorkingDirectory(cp, dir);
636   if(cmSystemTools::GetRunCommandHideConsole())
637     {
638     cmsysProcess_SetOption(cp, cmsysProcess_Option_HideWindow, 1);
639     }
640
641   if (outputflag == OUTPUT_PASSTHROUGH)
642     {
643     cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDOUT, 1);
644     cmsysProcess_SetPipeShared(cp, cmsysProcess_Pipe_STDERR, 1);
645     }
646
647   cmsysProcess_SetTimeout(cp, timeout);
648   cmsysProcess_Execute(cp);
649
650   std::vector<char> tempOutput;
651   char* data;
652   int length;
653   int pipe;
654   if(outputflag != OUTPUT_PASSTHROUGH && (output || outputflag != OUTPUT_NONE))
655     {
656     while((pipe = cmsysProcess_WaitForData(cp, &data, &length, 0)) > 0)
657       {
658       if(output || outputflag != OUTPUT_NONE)
659         {
660         // Translate NULL characters in the output into valid text.
661         // Visual Studio 7 puts these characters in the output of its
662         // build process.
663         for(int i=0; i < length; ++i)
664           {
665           if(data[i] == '\0')
666             {
667             data[i] = ' ';
668             }
669           }
670         }
671       if ( output )
672         {
673         tempOutput.insert(tempOutput.end(), data, data+length);
674         }
675       if(outputflag != OUTPUT_NONE)
676         {
677         if(outputflag == OUTPUT_MERGE)
678           {
679           cmSystemTools::Stdout(data, length);
680           }
681         else
682           {
683           if(pipe == cmsysProcess_Pipe_STDERR)
684             {
685             cmSystemTools::Stderr(data, length);
686             }
687           else if(pipe == cmsysProcess_Pipe_STDOUT)
688             {
689             cmSystemTools::Stdout(data, length);
690             }
691           }
692         }
693       }
694     }
695
696   cmsysProcess_WaitForExit(cp, 0);
697   if ( output && tempOutput.begin() != tempOutput.end())
698     {
699     output->append(&*tempOutput.begin(), tempOutput.size());
700     }
701
702   bool result = true;
703   if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exited)
704     {
705     if ( retVal )
706       {
707       *retVal = cmsysProcess_GetExitValue(cp);
708       }
709     else
710       {
711       if ( cmsysProcess_GetExitValue(cp) !=  0 )
712         {
713         result = false;
714         }
715       }
716     }
717   else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Exception)
718     {
719     const char* exception_str = cmsysProcess_GetExceptionString(cp);
720     if ( outputflag != OUTPUT_NONE )
721       {
722       std::cerr << exception_str << std::endl;
723       }
724     if ( output )
725       {
726       output->append(exception_str, strlen(exception_str));
727       }
728     result = false;
729     }
730   else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Error)
731     {
732     const char* error_str = cmsysProcess_GetErrorString(cp);
733     if ( outputflag != OUTPUT_NONE )
734       {
735       std::cerr << error_str << std::endl;
736       }
737     if ( output )
738       {
739       output->append(error_str, strlen(error_str));
740       }
741     result = false;
742     }
743   else if(cmsysProcess_GetState(cp) == cmsysProcess_State_Expired)
744     {
745     const char* error_str = "Process terminated due to timeout\n";
746     if ( outputflag != OUTPUT_NONE )
747       {
748       std::cerr << error_str << std::endl;
749       }
750     if ( output )
751       {
752       output->append(error_str, strlen(error_str));
753       }
754     result = false;
755     }
756
757   cmsysProcess_Delete(cp);
758   return result;
759 }
760
761 bool cmSystemTools::RunSingleCommand(
762   const char* command,
763   std::string* output,
764   int *retVal,
765   const char* dir,
766   OutputOption outputflag,
767   double timeout)
768 {
769   if(s_DisableRunCommandOutput)
770     {
771     outputflag = OUTPUT_NONE;
772     }
773
774   std::vector<cmStdString> args = cmSystemTools::ParseArguments(command);
775
776   if(args.size() < 1)
777     {
778     return false;
779     }
780   return cmSystemTools::RunSingleCommand(args, output,retVal,
781                                          dir, outputflag, timeout);
782 }
783 bool cmSystemTools::RunCommand(const char* command,
784                                std::string& output,
785                                const char* dir,
786                                bool verbose,
787                                int timeout)
788 {
789   int dummy;
790   return cmSystemTools::RunCommand(command, output, dummy,
791                                    dir, verbose, timeout);
792 }
793
794 #if defined(WIN32) && !defined(__CYGWIN__)
795 #include "cmWin32ProcessExecution.h"
796 // use this for shell commands like echo and dir
797 bool RunCommandViaWin32(const char* command,
798                         const char* dir,
799                         std::string& output,
800                         int& retVal,
801                         bool verbose,
802                         int timeout)
803 {
804 #if defined(__BORLANDC__)
805   return
806     cmWin32ProcessExecution::
807     BorlandRunCommand(command, dir, output,
808                       retVal,
809                       verbose, timeout,
810                       cmSystemTools::GetRunCommandHideConsole());
811 #else // Visual studio
812   ::SetLastError(ERROR_SUCCESS);
813   if ( ! command )
814     {
815     cmSystemTools::Error("No command specified");
816     return false;
817     }
818   cmWin32ProcessExecution resProc;
819   if(cmSystemTools::GetRunCommandHideConsole())
820     {
821     resProc.SetHideWindows(true);
822     }
823
824   if ( cmSystemTools::GetWindows9xComspecSubstitute() )
825     {
826     resProc.SetConsoleSpawn(cmSystemTools::GetWindows9xComspecSubstitute() );
827     }
828   if ( !resProc.StartProcess(command, dir, verbose) )
829     {
830     output = resProc.GetOutput();
831     if(verbose)
832       {
833       cmSystemTools::Stdout(output.c_str());
834       }
835     return false;
836     }
837   resProc.Wait(timeout);
838   output = resProc.GetOutput();
839   retVal = resProc.GetExitValue();
840   return true;
841 #endif
842 }
843
844 // use this for shell commands like echo and dir
845 bool RunCommandViaSystem(const char* command,
846                          const char* dir,
847                          std::string& output,
848                          int& retVal,
849                          bool verbose)
850 {
851   std::cout << "@@ " << command << std::endl;
852
853   std::string commandInDir;
854   if(dir)
855     {
856     commandInDir = "cd ";
857     commandInDir += cmSystemTools::ConvertToOutputPath(dir);
858     commandInDir += " && ";
859     commandInDir += command;
860     }
861   else
862     {
863     commandInDir = command;
864     }
865   command = commandInDir.c_str();
866   std::string commandToFile = command;
867   commandToFile += " > ";
868   std::string tempFile;
869   tempFile += _tempnam(0, "cmake");
870
871   commandToFile += tempFile;
872   retVal = system(commandToFile.c_str());
873   std::ifstream fin(tempFile.c_str());
874   if(!fin)
875     {
876     if(verbose)
877       {
878       std::string errormsg = "RunCommand produced no output: command: \"";
879       errormsg += command;
880       errormsg += "\"";
881       errormsg += "\nOutput file: ";
882       errormsg += tempFile;
883       cmSystemTools::Error(errormsg.c_str());
884       }
885     fin.close();
886     cmSystemTools::RemoveFile(tempFile.c_str());
887     return false;
888     }
889   bool multiLine = false;
890   std::string line;
891   while(cmSystemTools::GetLineFromStream(fin, line))
892     {
893     output += line;
894     if(multiLine)
895       {
896       output += "\n";
897       }
898     multiLine = true;
899     }
900   fin.close();
901   cmSystemTools::RemoveFile(tempFile.c_str());
902   return true;
903 }
904
905 #else // We have popen
906
907 // BeOS seems to return from a successful pclose() before the process has
908 //  legitimately exited, or at least before SIGCHLD is thrown...the signal may
909 //  come quite some time after pclose returns! This causes havoc with later
910 //  parts of CMake that expect to catch the signal from other child processes,
911 //  so we explicitly wait to catch it here. This should be safe to do with
912 //  popen() so long as we don't actually collect the zombie process ourselves.
913 #ifdef __BEOS__
914 #include <signal.h>
915 #undef SIGBUS  // this is the same as SIGSEGV on BeOS and causes issues below.
916 static volatile bool beos_seen_signal = false;
917 static void beos_popen_workaround(int sig)
918 {
919   beos_seen_signal = true;
920 }
921 #endif
922
923 bool RunCommandViaPopen(const char* command,
924                         const char* dir,
925                         std::string& output,
926                         int& retVal,
927                         bool verbose,
928                         int /*timeout*/)
929 {
930   // if only popen worked on windows.....
931   std::string commandInDir;
932   if(dir)
933     {
934     commandInDir = "cd \"";
935     commandInDir += dir;
936     commandInDir += "\" && ";
937     commandInDir += command;
938     }
939   else
940     {
941     commandInDir = command;
942     }
943 #ifndef __VMS
944   commandInDir += " 2>&1";
945 #endif
946   command = commandInDir.c_str();
947   const int BUFFER_SIZE = 4096;
948   char buffer[BUFFER_SIZE];
949   if(verbose)
950     {
951     cmSystemTools::Stdout("running ");
952     cmSystemTools::Stdout(command);
953     cmSystemTools::Stdout("\n");
954     }
955   fflush(stdout);
956   fflush(stderr);
957
958 #ifdef __BEOS__
959   beos_seen_signal = false;
960   signal(SIGCHLD, beos_popen_workaround);
961 #endif
962
963   FILE* cpipe = popen(command, "r");
964   if(!cpipe)
965     {
966 #ifdef __BEOS__
967     signal(SIGCHLD, SIG_DFL);
968 #endif
969     return false;
970     }
971   if (!fgets(buffer, BUFFER_SIZE, cpipe))
972     {
973     buffer[0] = 0;
974     }
975   while(!feof(cpipe))
976     {
977     if(verbose)
978       {
979       cmSystemTools::Stdout(buffer);
980       }
981     output += buffer;
982     if(!fgets(buffer, BUFFER_SIZE, cpipe))
983       {
984       buffer[0] = 0;
985       }
986     }
987
988   retVal = pclose(cpipe);
989
990 #ifdef __BEOS__
991   for (int i = 0; (!beos_seen_signal) && (i < 3); i++)
992     {
993     ::sleep(1);   // signals should interrupt this...
994     }
995
996   if (!beos_seen_signal)
997     {
998     signal(SIGCHLD, SIG_DFL);  // oh well, didn't happen. Go on anyhow.
999     }
1000 #endif
1001
1002   if (WIFEXITED(retVal))
1003     {
1004     retVal = WEXITSTATUS(retVal);
1005     return true;
1006     }
1007   if (WIFSIGNALED(retVal))
1008     {
1009     retVal = WTERMSIG(retVal);
1010     cmOStringStream error;
1011     error << "\nProcess terminated due to ";
1012     switch (retVal)
1013       {
1014 #ifdef SIGKILL
1015       case SIGKILL:
1016         error << "SIGKILL";
1017         break;
1018 #endif
1019 #ifdef SIGFPE
1020       case SIGFPE:
1021         error << "SIGFPE";
1022         break;
1023 #endif
1024 #ifndef __HAIKU__
1025 #ifdef SIGBUS
1026       case SIGBUS:
1027         error << "SIGBUS";
1028         break;
1029 #endif
1030 #endif
1031 #ifdef SIGSEGV
1032       case SIGSEGV:
1033         error << "SIGSEGV";
1034         break;
1035 #endif
1036       default:
1037         error << "signal " << retVal;
1038         break;
1039       }
1040     output += error.str();
1041     }
1042   return false;
1043 }
1044
1045 #endif  // endif WIN32 not CYGWIN
1046
1047
1048 // run a command unix uses popen (easy)
1049 // windows uses system and ShortPath
1050 bool cmSystemTools::RunCommand(const char* command,
1051                                std::string& output,
1052                                int &retVal,
1053                                const char* dir,
1054                                bool verbose,
1055                                int timeout)
1056 {
1057   if(s_DisableRunCommandOutput)
1058     {
1059     verbose = false;
1060     }
1061
1062 #if defined(WIN32) && !defined(__CYGWIN__)
1063   // if the command does not start with a quote, then
1064   // try to find the program, and if the program can not be
1065   // found use system to run the command as it must be a built in
1066   // shell command like echo or dir
1067   int count = 0;
1068   if(command[0] == '\"')
1069     {
1070     // count the number of quotes
1071     for(const char* s = command; *s != 0; ++s)
1072       {
1073       if(*s == '\"')
1074         {
1075         count++;
1076         if(count > 2)
1077           {
1078           break;
1079           }
1080         }
1081       }
1082     // if there are more than two double quotes use
1083     // GetShortPathName, the cmd.exe program in windows which
1084     // is used by system fails to execute if there are more than
1085     // one set of quotes in the arguments
1086     if(count > 2)
1087       {
1088       cmsys::RegularExpression quoted("^\"([^\"]*)\"[ \t](.*)");
1089       if(quoted.find(command))
1090         {
1091         std::string shortCmd;
1092         std::string cmd = quoted.match(1);
1093         std::string args = quoted.match(2);
1094         if(! cmSystemTools::FileExists(cmd.c_str()) )
1095           {
1096           shortCmd = cmd;
1097           }
1098         else if(!cmSystemTools::GetShortPath(cmd.c_str(), shortCmd))
1099           {
1100          cmSystemTools::Error("GetShortPath failed for " , cmd.c_str());
1101           return false;
1102           }
1103         shortCmd += " ";
1104         shortCmd += args;
1105
1106         //return RunCommandViaSystem(shortCmd.c_str(), dir,
1107         //                           output, retVal, verbose);
1108         //return WindowsRunCommand(shortCmd.c_str(), dir,
1109         //output, retVal, verbose);
1110         return RunCommandViaWin32(shortCmd.c_str(), dir,
1111                                   output, retVal, verbose, timeout);
1112         }
1113       else
1114         {
1115         cmSystemTools::Error("Could not parse command line with quotes ",
1116                              command);
1117         }
1118       }
1119     }
1120   // if there is only one set of quotes or no quotes then just run the command
1121   //return RunCommandViaSystem(command, dir, output, retVal, verbose);
1122   //return WindowsRunCommand(command, dir, output, retVal, verbose);
1123   return ::RunCommandViaWin32(command, dir, output, retVal, verbose, timeout);
1124 #else
1125   return ::RunCommandViaPopen(command, dir, output, retVal, verbose, timeout);
1126 #endif
1127 }
1128
1129 bool cmSystemTools::DoesFileExistWithExtensions(
1130   const char* name,
1131   const std::vector<std::string>& headerExts)
1132 {
1133   std::string hname;
1134
1135   for( std::vector<std::string>::const_iterator ext = headerExts.begin();
1136        ext != headerExts.end(); ++ext )
1137     {
1138     hname = name;
1139     hname += ".";
1140     hname += *ext;
1141     if(cmSystemTools::FileExists(hname.c_str()))
1142       {
1143       return true;
1144       }
1145     }
1146   return false;
1147 }
1148
1149 std::string cmSystemTools::FileExistsInParentDirectories(const char* fname,
1150   const char* directory, const char* toplevel)
1151 {
1152   std::string file = fname;
1153   cmSystemTools::ConvertToUnixSlashes(file);
1154   std::string dir = directory;
1155   cmSystemTools::ConvertToUnixSlashes(dir);
1156   std::string prevDir;
1157   while(dir != prevDir)
1158     {
1159     std::string path = dir + "/" + file;
1160     if ( cmSystemTools::FileExists(path.c_str()) )
1161       {
1162       return path;
1163       }
1164     if ( dir.size() < strlen(toplevel) )
1165       {
1166       break;
1167       }
1168     prevDir = dir;
1169     dir = cmSystemTools::GetParentDirectory(dir.c_str());
1170     }
1171   return "";
1172 }
1173
1174 bool cmSystemTools::cmCopyFile(const char* source, const char* destination)
1175 {
1176   return Superclass::CopyFileAlways(source, destination);
1177 }
1178
1179 bool cmSystemTools::CopyFileIfDifferent(const char* source,
1180   const char* destination)
1181 {
1182   return Superclass::CopyFileIfDifferent(source, destination);
1183 }
1184
1185 //----------------------------------------------------------------------------
1186 bool cmSystemTools::RenameFile(const char* oldname, const char* newname)
1187 {
1188 #ifdef _WIN32
1189 # ifndef INVALID_FILE_ATTRIBUTES
1190 #  define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
1191 # endif
1192   /* Windows MoveFileEx may not replace read-only or in-use files.  If it
1193      fails then remove the read-only attribute from any existing destination.
1194      Try multiple times since we may be racing against another process
1195      creating/opening the destination file just before our MoveFileEx.  */
1196   int tries = 5;
1197   while(!MoveFileEx(oldname, newname, MOVEFILE_REPLACE_EXISTING) && --tries)
1198     {
1199     // Try again only if failure was due to access permissions.
1200     if(GetLastError() != ERROR_ACCESS_DENIED)
1201       {
1202       return false;
1203       }
1204     DWORD attrs = GetFileAttributes(newname);
1205     if((attrs != INVALID_FILE_ATTRIBUTES) &&
1206        (attrs & FILE_ATTRIBUTE_READONLY))
1207       {
1208       // Remove the read-only attribute from the destination file.
1209       SetFileAttributes(newname, attrs & ~FILE_ATTRIBUTE_READONLY);
1210       }
1211     else
1212       {
1213       // The file may be temporarily in use so wait a bit.
1214       cmSystemTools::Delay(100);
1215       }
1216     }
1217   return tries > 0;
1218 #else
1219   /* On UNIX we have an OS-provided call to do this atomically.  */
1220   return rename(oldname, newname) == 0;
1221 #endif
1222 }
1223
1224 bool cmSystemTools::ComputeFileMD5(const char* source, char* md5out)
1225 {
1226 #if defined(CMAKE_BUILD_WITH_CMAKE)
1227   cmCryptoHashMD5 md5;
1228   std::string str = md5.HashFile(source);
1229   strncpy(md5out, str.c_str(), 32);
1230   return !str.empty();
1231 #else
1232   (void)source;
1233   (void)md5out;
1234   cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1235   return false;
1236 #endif
1237 }
1238
1239 std::string cmSystemTools::ComputeStringMD5(const char* input)
1240 {
1241 #if defined(CMAKE_BUILD_WITH_CMAKE)
1242   cmCryptoHashMD5 md5;
1243   return md5.HashString(input);
1244 #else
1245   (void)input;
1246   cmSystemTools::Message("md5sum not supported in bootstrapping mode","Error");
1247   return "";
1248 #endif
1249 }
1250
1251 void cmSystemTools::Glob(const char *directory, const char *regexp,
1252                          std::vector<std::string>& files)
1253 {
1254   cmsys::Directory d;
1255   cmsys::RegularExpression reg(regexp);
1256
1257   if (d.Load(directory))
1258     {
1259     size_t numf;
1260         unsigned int i;
1261     numf = d.GetNumberOfFiles();
1262     for (i = 0; i < numf; i++)
1263       {
1264       std::string fname = d.GetFile(i);
1265       if (reg.find(fname))
1266         {
1267         files.push_back(fname);
1268         }
1269       }
1270     }
1271 }
1272
1273
1274 void cmSystemTools::GlobDirs(const char *fullPath,
1275                              std::vector<std::string>& files)
1276 {
1277   std::string path = fullPath;
1278   std::string::size_type pos = path.find("/*");
1279   if(pos == std::string::npos)
1280     {
1281     files.push_back(fullPath);
1282     return;
1283     }
1284   std::string startPath = path.substr(0, pos);
1285   std::string finishPath = path.substr(pos+2);
1286
1287   cmsys::Directory d;
1288   if (d.Load(startPath.c_str()))
1289     {
1290     for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
1291       {
1292       if((std::string(d.GetFile(i)) != ".")
1293          && (std::string(d.GetFile(i)) != ".."))
1294         {
1295         std::string fname = startPath;
1296         fname +="/";
1297         fname += d.GetFile(i);
1298         if(cmSystemTools::FileIsDirectory(fname.c_str()))
1299           {
1300           fname += finishPath;
1301           cmSystemTools::GlobDirs(fname.c_str(), files);
1302           }
1303         }
1304       }
1305     }
1306 }
1307
1308
1309 void cmSystemTools::ExpandList(std::vector<std::string> const& arguments,
1310                                std::vector<std::string>& newargs)
1311 {
1312   std::vector<std::string>::const_iterator i;
1313   for(i = arguments.begin();i != arguments.end(); ++i)
1314     {
1315     cmSystemTools::ExpandListArgument(*i, newargs);
1316     }
1317 }
1318
1319 void cmSystemTools::ExpandListArgument(const std::string& arg,
1320                                        std::vector<std::string>& newargs,
1321                                        bool emptyArgs)
1322 {
1323   // If argument is empty, it is an empty list.
1324   if(arg.length() == 0 && !emptyArgs)
1325     {
1326     return;
1327     }
1328   // if there are no ; in the name then just copy the current string
1329   if(arg.find(';') == std::string::npos)
1330     {
1331     newargs.push_back(arg);
1332     return;
1333     }
1334   std::vector<char> newArgVec;
1335   // Break the string at non-escaped semicolons not nested in [].
1336   int squareNesting = 0;
1337   for(const char* c = arg.c_str(); *c; ++c)
1338     {
1339     switch(*c)
1340       {
1341       case '\\':
1342         {
1343         // We only want to allow escaping of semicolons.  Other
1344         // escapes should not be processed here.
1345         ++c;
1346         if(*c == ';')
1347           {
1348           newArgVec.push_back(*c);
1349           }
1350         else
1351           {
1352           newArgVec.push_back('\\');
1353           if(*c)
1354             {
1355             newArgVec.push_back(*c);
1356             }
1357           else
1358             {
1359             // Terminate the loop properly.
1360             --c;
1361             }
1362           }
1363         } break;
1364       case '[':
1365         {
1366         ++squareNesting;
1367         newArgVec.push_back(*c);
1368         } break;
1369       case ']':
1370         {
1371         --squareNesting;
1372         newArgVec.push_back(*c);
1373         } break;
1374       case ';':
1375         {
1376         // Break the string here if we are not nested inside square
1377         // brackets.
1378         if(squareNesting == 0)
1379           {
1380           if ( newArgVec.size() || emptyArgs )
1381             {
1382             // Add the last argument if the string is not empty.
1383             newArgVec.push_back(0);
1384             newargs.push_back(&*newArgVec.begin());
1385             newArgVec.clear();
1386             }
1387           }
1388         else
1389           {
1390           newArgVec.push_back(*c);
1391           }
1392         } break;
1393       default:
1394         {
1395         // Just append this character.
1396         newArgVec.push_back(*c);
1397         } break;
1398       }
1399     }
1400   if ( newArgVec.size() || emptyArgs )
1401     {
1402     // Add the last argument if the string is not empty.
1403     newArgVec.push_back(0);
1404     newargs.push_back(&*newArgVec.begin());
1405     }
1406 }
1407
1408 bool cmSystemTools::SimpleGlob(const cmStdString& glob,
1409                                std::vector<cmStdString>& files,
1410                                int type /* = 0 */)
1411 {
1412   files.clear();
1413   if ( glob[glob.size()-1] != '*' )
1414     {
1415     return false;
1416     }
1417   std::string path = cmSystemTools::GetFilenamePath(glob);
1418   std::string ppath = cmSystemTools::GetFilenameName(glob);
1419   ppath = ppath.substr(0, ppath.size()-1);
1420   if ( path.size() == 0 )
1421     {
1422     path = "/";
1423     }
1424
1425   bool res = false;
1426   cmsys::Directory d;
1427   if (d.Load(path.c_str()))
1428     {
1429     for (unsigned int i = 0; i < d.GetNumberOfFiles(); ++i)
1430       {
1431       if((std::string(d.GetFile(i)) != ".")
1432          && (std::string(d.GetFile(i)) != ".."))
1433         {
1434         std::string fname = path;
1435         if ( path[path.size()-1] != '/' )
1436           {
1437           fname +="/";
1438           }
1439         fname += d.GetFile(i);
1440         std::string sfname = d.GetFile(i);
1441         if ( type > 0 && cmSystemTools::FileIsDirectory(fname.c_str()) )
1442           {
1443           continue;
1444           }
1445         if ( type < 0 && !cmSystemTools::FileIsDirectory(fname.c_str()) )
1446           {
1447           continue;
1448           }
1449         if ( sfname.size() >= ppath.size() &&
1450              sfname.substr(0, ppath.size()) ==
1451              ppath )
1452           {
1453           files.push_back(fname);
1454           res = true;
1455           }
1456         }
1457       }
1458     }
1459   return res;
1460 }
1461
1462 cmSystemTools::FileFormat cmSystemTools::GetFileFormat(const char* cext)
1463 {
1464   if ( ! cext || *cext == 0 )
1465     {
1466     return cmSystemTools::NO_FILE_FORMAT;
1467     }
1468   //std::string ext = cmSystemTools::LowerCase(cext);
1469   std::string ext = cext;
1470   if ( ext == "c" || ext == ".c" ||
1471        ext == "m" || ext == ".m"
1472     ) { return cmSystemTools::C_FILE_FORMAT; }
1473   if (
1474     ext == "C" || ext == ".C" ||
1475     ext == "M" || ext == ".M" ||
1476     ext == "c++" || ext == ".c++" ||
1477     ext == "cc" || ext == ".cc" ||
1478     ext == "cpp" || ext == ".cpp" ||
1479     ext == "cxx" || ext == ".cxx" ||
1480     ext == "mm" || ext == ".mm"
1481     ) { return cmSystemTools::CXX_FILE_FORMAT; }
1482   if (
1483     ext == "f" || ext == ".f" ||
1484     ext == "F" || ext == ".F" ||
1485     ext == "f77" || ext == ".f77" ||
1486     ext == "f90" || ext == ".f90" ||
1487     ext == "for" || ext == ".for" ||
1488     ext == "f95" || ext == ".f95"
1489     ) { return cmSystemTools::FORTRAN_FILE_FORMAT; }
1490   if ( ext == "java" || ext == ".java" )
1491     { return cmSystemTools::JAVA_FILE_FORMAT; }
1492   if (
1493     ext == "H" || ext == ".H" ||
1494     ext == "h" || ext == ".h" ||
1495     ext == "h++" || ext == ".h++" ||
1496     ext == "hm" || ext == ".hm" ||
1497     ext == "hpp" || ext == ".hpp" ||
1498     ext == "hxx" || ext == ".hxx" ||
1499     ext == "in" || ext == ".in" ||
1500     ext == "txx" || ext == ".txx"
1501     ) { return cmSystemTools::HEADER_FILE_FORMAT; }
1502   if ( ext == "rc" || ext == ".rc" )
1503     { return cmSystemTools::RESOURCE_FILE_FORMAT; }
1504   if ( ext == "def" || ext == ".def" )
1505     { return cmSystemTools::DEFINITION_FILE_FORMAT; }
1506   if ( ext == "lib" || ext == ".lib" ||
1507        ext == "a" || ext == ".a")
1508     { return cmSystemTools::STATIC_LIBRARY_FILE_FORMAT; }
1509   if ( ext == "o" || ext == ".o" ||
1510        ext == "obj" || ext == ".obj")
1511     { return cmSystemTools::OBJECT_FILE_FORMAT; }
1512 #ifdef __APPLE__
1513   if ( ext == "dylib" || ext == ".dylib" )
1514     { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT; }
1515   if ( ext == "so" || ext == ".so" ||
1516        ext == "bundle" || ext == ".bundle" )
1517     { return cmSystemTools::MODULE_FILE_FORMAT; }
1518 #else // __APPLE__
1519   if ( ext == "so" || ext == ".so" ||
1520        ext == "sl" || ext == ".sl" ||
1521        ext == "dll" || ext == ".dll" )
1522     { return cmSystemTools::SHARED_LIBRARY_FILE_FORMAT; }
1523 #endif // __APPLE__
1524   return cmSystemTools::UNKNOWN_FILE_FORMAT;
1525 }
1526
1527 bool cmSystemTools::Split(const char* s, std::vector<cmStdString>& l)
1528 {
1529   std::vector<std::string> temp;
1530   bool res = Superclass::Split(s, temp);
1531   for(std::vector<std::string>::const_iterator i = temp.begin();
1532       i != temp.end(); ++i)
1533     {
1534     l.push_back(*i);
1535     }
1536   return res;
1537 }
1538
1539 std::string cmSystemTools::ConvertToOutputPath(const char* path)
1540 {
1541 #if defined(_WIN32) && !defined(__CYGWIN__)
1542   if(s_ForceUnixPaths)
1543     {
1544     return cmSystemTools::ConvertToUnixOutputPath(path);
1545     }
1546   return cmSystemTools::ConvertToWindowsOutputPath(path);
1547 #else
1548   return cmSystemTools::ConvertToUnixOutputPath(path);
1549 #endif
1550 }
1551
1552 void cmSystemTools::ConvertToOutputSlashes(std::string& path)
1553 {
1554 #if defined(_WIN32) && !defined(__CYGWIN__)
1555   if(!s_ForceUnixPaths)
1556     {
1557     // Convert to windows slashes.
1558     std::string::size_type pos = 0;
1559     while((pos = path.find('/', pos)) != std::string::npos)
1560       {
1561       path[pos++] = '\\';
1562       }
1563     }
1564 #else
1565   static_cast<void>(path);
1566 #endif
1567 }
1568
1569 std::string cmSystemTools::ConvertToRunCommandPath(const char* path)
1570 {
1571 #if defined(_WIN32) && !defined(__CYGWIN__)
1572   return cmSystemTools::ConvertToWindowsOutputPath(path);
1573 #else
1574   return cmSystemTools::ConvertToUnixOutputPath(path);
1575 #endif
1576 }
1577
1578 bool cmSystemTools::StringEndsWith(const char* str1, const char* str2)
1579 {
1580   if ( !str1 || !str2 || strlen(str1) < strlen(str2) )
1581     {
1582     return 0;
1583     }
1584   return !strncmp(str1 + (strlen(str1)-strlen(str2)), str2, strlen(str2));
1585 }
1586
1587 // compute the relative path from here to there
1588 std::string cmSystemTools::RelativePath(const char* local, const char* remote)
1589 {
1590   if(!cmSystemTools::FileIsFullPath(local))
1591     {
1592     cmSystemTools::Error("RelativePath must be passed a full path to local: ",
1593                          local);
1594     }
1595   if(!cmSystemTools::FileIsFullPath(remote))
1596     {
1597     cmSystemTools::Error
1598       ("RelativePath must be passed a full path to remote: ", remote);
1599     }
1600   return cmsys::SystemTools::RelativePath(local, remote);
1601 }
1602
1603 std::string cmSystemTools::CollapseCombinedPath(std::string const& dir,
1604                                                 std::string const& file)
1605 {
1606   if(dir.empty() || dir == ".")
1607     {
1608     return file;
1609     }
1610
1611   std::vector<std::string> dirComponents;
1612   std::vector<std::string> fileComponents;
1613   cmSystemTools::SplitPath(dir.c_str(), dirComponents);
1614   cmSystemTools::SplitPath(file.c_str(), fileComponents);
1615
1616   if(fileComponents.empty())
1617     {
1618     return dir;
1619     }
1620   if(fileComponents[0] != "")
1621     {
1622     // File is not a relative path.
1623     return file;
1624     }
1625
1626   std::vector<std::string>::iterator i = fileComponents.begin()+1;
1627   while(i != fileComponents.end() && *i == ".." && dirComponents.size() > 1)
1628     {
1629     ++i; // Remove ".." file component.
1630     dirComponents.pop_back(); // Remove last dir component.
1631     }
1632
1633   dirComponents.insert(dirComponents.end(), i, fileComponents.end());
1634   return cmSystemTools::JoinPath(dirComponents);
1635 }
1636
1637 #ifdef CMAKE_BUILD_WITH_CMAKE
1638 //----------------------------------------------------------------------
1639 bool cmSystemTools::UnsetEnv(const char* value)
1640 {
1641 #if !defined(HAVE_UNSETENV)
1642   std::string var = value;
1643   var += "=";
1644   return cmSystemTools::PutEnv(var.c_str());
1645 #else
1646   unsetenv(value);
1647   return true;
1648 #endif
1649 }
1650
1651 //----------------------------------------------------------------------
1652 std::vector<std::string> cmSystemTools::GetEnvironmentVariables()
1653 {
1654   std::vector<std::string> env;
1655   int cc;
1656   for ( cc = 0; environ[cc]; ++ cc )
1657     {
1658     env.push_back(environ[cc]);
1659     }
1660   return env;
1661 }
1662
1663 //----------------------------------------------------------------------
1664 void cmSystemTools::AppendEnv(std::vector<std::string> const& env)
1665 {
1666   for(std::vector<std::string>::const_iterator eit = env.begin();
1667       eit != env.end(); ++eit)
1668     {
1669     cmSystemTools::PutEnv(eit->c_str());
1670     }
1671 }
1672
1673 //----------------------------------------------------------------------
1674 cmSystemTools::SaveRestoreEnvironment::SaveRestoreEnvironment()
1675 {
1676   this->Env = cmSystemTools::GetEnvironmentVariables();
1677 }
1678
1679 //----------------------------------------------------------------------
1680 cmSystemTools::SaveRestoreEnvironment::~SaveRestoreEnvironment()
1681 {
1682   // First clear everything in the current environment:
1683   std::vector<std::string> currentEnv = GetEnvironmentVariables();
1684   for(std::vector<std::string>::const_iterator
1685         eit = currentEnv.begin(); eit != currentEnv.end(); ++eit)
1686     {
1687     std::string var(*eit);
1688
1689     std::string::size_type pos = var.find("=");
1690     if (pos != std::string::npos)
1691       {
1692       var = var.substr(0, pos);
1693       }
1694
1695     cmSystemTools::UnsetEnv(var.c_str());
1696     }
1697
1698   // Then put back each entry from the original environment:
1699   cmSystemTools::AppendEnv(this->Env);
1700 }
1701 #endif
1702
1703 void cmSystemTools::EnableVSConsoleOutput()
1704 {
1705 #ifdef _WIN32
1706   // Visual Studio 8 2005 (devenv.exe or VCExpress.exe) will not
1707   // display output to the console unless this environment variable is
1708   // set.  We need it to capture the output of these build tools.
1709   // Note for future work that one could pass "/out \\.\pipe\NAME" to
1710   // either of these executables where NAME is created with
1711   // CreateNamedPipe.  This would bypass the internal buffering of the
1712   // output and allow it to be captured on the fly.
1713   cmSystemTools::PutEnv("vsconsoleoutput=1");
1714
1715 # ifdef CMAKE_BUILD_WITH_CMAKE
1716   // VS sets an environment variable to tell MS tools like "cl" to report
1717   // output through a backdoor pipe instead of stdout/stderr.  Unset the
1718   // environment variable to close this backdoor for any path of process
1719   // invocations that passes through CMake so we can capture the output.
1720   cmSystemTools::UnsetEnv("VS_UNICODE_OUTPUT");
1721 # endif
1722 #endif
1723 }
1724
1725 bool cmSystemTools::IsPathToFramework(const char* path)
1726 {
1727   if(cmSystemTools::FileIsFullPath(path))
1728     {
1729     std::string libname = path;
1730     if(libname.find(".framework") == libname.size()+1-sizeof(".framework"))
1731       {
1732       return true;
1733       }
1734     }
1735   return false;
1736 }
1737
1738 bool cmSystemTools::CreateTar(const char* outFileName,
1739                               const std::vector<cmStdString>& files,
1740                               bool gzip, bool bzip2, bool verbose)
1741 {
1742 #if defined(CMAKE_BUILD_WITH_CMAKE)
1743   std::string cwd = cmSystemTools::GetCurrentWorkingDirectory();
1744   std::ofstream fout(outFileName, std::ios::out | cmsys_ios_binary);
1745   if(!fout)
1746     {
1747     std::string e = "Cannot open output file \"";
1748     e += outFileName;
1749     e += "\": ";
1750     e += cmSystemTools::GetLastSystemError();
1751     cmSystemTools::Error(e.c_str());
1752     return false;
1753     }
1754   cmArchiveWrite a(fout, (gzip? cmArchiveWrite::CompressGZip :
1755                           (bzip2? cmArchiveWrite::CompressBZip2 :
1756                            cmArchiveWrite::CompressNone)),
1757                            cmArchiveWrite::TypeTAR);
1758   a.SetVerbose(verbose);
1759   for(std::vector<cmStdString>::const_iterator i = files.begin();
1760       i != files.end(); ++i)
1761     {
1762     std::string path = *i;
1763     if(cmSystemTools::FileIsFullPath(path.c_str()))
1764       {
1765       // Get the relative path to the file.
1766       path = cmSystemTools::RelativePath(cwd.c_str(), path.c_str());
1767       }
1768     if(!a.Add(path))
1769       {
1770       break;
1771       }
1772     }
1773   if(!a)
1774     {
1775     cmSystemTools::Error(a.GetError().c_str());
1776     return false;
1777     }
1778   return true;
1779 #else
1780   (void)outFileName;
1781   (void)files;
1782   (void)gzip;
1783   (void)verbose;
1784   return false;
1785 #endif
1786 }
1787
1788 #if defined(CMAKE_BUILD_WITH_CMAKE)
1789 namespace{
1790 #define BSDTAR_FILESIZE_PRINTF  "%lu"
1791 #define BSDTAR_FILESIZE_TYPE    unsigned long
1792   void
1793     list_item_verbose(FILE *out, struct archive_entry *entry)
1794 {
1795   char                   tmp[100];
1796   size_t                         w;
1797   const char            *p;
1798   const char            *fmt;
1799   time_t                         tim;
1800   static time_t          now;
1801   size_t u_width = 6;
1802   size_t gs_width = 13;
1803
1804   /*
1805    * We avoid collecting the entire list in memory at once by
1806    * listing things as we see them.  However, that also means we can't
1807    * just pre-compute the field widths.  Instead, we start with guesses
1808    * and just widen them as necessary.  These numbers are completely
1809    * arbitrary.
1810    */
1811   if (!now)
1812     {
1813     time(&now);
1814     }
1815   fprintf(out, "%s %d ",
1816           archive_entry_strmode(entry),
1817           archive_entry_nlink(entry));
1818
1819   /* Use uname if it's present, else uid. */
1820   p = archive_entry_uname(entry);
1821   if ((p == NULL) || (*p == '\0'))
1822     {
1823     sprintf(tmp, "%lu ",
1824             (unsigned long)archive_entry_uid(entry));
1825     p = tmp;
1826     }
1827   w = strlen(p);
1828   if (w > u_width)
1829     {
1830     u_width = w;
1831     }
1832   fprintf(out, "%-*s ", (int)u_width, p);
1833   /* Use gname if it's present, else gid. */
1834   p = archive_entry_gname(entry);
1835   if (p != NULL && p[0] != '\0')
1836     {
1837     fprintf(out, "%s", p);
1838     w = strlen(p);
1839     }
1840   else
1841     {
1842     sprintf(tmp, "%lu",
1843             (unsigned long)archive_entry_gid(entry));
1844     w = strlen(tmp);
1845     fprintf(out, "%s", tmp);
1846     }
1847
1848   /*
1849    * Print device number or file size, right-aligned so as to make
1850    * total width of group and devnum/filesize fields be gs_width.
1851    * If gs_width is too small, grow it.
1852    */
1853   if (archive_entry_filetype(entry) == AE_IFCHR
1854       || archive_entry_filetype(entry) == AE_IFBLK)
1855     {
1856     sprintf(tmp, "%lu,%lu",
1857             (unsigned long)archive_entry_rdevmajor(entry),
1858             (unsigned long)archive_entry_rdevminor(entry));
1859     }
1860   else
1861     {
1862     /*
1863      * Note the use of platform-dependent macros to format
1864      * the filesize here.  We need the format string and the
1865      * corresponding type for the cast.
1866      */
1867     sprintf(tmp, BSDTAR_FILESIZE_PRINTF,
1868             (BSDTAR_FILESIZE_TYPE)archive_entry_size(entry));
1869     }
1870   if (w + strlen(tmp) >= gs_width)
1871     {
1872     gs_width = w+strlen(tmp)+1;
1873     }
1874   fprintf(out, "%*s", (int)(gs_width - w), tmp);
1875
1876   /* Format the time using 'ls -l' conventions. */
1877   tim = archive_entry_mtime(entry);
1878 #define HALF_YEAR (time_t)365 * 86400 / 2
1879 #if defined(_WIN32) && !defined(__CYGWIN__)
1880   /* Windows' strftime function does not support %e format. */
1881 #define DAY_FMT  "%d"
1882 #else
1883 #define DAY_FMT  "%e"  /* Day number without leading zeros */
1884 #endif
1885   if (tim < now - HALF_YEAR || tim > now + HALF_YEAR)
1886     {
1887     fmt = DAY_FMT " %b  %Y";
1888     }
1889   else
1890     {
1891     fmt = DAY_FMT " %b %H:%M";
1892     }
1893   strftime(tmp, sizeof(tmp), fmt, localtime(&tim));
1894   fprintf(out, " %s ", tmp);
1895   fprintf(out, "%s", archive_entry_pathname(entry));
1896
1897   /* Extra information for links. */
1898   if (archive_entry_hardlink(entry)) /* Hard link */
1899     {
1900     fprintf(out, " link to %s",
1901             archive_entry_hardlink(entry));
1902     }
1903   else if (archive_entry_symlink(entry)) /* Symbolic link */
1904     {
1905     fprintf(out, " -> %s", archive_entry_symlink(entry));
1906     }
1907 }
1908 #ifdef __BORLANDC__
1909 # pragma warn -8066 /* unreachable code */
1910 #endif
1911
1912 long copy_data(struct archive *ar, struct archive *aw)
1913 {
1914   long r;
1915   const void *buff;
1916   size_t size;
1917 #if defined(ARCHIVE_VERSION_NUMBER) && ARCHIVE_VERSION_NUMBER >= 3000000
1918   __LA_INT64_T offset;
1919 #else
1920   off_t offset;
1921 #endif
1922
1923   for (;;)
1924     {
1925     r = archive_read_data_block(ar, &buff, &size, &offset);
1926     if (r == ARCHIVE_EOF)
1927       {
1928       return (ARCHIVE_OK);
1929       }
1930     if (r != ARCHIVE_OK)
1931       {
1932       return (r);
1933       }
1934     r = archive_write_data_block(aw, buff, size, offset);
1935     if (r != ARCHIVE_OK)
1936       {
1937       cmSystemTools::Message("archive_write_data_block()",
1938                              archive_error_string(aw));
1939       return (r);
1940       }
1941     }
1942   return r;
1943 }
1944
1945 bool extract_tar(const char* outFileName, bool verbose,
1946                  bool extract)
1947 {
1948   struct archive* a = archive_read_new();
1949   struct archive *ext = archive_write_disk_new();
1950   archive_read_support_compression_all(a);
1951   archive_read_support_format_all(a);
1952   struct archive_entry *entry;
1953   int r = archive_read_open_file(a, outFileName, 10240);
1954   if(r)
1955     {
1956     cmSystemTools::Error("Problem with archive_read_open_file(): ",
1957                          archive_error_string(a));
1958     return false;
1959     }
1960   for (;;)
1961     {
1962     r = archive_read_next_header(a, &entry);
1963     if (r == ARCHIVE_EOF)
1964       {
1965       break;
1966       }
1967     if (r != ARCHIVE_OK)
1968       {
1969       cmSystemTools::Error("Problem with archive_read_next_header(): ",
1970                            archive_error_string(a));
1971       break;
1972       }
1973     if (verbose && extract)
1974       {
1975       cmSystemTools::Stdout("x ");
1976       cmSystemTools::Stdout(archive_entry_pathname(entry));
1977       }
1978     if(verbose && !extract)
1979       {
1980       list_item_verbose(stdout, entry);
1981       }
1982     else if(!extract)
1983       {
1984       cmSystemTools::Stdout(archive_entry_pathname(entry));
1985       }
1986     if(extract)
1987       {
1988       r = archive_write_disk_set_options(ext, ARCHIVE_EXTRACT_TIME);
1989       if (r != ARCHIVE_OK)
1990         {
1991         cmSystemTools::Error(
1992           "Problem with archive_write_disk_set_options(): ",
1993           archive_error_string(ext));
1994         break;
1995         }
1996
1997       r = archive_write_header(ext, entry);
1998       if (r != ARCHIVE_OK)
1999         {
2000         cmSystemTools::Error("Problem with archive_write_header(): ",
2001                              archive_error_string(ext));
2002         cmSystemTools::Error("Current file: ",
2003                              archive_entry_pathname(entry));
2004         break;
2005         }
2006       else
2007         {
2008         copy_data(a, ext);
2009         r = archive_write_finish_entry(ext);
2010         if (r != ARCHIVE_OK)
2011           {
2012           cmSystemTools::Error("Problem with archive_write_finish_entry(): ",
2013                                archive_error_string(ext));
2014           break;
2015           }
2016         }
2017       }
2018     if (verbose || !extract)
2019       {
2020       cmSystemTools::Stdout("\n");
2021       }
2022     }
2023   archive_read_close(a);
2024   archive_read_finish(a);
2025   return r == ARCHIVE_EOF || r == ARCHIVE_OK;
2026 }
2027 }
2028 #endif
2029
2030 bool cmSystemTools::ExtractTar(const char* outFileName,
2031                                bool , bool verbose)
2032 {
2033 #if defined(CMAKE_BUILD_WITH_CMAKE)
2034   return extract_tar(outFileName, verbose, true);
2035 #else
2036   (void)outFileName;
2037   (void)verbose;
2038   return false;
2039 #endif
2040 }
2041
2042 bool cmSystemTools::ListTar(const char* outFileName,
2043                             bool ,
2044                             bool verbose)
2045 {
2046 #if defined(CMAKE_BUILD_WITH_CMAKE)
2047   return extract_tar(outFileName, verbose, false);
2048 #else
2049   (void)outFileName;
2050   (void)verbose;
2051   return false;
2052 #endif
2053 }
2054
2055 int cmSystemTools::WaitForLine(cmsysProcess* process, std::string& line,
2056                                double timeout,
2057                                std::vector<char>& out,
2058                                std::vector<char>& err)
2059 {
2060   line = "";
2061   std::vector<char>::iterator outiter = out.begin();
2062   std::vector<char>::iterator erriter = err.begin();
2063   while(1)
2064     {
2065     // Check for a newline in stdout.
2066     for(;outiter != out.end(); ++outiter)
2067       {
2068       if((*outiter == '\r') && ((outiter+1) == out.end()))
2069         {
2070         break;
2071         }
2072       else if(*outiter == '\n' || *outiter == '\0')
2073         {
2074         std::vector<char>::size_type length = outiter-out.begin();
2075         if(length > 1 && *(outiter-1) == '\r')
2076           {
2077           --length;
2078           }
2079         if(length > 0)
2080           {
2081           line.append(&out[0], length);
2082           }
2083         out.erase(out.begin(), outiter+1);
2084         return cmsysProcess_Pipe_STDOUT;
2085         }
2086       }
2087
2088     // Check for a newline in stderr.
2089     for(;erriter != err.end(); ++erriter)
2090       {
2091       if((*erriter == '\r') && ((erriter+1) == err.end()))
2092         {
2093         break;
2094         }
2095       else if(*erriter == '\n' || *erriter == '\0')
2096         {
2097         std::vector<char>::size_type length = erriter-err.begin();
2098         if(length > 1 && *(erriter-1) == '\r')
2099           {
2100           --length;
2101           }
2102         if(length > 0)
2103           {
2104           line.append(&err[0], length);
2105           }
2106         err.erase(err.begin(), erriter+1);
2107         return cmsysProcess_Pipe_STDERR;
2108         }
2109       }
2110
2111     // No newlines found.  Wait for more data from the process.
2112     int length;
2113     char* data;
2114     int pipe = cmsysProcess_WaitForData(process, &data, &length, &timeout);
2115     if(pipe == cmsysProcess_Pipe_Timeout)
2116       {
2117       // Timeout has been exceeded.
2118       return pipe;
2119       }
2120     else if(pipe == cmsysProcess_Pipe_STDOUT)
2121       {
2122       // Append to the stdout buffer.
2123       std::vector<char>::size_type size = out.size();
2124       out.insert(out.end(), data, data+length);
2125       outiter = out.begin()+size;
2126       }
2127     else if(pipe == cmsysProcess_Pipe_STDERR)
2128       {
2129       // Append to the stderr buffer.
2130       std::vector<char>::size_type size = err.size();
2131       err.insert(err.end(), data, data+length);
2132       erriter = err.begin()+size;
2133       }
2134     else if(pipe == cmsysProcess_Pipe_None)
2135       {
2136       // Both stdout and stderr pipes have broken.  Return leftover data.
2137       if(!out.empty())
2138         {
2139         line.append(&out[0], outiter-out.begin());
2140         out.erase(out.begin(), out.end());
2141         return cmsysProcess_Pipe_STDOUT;
2142         }
2143       else if(!err.empty())
2144         {
2145         line.append(&err[0], erriter-err.begin());
2146         err.erase(err.begin(), err.end());
2147         return cmsysProcess_Pipe_STDERR;
2148         }
2149       else
2150         {
2151         return cmsysProcess_Pipe_None;
2152         }
2153       }
2154     }
2155 }
2156
2157 void cmSystemTools::DoNotInheritStdPipes()
2158 {
2159 #ifdef _WIN32
2160   // Check to see if we are attached to a console
2161   // if so, then do not stop the inherited pipes
2162   // or stdout and stderr will not show up in dos
2163   // shell windows
2164   CONSOLE_SCREEN_BUFFER_INFO hOutInfo;
2165   HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);
2166   if(GetConsoleScreenBufferInfo(hOut, &hOutInfo))
2167     {
2168     return;
2169     }
2170   {
2171   HANDLE out = GetStdHandle(STD_OUTPUT_HANDLE);
2172   DuplicateHandle(GetCurrentProcess(), out,
2173                   GetCurrentProcess(), &out, 0, FALSE,
2174                   DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
2175   SetStdHandle(STD_OUTPUT_HANDLE, out);
2176   }
2177   {
2178   HANDLE out = GetStdHandle(STD_ERROR_HANDLE);
2179   DuplicateHandle(GetCurrentProcess(), out,
2180                   GetCurrentProcess(), &out, 0, FALSE,
2181                   DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE);
2182   SetStdHandle(STD_ERROR_HANDLE, out);
2183   }
2184 #endif
2185 }
2186
2187 //----------------------------------------------------------------------------
2188 bool cmSystemTools::CopyFileTime(const char* fromFile, const char* toFile)
2189 {
2190 #if defined(_WIN32) && !defined(__CYGWIN__)
2191   cmSystemToolsWindowsHandle hFrom =
2192     CreateFile(fromFile, GENERIC_READ, FILE_SHARE_READ, 0,
2193                OPEN_EXISTING, 0, 0);
2194   cmSystemToolsWindowsHandle hTo =
2195     CreateFile(toFile, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
2196   if(!hFrom || !hTo)
2197     {
2198     return false;
2199     }
2200   FILETIME timeCreation;
2201   FILETIME timeLastAccess;
2202   FILETIME timeLastWrite;
2203   if(!GetFileTime(hFrom, &timeCreation, &timeLastAccess, &timeLastWrite))
2204     {
2205     return false;
2206     }
2207   if(!SetFileTime(hTo, &timeCreation, &timeLastAccess, &timeLastWrite))
2208     {
2209     return false;
2210     }
2211 #else
2212   struct stat fromStat;
2213   if(stat(fromFile, &fromStat) < 0)
2214     {
2215     return false;
2216     }
2217
2218   struct utimbuf buf;
2219   buf.actime = fromStat.st_atime;
2220   buf.modtime = fromStat.st_mtime;
2221   if(utime(toFile, &buf) < 0)
2222     {
2223     return false;
2224     }
2225 #endif
2226   return true;
2227 }
2228
2229 //----------------------------------------------------------------------------
2230 cmSystemToolsFileTime* cmSystemTools::FileTimeNew()
2231 {
2232   return new cmSystemToolsFileTime;
2233 }
2234
2235 //----------------------------------------------------------------------------
2236 void cmSystemTools::FileTimeDelete(cmSystemToolsFileTime* t)
2237 {
2238   delete t;
2239 }
2240
2241 //----------------------------------------------------------------------------
2242 bool cmSystemTools::FileTimeGet(const char* fname, cmSystemToolsFileTime* t)
2243 {
2244 #if defined(_WIN32) && !defined(__CYGWIN__)
2245   cmSystemToolsWindowsHandle h =
2246     CreateFile(fname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
2247   if(!h)
2248     {
2249     return false;
2250     }
2251   if(!GetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
2252     {
2253     return false;
2254     }
2255 #else
2256   struct stat st;
2257   if(stat(fname, &st) < 0)
2258     {
2259     return false;
2260     }
2261   t->timeBuf.actime = st.st_atime;
2262   t->timeBuf.modtime = st.st_mtime;
2263 #endif
2264   return true;
2265 }
2266
2267 //----------------------------------------------------------------------------
2268 bool cmSystemTools::FileTimeSet(const char* fname, cmSystemToolsFileTime* t)
2269 {
2270 #if defined(_WIN32) && !defined(__CYGWIN__)
2271   cmSystemToolsWindowsHandle h =
2272     CreateFile(fname, GENERIC_WRITE, 0, 0, OPEN_EXISTING, 0, 0);
2273   if(!h)
2274     {
2275     return false;
2276     }
2277   if(!SetFileTime(h, &t->timeCreation, &t->timeLastAccess, &t->timeLastWrite))
2278     {
2279     return false;
2280     }
2281 #else
2282   if(utime(fname, &t->timeBuf) < 0)
2283     {
2284     return false;
2285     }
2286 #endif
2287   return true;
2288 }
2289
2290 //----------------------------------------------------------------------------
2291 #ifdef _WIN32
2292 # ifndef CRYPT_SILENT
2293 #  define CRYPT_SILENT 0x40 /* Not defined by VS 6 version of header.  */
2294 # endif
2295 static int WinCryptRandom(void* data, size_t size)
2296 {
2297   int result = 0;
2298   HCRYPTPROV hProvider = 0;
2299   if(CryptAcquireContextW(&hProvider, 0, 0, PROV_RSA_FULL,
2300                           CRYPT_VERIFYCONTEXT | CRYPT_SILENT))
2301     {
2302     result = CryptGenRandom(hProvider, (DWORD)size, (BYTE*)data)? 1:0;
2303     CryptReleaseContext(hProvider, 0);
2304     }
2305   return result;
2306 }
2307 #endif
2308
2309 //----------------------------------------------------------------------------
2310 unsigned int cmSystemTools::RandomSeed()
2311 {
2312 #if defined(_WIN32) && !defined(__CYGWIN__)
2313   unsigned int seed = 0;
2314
2315   // Try using a real random source.
2316   if(WinCryptRandom(&seed, sizeof(seed)))
2317     {
2318     return seed;
2319     }
2320
2321   // Fall back to the time and pid.
2322   FILETIME ft;
2323   GetSystemTimeAsFileTime(&ft);
2324   unsigned int t1 = static_cast<unsigned int>(ft.dwHighDateTime);
2325   unsigned int t2 = static_cast<unsigned int>(ft.dwLowDateTime);
2326   unsigned int pid = static_cast<unsigned int>(GetCurrentProcessId());
2327   return t1 ^ t2 ^ pid;
2328 #else
2329   union
2330   {
2331     unsigned int integer;
2332     char bytes[sizeof(unsigned int)];
2333   } seed;
2334
2335   // Try using a real random source.
2336   std::ifstream fin("/dev/urandom");
2337   if(fin && fin.read(seed.bytes, sizeof(seed)) &&
2338      fin.gcount() == sizeof(seed))
2339     {
2340     return seed.integer;
2341     }
2342
2343   // Fall back to the time and pid.
2344   struct timeval t;
2345   gettimeofday(&t, 0);
2346   unsigned int pid = static_cast<unsigned int>(getpid());
2347   unsigned int tv_sec = static_cast<unsigned int>(t.tv_sec);
2348   unsigned int tv_usec = static_cast<unsigned int>(t.tv_usec);
2349   // Since tv_usec never fills more than 11 bits we shift it to fill
2350   // in the slow-changing high-order bits of tv_sec.
2351   return tv_sec ^ (tv_usec << 21) ^ pid;
2352 #endif
2353 }
2354
2355 //----------------------------------------------------------------------------
2356 static std::string cmSystemToolsExecutableDirectory;
2357 void cmSystemTools::FindExecutableDirectory(const char* argv0)
2358 {
2359 #if defined(_WIN32) && !defined(__CYGWIN__)
2360   (void)argv0; // ignore this on windows
2361   char modulepath[_MAX_PATH];
2362   ::GetModuleFileName(NULL, modulepath, sizeof(modulepath));
2363   cmSystemToolsExecutableDirectory =
2364     cmSystemTools::GetFilenamePath(modulepath);
2365   return;
2366 #else
2367   std::string errorMsg;
2368   std::string exe;
2369   if(cmSystemTools::FindProgramPath(argv0, exe, errorMsg))
2370     {
2371     // remove symlinks
2372     exe = cmSystemTools::GetRealPath(exe.c_str());
2373     cmSystemToolsExecutableDirectory =
2374       cmSystemTools::GetFilenamePath(exe.c_str());
2375     }
2376   else
2377     {
2378     // ???
2379     }
2380 #endif
2381 }
2382
2383 //----------------------------------------------------------------------------
2384 const char* cmSystemTools::GetExecutableDirectory()
2385 {
2386   return cmSystemToolsExecutableDirectory.c_str();
2387 }
2388
2389 //----------------------------------------------------------------------------
2390 #if defined(CMAKE_BUILD_WITH_CMAKE)
2391 void cmSystemTools::MakefileColorEcho(int color, const char* message,
2392                                       bool newline, bool enabled)
2393 {
2394   // On some platforms (an MSYS prompt) cmsysTerminal may not be able
2395   // to determine whether the stream is displayed on a tty.  In this
2396   // case it assumes no unless we tell it otherwise.  Since we want
2397   // color messages to be displayed for users we will assume yes.
2398   // However, we can test for some situations when the answer is most
2399   // likely no.
2400   int assumeTTY = cmsysTerminal_Color_AssumeTTY;
2401   if(cmSystemTools::GetEnv("DART_TEST_FROM_DART") ||
2402      cmSystemTools::GetEnv("DASHBOARD_TEST_FROM_CTEST") ||
2403      cmSystemTools::GetEnv("CTEST_INTERACTIVE_DEBUG_MODE"))
2404     {
2405     // Avoid printing color escapes during dashboard builds.
2406     assumeTTY = 0;
2407     }
2408
2409   if(enabled)
2410     {
2411     cmsysTerminal_cfprintf(color | assumeTTY, stdout, "%s%s",
2412                            message, newline? "\n" : "");
2413     }
2414   else
2415     {
2416     // Color is disabled.  Print without color.
2417     fprintf(stdout, "%s%s", message, newline? "\n" : "");
2418     }
2419 }
2420 #endif
2421
2422 //----------------------------------------------------------------------------
2423 bool cmSystemTools::GuessLibrarySOName(std::string const& fullPath,
2424                                        std::string& soname)
2425 {
2426   // For ELF shared libraries use a real parser to get the correct
2427   // soname.
2428 #if defined(CMAKE_USE_ELF_PARSER)
2429   cmELF elf(fullPath.c_str());
2430   if(elf)
2431     {
2432     return elf.GetSOName(soname);
2433     }
2434 #endif
2435
2436   // If the file is not a symlink we have no guess for its soname.
2437   if(!cmSystemTools::FileIsSymlink(fullPath.c_str()))
2438     {
2439     return false;
2440     }
2441   if(!cmSystemTools::ReadSymlink(fullPath.c_str(), soname))
2442     {
2443     return false;
2444     }
2445
2446   // If the symlink has a path component we have no guess for the soname.
2447   if(!cmSystemTools::GetFilenamePath(soname).empty())
2448     {
2449     return false;
2450     }
2451
2452   // If the symlink points at an extended version of the same name
2453   // assume it is the soname.
2454   std::string name = cmSystemTools::GetFilenameName(fullPath);
2455   if(soname.length() > name.length() &&
2456      soname.substr(0, name.length()) == name)
2457     {
2458     return true;
2459     }
2460   return false;
2461 }
2462
2463 //----------------------------------------------------------------------------
2464 bool cmSystemTools::GuessLibraryInstallName(std::string const& fullPath,
2465                                        std::string& soname)
2466 {
2467   std::vector<cmStdString> cmds;
2468   cmds.push_back("otool");
2469   cmds.push_back("-D");
2470   cmds.push_back(fullPath.c_str());
2471
2472   std::string output;
2473   if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
2474     {
2475     cmds.insert(cmds.begin(), "-r");
2476     cmds.insert(cmds.begin(), "xcrun");
2477     if(!RunSingleCommand(cmds, &output, 0, 0, OUTPUT_NONE))
2478       {
2479       return false;
2480       }
2481     }
2482
2483   std::vector<std::string> strs = cmSystemTools::tokenize(output, "\n");
2484   // otool returns extra lines reporting multiple install names
2485   // in case the binary is multi-arch and none of the architectures
2486   // is native (e.g. i386;ppc on x86_64)
2487   if(strs.size() >= 2)
2488     {
2489     soname = strs[1];
2490     return true;
2491     }
2492   return false;
2493 }
2494
2495 //----------------------------------------------------------------------------
2496 #if defined(CMAKE_USE_ELF_PARSER)
2497 std::string::size_type cmSystemToolsFindRPath(std::string const& have,
2498                                               std::string const& want)
2499 {
2500   // Search for the desired rpath.
2501   std::string::size_type pos = have.find(want);
2502
2503   // If the path is not present we are done.
2504   if(pos == std::string::npos)
2505     {
2506     return pos;
2507     }
2508
2509   // Build a regex to match a properly separated path instance.
2510   std::string regex_str = "(^|:)(";
2511   for(std::string::const_iterator i = want.begin(); i != want.end(); ++i)
2512     {
2513     int ch = *i;
2514     if(!(('a' <= ch && ch <= 'z') ||
2515          ('A' <= ch && ch <= 'Z') ||
2516          ('0' <= ch && ch <= '9')))
2517       {
2518       // Escape the non-alphanumeric character.
2519       regex_str += "\\";
2520       }
2521     // Store the character.
2522     regex_str.append(1, static_cast<char>(ch));
2523     }
2524   regex_str += ")(:|$)";
2525
2526   // Look for the separated path.
2527   cmsys::RegularExpression regex(regex_str.c_str());
2528   if(regex.find(have))
2529     {
2530     // Return the position of the path portion.
2531     return regex.start(2);
2532     }
2533   else
2534     {
2535     // The desired rpath was not found.
2536     return std::string::npos;
2537     }
2538 }
2539 #endif
2540
2541 #if defined(CMAKE_USE_ELF_PARSER)
2542 struct cmSystemToolsRPathInfo
2543 {
2544   unsigned long Position;
2545   unsigned long Size;
2546   std::string Name;
2547   std::string Value;
2548 };
2549 #endif
2550
2551 //----------------------------------------------------------------------------
2552 bool cmSystemTools::ChangeRPath(std::string const& file,
2553                                 std::string const& oldRPath,
2554                                 std::string const& newRPath,
2555                                 std::string* emsg,
2556                                 bool* changed)
2557 {
2558 #if defined(CMAKE_USE_ELF_PARSER)
2559   if(changed)
2560     {
2561     *changed = false;
2562     }
2563   int rp_count = 0;
2564   cmSystemToolsRPathInfo rp[2];
2565   {
2566   // Parse the ELF binary.
2567   cmELF elf(file.c_str());
2568
2569   // Get the RPATH and RUNPATH entries from it.
2570   int se_count = 0;
2571   cmELF::StringEntry const* se[2] = {0, 0};
2572   const char* se_name[2] = {0, 0};
2573   if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
2574     {
2575     se[se_count] = se_rpath;
2576     se_name[se_count] = "RPATH";
2577     ++se_count;
2578     }
2579   if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
2580     {
2581     se[se_count] = se_runpath;
2582     se_name[se_count] = "RUNPATH";
2583     ++se_count;
2584     }
2585   if(se_count == 0)
2586     {
2587     if(newRPath.empty())
2588       {
2589       // The new rpath is empty and there is no rpath anyway so it is
2590       // okay.
2591       return true;
2592       }
2593     else
2594       {
2595       if(emsg)
2596         {
2597         *emsg = "No valid ELF RPATH or RUNPATH entry exists in the file; ";
2598         *emsg += elf.GetErrorMessage();
2599         }
2600       return false;
2601       }
2602     }
2603
2604   for(int i=0; i < se_count; ++i)
2605     {
2606     // If both RPATH and RUNPATH refer to the same string literal it
2607     // needs to be changed only once.
2608     if(rp_count && rp[0].Position == se[i]->Position)
2609       {
2610       continue;
2611       }
2612
2613     // Make sure the current rpath contains the old rpath.
2614     std::string::size_type pos =
2615       cmSystemToolsFindRPath(se[i]->Value, oldRPath);
2616     if(pos == std::string::npos)
2617       {
2618       // If it contains the new rpath instead then it is okay.
2619       if(cmSystemToolsFindRPath(se[i]->Value, newRPath) != std::string::npos)
2620         {
2621         continue;
2622         }
2623       if(emsg)
2624         {
2625         cmOStringStream e;
2626         e << "The current " << se_name[i] << " is:\n"
2627           << "  " << se[i]->Value << "\n"
2628           << "which does not contain:\n"
2629           << "  " << oldRPath << "\n"
2630           << "as was expected.";
2631         *emsg = e.str();
2632         }
2633       return false;
2634       }
2635
2636     // Store information about the entry in the file.
2637     rp[rp_count].Position = se[i]->Position;
2638     rp[rp_count].Size = se[i]->Size;
2639     rp[rp_count].Name = se_name[i];
2640
2641     // Construct the new value which preserves the part of the path
2642     // not being changed.
2643     rp[rp_count].Value = se[i]->Value.substr(0, pos);
2644     rp[rp_count].Value += newRPath;
2645     rp[rp_count].Value += se[i]->Value.substr(pos+oldRPath.length(),
2646                                               oldRPath.npos);
2647
2648     // Make sure there is enough room to store the new rpath and at
2649     // least one null terminator.
2650     if(rp[rp_count].Size < rp[rp_count].Value.length()+1)
2651       {
2652       if(emsg)
2653         {
2654         *emsg = "The replacement path is too long for the ";
2655         *emsg += se_name[i];
2656         *emsg += " entry.";
2657         }
2658       return false;
2659       }
2660
2661     // This entry is ready for update.
2662     ++rp_count;
2663     }
2664   }
2665
2666   // If no runtime path needs to be changed, we are done.
2667   if(rp_count == 0)
2668     {
2669     return true;
2670     }
2671
2672   {
2673   // Open the file for update.
2674   std::ofstream f(file.c_str(),
2675                   std::ios::in | std::ios::out | std::ios::binary);
2676   if(!f)
2677     {
2678     if(emsg)
2679       {
2680       *emsg = "Error opening file for update.";
2681       }
2682     return false;
2683     }
2684
2685   // Store the new RPATH and RUNPATH strings.
2686   for(int i=0; i < rp_count; ++i)
2687     {
2688     // Seek to the RPATH position.
2689     if(!f.seekp(rp[i].Position))
2690       {
2691       if(emsg)
2692         {
2693         *emsg = "Error seeking to ";
2694         *emsg += rp[i].Name;
2695         *emsg += " position.";
2696         }
2697       return false;
2698       }
2699
2700     // Write the new rpath.  Follow it with enough null terminators to
2701     // fill the string table entry.
2702     f << rp[i].Value;
2703     for(unsigned long j=rp[i].Value.length(); j < rp[i].Size; ++j)
2704       {
2705       f << '\0';
2706       }
2707
2708     // Make sure it wrote correctly.
2709     if(!f)
2710       {
2711       if(emsg)
2712         {
2713         *emsg = "Error writing the new ";
2714         *emsg += rp[i].Name;
2715         *emsg += " string to the file.";
2716         }
2717       return false;
2718       }
2719     }
2720   }
2721
2722   // Everything was updated successfully.
2723   if(changed)
2724     {
2725     *changed = true;
2726     }
2727   return true;
2728 #else
2729   (void)file;
2730   (void)oldRPath;
2731   (void)newRPath;
2732   (void)emsg;
2733   (void)changed;
2734   return false;
2735 #endif
2736 }
2737
2738 //----------------------------------------------------------------------------
2739 bool cmSystemTools::VersionCompare(cmSystemTools::CompareOp op,
2740                                    const char* lhss, const char* rhss)
2741 {
2742   // Parse out up to 8 components.
2743   unsigned int lhs[8] = {0,0,0,0,0,0,0,0};
2744   unsigned int rhs[8] = {0,0,0,0,0,0,0,0};
2745   sscanf(lhss, "%u.%u.%u.%u.%u.%u.%u.%u",
2746          &lhs[0], &lhs[1], &lhs[2], &lhs[3],
2747          &lhs[4], &lhs[5], &lhs[6], &lhs[7]);
2748   sscanf(rhss, "%u.%u.%u.%u.%u.%u.%u.%u",
2749          &rhs[0], &rhs[1], &rhs[2], &rhs[3],
2750          &rhs[4], &rhs[5], &rhs[6], &rhs[7]);
2751
2752   // Do component-wise comparison.
2753   for(unsigned int i=0; i < 8; ++i)
2754     {
2755     if(lhs[i] < rhs[i])
2756       {
2757       // lhs < rhs, so true if operation is LESS
2758       return op == cmSystemTools::OP_LESS;
2759       }
2760     else if(lhs[i] > rhs[i])
2761       {
2762       // lhs > rhs, so true if operation is GREATER
2763       return op == cmSystemTools::OP_GREATER;
2764       }
2765     }
2766   // lhs == rhs, so true if operation is EQUAL
2767   return op == cmSystemTools::OP_EQUAL;
2768 }
2769
2770 //----------------------------------------------------------------------------
2771 bool cmSystemTools::RemoveRPath(std::string const& file, std::string* emsg,
2772                                 bool* removed)
2773 {
2774 #if defined(CMAKE_USE_ELF_PARSER)
2775   if(removed)
2776     {
2777     *removed = false;
2778     }
2779   int zeroCount = 0;
2780   unsigned long zeroPosition[2] = {0,0};
2781   unsigned long zeroSize[2] = {0,0};
2782   unsigned long bytesBegin = 0;
2783   std::vector<char> bytes;
2784   {
2785   // Parse the ELF binary.
2786   cmELF elf(file.c_str());
2787
2788   // Get the RPATH and RUNPATH entries from it and sort them by index
2789   // in the dynamic section header.
2790   int se_count = 0;
2791   cmELF::StringEntry const* se[2] = {0, 0};
2792   if(cmELF::StringEntry const* se_rpath = elf.GetRPath())
2793     {
2794     se[se_count++] = se_rpath;
2795     }
2796   if(cmELF::StringEntry const* se_runpath = elf.GetRunPath())
2797     {
2798     se[se_count++] = se_runpath;
2799     }
2800   if(se_count == 0)
2801     {
2802     // There is no RPATH or RUNPATH anyway.
2803     return true;
2804     }
2805   if(se_count == 2 && se[1]->IndexInSection < se[0]->IndexInSection)
2806     {
2807     cmsys_stl::swap(se[0], se[1]);
2808     }
2809
2810   // Get the size of the dynamic section header.
2811   unsigned int count = elf.GetDynamicEntryCount();
2812   if(count == 0)
2813     {
2814     // This should happen only for invalid ELF files where a DT_NULL
2815     // appears before the end of the table.
2816     if(emsg)
2817       {
2818       *emsg = "DYNAMIC section contains a DT_NULL before the end.";
2819       }
2820     return false;
2821     }
2822
2823   // Save information about the string entries to be zeroed.
2824   zeroCount = se_count;
2825   for(int i=0; i < se_count; ++i)
2826     {
2827     zeroPosition[i] = se[i]->Position;
2828     zeroSize[i] = se[i]->Size;
2829     }
2830
2831   // Get the range of file positions corresponding to each entry and
2832   // the rest of the table after them.
2833   unsigned long entryBegin[3] = {0,0,0};
2834   unsigned long entryEnd[2] = {0,0};
2835   for(int i=0; i < se_count; ++i)
2836     {
2837     entryBegin[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection);
2838     entryEnd[i] = elf.GetDynamicEntryPosition(se[i]->IndexInSection+1);
2839     }
2840   entryBegin[se_count] = elf.GetDynamicEntryPosition(count);
2841
2842   // The data are to be written over the old table entries starting at
2843   // the first one being removed.
2844   bytesBegin = entryBegin[0];
2845   unsigned long bytesEnd = entryBegin[se_count];
2846
2847   // Allocate a buffer to hold the part of the file to be written.
2848   // Initialize it with zeros.
2849   bytes.resize(bytesEnd - bytesBegin, 0);
2850
2851   // Read the part of the DYNAMIC section header that will move.
2852   // The remainder of the buffer will be left with zeros which
2853   // represent a DT_NULL entry.
2854   char* data = &bytes[0];
2855   for(int i=0; i < se_count; ++i)
2856     {
2857     // Read data between the entries being removed.
2858     unsigned long sz = entryBegin[i+1] - entryEnd[i];
2859     if(sz > 0 && !elf.ReadBytes(entryEnd[i], sz, data))
2860       {
2861       if(emsg)
2862         {
2863         *emsg = "Failed to read DYNAMIC section header.";
2864         }
2865       return false;
2866       }
2867     data += sz;
2868     }
2869   }
2870
2871   // Open the file for update.
2872   std::ofstream f(file.c_str(),
2873                   std::ios::in | std::ios::out | std::ios::binary);
2874   if(!f)
2875     {
2876     if(emsg)
2877       {
2878       *emsg = "Error opening file for update.";
2879       }
2880     return false;
2881     }
2882
2883   // Write the new DYNAMIC table header.
2884   if(!f.seekp(bytesBegin))
2885     {
2886     if(emsg)
2887       {
2888       *emsg = "Error seeking to DYNAMIC table header for RPATH.";
2889       }
2890     return false;
2891     }
2892   if(!f.write(&bytes[0], bytes.size()))
2893     {
2894     if(emsg)
2895       {
2896       *emsg = "Error replacing DYNAMIC table header.";
2897       }
2898     return false;
2899     }
2900
2901   // Fill the RPATH and RUNPATH strings with zero bytes.
2902   for(int i=0; i < zeroCount; ++i)
2903     {
2904     if(!f.seekp(zeroPosition[i]))
2905       {
2906       if(emsg)
2907         {
2908         *emsg = "Error seeking to RPATH position.";
2909         }
2910       return false;
2911       }
2912     for(unsigned long j=0; j < zeroSize[i]; ++j)
2913       {
2914       f << '\0';
2915       }
2916     if(!f)
2917       {
2918       if(emsg)
2919         {
2920         *emsg = "Error writing the empty rpath string to the file.";
2921         }
2922       return false;
2923       }
2924     }
2925
2926   // Everything was updated successfully.
2927   if(removed)
2928     {
2929     *removed = true;
2930     }
2931   return true;
2932 #else
2933   (void)file;
2934   (void)emsg;
2935   (void)removed;
2936   return false;
2937 #endif
2938 }
2939
2940 //----------------------------------------------------------------------------
2941 bool cmSystemTools::CheckRPath(std::string const& file,
2942                                std::string const& newRPath)
2943 {
2944 #if defined(CMAKE_USE_ELF_PARSER)
2945   // Parse the ELF binary.
2946   cmELF elf(file.c_str());
2947
2948   // Get the RPATH or RUNPATH entry from it.
2949   cmELF::StringEntry const* se = elf.GetRPath();
2950   if(!se)
2951     {
2952     se = elf.GetRunPath();
2953     }
2954
2955   // Make sure the current rpath contains the new rpath.
2956   if(newRPath.empty())
2957     {
2958     if(!se)
2959       {
2960       return true;
2961       }
2962     }
2963   else
2964     {
2965     if(se &&
2966        cmSystemToolsFindRPath(se->Value, newRPath) != std::string::npos)
2967       {
2968       return true;
2969       }
2970     }
2971   return false;
2972 #else
2973   (void)file;
2974   (void)newRPath;
2975   return false;
2976 #endif
2977 }
2978
2979 //----------------------------------------------------------------------------
2980 bool cmSystemTools::RepeatedRemoveDirectory(const char* dir)
2981 {
2982   // Windows sometimes locks files temporarily so try a few times.
2983   for(int i = 0; i < 10; ++i)
2984     {
2985     if(cmSystemTools::RemoveADirectory(dir))
2986       {
2987       return true;
2988       }
2989     cmSystemTools::Delay(100);
2990     }
2991   return false;
2992 }
2993
2994 //----------------------------------------------------------------------------
2995 std::vector<std::string> cmSystemTools::tokenize(const std::string& str,
2996                                   const std::string& sep)
2997 {
2998   std::vector<std::string> tokens;
2999   std::string::size_type tokend = 0;
3000
3001   do
3002     {
3003     std::string::size_type tokstart=str.find_first_not_of(sep, tokend);
3004     if (tokstart==std::string::npos)
3005       {
3006       break;    // no more tokens
3007       }
3008     tokend=str.find_first_of(sep,tokstart);
3009     if (tokend==std::string::npos)
3010       {
3011       tokens.push_back(str.substr(tokstart));
3012       }
3013     else
3014       {
3015       tokens.push_back(str.substr(tokstart,tokend-tokstart));
3016       }
3017     } while (tokend!=std::string::npos);
3018
3019   if (tokens.empty())
3020     {
3021     tokens.push_back("");
3022     }
3023   return tokens;
3024 }