xref: /onnv-gate/usr/src/cmd/cmd-inet/sbin/dhcpagent/script_handler.c (revision 9508:92d77d728f44)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
53431Scarlsonj  * Common Development and Distribution License (the "License").
63431Scarlsonj  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*9508SPeter.Memishian@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <time.h>
270Sstevel@tonic-gate #include <stdio.h>
280Sstevel@tonic-gate #include <assert.h>
290Sstevel@tonic-gate #include <string.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <unistd.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <sys/wait.h>
340Sstevel@tonic-gate #include <signal.h>
350Sstevel@tonic-gate #include <fcntl.h>
360Sstevel@tonic-gate #include <dhcpmsg.h>
373431Scarlsonj 
383431Scarlsonj #include "agent.h"
390Sstevel@tonic-gate #include "script_handler.h"
403431Scarlsonj #include "states.h"
413431Scarlsonj #include "interface.h"
420Sstevel@tonic-gate 
430Sstevel@tonic-gate /*
440Sstevel@tonic-gate  * scripts are directly managed by a script helper process. dhcpagent creates
450Sstevel@tonic-gate  * the helper process and it, in turn, creates a process to run the script
460Sstevel@tonic-gate  * dhcpagent owns one end of a pipe and the helper process owns the other end
470Sstevel@tonic-gate  * the helper process calls waitpid to wait for the script to exit. an alarm
480Sstevel@tonic-gate  * is set for SCRIPT_TIMEOUT seconds. If the alarm fires, SIGTERM is sent to
490Sstevel@tonic-gate  * the script process and a second alarm is set for SCRIPT_TIMEOUT_GRACE. if
500Sstevel@tonic-gate  * the second alarm fires, SIGKILL is sent to forcefully kill the script. when
510Sstevel@tonic-gate  * script exits, the helper process notifies dhcpagent by closing its end
520Sstevel@tonic-gate  * of the pipe.
530Sstevel@tonic-gate  */
540Sstevel@tonic-gate 
550Sstevel@tonic-gate unsigned int	script_count;
560Sstevel@tonic-gate 
570Sstevel@tonic-gate /*
580Sstevel@tonic-gate  * the signal to send to the script process. it is a global variable
590Sstevel@tonic-gate  * to this file as sigterm_handler needs it.
600Sstevel@tonic-gate  */
610Sstevel@tonic-gate 
620Sstevel@tonic-gate static int	script_signal = SIGTERM;
630Sstevel@tonic-gate 
640Sstevel@tonic-gate /*
650Sstevel@tonic-gate  * script's absolute timeout value. the first timeout is set to SCRIPT_TIMEOUT
660Sstevel@tonic-gate  * seconds from the time it is started. SIGTERM is sent on the first timeout
670Sstevel@tonic-gate  * the second timeout is set to SCRIPT_TIMEOUT_GRACE from the first timeout
680Sstevel@tonic-gate  * and SIGKILL is sent on the second timeout.
690Sstevel@tonic-gate  */
70*9508SPeter.Memishian@Sun.COM static time_t	timeout;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate /*
73*9508SPeter.Memishian@Sun.COM  * sigalarm_handler(): signal handler for SIGALRM
740Sstevel@tonic-gate  *
750Sstevel@tonic-gate  *   input: int: signal the handler was called with
760Sstevel@tonic-gate  *  output: void
770Sstevel@tonic-gate  */
780Sstevel@tonic-gate 
790Sstevel@tonic-gate /* ARGSUSED */
800Sstevel@tonic-gate static void
sigalarm_handler(int sig)810Sstevel@tonic-gate sigalarm_handler(int sig)
820Sstevel@tonic-gate {
830Sstevel@tonic-gate 	time_t	now;
840Sstevel@tonic-gate 
850Sstevel@tonic-gate 	/* set a another alarm if it fires too early */
860Sstevel@tonic-gate 	now = time(NULL);
870Sstevel@tonic-gate 	if (now < timeout)
880Sstevel@tonic-gate 		(void) alarm(timeout - now);
890Sstevel@tonic-gate }
900Sstevel@tonic-gate 
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate  * sigterm_handler(): signal handler for SIGTERM, fired when dhcpagent wants
930Sstevel@tonic-gate  *		      to stop the script
940Sstevel@tonic-gate  *   input: int: signal the handler was called with
950Sstevel@tonic-gate  *  output: void
960Sstevel@tonic-gate  */
970Sstevel@tonic-gate 
980Sstevel@tonic-gate /* ARGSUSED */
990Sstevel@tonic-gate static void
sigterm_handler(int sig)1000Sstevel@tonic-gate sigterm_handler(int sig)
1010Sstevel@tonic-gate {
1020Sstevel@tonic-gate 	if (script_signal != SIGKILL) {
1030Sstevel@tonic-gate 		/* send SIGKILL SCRIPT_TIMEOUT_GRACE seconds from now */
1040Sstevel@tonic-gate 		script_signal = SIGKILL;
1050Sstevel@tonic-gate 		timeout = time(NULL) + SCRIPT_TIMEOUT_GRACE;
1060Sstevel@tonic-gate 		(void) alarm(SCRIPT_TIMEOUT_GRACE);
1070Sstevel@tonic-gate 	}
1080Sstevel@tonic-gate }
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate /*
1110Sstevel@tonic-gate  * run_script(): it forks a process to execute the script
1120Sstevel@tonic-gate  *
1133431Scarlsonj  *   input: dhcp_smach_t *: the state machine
1140Sstevel@tonic-gate  *	    const char *: the event name
1150Sstevel@tonic-gate  *	    int: the pipe end owned by the script helper process
1160Sstevel@tonic-gate  *  output: void
1170Sstevel@tonic-gate  */
1183431Scarlsonj 
1190Sstevel@tonic-gate static void
run_script(dhcp_smach_t * dsmp,const char * event,int fd)1203431Scarlsonj run_script(dhcp_smach_t *dsmp, const char *event, int fd)
1210Sstevel@tonic-gate {
1220Sstevel@tonic-gate 	int		n;
1230Sstevel@tonic-gate 	char		c;
1243431Scarlsonj 	char		*path;
1250Sstevel@tonic-gate 	char		*name;
1260Sstevel@tonic-gate 	pid_t		pid;
1270Sstevel@tonic-gate 	time_t		now;
1280Sstevel@tonic-gate 
129*9508SPeter.Memishian@Sun.COM 	if ((pid = fork()) == -1)
1300Sstevel@tonic-gate 		return;
131*9508SPeter.Memishian@Sun.COM 
1320Sstevel@tonic-gate 	if (pid == 0) {
1333431Scarlsonj 		path = SCRIPT_PATH;
1343431Scarlsonj 		name = strrchr(path, '/') + 1;
1350Sstevel@tonic-gate 
1360Sstevel@tonic-gate 		/* close all files */
1370Sstevel@tonic-gate 		closefrom(0);
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 		/* redirect stdin, stdout and stderr to /dev/null */
1400Sstevel@tonic-gate 		if ((n = open("/dev/null", O_RDWR)) < 0)
1413431Scarlsonj 			_exit(127);
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 		(void) dup2(n, STDOUT_FILENO);
1440Sstevel@tonic-gate 		(void) dup2(n, STDERR_FILENO);
1453431Scarlsonj 		(void) execl(path, name, dsmp->dsm_name, event, NULL);
1460Sstevel@tonic-gate 		_exit(127);
1470Sstevel@tonic-gate 	}
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 	/*
1500Sstevel@tonic-gate 	 * the first timeout fires SCRIPT_TIMEOUT seconds from now.
1510Sstevel@tonic-gate 	 */
1520Sstevel@tonic-gate 	timeout = time(NULL) + SCRIPT_TIMEOUT;
1530Sstevel@tonic-gate 	(void) sigset(SIGALRM, sigalarm_handler);
1540Sstevel@tonic-gate 	(void) alarm(SCRIPT_TIMEOUT);
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	/*
1570Sstevel@tonic-gate 	 * pass script's pid to dhcpagent.
1580Sstevel@tonic-gate 	 */
1590Sstevel@tonic-gate 	(void) write(fd, &pid, sizeof (pid));
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 	for (;;) {
1620Sstevel@tonic-gate 		if (waitpid(pid, NULL, 0) >= 0) {
1630Sstevel@tonic-gate 			/* script has exited */
1640Sstevel@tonic-gate 			c = SCRIPT_OK;
1650Sstevel@tonic-gate 			break;
1660Sstevel@tonic-gate 		}
1670Sstevel@tonic-gate 
168*9508SPeter.Memishian@Sun.COM 		if (errno != EINTR)
1690Sstevel@tonic-gate 			return;
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 		now = time(NULL);
1720Sstevel@tonic-gate 		if (now >= timeout) {
1730Sstevel@tonic-gate 			(void) kill(pid, script_signal);
1740Sstevel@tonic-gate 			if (script_signal == SIGKILL) {
1750Sstevel@tonic-gate 				c = SCRIPT_KILLED;
1760Sstevel@tonic-gate 				break;
1770Sstevel@tonic-gate 			}
1780Sstevel@tonic-gate 
1790Sstevel@tonic-gate 			script_signal = SIGKILL;
1800Sstevel@tonic-gate 			timeout = now + SCRIPT_TIMEOUT_GRACE;
1810Sstevel@tonic-gate 			(void) alarm(SCRIPT_TIMEOUT_GRACE);
1820Sstevel@tonic-gate 		}
1830Sstevel@tonic-gate 	}
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 	(void) write(fd, &c, 1);
1860Sstevel@tonic-gate }
1870Sstevel@tonic-gate 
1880Sstevel@tonic-gate /*
189*9508SPeter.Memishian@Sun.COM  * script_init(): initialize script state on a given state machine
190*9508SPeter.Memishian@Sun.COM  *
191*9508SPeter.Memishian@Sun.COM  *   input: dhcp_smach_t *: the state machine
192*9508SPeter.Memishian@Sun.COM  *  output: void
193*9508SPeter.Memishian@Sun.COM  */
194*9508SPeter.Memishian@Sun.COM 
195*9508SPeter.Memishian@Sun.COM void
script_init(dhcp_smach_t * dsmp)196*9508SPeter.Memishian@Sun.COM script_init(dhcp_smach_t *dsmp)
197*9508SPeter.Memishian@Sun.COM {
198*9508SPeter.Memishian@Sun.COM 	dsmp->dsm_script_pid = -1;
199*9508SPeter.Memishian@Sun.COM 	dsmp->dsm_script_helper_pid = -1;
200*9508SPeter.Memishian@Sun.COM 	dsmp->dsm_script_event_id = -1;
201*9508SPeter.Memishian@Sun.COM 	dsmp->dsm_script_fd = -1;
202*9508SPeter.Memishian@Sun.COM 	dsmp->dsm_script_callback = NULL;
203*9508SPeter.Memishian@Sun.COM 	dsmp->dsm_script_event = NULL;
204*9508SPeter.Memishian@Sun.COM 	dsmp->dsm_callback_arg = NULL;
205*9508SPeter.Memishian@Sun.COM }
206*9508SPeter.Memishian@Sun.COM 
207*9508SPeter.Memishian@Sun.COM /*
2080Sstevel@tonic-gate  * script_cleanup(): cleanup helper function
2090Sstevel@tonic-gate  *
2103431Scarlsonj  *   input: dhcp_smach_t *: the state machine
2110Sstevel@tonic-gate  *  output: void
2120Sstevel@tonic-gate  */
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate static void
script_cleanup(dhcp_smach_t * dsmp)2153431Scarlsonj script_cleanup(dhcp_smach_t *dsmp)
2160Sstevel@tonic-gate {
217*9508SPeter.Memishian@Sun.COM 	/*
218*9508SPeter.Memishian@Sun.COM 	 * We must clear dsm_script_pid prior to invoking the callback or we
219*9508SPeter.Memishian@Sun.COM 	 * could get in an infinite loop via async_finish().
220*9508SPeter.Memishian@Sun.COM 	 */
221*9508SPeter.Memishian@Sun.COM 	dsmp->dsm_script_pid = -1;
2223431Scarlsonj 	dsmp->dsm_script_helper_pid = -1;
2230Sstevel@tonic-gate 
2243431Scarlsonj 	if (dsmp->dsm_script_fd != -1) {
2253431Scarlsonj 		assert(dsmp->dsm_script_event_id != -1);
2263431Scarlsonj 		(void) iu_unregister_event(eh, dsmp->dsm_script_event_id, NULL);
2273431Scarlsonj 		(void) close(dsmp->dsm_script_fd);
228*9508SPeter.Memishian@Sun.COM 
229*9508SPeter.Memishian@Sun.COM 		assert(dsmp->dsm_script_callback != NULL);
2303431Scarlsonj 		dsmp->dsm_script_callback(dsmp, dsmp->dsm_callback_arg);
231*9508SPeter.Memishian@Sun.COM 		script_init(dsmp);
2320Sstevel@tonic-gate 		script_count--;
233*9508SPeter.Memishian@Sun.COM 		release_smach(dsmp);	/* hold from script_start() */
2340Sstevel@tonic-gate 	}
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate /*
238*9508SPeter.Memishian@Sun.COM  * script_exit(): does cleanup and invokes the callback when the script exits
2390Sstevel@tonic-gate  *
2400Sstevel@tonic-gate  *   input: eh_t *: unused
2410Sstevel@tonic-gate  *	    int: the end of pipe owned by dhcpagent
2420Sstevel@tonic-gate  *	    short: unused
2430Sstevel@tonic-gate  *	    eh_event_id_t: unused
2443431Scarlsonj  *	    void *: the state machine
2450Sstevel@tonic-gate  *  output: void
2460Sstevel@tonic-gate  */
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate /* ARGSUSED */
2490Sstevel@tonic-gate static void
script_exit(iu_eh_t * ehp,int fd,short events,iu_event_id_t id,void * arg)2500Sstevel@tonic-gate script_exit(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg)
2510Sstevel@tonic-gate {
252*9508SPeter.Memishian@Sun.COM 	char c;
2530Sstevel@tonic-gate 
254*9508SPeter.Memishian@Sun.COM 	if (read(fd, &c, 1) <= 0)
2550Sstevel@tonic-gate 		c = SCRIPT_FAILED;
2560Sstevel@tonic-gate 
257*9508SPeter.Memishian@Sun.COM 	if (c == SCRIPT_OK)
2580Sstevel@tonic-gate 		dhcpmsg(MSG_DEBUG, "script ok");
259*9508SPeter.Memishian@Sun.COM 	else if (c == SCRIPT_KILLED)
2600Sstevel@tonic-gate 		dhcpmsg(MSG_DEBUG, "script killed");
261*9508SPeter.Memishian@Sun.COM 	else
2620Sstevel@tonic-gate 		dhcpmsg(MSG_DEBUG, "script failed");
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	script_cleanup(arg);
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate /*
268*9508SPeter.Memishian@Sun.COM  * script_start(): tries to start a script.
269*9508SPeter.Memishian@Sun.COM  *		   if a script is already running, it's stopped first.
270*9508SPeter.Memishian@Sun.COM  *
2710Sstevel@tonic-gate  *
2723431Scarlsonj  *   input: dhcp_smach_t *: the state machine
2730Sstevel@tonic-gate  *	    const char *: the event name
2740Sstevel@tonic-gate  *	    script_callback_t: callback function
2750Sstevel@tonic-gate  *	    void *: data to the callback function
2763431Scarlsonj  *  output: boolean_t: B_TRUE if script starts successfully
2770Sstevel@tonic-gate  *	    int *: the returned value of the callback function if script
2780Sstevel@tonic-gate  *		starts unsuccessfully
2790Sstevel@tonic-gate  */
2803431Scarlsonj 
2813431Scarlsonj boolean_t
script_start(dhcp_smach_t * dsmp,const char * event,script_callback_t * callback,void * arg,int * status)2823431Scarlsonj script_start(dhcp_smach_t *dsmp, const char *event,
2833431Scarlsonj     script_callback_t *callback, void *arg, int *status)
2840Sstevel@tonic-gate {
2850Sstevel@tonic-gate 	int		n;
2860Sstevel@tonic-gate 	int		fds[2];
2870Sstevel@tonic-gate 	pid_t		pid;
2880Sstevel@tonic-gate 	iu_event_id_t	event_id;
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 	assert(callback != NULL);
2910Sstevel@tonic-gate 
292*9508SPeter.Memishian@Sun.COM 	if (dsmp->dsm_script_pid != -1) {
293*9508SPeter.Memishian@Sun.COM 		/* script is running, stop it */
294*9508SPeter.Memishian@Sun.COM 		dhcpmsg(MSG_DEBUG, "script_start: stopping ongoing script");
295*9508SPeter.Memishian@Sun.COM 		script_stop(dsmp);
296*9508SPeter.Memishian@Sun.COM 	}
297*9508SPeter.Memishian@Sun.COM 
2980Sstevel@tonic-gate 	if (access(SCRIPT_PATH, X_OK) == -1) {
2990Sstevel@tonic-gate 		/* script does not exist */
3000Sstevel@tonic-gate 		goto out;
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	/*
3040Sstevel@tonic-gate 	 * dhcpagent owns one end of the pipe and script helper process
3050Sstevel@tonic-gate 	 * owns the other end. dhcpagent reads on the pipe; and the helper
3060Sstevel@tonic-gate 	 * process notifies it when the script exits.
3070Sstevel@tonic-gate 	 */
3080Sstevel@tonic-gate 	if (pipe(fds) < 0) {
3090Sstevel@tonic-gate 		dhcpmsg(MSG_ERROR, "script_start: can't create pipe");
3100Sstevel@tonic-gate 		goto out;
3110Sstevel@tonic-gate 	}
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	if ((pid = fork()) < 0) {
3140Sstevel@tonic-gate 		dhcpmsg(MSG_ERROR, "script_start: can't fork");
3150Sstevel@tonic-gate 		(void) close(fds[0]);
3160Sstevel@tonic-gate 		(void) close(fds[1]);
3170Sstevel@tonic-gate 		goto out;
3180Sstevel@tonic-gate 	}
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	if (pid == 0) {
3210Sstevel@tonic-gate 		/*
3220Sstevel@tonic-gate 		 * SIGCHLD is ignored in dhcpagent, the helper process
3230Sstevel@tonic-gate 		 * needs it. it calls waitpid to wait for the script to exit.
3240Sstevel@tonic-gate 		 */
3250Sstevel@tonic-gate 		(void) close(fds[0]);
3260Sstevel@tonic-gate 		(void) sigset(SIGCHLD, SIG_DFL);
3270Sstevel@tonic-gate 		(void) sigset(SIGTERM, sigterm_handler);
3283431Scarlsonj 		run_script(dsmp, event, fds[1]);
3290Sstevel@tonic-gate 		exit(0);
3300Sstevel@tonic-gate 	}
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate 	(void) close(fds[1]);
3330Sstevel@tonic-gate 
3340Sstevel@tonic-gate 	/* get the script's pid */
3353431Scarlsonj 	if (read(fds[0], &dsmp->dsm_script_pid, sizeof (pid_t)) !=
3360Sstevel@tonic-gate 	    sizeof (pid_t)) {
3370Sstevel@tonic-gate 		(void) kill(pid, SIGKILL);
3383431Scarlsonj 		dsmp->dsm_script_pid = -1;
3390Sstevel@tonic-gate 		(void) close(fds[0]);
3400Sstevel@tonic-gate 		goto out;
3410Sstevel@tonic-gate 	}
3420Sstevel@tonic-gate 
3433431Scarlsonj 	dsmp->dsm_script_helper_pid = pid;
3443431Scarlsonj 	event_id = iu_register_event(eh, fds[0], POLLIN, script_exit, dsmp);
3450Sstevel@tonic-gate 	if (event_id == -1) {
3460Sstevel@tonic-gate 		(void) close(fds[0]);
3473431Scarlsonj 		script_stop(dsmp);
3480Sstevel@tonic-gate 		goto out;
3490Sstevel@tonic-gate 	}
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate 	script_count++;
3523431Scarlsonj 	dsmp->dsm_script_event_id = event_id;
3533431Scarlsonj 	dsmp->dsm_script_callback = callback;
3543431Scarlsonj 	dsmp->dsm_script_event = event;
3553431Scarlsonj 	dsmp->dsm_callback_arg = arg;
3563431Scarlsonj 	dsmp->dsm_script_fd = fds[0];
3573431Scarlsonj 	hold_smach(dsmp);
3583431Scarlsonj 	return (B_TRUE);
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate out:
3610Sstevel@tonic-gate 	/* callback won't be called in script_exit, so call it here */
3623431Scarlsonj 	n = callback(dsmp, arg);
3630Sstevel@tonic-gate 	if (status != NULL)
3640Sstevel@tonic-gate 		*status = n;
3650Sstevel@tonic-gate 
3663431Scarlsonj 	return (B_FALSE);
3670Sstevel@tonic-gate }
3680Sstevel@tonic-gate 
3690Sstevel@tonic-gate /*
3700Sstevel@tonic-gate  * script_stop(): stops the script if it is running
3710Sstevel@tonic-gate  *
3723431Scarlsonj  *   input: dhcp_smach_t *: the state machine
3730Sstevel@tonic-gate  *  output: void
3740Sstevel@tonic-gate  */
3753431Scarlsonj 
3760Sstevel@tonic-gate void
script_stop(dhcp_smach_t * dsmp)3773431Scarlsonj script_stop(dhcp_smach_t *dsmp)
3780Sstevel@tonic-gate {
3793431Scarlsonj 	if (dsmp->dsm_script_pid != -1) {
3803431Scarlsonj 		assert(dsmp->dsm_script_helper_pid != -1);
3810Sstevel@tonic-gate 
3820Sstevel@tonic-gate 		/*
3830Sstevel@tonic-gate 		 * sends SIGTERM to the script and asks the helper process
3840Sstevel@tonic-gate 		 * to send SIGKILL if it does not exit after
3850Sstevel@tonic-gate 		 * SCRIPT_TIMEOUT_GRACE seconds.
3860Sstevel@tonic-gate 		 */
3873431Scarlsonj 		(void) kill(dsmp->dsm_script_pid, SIGTERM);
3883431Scarlsonj 		(void) kill(dsmp->dsm_script_helper_pid, SIGTERM);
3890Sstevel@tonic-gate 	}
3900Sstevel@tonic-gate 
3913431Scarlsonj 	script_cleanup(dsmp);
3920Sstevel@tonic-gate }
393