#!/bin/sh
# distributed by cfengine
# Copyright 1999-2011 Gentoo Foundation
# Distributed under the beerware license
# Author: Robin H. Johnson <robbat2@gentoo.org>
# Path on server: /usr/local/bin/
# Permissions: -rwxr-xr-x root root
# Comments:
# If you want to use this under minimal busybox, update the defines at the
# start, and pass PIDDIR/MYSUFFIX/DEBUG via the env.

RM=/bin/rm
MKDIR=/bin/mkdir
BASENAME=/bin/basename

# The following are only for pretty error output
GREP=/bin/grep
TR=/usr/bin/tr
PSTREE=/usr/bin/pstree
WHOAMI=/usr/bin/whoami

debug() {
	if [ ${DEBUG:-0} -eq 1 ]; then
		echo "DEBUG: pidlock: ${*}"
	fi
}

# This is for the minimal busybox crowd.
# They need to set PIDDIR/MYSUFFIX/DEBUG on the commandline env.
if [ -n "$(type -t getopts)" ]; then
	while getopts ":l:s:d?" opt; do
		case $opt in
			l)
				PIDDIR=$OPTARG
				;;
			s)
				MYSUFFIX=$OPTARG
				;;
			d)
				DEBUG=1
				;;
			:)
				echo "Option '-${OPTARG}' requires an argument." 1>&2
				exit 1
				;;
			\?)
				echo "Usage: ${0}: [-l PIDDIR] [-s PIDFILE_SUFFIX] [-d] -- args"
				exit 0
				;;
			*)
				continue
				;;
		esac
	done
	shift $(($OPTIND - 1))
else
	[ "$1" == "--" ] && shift
fi

if [ -z "${PIDDIR}" ]; then
	[ -x "${WHOAMI}" ] && _who=$($WHOAMI)
	[ -z "${_who}" ] && _who=$USER
	[ -z "${_who}" ] && _who=$LOGNAME
	[ -z "${_who}" ] && {
		echo "pidlock: Error: Neither whoami, \$USER nor \$LOGNAME returned a username!" 1>&2
		exit 1
	}

	PIDDIR=/tmp/${_who}
	$MKDIR -m 0700 -p ${PIDDIR}
	if [ "${?:-0}" -gt 0 ]; then
		echo "An error occured during mkdir of PIDDIR!" 1>&2
		exit 3
	fi
fi

if [ ! -d "${PIDDIR}" ]; then
	echo "Error: '${PIDDIR}' does not exist!" 1>&2
	exit 3
fi

if [ -z "${1}" ]; then
	echo "Error! You need to specify a command to run!" 1>&2
	exit 1
fi

MYPID=$$
MYNAME=`$BASENAME $0`-`$BASENAME $1`
CMD="${*}"

if [ -n "${MYSUFFIX}" ]; then
	PIDFILE=${PIDDIR}/${MYNAME}-${MYSUFFIX}.pid
else
	PIDFILE=${PIDDIR}/${MYNAME}.pid
fi

if [ -f "${PIDFILE}" ]; then
	OLDPID=$(< ${PIDFILE})
	if [ -n "${OLDPID}" -a -d "/proc/${OLDPID}/" ]; then
		OLDCMD=$($TR '\000' ' ' < /proc/${OLDPID}/cmdline | $GREP -o "${0} ${CMD}")
		if [ -n "${OLDCMD}" ]; then
			echo "Error! '${MYNAME}' is running already!" 1>&2
			exit 4
		else
			echo "Error: A running process with the pid '${OLDPID}' taken from '${PIDFILE}' has been found!" 1>&2
			echo "pstree -naup ${OLDPID}:"
			$PSTREE -naup ${OLDPID}
			exit 4
		fi
	fi

	debug "Stale pidfile detected. Removing"
	$RM -f ${PIDFILE}
fi

debug "Not running already, putting PID in pidfile"
echo ${MYPID} >${PIDFILE}
debug "Doing something (${CMD})"
eval ${CMD}
debug "Cleaning up ${PIDFILE}"
$RM -f ${PIDFILE}