-
Notifications
You must be signed in to change notification settings - Fork 1
/
libopenredir.c.in
111 lines (97 loc) · 3.42 KB
/
libopenredir.c.in
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
#include<stdarg.h>
#include<dlfcn.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
#include<unistd.h>
#include<lua.h>
#include<lualib.h>
#include<lauxlib.h>
{% set functions = [
['open', [['const char*', 'file'], ['int', 'flags'], ['mode_t', 'mode']]],
['open64', [['const char*', 'file'], ['int', 'flags'], ['mode_t', 'mode']]],
['creat', [['const char*', 'file'], ['mode_t', 'mode']]],
['readlink', [['const char*', 'file'], ['char*', 'buf'], ['size_t', 'bufsiz']], 'ssize_t'],
['__open_2', [['const char*', 'file'], ['int', 'flags']]],
['__open64_2', [['const char*', 'file'], ['int', 'flags']]],
['stat', [['const char*', 'file'], ['void*', 'buf']]],
['statx', [['int', 'fd'], ['const char*', 'file'], ['int', 'flags'], ['unsigned int', 'mask'], ['void*', 'buf']]],
['__lxstat', [['int', 'vers'], ['const char*', 'file'], ['void*', 'buf']]],
['__lxstat64', [['int', 'vers'], ['const char*', 'file'], ['void*', 'buf']]],
['execve', [['const char*', 'file'], ['char *const*', 'argv'], ['char *const*', 'envp']]],
['opendir', [['const char*', 'file']], 'void*'],
['getxattr', [['const char*', 'file'], ['const char*', 'name'], ['void*', 'value'], ['size_t', 'size']], 'ssize_t'],
['lgetxattr', [['const char*', 'file'], ['const char*', 'name'], ['void*', 'value'], ['size_t', 'size']], 'ssize_t'],
] %}
{% autoescape None %}
static int lib_initialized = 0;
{% for func, args, *rest in functions %}static {{rest[0] if rest else 'int'}} (*orig_{{func}})({{', '.join(x[0] for x in args)}}) = 0;
{% end %}
static lua_State *L = NULL;
void lib_init();
void die(char *fmt, ...) {
va_list args;
va_start(args, fmt);
vfprintf(stderr, fmt, args);
va_end(args);
fprintf(stderr, "\n");
fflush(stderr);
exit(-1);
}
static char* redirect(const char* func, const char* file){
int ret;
const char *new;
lua_getglobal(L, "redirect");
lua_pushstring(L, func);
lua_pushstring(L, file);
ret = lua_pcall(L, 2, 1, 0);
if(ret){
fprintf(stderr, "取得重定向文件路径时出错了: %s\n", lua_tostring(L, -1));
lua_pop(L, 1); /* 错误信息 */
return (char*)file;
}else{
new = lua_tostring(L, -1);
lua_pop(L, 1); /* 返回值 */
}
return (char*)new;
}
{% for func, args, *rest in functions %}
{{rest[0] if rest else 'int'}} {{func}}({{', '.join(' '.join(x) for x in args)}}) {
lib_init();
file = redirect({{'"' + func.replace('"', r'\"') + '"'}}, file);
return orig_{{func}}({{', '.join(x[1] for x in args)}});
}
{% end %}
void lib_init() {
void *libhdl;
char *dlerr;
if (lib_initialized) return;
if (!(libhdl=dlopen("libc.so.6", RTLD_LAZY)))
die("Failed to patch library calls: %s", dlerror());
{% for func, args, *rest in functions %}
orig_{{func}} = dlsym(libhdl, "{{func}}");
if ((dlerr=dlerror()) != NULL)
die("Failed to patch {{func}}() library call: %s", dlerr);
{% end %}
int ret;
L = luaL_newstate();
luaL_openlibs(L);
char config[PATH_MAX];
if (getenv("OPENREDIR_CONFDIR"))
strncpy(config, getenv("OPENREDIR_CONFDIR"), PATH_MAX);
else
strncpy(config, getenv("HOME"), PATH_MAX);
strcat(config, "/.openredir.lua");
ret = luaL_dofile(L, config);
if(ret){
die("Error run ~/.openredir.lua");
}
lua_getglobal(L, "redirect");
if(!lua_isfunction(L,-1)){
die("Error run 'redirect' function in openredir.lua");
}
lua_pop(L, 1);
lib_initialized = 1;
}
/* vim: set syntax=c.tornadotmpl: */