#!/bin/sh

# Simple wrapper shell script for FTPL (faketime preload library)
# Thanks to Daniel Kahn Gillmor for improvement suggestions. 

# It allows you to modify the date and time a program sees when using
# system library calls such as time() and fstat(). 

# This wrapper exposes only a small subset of the FTPL functionality.
# Please see FTPL's README file for more details

# Acknowledgment: Parts of the functionality of this wrapper have been 
# inspired by Matthias Urlichs' datefudge 1.14.

# Configuration: Path where the libfaketime libraries can be found.
FTPL_PATH=/usr/lib/faketime

offset="$1"

USEMT=0
USEDIRECT=0

if [ "$offset" = "-v" -o "$offset" = "--version" ] ; then
	echo ""
	echo "$0: Version 0.8"
	echo "For usage information please use '$0 --help'."
	echo ""
	exit 0
fi

if [ "$offset" = "-m" ] ; then USEMT=1; shift; offset="$1"; fi
if [ "$offset" = "-f" ] ; then USEDIRECT=1; shift; offset="$1"; fi
if [ "$offset" = "-m" ] ; then USEMT=1; shift; offset="$1"; fi

if [ -z "$offset" -o "$offset" = "-h" -o "$offset" = "-?" -o "$offset" = "--help" ] ; then
	echo ""
	echo "Usage: $0 [switches] timestamp program arguments"
	echo ""
	echo "This will run the specified 'program' with the given 'arguments'."
	echo "The program will be tricked into seeing the given 'timestamp' as its starting date and time."
	echo "The clock will continue to run from this timestamp. Please see the manpage (man faketime)"
	echo "for advanced options, such as stopping the wall clock and make it run faster or slower."
	echo ""
	echo "The optional switches are:"
	echo "  -m        : Use the multi-threaded version of libfaketime"
	echo "  -f        : Use the advanced timestamp specification format (see manpage)"
	echo ""
	echo "Examples:"
	echo "$0 'last friday 5 pm' /bin/date"
	echo "$0 '2008-12-24 08:15:42' /bin/date"
	echo "$0 -f '+2,5y x10,0' /bin/bash -c 'date; while true; do echo \$SECONDS ; sleep 1 ; done'"
	echo "$0 -f '+2,5y x0,50' /bin/bash -c 'date; while true; do echo \$SECONDS ; sleep 1 ; done'"
	echo "(Please note that it depends on your locale settings whether . or , has to be used for fractions)"
	echo ""
	if [ -z "$offset" ] ; then
		exit 1;
	fi
	exit 0
fi

shift

# Setting LD_PRELOAD ...

if [ "$USEMT" -eq 0 ] ; then
	export LD_PRELOAD="${LD_PRELOAD}${LD_PRELOAD:+:}$FTPL_PATH/libfaketime.so.1"
fi
if [ "$USEMT" -eq 1 ] ; then
	export LD_PRELOAD="${LD_PRELOAD}${LD_PRELOAD:+:}$FTPL_PATH/libfaketimeMT.so.1"
fi

###

# Setting FAKETIME ...

if [ "$USEDIRECT" -eq 0 ] ; then
	seconds=$(date -d "$offset" '+%s')
	if [ $? -ne 0 ] ; then 
		echo "Error: Timestamp to fake not recognized, please re-try with a different timestamp."
		exit 1 
	fi

	offset=$(expr $seconds - $(date '+%s'))
	if [ $? -ne 0 ] ; then 
		echo "Error: Cannot calculate the faketime offset in seconds, please re-try with a different timestamp."
		exit 1
	fi

	FAKETIMEPREFIX=""
	if [ "$offset" -ge 0 ] ; then
		FAKETIMEPREFIX="+"
	fi

	export FAKETIME="$FAKETIMEPREFIX$offset"
fi
if [ "$USEDIRECT" -eq 1 ] ; then
	export FAKETIME="$offset"
fi
###

# Executing the user-specified command ...
exec "$@"
