Skip to content

Commit

Permalink
add .exe shims for programs that only look for .exes (e.g. tar callin…
Browse files Browse the repository at this point in the history
…g gzip)
  • Loading branch information
lukesampson committed Jan 5, 2014
1 parent e728188 commit 5c52166
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 2 deletions.
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# retain windows line-endings in case checked out on mac or linux
* text eol=crlf
*.exe -text
8 changes: 6 additions & 2 deletions lib/core.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,12 @@ function shim($path, $global) {
echo "`$path = '$path'" >> $shim
echo 'if($myinvocation.expectingInput) { $input | & $path @args } else { & $path @args }' >> $shim

if($path -match '\.((exe)|(bat)|(cmd))$') {
# shim .exe, .bat, .cmd so they can be used by programs with no awareness of PSH
if($path -match '\.exe$') {
# for programs with no awareness of any shell
cp "$(versiondir 'scoop' 'current')\supporting\shimexe\shim.exe" "$(strip_ext($shim)).exe" -force
echo "path = $(resolve-path $path)" | out-file "$(strip_ext($shim)).shim" -encoding oem
} elseif($path -match '\.((bat)|(cmd))$') {
# shim .bat, .cmd so they can be used by programs with no awareness of PSH
$shim_cmd = "$(strip_ext($shim)).cmd"
':: ensure $HOME is set for MSYS programs' | out-file $shim_cmd -encoding oem
'@if "%home%"=="" set home=%homedrive%%homepath%\' | out-file $shim_cmd -encoding oem -append
Expand Down
3 changes: 3 additions & 0 deletions supporting/shimexe/build.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
$fwdir = gci C:\Windows\Microsoft.NET\Framework\ -dir | sort -desc | select -first 1

& "$($fwdir.fullname)\csc.exe" /nologo shim.cs
84 changes: 84 additions & 0 deletions supporting/shimexe/shim.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace shim {

class Program {
static int Main(string[] args) {
var exe = Assembly.GetExecutingAssembly().Location;
var dir = Path.GetDirectoryName(exe);
var name = Path.GetFileNameWithoutExtension(exe);

var configPath = Path.Combine(dir, name + ".shim");
if(!File.Exists(configPath)) {
Console.Error.WriteLine("Couldn't find " + Path.GetFileName(configPath) + " in " + dir);
return 1;
}

var config = Config(configPath);
var path = Get(config, "path");

var p = new Process();
p.StartInfo.FileName = path;
p.StartInfo.Arguments = Serialize(args);

p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardError = true;
p.StartInfo.RedirectStandardOutput = true;

p.Start();

ReadChars(p.StandardOutput, Console.Out);
ReadChars(p.StandardError, Console.Error);

p.WaitForExit();
return p.ExitCode;
}

// Once stdout or stderr starts sending, keep forwarding the stream to the console
// until it stops sending. Otherwise the output from both streams is mixed up.
static object sync = new object();
static async void ReadChars(StreamReader r, TextWriter sendTo) {
var buffer = new char[100];
while(true) {
var read = await r.ReadAsync(buffer, 0, buffer.Length);
lock(sync) { // prevent other streams from writing
while(true) {
sendTo.Write(buffer, 0, read);

if(read < buffer.Length) break; // release lock
read = r.Read(buffer, 0, buffer.Length);
}
if(read == 0) return; // EOF
}
}
}

static string Serialize(string[] args) {
return string.Join(" ", args.Select(a => a.Contains(' ') ? '"' + a + '"' : a));
}

static string Get(Dictionary<string, string> dic, string key) {
string value = null;
dic.TryGetValue(key, out value);
return value;
}

static Dictionary<string, string> Config(string path) {
var config = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
foreach(var line in File.ReadAllLines(path)) {
var m = Regex.Match(line, @"([^=]+)=(.*)");
if(m.Success) {
config[m.Groups[1].Value.Trim()] = m.Groups[2].Value.Trim();
}
}
return config;
}
}
}
Binary file added supporting/shimexe/shim.exe
Binary file not shown.

0 comments on commit 5c52166

Please sign in to comment.