1#!/bin/sh
2#
3# $Header: /usr/local/src/dhcp_probe-latest/extras/RCS/site-application-dhcp_probe,v 1.1 2011/12/14 20:32:03 root Exp root $
4#
5# This is a Solaris SMF method script (a startup script) for the dhcp_probe daemon.
6#
7# Usage:
8#   site-application-dhcp_probe [-v] -i interface [-Q vlan_id|none] [-r] [-d debuglevel] start
9#   site-application-dhcp_probe [-v] -i interface stop contract_id
10#
11# -d debuglevel   call dhcp_probe with '-d debuglevel' overridding default DEBUG_OPT constant below.
12# -i interface    name of network interface on which to run
13# -Q vlan_id      call dhcp_probe with '-Q vlan_id'
14# -r              rotate capture files before starting daemon
15# -v              enable verbosity
16#
17#
18# When starting, if the daemon is already executing (based on $PIDFILE), don't re-execute it.
19#
20# To try to minimize the likelihood that the processid stored in the PID file corresponds
21# to an unrelated process (common with startup scripts), we'll clear the contents of the
22# PID file when we kill the daemon using this script.   When starting or stopping, when we find a pid in that file,
23# we'll both check that a process with that pid exists, and that the commandname for the process
24# looks like the one we're interested in before we treat the pid value as valid.
25#
26# When stopping, we kill the pid specified in $PIDFILE, if $PIDFILE exists and
27# contains a value that is for a running process whose commandname looks like
28# the one we're interested in.  Regardless of how that goes, we'll also
29# kill the service contract (assuming a contract_id is given); that will help
30# us kill the daemon in those cases where the pidfile and the daemon have
31# gotten out-of-sync, as well as ensure all children of the daemon are killed.
32
33
34. /lib/svc/share/smf_include.sh
35
36PATH=/usr/bin:/bin
37
38SERVERROOT=/usr/local/sbin
39
40PROGNAME=dhcp_probe
41
42# If PIDFILE exists and refers to a running process,
43# and that process's command string contains PS_SEARCH,
44# we'll assume this program instance is already running.
45PS_SEARCH=$PROGNAME
46
47EXECUTABLE=$SERVERROOT/$PROGNAME
48
49# Working directory before starting daemon.
50CWD=/tmp
51
52# Directory in which to write the pidfile
53PIDFILEDIR=/var/run
54
55# Directory in which to find the config file
56CONFIGFILEDIR=/etc
57
58# Signal to kill daemon gracefully.
59SIGNAL=TERM
60
61# This will be set via cmdline option '-i interface'
62INTERFACE=
63
64# This may be overridden via cmdline option '-Q vlan_id'
65VLAN_OPT=
66
67# Directory in which to write the capture files
68CAPTUREDIR=/var/local/logs
69
70# Number of capture files to retain (when rotating these files)
71CAPTUREFILES_MAX=20
72
73# Absolute path of the rotate_logs executable.
74# Used when starting service iff '-r' option specified.
75ROTATE_LOGS_EXEC=/usr/local/etc/rotate_logs
76
77# Debug option to pass to dhcp_probe.
78# Set to empty string to disable.
79# May be overridden via '-d debuglevel'.
80DEBUG_OPT="-d 1"
81
82cd $CWD
83
84while [ $# -gt 0 ]
85do
86	case "$1" in
87
88		'-d')
89			# The debuglevel is supposed to be the token after '-d'.
90			# Overrride default DEBUG constant.
91			shift
92			DEBUG_OPT="-d $1"
93			;;
94
95		'-i')
96			# The interface name is supposed to be the token after '-i'.
97			shift
98			INTERFACE="$1"
99			;;
100
101		'-Q')
102			# The vlan_id is supposed to be the token after '-Q'.
103			shift
104			if [ "$1" = "none" ]; then
105				# The token "none" is special, indicating that no -Q option should be passed.
106				# It's a kludge to allow our caller to always pass a '-Q value' option,
107				# for those callers (like SMF) which make it hard to pass *optional* options which take values.
108				:
109			else
110				VLAN_OPT="-Q $1"
111			fi
112			;;
113
114		'-r')
115			rotate_capturefile=1
116			;;
117
118		'-v')
119			verbose=1
120			;;
121
122		'start')
123			# The interface must have been specified before the 'start' argument.
124			if [ -z "$INTERFACE" ]; then
125				echo "$0: interface not specified, cannot start $PROGNAME" 2>&1 | smf_console
126				exit $SMF_EXIT_ERR_FATAL
127			fi
128
129			# Some values we could not determine until the INTERFACE was set.
130
131			PIDFILE=$PIDFILEDIR/$PROGNAME.$INTERFACE.pid
132
133			CONFIGFILE=$CONFIGFILEDIR/$PROGNAME.$INTERFACE.cf
134
135			# Capture file name (without the directory name)
136			CAPTUREFILENAME=$PROGNAME.$INTERFACE.capture
137
138			# Absolute capture file name
139			CAPTUREFILE=$CAPTUREDIR/$CAPTUREFILENAME
140
141			STARTCOMMAND="$EXECUTABLE $DEBUG_OPT -c $CONFIGFILE -o $CAPTUREFILE -p $PIDFILE $VLAN_OPT $INTERFACE"
142
143			echo "$0: starting $PROGNAME instance on interface $INTERFACE ..." 2>&1 | smf_console
144
145			if [ !  -f $EXECUTABLE ]; then
146				echo "$0: executable $EXECUTABLE does not exist, cannot start $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console
147				exit $SMF_EXIT_ERR_FATAL
148			fi
149
150			if [ !  -f $CONFIGFILE ]; then
151				echo "$0: configuration file $CONFIGFILE does not exist, cannot start $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console
152				exit $SMF_EXIT_ERR_CONFIG
153			fi
154
155			# If we find the daemon already running, exit.  Else fall through to the $STARTCOMMAND
156			if [ -f $PIDFILE ]; then
157				pid=`/usr/bin/cat $PIDFILE`
158				if [ -n "$pid" ]; then
159					if kill -0 "$pid" > /dev/null 2>&1 ; then
160						# there is a process with that pid, but is it the right one?
161						/usr/bin/ps -f -p $pid | /usr/bin/tail -1 | /usr/bin/grep $PS_SEARCH > /dev/null 2>&1
162						if [ $? -eq 0 ] ; then
163							echo "$0: $PIDFILE=$pid processid exists with reasonable name, assuming $PROGNAME instance on interface $INTERFACE is already running" 2>&1 | smf_console
164							exit $SMF_EXIT_OK
165						else
166							# that process is something else, so we can assume ours isn't already running
167							# Clearing our pidfile is just good housekeeping, not required
168							/usr/bin/cp /dev/null $PIDFILE
169						fi
170					fi	# else no process running with that pid, so we assume it's not already running
171				fi	# else pidfile doesn't contain a number, so we assume it's not already running
172			fi	# else no pidfile, so we assume it's not already running
173
174			# Success!  It really looks like the daemon isn't already running, so start it
175
176			###
177			# This is specific to dhcp_probe
178			#
179			# As each time dhcp_probe starts, it overwrites the capture file.
180			# If you want to preserve the previous capture file(s), rotate those file(s) before starting dhcp_probe.
181			if [ -n "$rotate_capturefile" ] ; then
182				# Note that we could not determine some of these args until after $INTERFACE was set.
183  				$ROTATE_LOGS_EXEC -logdir="$CAPTUREDIR" -logname="$CAPTUREFILENAME" -max="-$CAPTUREFILES_MAX"
184			fi
185			#
186			####
187
188			$STARTCOMMAND
189			echo "done starting $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console
190			exit $SMF_EXIT_OK
191
192
193			;;
194
195
196
197		'stop')
198
199			if [ -z "$INTERFACE" ]; then
200				echo "$0: interface not specified, cannot stop $PROGNAME" 2>&1 | smf_console
201				exit $SMF_EXIT_ERR_FATAL
202
203				# XXX Does Solaris ever call the stop method with just the contract_id (lacking the interface name)?
204				# If so, then we should allow the method to run even without an interface name.
205				# (We really want the interface name as it allows us to find the PIDFILE.)
206			fi
207
208			# We could not determine the PIDFILE until the INTERFACE was set.
209			PIDFILE=$PIDFILEDIR/$PROGNAME.$INTERFACE.pid
210
211			echo "$0: stopping $PROGNAME instance on interface $INTERFACE ..." 2>&1 | smf_console
212
213			# The service contract_id is supposed to be the token after 'stop'.
214			shift
215			contract_id="$1"
216
217			if [ -f $PIDFILE ] ; then
218
219				pid=`/usr/bin/cat $PIDFILE`
220				if [ -n "$pid" ]; then
221
222					if kill -0 "$pid" > /dev/null 2>&1 ; then
223						# there is a process with that pid, but is it the right one?
224						/usr/bin/ps -f -p $pid | /usr/bin/tail -1 | /usr/bin/grep $PS_SEARCH > /dev/null 2>&1
225						if [ $? -eq 0 ] ; then
226							# Success! The process has reasonable name, go ahead and kill it
227							kill -$SIGNAL $pid
228
229							/usr/bin/cp /dev/null $PIDFILE
230
231							# Kill any processes left in service contract
232							if [ -n "$contract_id" ] ; then
233								smf_kill_contract $contract_id $SIGNAL 1
234								[ $? -ne 0 ] && exit 1
235							fi
236
237							echo "done stopping $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console
238							exit $SMF_EXIT_OK
239
240						else
241							# The process with that pid does NOT have a reasonable name.
242							if [ -n "$verbose" ]; then
243								echo "$0: $PIDFILE=$pid processid is for different daemon, will NOT kill that pid" 2>&1 | smf_console
244							fi
245							# Clearing our pidfile is just good housekeeping, not required
246							/usr/bin/cp /dev/null $PIDFILE
247
248							# It's not clear why the $PIDFILE doesn't correspond to the correct daemon, but perhaps the service is still running with a different pid.
249							# Kill any processes left in service contract
250							if [ -n "$contract_id" ] ; then
251								smf_kill_contract $contract_id $SIGNAL 1
252								[ $? -ne 0 ] && exit 1
253							fi
254
255							echo "done stopping $PROGNAME" 2>&1 | smf_console
256							exit $SMF_EXIT_OK
257						fi
258
259					else
260						# there is no process with that pid
261						if [ -n "$verbose" ]; then
262							echo "$0: $PIDFILE=$pid processid does not exist" 2>&1 | smf_console
263						fi
264						# Clearing our pidfile is just good housekeeping, not required
265						/usr/bin/cp /dev/null $PIDFILE
266
267						# Perhaps the $PIDFILE was overwritten as a result of some problem, but the service is still running.
268						# Kill any processes left in service contract
269						if [ -n "$contract_id" ] ; then
270							smf_kill_contract $contract_id $SIGNAL 1
271							[ $? -ne 0 ] && exit 1
272						fi
273
274						echo "done stopping $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console
275						exit $SMF_EXIT_OK
276					fi
277				else
278					if [ -n "$verbose" ]; then
279						echo "$0: pidfile $PIDFILE is empty" 2>&1 | smf_console
280					fi
281
282					# Perhaps the $PIDFILE was emptied as a result of some problem, but the service is still running.
283					# Kill any processes left in service contract
284					if [ -n "$contract_id" ] ; then
285						smf_kill_contract $contract_id $SIGNAL 1
286						[ $? -ne 0 ] && exit 1
287					fi
288
289					echo "done stopping $PROGNAME instance on interface $INTERFACE" 2>&1 | smf_console
290					exit $SMF_EXIT_OK
291				fi
292
293			else
294				if [ -n "$verbose" ]; then
295					echo "$0: pidfile $PIDFILE not found" 2>&1 | smf_console
296				fi
297
298				# Perhaps the $PIDFILE was removed as a result of some problem, but the service is still running.
299				# Kill any processes left in service contract
300				if [ -n "$contract_id" ] ; then
301					smf_kill_contract $contract_id $SIGNAL 1
302					[ $? -ne 0 ] && exit 1
303				fi
304
305				echo "done stopping $PROGNAME instance on interface $INTERFACE"  2>&1 | smf_console
306				exit $SMF_EXIT_OK
307			fi
308
309			# NOTREACHED
310			;;
311
312		*)
313			echo "$0: Unrecognized argument: $1"
314			echo "Usage:"
315			echo "  $0 [-v] -i interface [-Q vlan_id|none] [-r] [-d debuglevel] start"
316			echo "  $0 [-v] -i interface stop contract_id"
317
318			exit $SMF_EXIT_ERR_CONFIG
319			;;
320	esac
321
322	shift
323
324done
325
326