Пример #1
0
        private static IEnumerable <string> /*!*/ GetAbsolutePaths(PlatformAdaptationLayer /*!*/ pal, string /*!*/ path)
        {
            if (pal.IsAbsolutePath(path))
            {
                yield return(path);
            }
            else
            {
                yield return(pal.GetFullPath(path));

                string var = pal.GetEnvironmentVariable("PATH");
                if (!String.IsNullOrEmpty(var))
                {
                    foreach (var prefix in var.Split(Path.PathSeparator))
                    {
                        if (prefix.Length > 0)
                        {
                            yield return(Path.Combine(prefix, path));
                        }
                    }
                }

                var = Environment.GetFolderPath(Environment.SpecialFolder.System);
                if (!String.IsNullOrEmpty(var))
                {
                    yield return(Path.Combine(var, path));
                }

                var = pal.GetEnvironmentVariable("SystemRoot");
                if (!String.IsNullOrEmpty(var))
                {
                    yield return(Path.Combine(var, path));
                }
            }
        }
Пример #2
0
        // Expand directory path - these cases exist:
        //
        // 1. Empty string or nil means return current directory
        // 2. ~ with non-existent HOME directory throws exception
        // 3. ~, ~/ or ~\ which expands to HOME
        // 4. ~foo is left unexpanded
        // 5. Expand to full path if path is a relative path
        //
        // No attempt is made to determine whether the path is valid or not
        // Returned path is always canonicalized to forward slashes

        private static MutableString /*!*/ ExpandPath(RubyContext /*!*/ context, MutableString /*!*/ path)
        {
            PlatformAdaptationLayer pal = context.DomainManager.Platform;
            int length = path.Length;

            try {
                if (path == null || length == 0)
                {
                    return(Glob.CanonicalizePath(MutableString.Create(Directory.GetCurrentDirectory())));
                }

                if (length == 1 && path.GetChar(0) == '~')
                {
                    return(Glob.CanonicalizePath(MutableString.Create(Path.GetFullPath(pal.GetEnvironmentVariable("HOME")))));
                }

                if (path.GetChar(0) == '~' && (path.GetChar(1) == Path.DirectorySeparatorChar || path.GetChar(1) == Path.AltDirectorySeparatorChar))
                {
                    string homeDirectory = pal.GetEnvironmentVariable("HOME");
                    return(Glob.CanonicalizePath(length < 3 ? MutableString.Create(homeDirectory) : MutableString.Create(Path.Combine(homeDirectory, path.GetSlice(2).ConvertToString()))));
                }
                else
                {
                    return(Glob.CanonicalizePath(MutableString.Create(Path.GetFullPath(path.ConvertToString()))));
                }
            } catch (Exception e) {
                // Re-throw exception as a reasonable Ruby exception
                throw new Errno.InvalidError(path.ConvertToString(), e);
            }
        }
Пример #3
0
        public static MutableString GetVariable(RubyContext /*!*/ context, object /*!*/ self, [DefaultProtocol, NotNull] MutableString /*!*/ name)
        {
            PlatformAdaptationLayer pal = context.DomainManager.Platform;
            string value = pal.GetEnvironmentVariable(name.ConvertToString());

            return((value != null) ? FrozenString(context, value) : null);
        }
Пример #4
0
        // Algorithm to find HOME equivalents under Windows. This is equivalent to Ruby 1.9 behavior:
        //
        // 1. Try get HOME
        // 2. Try to generate HOME equivalent using HOMEDRIVE + HOMEPATH
        // 3. Try to generate HOME equivalent from USERPROFILE
        // 4. Try to generate HOME equivalent from Personal special folder

        internal static string /*!*/ GetHomeDirectory(RubyContext /*!*/ context)
        {
            PlatformAdaptationLayer pal = context.DomainManager.Platform;
            string result = pal.GetEnvironmentVariable("HOME");

            if (result == null)
            {
                string homeDrive = pal.GetEnvironmentVariable("HOMEDRIVE");
                string homePath  = pal.GetEnvironmentVariable("HOMEPATH");
                if (homeDrive == null && homePath == null)
                {
                    string userEnvironment = pal.GetEnvironmentVariable("USERPROFILE");
                    if (userEnvironment == null)
                    {
                        // This will always succeed with a non-null string, but it can fail
                        // if the Personal folder was renamed or deleted. In this case it returns
                        // an empty string.
                        result = Environment.GetFolderPath(Environment.SpecialFolder.Personal);
                    }
                    else
                    {
                        result = userEnvironment;
                    }
                }
                else if (homeDrive == null)
                {
                    result = homePath;
                }
                else if (homePath == null)
                {
                    result = homeDrive;
                }
                else
                {
                    result = Path.Combine(homeDrive, homePath);
                }
            }
            return(result);
        }
