Advertisement
rockdrilla

wine-proxy.c: helper for Debian's wine packages

Aug 19th, 2014
746
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.76 KB | None | 0 0
  1. /*
  2. compile:
  3.   WINE_SUFFIX=-development
  4.   WINE_PROXY=wine
  5.   gcc -std=c99 wine-proxy.c -ldpkg -o ${WINE_PROXY} -s -DSUFFIX=${WINE_SUFFIX}
  6.   sudo install ${WINE_PROXY} /usr/bin
  7. */
  8.  
  9. #define _GNU_SOURCE
  10.  
  11. #include <errno.h>
  12. #include <fcntl.h>
  13. #include <stdarg.h>
  14. #include <stdlib.h>
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include <unistd.h>
  18.  
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21.  
  22. // libdpkg-dev
  23. #define LIBDPKG_VOLATILE_API
  24. #include <dpkg/arch.h>
  25.  
  26. // --------------------------
  27. // configuration
  28. // --------------------------
  29.  
  30. #ifdef  SUFFIX
  31. /*
  32.  two-pass stringification according to
  33.  http://gcc.gnu.org/onlinedocs/cpp/Stringification.html
  34. */
  35. #define S0(a) #a
  36. #define S1(a) S0(a)
  37. #define WINE_SUFFIX  S1(SUFFIX)
  38. #else
  39. #define WINE_SUFFIX  ""
  40. #endif
  41.  
  42. #define WINE_BINDIR  "/usr/lib/wine"WINE_SUFFIX
  43. #define WINE32       WINE_BINDIR"/wine"
  44. #define WINE64       WINE_BINDIR"/wine64"
  45.  
  46. // --------------------------
  47.  
  48. #define TRUE 1
  49. #define FALSE 0
  50. #define TEST(what, with)  (((what)&(with))==(with))
  51.  
  52. #define _err(format, args...) fprintf(stderr, format, ##args);
  53. #define _log(facility, format, args...) _err("wine-proxy: %s: " format "\n", facility, ##args);
  54. #define _log_D(format, args...)  _log("debug", format, ##args);
  55. #define _log_I(format, args...)  _log("info",  format, ##args);
  56. #define _log_W(format, args...)  _log("warn",  format, ##args);
  57. #define _log_E(format, args...)  _log("error", format, ##args);
  58.  
  59. void env_default(char * name, char * value) {
  60.     char * curr = getenv(name);
  61.  
  62.     while (TRUE) {
  63.         if (curr != NULL) {
  64.             if (strlen(curr) > 0) { break; }
  65.  
  66.             _log_D("env['%s'] is set but empty, overwriting", name, curr);
  67.         }
  68.  
  69.         curr = value;
  70.         setenv(name, value, TRUE);
  71.         break;
  72.     }
  73.  
  74.     _log_D("env['%s'] = '%s'", name, curr);
  75. }
  76.  
  77. int is_binary(char * path, int * out_handle) {
  78.     int file, err;
  79.     struct stat file_stat;
  80.  
  81.     file = open(path, O_NOATIME | O_NOCTTY | O_PATH | O_CLOEXEC, O_ACCMODE);
  82.     err = errno;
  83.     if (file == -1) {
  84.         _log_W("is_binary# open() = %d: %s", err, strerror(err));
  85.         return FALSE;
  86.     }
  87.  
  88.     while (TRUE) {
  89.         if (0 != fstat(file, &file_stat)) {
  90.             err = errno;
  91.             _log_W("is_binary# fstat() = %d: %s", err, strerror(err));
  92.             break;
  93.         }
  94.  
  95.         if (!S_ISREG(file_stat.st_mode)) { break; }
  96.         if (!TEST(file_stat.st_mode, S_IROTH | S_IXOTH)) { break; }
  97.  
  98.         *out_handle = file;
  99.  
  100.         return TRUE;
  101.     }
  102.  
  103.     close(file);
  104.  
  105.     return FALSE;
  106. }
  107.  
  108. // never returns if succeed
  109. int try_exec(int binary_handle, char ** argv, char ** env) {
  110.     int result, err;
  111.     result = fexecve(binary_handle, argv, env);
  112.     err = errno;
  113.     close(binary_handle);
  114.     _log_E("try_exec# fexecve() = %d: %s", result, strerror(err));
  115.     return result;
  116. }
  117.  
  118. char * dpkg_arch_to_string(enum dpkg_arch_type type) {
  119.     switch(type) {
  120.     case DPKG_ARCH_NONE:     return "none";
  121.     case DPKG_ARCH_EMPTY:    return "empty";
  122.     case DPKG_ARCH_ILLEGAL:  return "illegal";
  123.     case DPKG_ARCH_WILDCARD: return "wildcard";
  124.     case DPKG_ARCH_ALL:      return "all";
  125.     case DPKG_ARCH_NATIVE:   return "native";
  126.     case DPKG_ARCH_FOREIGN:  return "foreign";
  127.     case DPKG_ARCH_UNKNOWN:  return "unknown";
  128.     default:                 return "BAD VALUE";
  129.     }
  130. }
  131.  
  132. void dpkg_list_archs(void) {
  133.     for (struct dpkg_arch * i = dpkg_arch_get_list(); i != NULL; i = i->next) {
  134.         _log_D("dpkg_arch['%s'] = %s", i->name, dpkg_arch_to_string(i->type));
  135.     }
  136. }
  137.  
  138. // --------------------------
  139.  
  140. char * wine32 = WINE32;
  141. char * wine64 = WINE64;
  142.  
  143. extern char ** environ;
  144.  
  145. // --------------------------
  146.  
  147. int main(int argc, char ** argv) {
  148.     char * wine_path = NULL;
  149.     int wine_handle = NULL;
  150.  
  151.     _log_I("written by rockdrilla, 2014.");
  152.  
  153.     dpkg_list_archs();
  154.  
  155.     if (is_binary(wine32, &wine_handle)) {
  156.         _log_D("found 32-bit wine binary");
  157.         wine_path = wine32;
  158.     } else if (is_binary(wine64, &wine_handle)) {
  159.         _log_D("found 64-bit wine binary");
  160.         wine_path = wine64;
  161.  
  162.         struct dpkg_arch * a_amd64 = dpkg_arch_find("amd64");
  163.         struct dpkg_arch * a_i386 = dpkg_arch_find("i386");
  164.  
  165.         if (
  166.             (a_amd64->type == DPKG_ARCH_NATIVE)
  167.             &&
  168.             (a_i386->type != DPKG_ARCH_FOREIGN)
  169.         ) {
  170.             _log_W("it looks like multiarch needs to be enabled!");
  171.             _log_W("as root, please execute following:");
  172.             _log_W("    dpkg --add-architecture i386 && apt-get install wine32"WINE_SUFFIX);
  173.         }
  174.     } else {
  175.         _log_E("unable to find wine executable. this shouldn't happen.");
  176.         return 1;
  177.     }
  178.  
  179.     env_default("WINELOADER", wine_path);
  180.     env_default("WINEDEBUG", "-all");
  181.  
  182.     argv[0] = wine_path;
  183.  
  184.     return try_exec(wine_handle, argv, environ);
  185. }
  186.  
  187. /*
  188. sample output:
  189. krd@office:~$ ./wine --version
  190. wine-proxy: info: written by rockdrilla, 2014.
  191. wine-proxy: debug: dpkg_arch['i386'] = native
  192. wine-proxy: debug: dpkg_arch['all'] = all
  193. wine-proxy: debug: dpkg_arch['any'] = wildcard
  194. wine-proxy: debug: found 32-bit wine binary
  195. wine-proxy: debug: env['WINELOADER'] = '/usr/lib/wine-development/wine'
  196. wine-proxy: debug: env['WINEDEBUG'] = '-all'
  197. wine-1.7.24
  198.  
  199. krd@office:~$ WINEDEBUG=+all ./wine --version
  200. wine-proxy: info: written by rockdrilla, 2014.
  201. wine-proxy: debug: dpkg_arch['i386'] = native
  202. wine-proxy: debug: dpkg_arch['all'] = all
  203. wine-proxy: debug: dpkg_arch['any'] = wildcard
  204. wine-proxy: debug: found 32-bit wine binary
  205. wine-proxy: debug: env['WINELOADER'] = '/usr/lib/wine-development/wine'
  206. wine-proxy: debug: env['WINEDEBUG'] = '+all'
  207. wine-1.7.24
  208.  
  209. krd@office:~$ WINEDEBUG= ./wine --version
  210. wine-proxy: info: written by rockdrilla, 2014.
  211. wine-proxy: debug: dpkg_arch['i386'] = native
  212. wine-proxy: debug: dpkg_arch['all'] = all
  213. wine-proxy: debug: dpkg_arch['any'] = wildcard
  214. wine-proxy: debug: found 32-bit wine binary
  215. wine-proxy: debug: env['WINELOADER'] = '/usr/lib/wine-development/wine'
  216. wine-proxy: debug: env['WINEDEBUG'] is set but empty, overwriting
  217. wine-proxy: debug: env['WINEDEBUG'] = '-all'
  218. wine-1.7.24
  219. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement