17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5d04ccbb3Scarlsonj * Common Development and Distribution License (the "License").
6d04ccbb3Scarlsonj * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*3644994cSmeem * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
237c478bd9Sstevel@tonic-gate * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate */
257c478bd9Sstevel@tonic-gate
267c478bd9Sstevel@tonic-gate #include <time.h>
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <assert.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <stdlib.h>
317c478bd9Sstevel@tonic-gate #include <unistd.h>
327c478bd9Sstevel@tonic-gate #include <sys/types.h>
337c478bd9Sstevel@tonic-gate #include <sys/wait.h>
347c478bd9Sstevel@tonic-gate #include <signal.h>
357c478bd9Sstevel@tonic-gate #include <fcntl.h>
367c478bd9Sstevel@tonic-gate #include <dhcpmsg.h>
37d04ccbb3Scarlsonj
38d04ccbb3Scarlsonj #include "agent.h"
397c478bd9Sstevel@tonic-gate #include "script_handler.h"
40d04ccbb3Scarlsonj #include "states.h"
41d04ccbb3Scarlsonj #include "interface.h"
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate * scripts are directly managed by a script helper process. dhcpagent creates
457c478bd9Sstevel@tonic-gate * the helper process and it, in turn, creates a process to run the script
467c478bd9Sstevel@tonic-gate * dhcpagent owns one end of a pipe and the helper process owns the other end
477c478bd9Sstevel@tonic-gate * the helper process calls waitpid to wait for the script to exit. an alarm
487c478bd9Sstevel@tonic-gate * is set for SCRIPT_TIMEOUT seconds. If the alarm fires, SIGTERM is sent to
497c478bd9Sstevel@tonic-gate * the script process and a second alarm is set for SCRIPT_TIMEOUT_GRACE. if
507c478bd9Sstevel@tonic-gate * the second alarm fires, SIGKILL is sent to forcefully kill the script. when
517c478bd9Sstevel@tonic-gate * script exits, the helper process notifies dhcpagent by closing its end
527c478bd9Sstevel@tonic-gate * of the pipe.
537c478bd9Sstevel@tonic-gate */
547c478bd9Sstevel@tonic-gate
557c478bd9Sstevel@tonic-gate unsigned int script_count;
567c478bd9Sstevel@tonic-gate
577c478bd9Sstevel@tonic-gate /*
587c478bd9Sstevel@tonic-gate * the signal to send to the script process. it is a global variable
597c478bd9Sstevel@tonic-gate * to this file as sigterm_handler needs it.
607c478bd9Sstevel@tonic-gate */
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate static int script_signal = SIGTERM;
637c478bd9Sstevel@tonic-gate
647c478bd9Sstevel@tonic-gate /*
657c478bd9Sstevel@tonic-gate * script's absolute timeout value. the first timeout is set to SCRIPT_TIMEOUT
667c478bd9Sstevel@tonic-gate * seconds from the time it is started. SIGTERM is sent on the first timeout
677c478bd9Sstevel@tonic-gate * the second timeout is set to SCRIPT_TIMEOUT_GRACE from the first timeout
687c478bd9Sstevel@tonic-gate * and SIGKILL is sent on the second timeout.
697c478bd9Sstevel@tonic-gate */
707c478bd9Sstevel@tonic-gate static time_t timeout;
717c478bd9Sstevel@tonic-gate
727c478bd9Sstevel@tonic-gate /*
73*3644994cSmeem * sigalarm_handler(): signal handler for SIGALRM
747c478bd9Sstevel@tonic-gate *
757c478bd9Sstevel@tonic-gate * input: int: signal the handler was called with
767c478bd9Sstevel@tonic-gate * output: void
777c478bd9Sstevel@tonic-gate */
787c478bd9Sstevel@tonic-gate
797c478bd9Sstevel@tonic-gate /* ARGSUSED */
807c478bd9Sstevel@tonic-gate static void
sigalarm_handler(int sig)817c478bd9Sstevel@tonic-gate sigalarm_handler(int sig)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate time_t now;
847c478bd9Sstevel@tonic-gate
857c478bd9Sstevel@tonic-gate /* set a another alarm if it fires too early */
867c478bd9Sstevel@tonic-gate now = time(NULL);
877c478bd9Sstevel@tonic-gate if (now < timeout)
887c478bd9Sstevel@tonic-gate (void) alarm(timeout - now);
897c478bd9Sstevel@tonic-gate }
907c478bd9Sstevel@tonic-gate
917c478bd9Sstevel@tonic-gate /*
927c478bd9Sstevel@tonic-gate * sigterm_handler(): signal handler for SIGTERM, fired when dhcpagent wants
937c478bd9Sstevel@tonic-gate * to stop the script
947c478bd9Sstevel@tonic-gate * input: int: signal the handler was called with
957c478bd9Sstevel@tonic-gate * output: void
967c478bd9Sstevel@tonic-gate */
977c478bd9Sstevel@tonic-gate
987c478bd9Sstevel@tonic-gate /* ARGSUSED */
997c478bd9Sstevel@tonic-gate static void
sigterm_handler(int sig)1007c478bd9Sstevel@tonic-gate sigterm_handler(int sig)
1017c478bd9Sstevel@tonic-gate {
1027c478bd9Sstevel@tonic-gate if (script_signal != SIGKILL) {
1037c478bd9Sstevel@tonic-gate /* send SIGKILL SCRIPT_TIMEOUT_GRACE seconds from now */
1047c478bd9Sstevel@tonic-gate script_signal = SIGKILL;
1057c478bd9Sstevel@tonic-gate timeout = time(NULL) + SCRIPT_TIMEOUT_GRACE;
1067c478bd9Sstevel@tonic-gate (void) alarm(SCRIPT_TIMEOUT_GRACE);
1077c478bd9Sstevel@tonic-gate }
1087c478bd9Sstevel@tonic-gate }
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate /*
1117c478bd9Sstevel@tonic-gate * run_script(): it forks a process to execute the script
1127c478bd9Sstevel@tonic-gate *
113d04ccbb3Scarlsonj * input: dhcp_smach_t *: the state machine
1147c478bd9Sstevel@tonic-gate * const char *: the event name
1157c478bd9Sstevel@tonic-gate * int: the pipe end owned by the script helper process
1167c478bd9Sstevel@tonic-gate * output: void
1177c478bd9Sstevel@tonic-gate */
118d04ccbb3Scarlsonj
1197c478bd9Sstevel@tonic-gate static void
run_script(dhcp_smach_t * dsmp,const char * event,int fd)120d04ccbb3Scarlsonj run_script(dhcp_smach_t *dsmp, const char *event, int fd)
1217c478bd9Sstevel@tonic-gate {
1227c478bd9Sstevel@tonic-gate int n;
1237c478bd9Sstevel@tonic-gate char c;
124d04ccbb3Scarlsonj char *path;
1257c478bd9Sstevel@tonic-gate char *name;
1267c478bd9Sstevel@tonic-gate pid_t pid;
1277c478bd9Sstevel@tonic-gate time_t now;
1287c478bd9Sstevel@tonic-gate
129*3644994cSmeem if ((pid = fork()) == -1)
1307c478bd9Sstevel@tonic-gate return;
131*3644994cSmeem
1327c478bd9Sstevel@tonic-gate if (pid == 0) {
133d04ccbb3Scarlsonj path = SCRIPT_PATH;
134d04ccbb3Scarlsonj name = strrchr(path, '/') + 1;
1357c478bd9Sstevel@tonic-gate
1367c478bd9Sstevel@tonic-gate /* close all files */
1377c478bd9Sstevel@tonic-gate closefrom(0);
1387c478bd9Sstevel@tonic-gate
1397c478bd9Sstevel@tonic-gate /* redirect stdin, stdout and stderr to /dev/null */
1407c478bd9Sstevel@tonic-gate if ((n = open("/dev/null", O_RDWR)) < 0)
141d04ccbb3Scarlsonj _exit(127);
1427c478bd9Sstevel@tonic-gate
1437c478bd9Sstevel@tonic-gate (void) dup2(n, STDOUT_FILENO);
1447c478bd9Sstevel@tonic-gate (void) dup2(n, STDERR_FILENO);
145d04ccbb3Scarlsonj (void) execl(path, name, dsmp->dsm_name, event, NULL);
1467c478bd9Sstevel@tonic-gate _exit(127);
1477c478bd9Sstevel@tonic-gate }
1487c478bd9Sstevel@tonic-gate
1497c478bd9Sstevel@tonic-gate /*
1507c478bd9Sstevel@tonic-gate * the first timeout fires SCRIPT_TIMEOUT seconds from now.
1517c478bd9Sstevel@tonic-gate */
1527c478bd9Sstevel@tonic-gate timeout = time(NULL) + SCRIPT_TIMEOUT;
1537c478bd9Sstevel@tonic-gate (void) sigset(SIGALRM, sigalarm_handler);
1547c478bd9Sstevel@tonic-gate (void) alarm(SCRIPT_TIMEOUT);
1557c478bd9Sstevel@tonic-gate
1567c478bd9Sstevel@tonic-gate /*
1577c478bd9Sstevel@tonic-gate * pass script's pid to dhcpagent.
1587c478bd9Sstevel@tonic-gate */
1597c478bd9Sstevel@tonic-gate (void) write(fd, &pid, sizeof (pid));
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate for (;;) {
1627c478bd9Sstevel@tonic-gate if (waitpid(pid, NULL, 0) >= 0) {
1637c478bd9Sstevel@tonic-gate /* script has exited */
1647c478bd9Sstevel@tonic-gate c = SCRIPT_OK;
1657c478bd9Sstevel@tonic-gate break;
1667c478bd9Sstevel@tonic-gate }
1677c478bd9Sstevel@tonic-gate
168*3644994cSmeem if (errno != EINTR)
1697c478bd9Sstevel@tonic-gate return;
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate now = time(NULL);
1727c478bd9Sstevel@tonic-gate if (now >= timeout) {
1737c478bd9Sstevel@tonic-gate (void) kill(pid, script_signal);
1747c478bd9Sstevel@tonic-gate if (script_signal == SIGKILL) {
1757c478bd9Sstevel@tonic-gate c = SCRIPT_KILLED;
1767c478bd9Sstevel@tonic-gate break;
1777c478bd9Sstevel@tonic-gate }
1787c478bd9Sstevel@tonic-gate
1797c478bd9Sstevel@tonic-gate script_signal = SIGKILL;
1807c478bd9Sstevel@tonic-gate timeout = now + SCRIPT_TIMEOUT_GRACE;
1817c478bd9Sstevel@tonic-gate (void) alarm(SCRIPT_TIMEOUT_GRACE);
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate (void) write(fd, &c, 1);
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate
1887c478bd9Sstevel@tonic-gate /*
189*3644994cSmeem * script_init(): initialize script state on a given state machine
190*3644994cSmeem *
191*3644994cSmeem * input: dhcp_smach_t *: the state machine
192*3644994cSmeem * output: void
193*3644994cSmeem */
194*3644994cSmeem
195*3644994cSmeem void
script_init(dhcp_smach_t * dsmp)196*3644994cSmeem script_init(dhcp_smach_t *dsmp)
197*3644994cSmeem {
198*3644994cSmeem dsmp->dsm_script_pid = -1;
199*3644994cSmeem dsmp->dsm_script_helper_pid = -1;
200*3644994cSmeem dsmp->dsm_script_event_id = -1;
201*3644994cSmeem dsmp->dsm_script_fd = -1;
202*3644994cSmeem dsmp->dsm_script_callback = NULL;
203*3644994cSmeem dsmp->dsm_script_event = NULL;
204*3644994cSmeem dsmp->dsm_callback_arg = NULL;
205*3644994cSmeem }
206*3644994cSmeem
207*3644994cSmeem /*
2087c478bd9Sstevel@tonic-gate * script_cleanup(): cleanup helper function
2097c478bd9Sstevel@tonic-gate *
210d04ccbb3Scarlsonj * input: dhcp_smach_t *: the state machine
2117c478bd9Sstevel@tonic-gate * output: void
2127c478bd9Sstevel@tonic-gate */
2137c478bd9Sstevel@tonic-gate
2147c478bd9Sstevel@tonic-gate static void
script_cleanup(dhcp_smach_t * dsmp)215d04ccbb3Scarlsonj script_cleanup(dhcp_smach_t *dsmp)
2167c478bd9Sstevel@tonic-gate {
217*3644994cSmeem /*
218*3644994cSmeem * We must clear dsm_script_pid prior to invoking the callback or we
219*3644994cSmeem * could get in an infinite loop via async_finish().
220*3644994cSmeem */
221d04ccbb3Scarlsonj dsmp->dsm_script_pid = -1;
222*3644994cSmeem dsmp->dsm_script_helper_pid = -1;
2237c478bd9Sstevel@tonic-gate
224d04ccbb3Scarlsonj if (dsmp->dsm_script_fd != -1) {
225d04ccbb3Scarlsonj assert(dsmp->dsm_script_event_id != -1);
226d04ccbb3Scarlsonj (void) iu_unregister_event(eh, dsmp->dsm_script_event_id, NULL);
227d04ccbb3Scarlsonj (void) close(dsmp->dsm_script_fd);
2287c478bd9Sstevel@tonic-gate
229*3644994cSmeem assert(dsmp->dsm_script_callback != NULL);
230*3644994cSmeem dsmp->dsm_script_callback(dsmp, dsmp->dsm_callback_arg);
231*3644994cSmeem script_init(dsmp);
2327c478bd9Sstevel@tonic-gate script_count--;
233*3644994cSmeem release_smach(dsmp); /* hold from script_start() */
2347c478bd9Sstevel@tonic-gate }
2357c478bd9Sstevel@tonic-gate }
2367c478bd9Sstevel@tonic-gate
2377c478bd9Sstevel@tonic-gate /*
238*3644994cSmeem * script_exit(): does cleanup and invokes the callback when the script exits
2397c478bd9Sstevel@tonic-gate *
2407c478bd9Sstevel@tonic-gate * input: eh_t *: unused
2417c478bd9Sstevel@tonic-gate * int: the end of pipe owned by dhcpagent
2427c478bd9Sstevel@tonic-gate * short: unused
2437c478bd9Sstevel@tonic-gate * eh_event_id_t: unused
244d04ccbb3Scarlsonj * void *: the state machine
2457c478bd9Sstevel@tonic-gate * output: void
2467c478bd9Sstevel@tonic-gate */
2477c478bd9Sstevel@tonic-gate
2487c478bd9Sstevel@tonic-gate /* ARGSUSED */
2497c478bd9Sstevel@tonic-gate static void
script_exit(iu_eh_t * ehp,int fd,short events,iu_event_id_t id,void * arg)2507c478bd9Sstevel@tonic-gate script_exit(iu_eh_t *ehp, int fd, short events, iu_event_id_t id, void *arg)
2517c478bd9Sstevel@tonic-gate {
2527c478bd9Sstevel@tonic-gate char c;
2537c478bd9Sstevel@tonic-gate
254*3644994cSmeem if (read(fd, &c, 1) <= 0)
2557c478bd9Sstevel@tonic-gate c = SCRIPT_FAILED;
2567c478bd9Sstevel@tonic-gate
257*3644994cSmeem if (c == SCRIPT_OK)
2587c478bd9Sstevel@tonic-gate dhcpmsg(MSG_DEBUG, "script ok");
259*3644994cSmeem else if (c == SCRIPT_KILLED)
2607c478bd9Sstevel@tonic-gate dhcpmsg(MSG_DEBUG, "script killed");
261*3644994cSmeem else
2627c478bd9Sstevel@tonic-gate dhcpmsg(MSG_DEBUG, "script failed");
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate script_cleanup(arg);
2657c478bd9Sstevel@tonic-gate }
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /*
268*3644994cSmeem * script_start(): tries to start a script.
269*3644994cSmeem * if a script is already running, it's stopped first.
270*3644994cSmeem *
2717c478bd9Sstevel@tonic-gate *
272d04ccbb3Scarlsonj * input: dhcp_smach_t *: the state machine
2737c478bd9Sstevel@tonic-gate * const char *: the event name
2747c478bd9Sstevel@tonic-gate * script_callback_t: callback function
2757c478bd9Sstevel@tonic-gate * void *: data to the callback function
276d04ccbb3Scarlsonj * output: boolean_t: B_TRUE if script starts successfully
2777c478bd9Sstevel@tonic-gate * int *: the returned value of the callback function if script
2787c478bd9Sstevel@tonic-gate * starts unsuccessfully
2797c478bd9Sstevel@tonic-gate */
280d04ccbb3Scarlsonj
281d04ccbb3Scarlsonj boolean_t
script_start(dhcp_smach_t * dsmp,const char * event,script_callback_t * callback,void * arg,int * status)282d04ccbb3Scarlsonj script_start(dhcp_smach_t *dsmp, const char *event,
283d04ccbb3Scarlsonj script_callback_t *callback, void *arg, int *status)
2847c478bd9Sstevel@tonic-gate {
2857c478bd9Sstevel@tonic-gate int n;
2867c478bd9Sstevel@tonic-gate int fds[2];
2877c478bd9Sstevel@tonic-gate pid_t pid;
2887c478bd9Sstevel@tonic-gate iu_event_id_t event_id;
2897c478bd9Sstevel@tonic-gate
2907c478bd9Sstevel@tonic-gate assert(callback != NULL);
2917c478bd9Sstevel@tonic-gate
292*3644994cSmeem if (dsmp->dsm_script_pid != -1) {
293*3644994cSmeem /* script is running, stop it */
294*3644994cSmeem dhcpmsg(MSG_DEBUG, "script_start: stopping ongoing script");
295*3644994cSmeem script_stop(dsmp);
296*3644994cSmeem }
297*3644994cSmeem
2987c478bd9Sstevel@tonic-gate if (access(SCRIPT_PATH, X_OK) == -1) {
2997c478bd9Sstevel@tonic-gate /* script does not exist */
3007c478bd9Sstevel@tonic-gate goto out;
3017c478bd9Sstevel@tonic-gate }
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate /*
3047c478bd9Sstevel@tonic-gate * dhcpagent owns one end of the pipe and script helper process
3057c478bd9Sstevel@tonic-gate * owns the other end. dhcpagent reads on the pipe; and the helper
3067c478bd9Sstevel@tonic-gate * process notifies it when the script exits.
3077c478bd9Sstevel@tonic-gate */
3087c478bd9Sstevel@tonic-gate if (pipe(fds) < 0) {
3097c478bd9Sstevel@tonic-gate dhcpmsg(MSG_ERROR, "script_start: can't create pipe");
3107c478bd9Sstevel@tonic-gate goto out;
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate if ((pid = fork()) < 0) {
3147c478bd9Sstevel@tonic-gate dhcpmsg(MSG_ERROR, "script_start: can't fork");
3157c478bd9Sstevel@tonic-gate (void) close(fds[0]);
3167c478bd9Sstevel@tonic-gate (void) close(fds[1]);
3177c478bd9Sstevel@tonic-gate goto out;
3187c478bd9Sstevel@tonic-gate }
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate if (pid == 0) {
3217c478bd9Sstevel@tonic-gate /*
3227c478bd9Sstevel@tonic-gate * SIGCHLD is ignored in dhcpagent, the helper process
3237c478bd9Sstevel@tonic-gate * needs it. it calls waitpid to wait for the script to exit.
3247c478bd9Sstevel@tonic-gate */
3257c478bd9Sstevel@tonic-gate (void) close(fds[0]);
3267c478bd9Sstevel@tonic-gate (void) sigset(SIGCHLD, SIG_DFL);
3277c478bd9Sstevel@tonic-gate (void) sigset(SIGTERM, sigterm_handler);
328d04ccbb3Scarlsonj run_script(dsmp, event, fds[1]);
3297c478bd9Sstevel@tonic-gate exit(0);
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate
3327c478bd9Sstevel@tonic-gate (void) close(fds[1]);
3337c478bd9Sstevel@tonic-gate
3347c478bd9Sstevel@tonic-gate /* get the script's pid */
335d04ccbb3Scarlsonj if (read(fds[0], &dsmp->dsm_script_pid, sizeof (pid_t)) !=
3367c478bd9Sstevel@tonic-gate sizeof (pid_t)) {
3377c478bd9Sstevel@tonic-gate (void) kill(pid, SIGKILL);
338d04ccbb3Scarlsonj dsmp->dsm_script_pid = -1;
3397c478bd9Sstevel@tonic-gate (void) close(fds[0]);
3407c478bd9Sstevel@tonic-gate goto out;
3417c478bd9Sstevel@tonic-gate }
3427c478bd9Sstevel@tonic-gate
343d04ccbb3Scarlsonj dsmp->dsm_script_helper_pid = pid;
344d04ccbb3Scarlsonj event_id = iu_register_event(eh, fds[0], POLLIN, script_exit, dsmp);
3457c478bd9Sstevel@tonic-gate if (event_id == -1) {
3467c478bd9Sstevel@tonic-gate (void) close(fds[0]);
347d04ccbb3Scarlsonj script_stop(dsmp);
3487c478bd9Sstevel@tonic-gate goto out;
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate
3517c478bd9Sstevel@tonic-gate script_count++;
352d04ccbb3Scarlsonj dsmp->dsm_script_event_id = event_id;
353d04ccbb3Scarlsonj dsmp->dsm_script_callback = callback;
354d04ccbb3Scarlsonj dsmp->dsm_script_event = event;
355d04ccbb3Scarlsonj dsmp->dsm_callback_arg = arg;
356d04ccbb3Scarlsonj dsmp->dsm_script_fd = fds[0];
357d04ccbb3Scarlsonj hold_smach(dsmp);
358d04ccbb3Scarlsonj return (B_TRUE);
3597c478bd9Sstevel@tonic-gate
3607c478bd9Sstevel@tonic-gate out:
3617c478bd9Sstevel@tonic-gate /* callback won't be called in script_exit, so call it here */
362d04ccbb3Scarlsonj n = callback(dsmp, arg);
3637c478bd9Sstevel@tonic-gate if (status != NULL)
3647c478bd9Sstevel@tonic-gate *status = n;
3657c478bd9Sstevel@tonic-gate
366d04ccbb3Scarlsonj return (B_FALSE);
3677c478bd9Sstevel@tonic-gate }
3687c478bd9Sstevel@tonic-gate
3697c478bd9Sstevel@tonic-gate /*
3707c478bd9Sstevel@tonic-gate * script_stop(): stops the script if it is running
3717c478bd9Sstevel@tonic-gate *
372d04ccbb3Scarlsonj * input: dhcp_smach_t *: the state machine
3737c478bd9Sstevel@tonic-gate * output: void
3747c478bd9Sstevel@tonic-gate */
375d04ccbb3Scarlsonj
3767c478bd9Sstevel@tonic-gate void
script_stop(dhcp_smach_t * dsmp)377d04ccbb3Scarlsonj script_stop(dhcp_smach_t *dsmp)
3787c478bd9Sstevel@tonic-gate {
379d04ccbb3Scarlsonj if (dsmp->dsm_script_pid != -1) {
380d04ccbb3Scarlsonj assert(dsmp->dsm_script_helper_pid != -1);
3817c478bd9Sstevel@tonic-gate
3827c478bd9Sstevel@tonic-gate /*
3837c478bd9Sstevel@tonic-gate * sends SIGTERM to the script and asks the helper process
3847c478bd9Sstevel@tonic-gate * to send SIGKILL if it does not exit after
3857c478bd9Sstevel@tonic-gate * SCRIPT_TIMEOUT_GRACE seconds.
3867c478bd9Sstevel@tonic-gate */
387d04ccbb3Scarlsonj (void) kill(dsmp->dsm_script_pid, SIGTERM);
388d04ccbb3Scarlsonj (void) kill(dsmp->dsm_script_helper_pid, SIGTERM);
3897c478bd9Sstevel@tonic-gate }
3907c478bd9Sstevel@tonic-gate
391d04ccbb3Scarlsonj script_cleanup(dsmp);
3927c478bd9Sstevel@tonic-gate }
393