#!/bin/bash
####################################################################
# Prey Core Action Functions - by Tomas Pollak (bootlog.org)
# URL: http://preyproject.com
# License: GPLv3
####################################################################

# modules can queue specific actions by calling
# add_action 'module_name' 'function_name'
add_action(){
	log " ++ Queueing action for $1 module!"
	if [ -z "$2" ]; then
		function=1
	else
		function=$2
	fi
	actions[${#actions[*]}]="${1}=${function}"
}

# sets the running pid to the action/module name
add_running_action(){
	running_actions[${#running_actions[*]}]="${1}=${2}"
}

get_action(){
	get_var actions $1
}

# gets the pid of the running process
get_running_action(){
	get_var running_actions $1
}

action_callback(){
	until read -st 1; do
		echo -n ""
	done

	log " -- Action finished. Running callback!"
	eval '$1 $REPLY'
}

# receives the pid name, assigns it to the module name
create_pidfile_for(){
	log " -- Creating pidfile for $current_module's $1..."
	echo $1 > "$tmpbase/prey-action-$current_module.pid"
}

unload_action(){
	log " -- Unloading $1 from memory..."
	local pidfile="$tmpbase/prey-action-$1.pid"
	kill -HUP -- -`cat $pidfile` &> /dev/null
}

remove_pidfile(){
	local pidfile="$tmpbase/prey-action-$1.pid"
	if [ -f "$pidfile" ]; then
		log ' -- Removing pidfile...'
		rm -f "$pidfile" 2> /dev/null
	else
		log " -- Pidfile doesn't exist!"
	fi
}

check_running_actions(){

	for pidfile in `ls $tmpbase/prey-action-*.pid 2> /dev/null`; do

		if [ ! -f $pidfile ]; then
			continue # just to make sure
		fi

		local action_name=`basename $pidfile | sed -e 's/prey-action-//' -e 's/\.pid//'`
		log " -- Found PID for running action: $action_name"

		local pid=`cat $pidfile`
		local actually_running=`ps ax | grep $pid | grep -v grep > /dev/null && echo 1`

		if [ -z `get_action $action_name` ]; then # action was removed from options
			# log " -- Removing $action_name which was untoggled by user..."
			unload_action $action_name
			sleep 1
		elif [ -z "$actually_running" ]; then
			log " -- Not really running! PID file was just lying around."
			rm -f "$pidfile"
		else
			add_running_action $action_name $pid
		fi

	done
}

action_finished(){
	if [[ -n "$2" && `get_running_action $2` == $1 ]]; then
		wait $1
		return_status=$?
		log " -- Action $2 exited with status $return_status."
		remove_pidfile $2
	fi
}

run_pending_actions(){

	# -b -> Cause the status of terminated background jobs to be reported immediately,
	# rather than before printing the next primary prompt.
	# -m job control enabled
	set -bm

	log "\n${bold} >> Running pending actions...${bold_end}"
	for action in "${actions[@]}"; do

		local current_module=`echo $action | sed 's/=.*//'`
		local function=`echo $action | sed 's/.*=\(.*\)/\1/'`

		if [ ! -z `get_running_action $current_module` ]; then
			log " -- $current_module is already running! Skipping..."
			continue
		fi

		set_module_paths_for $current_module

		if [ "$function" != "1" ]; then # specific function requested
			log " -- Running action $function from $current_module module."
			eval "$function" &
		else # no specific action requested, we'll assume there's a run file
			log "\n${bold} >> Running $current_module module!${bold_end}\n"
			. "$module_path/core/run" &
		fi

		pid=$!
		create_pidfile_for $pid
		add_running_action $current_module $pid
		trap 'action_finished $pid $current_module' SIGCHLD

	done

	wait
	log " -- No pending actions left. All done!\n"
	trap - SIGCHLD
	cleanup
	# set +bm

}