Пример #5
0
        private static void GetExecutable(PlatformAdaptationLayer /*!*/ pal, string /*!*/ command, out string executable, out string arguments)
        {
            command = command.Trim(' ');
            if (command.Length == 0)
            {
                throw RubyExceptions.CreateEINVAL(command);
            }

            // This seems to be quite complicated:
            // 1) If the first part of the command is a shell command (DIR, ECHO, ...) or
            //    if the command contains unquoted <, > or | then
            //    it uses ENV['COMSPEC'] to execute the command: %COMSPEC% /c "COMMAND"
            // 2) It looks for the shortest prefix of command that is separated by space from the rest of the command that is either
            //      a) An absolute path to an executable file.
            //      b) Try prepend paths from ENV['PATH']
            //      c) Try Environment.SpecialFolder.System.
            //      d) Try SHGetFolderPath(CSIDL_WINDOWS) - we can't get this from Environment.SpecialFolder, so we need to use
            //         ENV["SystemRoot"] environment variable.
            //    In each step it tries to append ".exe" or ".com" extension if the path doesn't exist.
            //
            //    For example, if the command is `x/a b/x` and the directory structure is
            //      x\a b\x.exe
            //      x\a.exe
            //    it executes a.exe.
            //
            //    MRI probably calls CreateProcess Win32 API with lpApplicationName it resolves as described above and
            //    lpCommandLine == command. System.Diagnostics.Process also uses this API with lpApplicationName == NULL and
            //    lpCommandLine == '"{ProcessStartInfo.FileName}" {ProcessStartInfo.Arguments}'.
            //
            //    Although CreateProcess does all the searching for an executable if passed no lpApplicationName,
            //    we need to do it ourselves because it is slightly different in MRI (is that a bug?) and also because System.Diagnostics.Process
            //    quotes the FileName :(
            //

            string comspec = pal.GetEnvironmentVariable("COMSPEC");

            if (!pal.FileExists(comspec))
            {
                comspec = null;
            }

            if (comspec != null && IndexOfUnquotedSpecialCharacter(command) >= 0)
            {
                executable = comspec;
                arguments  = "/c \"" + command + "\"";
                return;
            }

            int start = 0;

            while (true)
            {
                int next = command.IndexOf(' ', start);

                executable = (next >= 0) ? command.Substring(0, next) : command;
                arguments  = (next >= 0) ? command.Substring(next + 1) : "";

                if (start == 0 && comspec != null && IsShellCommand(executable))
                {
                    executable = comspec;
                    arguments  = "/c \"" + command + "\"";
                    return;
                }

                try {
                    foreach (var path in GetExecutableFiles(pal, executable))
                    {
                        if (pal.FileExists(path))
                        {
                            // We need to set the path we found as executable. Althought makes command line of the target process
                            // different from when called by MRI it will execute the right process. If we passed the original executable name
                            // CreateProcess might resolve it to a different executable.
                            executable = path;
                            return;
                        }
                    }
                } catch (Exception e) {
                    if (next < 0)
                    {
                        throw RubyExceptions.CreateENOENT(command, e);
                    }
                }

                if (next < 0)
                {
                    throw RubyExceptions.CreateENOENT(command);
                }

                start = next + 1;
                while (start < command.Length && command[start] == ' ')
                {
                    start++;
                }
            }
        }
Пример #6
0
        public static bool HasKey(RubyContext /*!*/ context, object /*!*/ self, [DefaultProtocol, NotNull] MutableString /*!*/ key)
        {
            PlatformAdaptationLayer pal = context.DomainManager.Platform;

            return(pal.GetEnvironmentVariable(key.ConvertToString()) != null);
        }