--- /dev/null
+src = $(wildcard src/*.c)
+obj = $(src:.c=.o)
+lib_so = libgliar.so
+
+CFLAGS = -pedantic -Wall -g -fPIC -D_GNU_SOURCE
+
+$(lib_so): $(obj)
+ $(CC) -o $@ -shared $(obj) $(LDFLAGS)
+
+.PHONY: clean
+clean:
+ rm -f $(obj) $(lib_so)
--- /dev/null
+# libgliar - a library that can fake the OpenGL context info returned by
+# the glGet OpenGL calls
+#
+# authored by: Eleni Maria Stea <elene.mst@gmail.com>
+
+For instructions on how to build the code, see the INSTALL file.
+
+Usage:
+------
+LD_PRELOAD=./libgliar.so <opengl_executable>
+
+The library will read the gliar.conf file in the user's library directory or
+the .gliar.conf file in the user's home directory.
+
+Example gliar.conf:
+-------------------
+[key1]
+value1
+value2
+.
+.
+.
+valueN
+
+[key2]
+value1
+.
+.
+.
+valueN
+
+[keyN]
+value1
+.
+.
+.
+valueN
+
+Currently supported keys:
+"vendor" (the vendor string), "extensions" (the extensions string), "version" (the opengl version string)
+
+Example:
+---------
+gliar.conf:
+[vendor]
+Mutant Stargoat
+
+[extensions]
+GL_MSG_hikiko_ext
+GL_MSG_test
+
+$ LD_PRELOAD=./libgliar glxinfo | grep -A2 "OpenGL extensions"
+OpenGL extensions:
+ GL_MSG_hikiko_ext, GL_MSG_test
+
+
+
--- /dev/null
+[vendor]
+Mutant Stargoat
+
+[extensions]
+GL_MSG_hikiko_ext
+GL_MSG_test
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include "cfg.h"
+
+static char *stripspace(char *s);
+
+
+struct cfgopt *gliar_load_cfg(const char *fname)
+{
+ FILE *fp;
+ char buf[512];
+ struct cfgopt *optlist = 0;
+ struct cfgopt *opt = 0;
+
+ if(!(fp = fopen(fname, "r"))) {
+ return 0;
+ }
+
+ while(fgets(buf, sizeof buf, fp)) {
+ char *line = stripspace(buf);
+
+ if(!*line || *line == '#') {
+ continue;
+ }
+
+ if(*line == '[') {
+ char *end = strrchr(line, ']');
+ if(!end) {
+ fprintf(stderr, "invalid config %s: %s\n", fname, line);
+ continue;
+ }
+ line++;
+ *end = 0;
+
+ if(opt) {
+ opt->next = optlist;
+ optlist = opt;
+ }
+
+ if((opt = malloc(sizeof *opt))) {
+ if((opt->key = malloc(strlen(line) + 1))) {
+ strcpy(opt->key, line);
+ opt->val = 0;
+ } else {
+ free(opt);
+ opt = 0;
+ }
+ }
+ } else {
+ char *tmp;
+ int prev_len = opt->val ? strlen(opt->val) : 0;
+
+ if(opt && (tmp = realloc(opt->val, prev_len + strlen(line) + 2))) {
+ opt->val = tmp;
+ if(prev_len) {
+ strcat(opt->val, " ");
+ strcat(opt->val, line);
+ } else {
+ strcpy(opt->val, line);
+ }
+ }
+ }
+ }
+
+ if(opt) {
+ opt->next = optlist;
+ optlist = opt;
+ }
+
+ fclose(fp);
+ return optlist;
+}
+
+const char *gliar_find_opt(struct cfgopt *list, const char *name)
+{
+ if(!list || !name) {
+ return 0;
+ }
+
+ while(list) {
+ if(strcmp(list->key, name) == 0) {
+ return list->val;
+ }
+ list = list->next;
+ }
+ return 0;
+}
+
+void gliar_print_opt(struct cfgopt *list)
+{
+ printf("OPTIONS\n");
+ while(list) {
+ printf("\"%s\" -> \"%s\"\n", list->key, list->val);
+ list = list->next;
+ }
+}
+
+static char *stripspace(char *s)
+{
+ char *end = s + strlen(s) - 1;
+
+ while(isspace(*s)) s++;
+
+ while(isspace(*end)) {
+ *end-- = 0;
+ }
+ return s;
+}
--- /dev/null
+#ifndef CFG_H_
+#define CFG_H_
+
+struct cfgopt {
+ char *key;
+ char *val;
+
+ struct cfgopt *next;
+};
+
+struct cfgopt *gliar_load_cfg(const char *fname);
+
+const char *gliar_find_opt(struct cfgopt *list, const char *name);
+
+void gliar_print_opt(struct cfgopt *list);
+
+#endif /* CFG_H_ */
--- /dev/null
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <dlfcn.h>
+#include <pwd.h>
+#include <GL/gl.h>
+#include "cfg.h"
+
+static int done_init;
+static const GLubyte* (*gl_get_string)(GLenum);
+static struct cfgopt *cfglist;
+
+static int init(void)
+{
+ if(done_init) {
+ return 0;
+ }
+
+ if(!(cfglist = gliar_load_cfg("gliar.conf"))) {
+ struct passwd *pw;
+ char *homedir, *path;
+
+ if((pw = getpwuid(getuid()))) {
+ homedir = pw->pw_dir;
+ } else {
+ homedir = getenv("HOME");
+ }
+
+ if(homedir) {
+ path = alloca(strlen(homedir) + strlen(".gliar.conf") + 2);
+ sprintf(path, "%s/.gliar.conf", homedir);
+
+ cfglist = gliar_load_cfg(path);
+ }
+ }
+
+ gl_get_string = dlsym(RTLD_NEXT, "glGetString");
+
+ done_init = 1;
+ return 0;
+}
+
+const GLubyte *glGetString(GLenum name)
+{
+ const char *key, *value;
+
+ init();
+
+ switch(name) {
+ case GL_VENDOR:
+ key = "vendor";
+ break;
+
+ case GL_VERSION:
+ key = "version";
+ break;
+
+ case GL_EXTENSIONS:
+ key = "extensions";
+ break;
+
+ default:
+ key = 0;
+ }
+
+ if(key && (value = gliar_find_opt(cfglist, key))) {
+ return value;
+ }
+
+ return gl_get_string(name);
+}