--- /dev/null
+CFLAGS=-ggdb3 -Wall -pedantic -ansi -D_GNU_SOURCE
+LDFLAGS=-shared -ldl
+
+all: libwayback.so
+
+libwayback.so: libwayback.o
+ $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) $(TARGET_ARCH) $^ $(OUTPUT_OPTION)
+
+libwayback.o: libwayback.c
+
+.PHONY: clean
+clean:
+ $(RM) libwayback.so *.o
--- /dev/null
+#include <sys/time.h>
+#include <dlfcn.h>
+#include <sys/timeb.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <pthread.h>
+
+
+typedef int (*gettimeofday_func_t)(struct timeval *tv, struct timezone *tz);
+static gettimeofday_func_t gettimeofday_orig;
+
+typedef time_t (*time_func_t)(time_t *t);
+static time_func_t time_orig;
+
+typedef int (*ftime_func_t)(struct timeb *tp);
+static ftime_func_t ftime_orig;
+
+static time_t wayback=0;
+
+
+static int inside=0;
+static pthread_mutex_t inside_mutex=PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
+
+static void enter(void)
+{
+static int done=0;
+void *libc_handle;
+char *wayback_s;
+
+ if (pthread_mutex_lock(&inside_mutex)) {
+ fprintf(stderr,"libwayback: 'inside_mutex' lock fail!\n");
+ _exit(1);
+ }
+ if (inside<0) {
+ fprintf(stderr,"libwayback: 'inside' sanity fail!\n");
+ _exit(1);
+ }
+ if (inside) {
+ fprintf(stderr,"libwayback: looping!\n");
+ _exit(1);
+ }
+ inside++;
+
+ if (done)
+ return;
+ done=1;
+
+ if ((wayback_s=getenv("WAYBACK")))
+ wayback=atol(wayback_s);
+
+ libc_handle=dlopen("/lib/libc.so.6",RTLD_LAZY); /* RTLD_LAZY is mandatory */
+ gettimeofday_orig=(gettimeofday_func_t)dlsym(libc_handle,"gettimeofday");
+ time_orig=(time_func_t)dlsym(libc_handle,"time");
+ ftime_orig=(ftime_func_t)dlsym(libc_handle,"ftime");
+}
+
+static void leave(void)
+{
+ if (inside!=1) {
+ fprintf(stderr,"libwayback: 'inside' sanity fail!\n");
+ _exit(1);
+ }
+ inside--;
+ if (pthread_mutex_unlock(&inside_mutex)) {
+ fprintf(stderr,"libwayback: 'inside_mutex' unlock fail!\n");
+ _exit(1);
+ }
+}
+
+
+int gettimeofday(struct timeval *tv, struct timezone *tz)
+{
+int r;
+
+ enter();
+
+ r=(*gettimeofday_orig)(tv,tz);
+ if (tv)
+ tv->tv_sec-=wayback;
+
+ leave();
+
+ return r;
+}
+
+
+time_t time(time_t *t)
+{
+time_t r;
+
+ enter();
+ r=(*time_orig)(t);
+
+ if (t)
+ *t-=wayback;
+ r-=wayback;
+
+ leave();
+ return r;
+}
+
+
+int ftime(struct timeb *tp)
+{
+int r;
+
+ enter();
+ r=(*ftime_orig)(tp);
+
+ if (tp)
+ tp->time-=wayback;
+
+ leave();
+ return r;
+}