summaryrefslogtreecommitdiff
blob: f516f1b7228129ea5c8428ae4acecaa37fe3a2ce (plain)
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
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/wait.h>

#define VERSION_LEN 10

#define FORMAT EPREFIX PLUGIN_DIR "/kpython%spluginfactory.so"

static void *handle;
static void *(*wrapped_qt_plugin_instance)();

static void get_python_version(char* out) {
	int pipefd[2];
	pipe(pipefd);
	pid_t cpid = fork();
	if (cpid > 0) {
		close(pipefd[1]);
		read(pipefd[0], out, VERSION_LEN);
		close(pipefd[0]);
		waitpid(cpid, NULL, 0);
	} else if (cpid < 0) {
		/* fork failed, guess 2.7 */
		strcpy(out, "2.7\n");
		close(pipefd[0]);
		close(pipefd[1]);
	} else {
		close(pipefd[0]);
		close(1);
		dup2(pipefd[1], 1);
		close(pipefd[1]);
		close(0);
		char *args[] = { "eselect", "python", "show", "--ABI", "--python2", 0 };
		execv(EPREFIX "/usr/bin/eselect", args);
		/* exec failed, guess 2.7 */
		write(1, "2.7\n", 4);
		exit(0);
	}
}

__attribute__((constructor))
static void init() {
	char buf[VERSION_LEN + 1];
	memset(buf, 0, VERSION_LEN + 1);
	get_python_version(buf);
	char *s = buf;
	while(*s != '\0') {
		if(*s == '\n') {
			*s = '\0';
			break;
		}
		++s;
	}
	int length = strlen(FORMAT) + strlen(buf) + 1;
	char *name = malloc(length + 1);
	snprintf(name, length, FORMAT, buf);
	handle = dlopen(name, RTLD_NOW);
	free(name);
	wrapped_qt_plugin_instance = dlsym(handle, "qt_plugin_instance");
}

__attribute__((destructor))
static void fini() {
	dlclose(handle);
}

void *qt_plugin_instance() {
	return wrapped_qt_plugin_instance();
}