Skip to content

Instantly share code, notes, and snippets.

@ftk
Last active February 3, 2019 14:52
Show Gist options
  • Save ftk/e55ad62656baca20c2aa2c05c5f75f0d to your computer and use it in GitHub Desktop.
Save ftk/e55ad62656baca20c2aa2c05c5f75f0d to your computer and use it in GitHub Desktop.
Wrapper for windows subsystem for linux: run ubuntu applications from windows
// Wrapper for windows subsystem for linux (Bash on Ubuntu on Windows)
// It allows running native ubuntu applications from Windows
// 1. Compile (on windows, the command below is for mingw-gcc):
// g++ -O3 -flto -fwhole-program -fvisibility=hidden -fno-exceptions -fno-rtti -s win2lin.cpp -o win2lin.exe
// 2. make a copy for each program
// for i in git python perl; do cp win2lin.exe ${i}.exe; done
// 3. put directory with exes in windows PATH
// 4. example (from cmd.exe):
// cat "c:\test 1.txt"
// will be translated to: bash -c "exec cat \"/mnt/c/test 1.txt\""
// Warning: single quotes might not work
// 5. for debugging you can set enviroment variable W2L_LOG=c:/w2l.log
//
#include <cstdio>
#include <cstdlib>
#include <string>
#include <algorithm>
#include <cctype>
#include <cstring>
unsigned StrSize(const std::string& str)
{
return str.size();
}
template <unsigned N>
unsigned StrSize(const char str[N])
{
return N - 1;
}
unsigned StrSize(const char c)
{
return 1;
}
unsigned StrSize(const char * str)
{
return strlen(str);
}
template <typename T1, typename T2>
std::string ReplaceAll(std::string s, const T1 &search, const T2 &replace, std::size_t pos = 0)
{
for( ; ; pos += StrSize(replace)) {
// Locate the substring to replace
pos = s.find(search, pos);
if(pos == std::string::npos) break;
s.replace(pos, StrSize(search), replace);
}
return s;
}
std::string ReplaceAll(std::string s, char search, char replace, std::size_t pos = 0)
{
std::replace(s.begin() + pos, s.end(), search, replace);
return s;
}
std::string Enquote(std::string s)
{
return '"' + ReplaceAll(ReplaceAll(s, '\\', "\\\\"), '"', "\\\"") + '"';
}
std::string Enquote2(std::string s)
{
return (s.find_first_of(" \t\"\\") != std::string::npos) ? Enquote(s) : s;
}
std::string TransformPath(std::string arg)
{
if(arg.find("^^^") == 0)
return arg.substr(3); // do not transform
std::size_t pos = arg.find(":\\");
if(pos > 0 && pos != std::string::npos)
{
/* good: C:\ a=z:\
bad: hello:\ 0:\ 0c:\ :\
*/
if(!isalpha(arg[pos-1]))
return arg;
if(pos >= 2 && isalnum(arg[pos - 2]))
return arg;
// replace C: with /mnt/c
arg.replace(pos - 1, 2, std::string("/mnt/") + static_cast<char>(tolower(arg[pos-1])));
return ReplaceAll(arg, '\\', '/', pos);
}
return arg;
}
int main(int argc, const char * argv[])
{
{
FILE * log = NULL;
if(getenv("W2L_LOG"))
log = fopen(getenv("W2L_LOG"), "a");
if(log)
{
for(int i = 0; i < argc; i++)
{
if(i)
fputs("\t", log);
fputs(argv[i], log);
}
fputs("\n", log);
fclose(log);
}
}
// find executable name
std::string name = argv[0];
// cut path
if(name.find_last_of("\\/") != std::string::npos)
name = name.substr(name.find_last_of("\\/") + 1);
// cut .exe
if(name.size() > 4 && name.rfind(".exe") == name.size() - 4)
{
name = name.substr(0, name.size() - 4);
}
//puts(name.c_str());
std::string args;
for(int i = 1; i < argc; i++)
{
args += ' ';
args += Enquote2(TransformPath(argv[i]));
}
if(getenv("W2L_EXEC"))
{
std::string cmdline = getenv("W2L_EXEC") + name + args;
return system(cmdline.c_str());
}
else
{
std::string bashexe = std::string(getenv("SystemRoot") ? getenv("SystemRoot") : "C:\\Windows") + "\\System32\\bash.exe";
std::string env;
// pass enviroment:
// set "W2L_ENV=DISPLAY=:0 LANG=C"
if(getenv("W2L_ENV"))
env = env + "env " + getenv("W2L_ENV") + ' ';
std::string cmdline = bashexe + " -c " + Enquote("exec " + env + name + args);
//fprintf(stderr, "%s\n", cmdline.c_str());
return system(cmdline.c_str());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment