Skip to content

Instantly share code, notes, and snippets.

@sebgod
Created January 1, 2019 13:47
Show Gist options
  • Save sebgod/3654d7867ca5a0a6acccf45faee6ed05 to your computer and use it in GitHub Desktop.
Save sebgod/3654d7867ca5a0a6acccf45faee6ed05 to your computer and use it in GitHub Desktop.
A wrapper executable to wrap Linux executable files on WSL to be callable from Windows.
#define __STDC_WANT_LIB_EXT1__ 1
#include <stdio.h>
#include <stdlib.h>
#define _GNU_SOURCE
#include <string.h>
#if _WIN32 || _WIN64
# define CDECL __cdecl
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# define GET_CMD_LINE() GetCommandLine()
# define EXEC_CMD(cmd) \
do { \
STARTUPINFO si = { 0 }; \
PROCESS_INFORMATION pi = { 0 }; \
if ( !CreateProcess( \
NULL, /* No module name (use command line) */ \
(cmd), /* Command line */ \
NULL, /* Process handle not inheritable */ \
NULL, /* Thread handle not inheritable */ \
TRUE, /* Set handle inheritance to TRUE */ \
0, /* No creation flags */ \
NULL, /* Use parent's environment block */ \
NULL, /* Use parent's starting directory */ \
&si, /* Pointer to STARTUPINFO structure */ \
&pi ) /* Pointer to PROCESS_INFORMATION structure */ \
) \
{ \
fprintf(stderr, "CreateProcess failed (%d).\n", GetLastError() ); \
return EXIT_FAILURE; \
} \
/* Wait until child process exits. */ \
WaitForSingleObject( pi.hProcess, INFINITE ); \
CloseHandle( pi.hProcess ); /* Close process and thread handles. */ \
CloseHandle( pi.hThread ); \
} while (0)
#else
# include <unistd.h>
# include <libgen.h>
# define CDECL
#endif
#ifdef _MSC_VER
# define __STDC_LIB_EXT1__ 1
#endif
#ifndef _countof
# define _countof(array) (sizeof(array) / sizeof(array[0]))
#endif
#ifndef _MAX_ARG
# define _MAX_ARG 0x8000
#endif
#ifndef _MAX_FNAME
# define _MAX_FNAME 256
#endif
#if __STDC_LIB_EXT1__
# define STRCAT(p, s) strcat_s((p), _countof((p)), (s))
# define FILENAME(p, f) _splitpath_s((p), NULL, 0, NULL, 0, (f), _countof((f)), NULL, 0)
#else
# define STRCAT(p, s) strcat(p, s)
# define FILENAME(p, f) _splitpath((p), NULL, NULL, (f), NULL)
#endif
int
CDECL main(int argc, char *argv[])
{
#ifdef GET_CMD_LINE
char wslArgs[_MAX_ARG] = { 0 };
char fname[_MAX_FNAME] = { 0 };
char *cmdLine;
char *spaceOrQuote;
int spaceOrQuoteIdx;
cmdLine = GET_CMD_LINE();
if (strchr(argv[0], ' '))
{
if (spaceOrQuote = strchr(strchr(cmdLine, ' '), '"'))
{
spaceOrQuoteIdx = (spaceOrQuote - cmdLine) + 1;
}
else
{
fprintf(stderr, "%s is not properly escaped!\n", argv[0]);
return EXIT_FAILURE;
}
}
else
{
spaceOrQuoteIdx = strlen(argv[0]);
}
FILENAME(argv[0], fname);
STRCAT(wslArgs, "wsl.exe \"");
STRCAT(wslArgs, fname);
STRCAT(wslArgs, "\" ");
STRCAT(wslArgs, cmdLine + spaceOrQuoteIdx);
EXEC_CMD(wslArgs);
#else
char *cargv[argc + 1];
cargv[0] = basename(argv[0]);
for (int i = 1; i < argc; i++)
{
cargv[i] = argv[i];
}
cargv[argc] = NULL;
/* basically just pass through all arguments and use the executable
in the path. So `./cp' will turn into `cp' and thus `/bin/cp' */
execvp(cargv[0], cargv);
#endif
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment