Last active
February 3, 2019 14:52
-
-
Save ftk/e55ad62656baca20c2aa2c05c5f75f0d to your computer and use it in GitHub Desktop.
Wrapper for windows subsystem for linux: run ubuntu applications from windows
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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