loader.c (3860B)
1#include <linux/limits.h> 2#include <sys/stat.h> 3#include <err.h> 4#include <dirent.h> 5#include <limits.h> 6#include <unistd.h> 7#include <string.h> 8#include <stdio.h> 9#include <stdbool.h> 10#include <stdlib.h> 11 12#define ARRLEN(x) (sizeof(x) / sizeof((x)[0])) 13 14static const char *libpath = "/tmp/winpl.so"; 15 16extern char _binary_winpl_so_start[]; 17extern char _binary_winpl_so_end[]; 18 19extern char **environ; 20 21void 22usage(int rc, bool full) 23{ 24 fprintf(stderr, "Usage: winpl [OPT].. -- CMD [ARG]..\n"); 25 if (!full) exit(rc); 26 fprintf(stderr, "\n"); 27 fprintf(stderr, " -ow Always write preload library\n"); 28 fprintf(stderr, " [-ax|-ay] POS Absolute window position\n"); 29 fprintf(stderr, " [-mx|-my] POS Window position relative to monitor\n"); 30 fprintf(stderr, " [-rx|-ry] SCALE Window position relative to monitor\n" 31 " as a factor of monitor size\n"); 32 fprintf(stderr, " [-aw|-ah] SIZE Absolute window width/height\n"); 33 fprintf(stderr, " [-rw|-rh] SCALE Window size relative to monitor\n"); 34 fprintf(stderr, " -c Center window on monitor\n"); 35 fprintf(stderr, " -f Tag window as dialog (floating)\n"); 36 fprintf(stderr, " -mn SCREEN Select monitor based on number\n"); 37 fprintf(stderr, " -mp Select monitor based on cursor\n"); 38 fprintf(stderr, " -mf Select monitor based on focus\n"); 39 fprintf(stderr, " -ni Window does not take input (focus)\n"); 40 fprintf(stderr, " -name NAME Set window name\n"); 41 fprintf(stderr, "\n"); 42 exit(rc); 43} 44 45void 46write_lib(const char *filename) 47{ 48 FILE *file; 49 size_t size; 50 void *data; 51 52 file = fopen(filename, "wb+"); 53 if (!file) err(1, "fopen %s", filename); 54 55 data = (void*) _binary_winpl_so_start; 56 size = (size_t) (_binary_winpl_so_end - _binary_winpl_so_start); 57 58 if (fwrite(data, size, 1, file) != 1) 59 errx(1, "failed to write winpl lib"); 60 61 fclose(file); 62} 63 64int 65main(int argc, char *const *argv) 66{ 67 char *const *cmd_argv = NULL; 68 char *const *arg; 69 char pathbuf[PATH_MAX]; 70 struct stat st; 71 bool overwrite = false; 72 73 if (argc < 1) return 0; 74 75 for (arg = argv + 1; *arg; arg++) { 76 if (!strcmp(*arg, "-h")) { 77 usage(0, true); 78 } else if (!strcmp(*arg, "-ax")) { 79 setenv("WINPL_WX", *++arg, true); 80 } else if (!strcmp(*arg, "-ay")) { 81 setenv("WINPL_WY", *++arg, true); 82 } else if (!strcmp(*arg, "-mx")) { 83 setenv("WINPL_MWX", *++arg, true); 84 } else if (!strcmp(*arg, "-my")) { 85 setenv("WINPL_MWY", *++arg, true); 86 } else if (!strcmp(*arg, "-rx")) { 87 setenv("WINPL_RWX", *++arg, true); 88 } else if (!strcmp(*arg, "-ry")) { 89 setenv("WINPL_RWY", *++arg, true); 90 } else if (!strcmp(*arg, "-aw")) { 91 setenv("WINPL_WW", *++arg, true); 92 } else if (!strcmp(*arg, "-ah")) { 93 setenv("WINPL_WH", *++arg, true); 94 } else if (!strcmp(*arg, "-rw")) { 95 setenv("WINPL_RWW", *++arg, true); 96 } else if (!strcmp(*arg, "-rh")) { 97 setenv("WINPL_RWH", *++arg, true); 98 } else if (!strcmp(*arg, "-c")) { 99 setenv("WINPL_CENTER", "1", true); 100 } else if (!strcmp(*arg, "-f")) { 101 setenv("WINPL_FLOAT", "1", true); 102 } else if (!strcmp(*arg, "-mn")) { 103 setenv("WINPL_MON_NUM", *++arg, true); 104 } else if (!strcmp(*arg, "-mp")) { 105 setenv("WINPL_MON_PTR", "1", true); 106 } else if (!strcmp(*arg, "-mf")) { 107 setenv("WINPL_MON_FOCUS", "1", true); 108 } else if (!strcmp(*arg, "-ni")) { 109 setenv("WINPL_NO_INPUT", "1", true); 110 } else if (!strcmp(*arg, "-name")) { 111 setenv("WINPL_NAME", *++arg, true); 112 } else if (!strcmp(*arg, "-ow")) { 113 overwrite = true; 114 } else if (!strcmp(*arg, "--") && *(arg+1)) { 115 cmd_argv = arg + 1; 116 break; 117 } else { 118 usage(1, true); 119 } 120 } 121 if (!cmd_argv) usage(1, false); 122 123 if (overwrite || stat(libpath, &st)) 124 write_lib(libpath); 125 126 setenv("LD_PRELOAD", libpath, true); 127 128 execvp(*cmd_argv, cmd_argv); 129 130 err(1, "execve %s", pathbuf); 131}