/* * libyesterday.c * * Captures gettimeofday(), time() and clock_gettime() to simulate yesterday's date * * History: * 01/11/2025 Creation. * * Documentation: * https://rafalcieslak.wordpress.com/2013/04/02/dynamic-linker-tricks-using-ld_preload-to-cheat-inject-features-and-investigate-programs/ * * Usage examples: * # load date program with day set to yesterday * LD_PRELOAD=/path/to/libyesterday.so /bin/date * # load date program with day set to a week ago * LIBYESTERDAY=$((3600*24*7)) LD_PRELOAD=/path/to/libyesterday.so /bin/date * * Author: Dario Rodriguez antartica@whereismybit.com * This program is licensed under the terms of the MIT/X license. */ #define _GNU_SOURCE #include #include #include #include typedef time_t (*time_fn_type)(time_t *tloc); typedef int (*gettimeofday_fn_type)(struct timeval *restrict tv, void *restrict tz); typedef int (*clock_gettime_fn_type)(clockid_t clockid, struct timespec *tp); static int libyesterdaydata(time_fn_type *paramtime_fn, gettimeofday_fn_type *paramgettimeofday_fn, clock_gettime_fn_type *paramclock_gettime_fn) { static int init=0; static int seconds=3600*24; static time_fn_type realtimefn=(time_fn_type)NULL; static gettimeofday_fn_type realgettimeofdayfn=(gettimeofday_fn_type)NULL; static clock_gettime_fn_type realclock_gettimefn=(clock_gettime_fn_type)NULL; if(init==0) { char *ptr; realtimefn = (time_fn_type)dlsym(RTLD_NEXT,"time"); realgettimeofdayfn = (gettimeofday_fn_type)dlsym(RTLD_NEXT,"gettimeofday"); realclock_gettimefn = (clock_gettime_fn_type)dlsym(RTLD_NEXT,"clock_gettime"); if((ptr=getenv("LIBYESTERDAY"))!=NULL) seconds=atoi(ptr); init=1; } if(paramtime_fn!=NULL) *paramtime_fn=realtimefn; if(paramgettimeofday_fn!=NULL) *paramgettimeofday_fn=realgettimeofdayfn; if(paramclock_gettime_fn!=NULL) *paramclock_gettime_fn=realclock_gettimefn; return(seconds); } extern time_t time(time_t *tloc) { time_fn_type realtimefn=(time_fn_type)NULL; int seconds; int res; seconds=libyesterdaydata(&realtimefn,NULL,NULL); res=realtimefn(NULL); res-=seconds; if(tloc!=NULL) *tloc=res; return(res); } extern int gettimeofday(struct timeval *restrict tv, void *restrict tz) { static gettimeofday_fn_type realgettimeofdayfn=(gettimeofday_fn_type)NULL; int seconds; int res; seconds=libyesterdaydata(NULL,&realgettimeofdayfn,NULL); res=realgettimeofdayfn(tv,tz); tv->tv_sec-=seconds; return(res); } extern int clock_gettime(clockid_t clockid, struct timespec *tp) { static clock_gettime_fn_type realclock_gettimefn=(clock_gettime_fn_type)NULL; int seconds; int res; seconds=libyesterdaydata(NULL,NULL,&realclock_gettimefn); res=realclock_gettimefn(clockid,tp); tp->tv_sec-=seconds; return(res); }