Annotation of src/external/bsd/dhcpcd/dist/src/script.c, Revision 1.1.1.10
1.1.1.8 roy 1: /* SPDX-License-Identifier: BSD-2-Clause */
1.1 roy 2: /*
3: * dhcpcd - DHCP client daemon
1.1.1.5 roy 4: * Copyright (c) 2006-2019 Roy Marples <roy@marples.name>
1.1 roy 5: * All rights reserved
6:
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: *
16: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26: * SUCH DAMAGE.
27: */
28:
29: #include <sys/stat.h>
30: #include <sys/uio.h>
31: #include <sys/wait.h>
32:
33: #include <netinet/in.h>
34: #include <arpa/inet.h>
35:
36: #include <ctype.h>
37: #include <errno.h>
38: #include <signal.h>
39: #include <spawn.h>
1.1.1.8 roy 40: #include <stdarg.h>
1.1 roy 41: #include <stdlib.h>
42: #include <string.h>
43: #include <unistd.h>
44:
45: #include "config.h"
46: #include "common.h"
47: #include "dhcp.h"
48: #include "dhcp6.h"
49: #include "if.h"
50: #include "if-options.h"
51: #include "ipv4ll.h"
52: #include "ipv6nd.h"
1.1.1.2 roy 53: #include "logerr.h"
1.1 roy 54: #include "script.h"
55:
56: /* Allow the OS to define another script env var name */
57: #ifndef RC_SVCNAME
58: #define RC_SVCNAME "RC_SVCNAME"
59: #endif
60:
1.1.1.8 roy 61: #define DEFAULT_PATH "/usr/bin:/usr/sbin:/bin:/sbin"
1.1 roy 62:
63: static const char * const if_params[] = {
64: "interface",
1.1.1.3 roy 65: "protocol",
1.1 roy 66: "reason",
67: "pid",
68: "ifcarrier",
69: "ifmetric",
70: "ifwireless",
71: "ifflags",
72: "ssid",
73: "profile",
74: "interface_order",
75: NULL
76: };
77:
78: void
79: if_printoptions(void)
80: {
81: const char * const *p;
82:
83: for (p = if_params; *p; p++)
84: printf(" - %s\n", *p);
85: }
86:
87: static int
88: exec_script(const struct dhcpcd_ctx *ctx, char *const *argv, char *const *env)
89: {
90: pid_t pid;
91: posix_spawnattr_t attr;
92: int r;
93: #ifdef USE_SIGNALS
94: size_t i;
95: short flags;
96: sigset_t defsigs;
97: #else
98: UNUSED(ctx);
99: #endif
100:
101: /* posix_spawn is a safe way of executing another image
102: * and changing signals back to how they should be. */
103: if (posix_spawnattr_init(&attr) == -1)
104: return -1;
105: #ifdef USE_SIGNALS
106: flags = POSIX_SPAWN_SETSIGMASK | POSIX_SPAWN_SETSIGDEF;
107: posix_spawnattr_setflags(&attr, flags);
108: sigemptyset(&defsigs);
109: for (i = 0; i < dhcpcd_signals_len; i++)
110: sigaddset(&defsigs, dhcpcd_signals[i]);
111: posix_spawnattr_setsigdefault(&attr, &defsigs);
112: posix_spawnattr_setsigmask(&attr, &ctx->sigset);
113: #endif
114: errno = 0;
115: r = posix_spawn(&pid, argv[0], NULL, &attr, argv, env);
116: posix_spawnattr_destroy(&attr);
117: if (r) {
118: errno = r;
119: return -1;
120: }
121: return pid;
122: }
123:
124: #ifdef INET
125: static int
1.1.1.8 roy 126: append_config(FILE *fp, const char *prefix, const char *const *config)
1.1 roy 127: {
1.1.1.8 roy 128: size_t i;
1.1 roy 129:
130: if (config == NULL)
131: return 0;
132:
1.1.1.8 roy 133: /* Do we need to replace existing config rather than append? */
1.1 roy 134: for (i = 0; config[i] != NULL; i++) {
1.1.1.8 roy 135: if (efprintf(fp, "%s_%s", prefix, config[i]) == -1)
136: return -1;
1.1 roy 137: }
1.1.1.8 roy 138: return 1;
1.1 roy 139: }
140:
1.1.1.8 roy 141: #endif
1.1 roy 142:
1.1.1.4 roy 143: #define PROTO_LINK 0
1.1.1.3 roy 144: #define PROTO_DHCP 1
145: #define PROTO_IPV4LL 2
146: #define PROTO_RA 3
147: #define PROTO_DHCP6 4
148: #define PROTO_STATIC6 5
149: static const char *protocols[] = {
1.1.1.4 roy 150: "link",
1.1.1.3 roy 151: "dhcp",
152: "ipv4ll",
153: "ra",
154: "dhcp6",
155: "static6"
156: };
157:
1.1.1.8 roy 158: int
159: efprintf(FILE *fp, const char *fmt, ...)
160: {
161: va_list args;
162: int r;
163:
164: va_start(args, fmt);
165: r = vfprintf(fp, fmt, args);
166: va_end(args);
167: if (r == -1)
168: return -1;
169: /* Write a trailing NULL so we can easily create env strings. */
170: if (fputc('\0', fp) == EOF)
171: return -1;
172: return r;
173: }
174:
1.1 roy 175: static ssize_t
1.1.1.8 roy 176: make_env(const struct interface *ifp, const char *reason)
1.1 roy 177: {
1.1.1.8 roy 178: struct dhcpcd_ctx *ctx = ifp->ctx;
179: FILE *fp;
180: char **env, **envp, *buf, *bufp, *endp, *path;
181: size_t nenv;
182: long buf_pos, i;
1.1.1.9 roy 183: int protocol = PROTO_LINK;
1.1 roy 184: const struct if_options *ifo = ifp->options;
185: const struct interface *ifp2;
186: int af;
187: #ifdef INET
188: const struct dhcp_state *state;
189: #ifdef IPV4LL
190: const struct ipv4ll_state *istate;
191: #endif
192: #endif
1.1.1.6 roy 193: #ifdef DHCP6
1.1 roy 194: const struct dhcp6_state *d6_state;
195: #endif
196:
1.1.1.8 roy 197: #ifdef HAVE_OPEN_MEMSTREAM
198: if (ctx->script_fp == NULL) {
199: fp = open_memstream(&ctx->script_buf, &ctx->script_buflen);
200: if (fp == NULL)
201: goto eexit;
202: ctx->script_fp = fp;
203: } else {
204: fp = ctx->script_fp;
205: rewind(fp);
206: }
207: #else
208: char tmpfile[] = "/tmp/dhcpcd-script-env-XXXXXX";
209: int tmpfd;
210:
211: fp = NULL;
212: tmpfd = mkstemp(tmpfile);
213: if (tmpfd == -1)
214: goto eexit;
215: unlink(tmpfile);
1.1.1.10! roy 216: fp = fdopen(tmpfd, "w+");
! 217: if (fp == NULL) {
! 218: close(tmpfd);
1.1.1.8 roy 219: goto eexit;
1.1.1.10! roy 220: }
1.1.1.8 roy 221: #endif
222:
1.1 roy 223: #ifdef INET
224: state = D_STATE(ifp);
225: #ifdef IPV4LL
226: istate = IPV4LL_CSTATE(ifp);
227: #endif
228: #endif
1.1.1.6 roy 229: #ifdef DHCP6
1.1 roy 230: d6_state = D6_CSTATE(ifp);
231: #endif
232: if (strcmp(reason, "TEST") == 0) {
233: if (1 == 2) {}
234: #ifdef INET6
1.1.1.6 roy 235: #ifdef DHCP6
1.1 roy 236: else if (d6_state && d6_state->new)
1.1.1.3 roy 237: protocol = PROTO_DHCP6;
1.1.1.6 roy 238: #endif
1.1 roy 239: else if (ipv6nd_hasra(ifp))
1.1.1.3 roy 240: protocol = PROTO_RA;
1.1 roy 241: #endif
242: #ifdef INET
243: #ifdef IPV4LL
244: else if (istate && istate->addr != NULL)
1.1.1.3 roy 245: protocol = PROTO_IPV4LL;
1.1 roy 246: #endif
247: else
1.1.1.3 roy 248: protocol = PROTO_DHCP;
1.1 roy 249: #endif
250: }
251: #ifdef INET6
252: else if (strcmp(reason, "STATIC6") == 0)
1.1.1.3 roy 253: protocol = PROTO_STATIC6;
1.1.1.6 roy 254: #ifdef DHCP6
1.1 roy 255: else if (reason[strlen(reason) - 1] == '6')
1.1.1.3 roy 256: protocol = PROTO_DHCP6;
1.1.1.6 roy 257: #endif
1.1 roy 258: else if (strcmp(reason, "ROUTERADVERT") == 0)
1.1.1.3 roy 259: protocol = PROTO_RA;
1.1 roy 260: #endif
261: else if (strcmp(reason, "PREINIT") == 0 ||
262: strcmp(reason, "CARRIER") == 0 ||
263: strcmp(reason, "NOCARRIER") == 0 ||
264: strcmp(reason, "UNKNOWN") == 0 ||
265: strcmp(reason, "DEPARTED") == 0 ||
266: strcmp(reason, "STOPPED") == 0)
1.1.1.4 roy 267: protocol = PROTO_LINK;
1.1 roy 268: #ifdef INET
269: #ifdef IPV4LL
270: else if (strcmp(reason, "IPV4LL") == 0)
1.1.1.3 roy 271: protocol = PROTO_IPV4LL;
1.1 roy 272: #endif
273: else
1.1.1.3 roy 274: protocol = PROTO_DHCP;
1.1 roy 275: #endif
276:
1.1.1.8 roy 277: /* Needed for scripts */
278: path = getenv("PATH");
279: if (efprintf(fp, "PATH=%s", path == NULL ? DEFAULT_PATH:path) == -1)
280: goto eexit;
1.1 roy 281:
1.1.1.8 roy 282: if (efprintf(fp, "interface=%s", ifp->name) == -1)
283: goto eexit;
284: if (efprintf(fp, "reason=%s", reason) == -1)
285: goto eexit;
1.1 roy 286: if (ifp->ctx->options & DHCPCD_DUMPLEASE)
287: goto dumplease;
1.1.1.8 roy 288: if (efprintf(fp, "pid=%d", getpid()) == -1)
289: goto eexit;
290: if (efprintf(fp, "ifcarrier=%s",
1.1 roy 291: ifp->carrier == LINK_UNKNOWN ? "unknown" :
1.1.1.8 roy 292: ifp->carrier == LINK_UP ? "up" : "down") == -1)
293: goto eexit;
294: if (efprintf(fp, "ifmetric=%d", ifp->metric) == -1)
295: goto eexit;
296: if (efprintf(fp, "ifwireless=%d", ifp->wireless) == -1)
297: goto eexit;
298: if (efprintf(fp, "ifflags=%u", ifp->flags) == -1)
299: goto eexit;
300: if (efprintf(fp, "ifmtu=%d", if_getmtu(ifp)) == -1)
301: goto eexit;
302:
303: if (fprintf(fp, "interface_order=") == -1)
304: goto eexit;
1.1 roy 305: TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
1.1.1.8 roy 306: if (ifp2 != TAILQ_FIRST(ifp->ctx->ifaces)) {
307: if (fputc(' ', fp) == EOF)
308: return -1;
309: }
310: if (fprintf(fp, "%s", ifp2->name) == -1)
311: return -1;
1.1 roy 312: }
1.1.1.8 roy 313: if (fputc('\0', fp) == EOF)
314: return -1;
315:
1.1 roy 316: if (strcmp(reason, "STOPPED") == 0) {
1.1.1.8 roy 317: if (efprintf(fp, "if_up=false") == -1)
318: goto eexit;
319: if (efprintf(fp, "if_down=%s",
320: ifo->options & DHCPCD_RELEASE ? "true" : "false") == -1)
321: goto eexit;
1.1 roy 322: } else if (strcmp(reason, "TEST") == 0 ||
323: strcmp(reason, "PREINIT") == 0 ||
324: strcmp(reason, "CARRIER") == 0 ||
325: strcmp(reason, "UNKNOWN") == 0)
326: {
1.1.1.8 roy 327: if (efprintf(fp, "if_up=false") == -1)
328: goto eexit;
329: if (efprintf(fp, "if_down=false") == -1)
330: goto eexit;
1.1 roy 331: } else if (1 == 2 /* appease ifdefs */
332: #ifdef INET
1.1.1.3 roy 333: || (protocol == PROTO_DHCP && state && state->new)
1.1 roy 334: #ifdef IPV4LL
1.1.1.3 roy 335: || (protocol == PROTO_IPV4LL && IPV4LL_STATE_RUNNING(ifp))
1.1 roy 336: #endif
337: #endif
338: #ifdef INET6
1.1.1.3 roy 339: || (protocol == PROTO_STATIC6 && IPV6_STATE_RUNNING(ifp))
1.1.1.6 roy 340: #ifdef DHCP6
1.1.1.3 roy 341: || (protocol == PROTO_DHCP6 && d6_state && d6_state->new)
1.1.1.6 roy 342: #endif
1.1.1.3 roy 343: || (protocol == PROTO_RA && ipv6nd_hasra(ifp))
1.1 roy 344: #endif
345: )
346: {
1.1.1.8 roy 347: if (efprintf(fp, "if_up=true") == -1)
348: goto eexit;
349: if (efprintf(fp, "if_down=false") == -1)
350: goto eexit;
1.1 roy 351: } else {
1.1.1.8 roy 352: if (efprintf(fp, "if_up=false") == -1)
353: goto eexit;
354: if (efprintf(fp, "if_down=true") == -1)
355: goto eexit;
1.1 roy 356: }
1.1.1.3 roy 357: if (protocols[protocol] != NULL) {
1.1.1.8 roy 358: if (efprintf(fp, "protocol=%s", protocols[protocol]) == -1)
1.1.1.3 roy 359: goto eexit;
360: }
1.1 roy 361: if ((af = dhcpcd_ifafwaiting(ifp)) != AF_MAX) {
1.1.1.8 roy 362: if (efprintf(fp, "if_afwaiting=%d", af) == -1)
363: goto eexit;
1.1 roy 364: }
365: if ((af = dhcpcd_afwaiting(ifp->ctx)) != AF_MAX) {
366: TAILQ_FOREACH(ifp2, ifp->ctx->ifaces, next) {
367: if ((af = dhcpcd_ifafwaiting(ifp2)) != AF_MAX)
368: break;
369: }
370: }
371: if (af != AF_MAX) {
1.1.1.8 roy 372: if (efprintf(fp, "af_waiting=%d", af) == -1)
373: goto eexit;
1.1 roy 374: }
375: if (ifo->options & DHCPCD_DEBUG) {
1.1.1.8 roy 376: if (efprintf(fp, "syslog_debug=true") == -1)
377: goto eexit;
1.1 roy 378: }
379: if (*ifp->profile) {
1.1.1.8 roy 380: if (efprintf(fp, "profile=%s", ifp->profile) == -1)
381: goto eexit;
1.1 roy 382: }
383: if (ifp->wireless) {
1.1.1.8 roy 384: char pssid[IF_SSIDLEN * 4];
385:
386: if (print_string(pssid, sizeof(pssid), OT_ESCSTRING,
387: ifp->ssid, ifp->ssid_len) != -1)
388: {
389: if (efprintf(fp, "ifssid=%s", pssid) == -1)
390: goto eexit;
1.1 roy 391: }
392: }
393: #ifdef INET
1.1.1.3 roy 394: if (protocol == PROTO_DHCP && state && state->old) {
1.1.1.8 roy 395: if (dhcp_env(fp, "old", ifp,
396: state->old, state->old_len) == -1)
1.1 roy 397: goto eexit;
1.1.1.8 roy 398: if (append_config(fp, "old",
1.1 roy 399: (const char *const *)ifo->config) == -1)
400: goto eexit;
401: }
402: #endif
1.1.1.6 roy 403: #ifdef DHCP6
1.1.1.3 roy 404: if (protocol == PROTO_DHCP6 && d6_state && d6_state->old) {
1.1.1.8 roy 405: if (dhcp6_env(fp, "old", ifp,
406: d6_state->old, d6_state->old_len) == -1)
407: goto eexit;
1.1 roy 408: }
409: #endif
410:
411: dumplease:
412: #ifdef INET
413: #ifdef IPV4LL
1.1.1.3 roy 414: if (protocol == PROTO_IPV4LL) {
1.1.1.8 roy 415: if (ipv4ll_env(fp, istate->down ? "old" : "new", ifp) == -1)
416: goto eexit;
1.1 roy 417: }
418: #endif
1.1.1.3 roy 419: if (protocol == PROTO_DHCP && state && state->new) {
1.1.1.8 roy 420: if (dhcp_env(fp, "new", ifp,
421: state->new, state->new_len) == -1)
422: goto eexit;
423: if (append_config(fp, "new",
1.1 roy 424: (const char *const *)ifo->config) == -1)
425: goto eexit;
426: }
427: #endif
428: #ifdef INET6
1.1.1.3 roy 429: if (protocol == PROTO_STATIC6) {
1.1.1.8 roy 430: if (ipv6_env(fp, "new", ifp) == -1)
431: goto eexit;
1.1 roy 432: }
1.1.1.6 roy 433: #ifdef DHCP6
1.1.1.3 roy 434: if (protocol == PROTO_DHCP6 && D6_STATE_RUNNING(ifp)) {
1.1.1.8 roy 435: if (dhcp6_env(fp, "new", ifp,
436: d6_state->new, d6_state->new_len) == -1)
437: goto eexit;
1.1 roy 438: }
1.1.1.6 roy 439: #endif
1.1.1.3 roy 440: if (protocol == PROTO_RA) {
1.1.1.8 roy 441: if (ipv6nd_env(fp, ifp) == -1)
442: goto eexit;
1.1 roy 443: }
444: #endif
445:
446: /* Add our base environment */
447: if (ifo->environ) {
1.1.1.8 roy 448: for (i = 0; ifo->environ[i] != NULL; i++)
449: if (efprintf(fp, "%s", ifo->environ[i]) == -1)
1.1 roy 450: goto eexit;
451: }
452:
1.1.1.8 roy 453: /* Convert buffer to argv */
454: fflush(fp);
455:
456: buf_pos = ftell(fp);
457: if (buf_pos == -1) {
458: logerr(__func__);
459: goto eexit;
460: }
461: #ifdef HAVE_OPEN_MEMSTREAM
462: buf = ctx->script_buf;
463: #else
464: size_t buf_len = (size_t)buf_pos;
465: if (ctx->script_buflen < buf_len) {
466: buf = realloc(ctx->script_buf, buf_len);
467: if (buf == NULL)
468: goto eexit;
469: ctx->script_buf = buf;
470: ctx->script_buflen = buf_len;
471: }
472: buf = ctx->script_buf;
473: rewind(fp);
474: if (fread(buf, sizeof(char), buf_len, fp) != buf_len)
475: goto eexit;
476: fclose(fp);
477: fp = NULL;
478: #endif
479:
480: nenv = 0;
481: endp = buf + buf_pos;
482: for (bufp = buf; bufp < endp; bufp++) {
483: if (*bufp == '\0')
484: nenv++;
485: }
486: if (ctx->script_envlen < nenv) {
487: env = reallocarray(ctx->script_env, nenv + 1, sizeof(*env));
488: if (env == NULL)
489: goto eexit;
490: ctx->script_env = env;
491: ctx->script_envlen = nenv;
492: }
493: bufp = buf;
494: envp = ctx->script_env;
495: *envp++ = bufp++;
496: endp--; /* Avoid setting the last \0 to an invalid pointer */
497: for (; bufp < endp; bufp++) {
498: if (*bufp == '\0')
499: *envp++ = bufp + 1;
500: }
501: *envp = NULL;
502:
503: return (ssize_t)nenv;
1.1 roy 504:
505: eexit:
1.1.1.2 roy 506: logerr(__func__);
1.1.1.8 roy 507: #ifndef HAVE_OPEN_MEMSTREAM
508: if (fp != NULL)
509: fclose(fp);
510: #endif
1.1 roy 511: return -1;
512: }
513:
514: static int
1.1.1.8 roy 515: send_interface1(struct fd_list *fd, const struct interface *ifp,
1.1 roy 516: const char *reason)
517: {
1.1.1.8 roy 518: struct dhcpcd_ctx *ctx = ifp->ctx;
1.1 roy 519:
1.1.1.8 roy 520: if (make_env(ifp, reason) == -1)
1.1 roy 521: return -1;
1.1.1.8 roy 522: return control_queue(fd, ctx->script_buf, ctx->script_buflen, 1);
1.1 roy 523: }
524:
525: int
526: send_interface(struct fd_list *fd, const struct interface *ifp)
527: {
528: const char *reason;
529: int retval = 0;
530: #ifdef INET
531: const struct dhcp_state *d;
532: #endif
1.1.1.6 roy 533: #ifdef DHCP6
1.1 roy 534: const struct dhcp6_state *d6;
535: #endif
536:
537: switch (ifp->carrier) {
538: case LINK_UP:
539: reason = "CARRIER";
540: break;
541: case LINK_DOWN:
1.1.1.6 roy 542: case LINK_DOWN_IFFUP:
1.1 roy 543: reason = "NOCARRIER";
544: break;
545: default:
546: reason = "UNKNOWN";
547: break;
548: }
549: if (send_interface1(fd, ifp, reason) == -1)
550: retval = -1;
551: #ifdef INET
552: if (D_STATE_RUNNING(ifp)) {
553: d = D_CSTATE(ifp);
554: if (send_interface1(fd, ifp, d->reason) == -1)
555: retval = -1;
556: }
557: #ifdef IPV4LL
558: if (IPV4LL_STATE_RUNNING(ifp)) {
559: if (send_interface1(fd, ifp, "IPV4LL") == -1)
560: retval = -1;
561: }
562: #endif
563: #endif
564:
565: #ifdef INET6
566: if (IPV6_STATE_RUNNING(ifp)) {
567: if (send_interface1(fd, ifp, "STATIC6") == -1)
568: retval = -1;
569: }
570: if (RS_STATE_RUNNING(ifp)) {
571: if (send_interface1(fd, ifp, "ROUTERADVERT") == -1)
572: retval = -1;
573: }
1.1.1.6 roy 574: #ifdef DHCP6
1.1 roy 575: if (D6_STATE_RUNNING(ifp)) {
576: d6 = D6_CSTATE(ifp);
577: if (send_interface1(fd, ifp, d6->reason) == -1)
578: retval = -1;
579: }
580: #endif
1.1.1.6 roy 581: #endif
1.1 roy 582:
583: return retval;
584: }
585:
586: int
587: script_runreason(const struct interface *ifp, const char *reason)
588: {
1.1.1.8 roy 589: struct dhcpcd_ctx *ctx = ifp->ctx;
1.1 roy 590: char *argv[2];
591: pid_t pid;
592: int status = 0;
593: struct fd_list *fd;
594:
1.1.1.7 roy 595: if (ifp->options->script == NULL &&
1.1 roy 596: TAILQ_FIRST(&ifp->ctx->control_fds) == NULL)
597: return 0;
598:
599: /* Make our env */
1.1.1.8 roy 600: if (make_env(ifp, reason) == -1) {
1.1.1.2 roy 601: logerr(__func__);
1.1 roy 602: return -1;
603: }
604:
1.1.1.7 roy 605: if (ifp->options->script == NULL)
1.1 roy 606: goto send_listeners;
607:
1.1.1.7 roy 608: argv[0] = ifp->options->script;
1.1 roy 609: argv[1] = NULL;
1.1.1.2 roy 610: logdebugx("%s: executing `%s' %s", ifp->name, argv[0], reason);
1.1 roy 611:
1.1.1.8 roy 612: pid = exec_script(ctx, argv, ctx->script_env);
1.1 roy 613: if (pid == -1)
1.1.1.2 roy 614: logerr("%s: %s", __func__, argv[0]);
1.1 roy 615: else if (pid != 0) {
616: /* Wait for the script to finish */
617: while (waitpid(pid, &status, 0) == -1) {
618: if (errno != EINTR) {
1.1.1.2 roy 619: logerr("%s: waitpid", __func__);
1.1 roy 620: status = 0;
621: break;
622: }
623: }
624: if (WIFEXITED(status)) {
625: if (WEXITSTATUS(status))
1.1.1.2 roy 626: logerrx("%s: %s: WEXITSTATUS %d",
1.1 roy 627: __func__, argv[0], WEXITSTATUS(status));
628: } else if (WIFSIGNALED(status))
1.1.1.2 roy 629: logerrx("%s: %s: %s",
1.1 roy 630: __func__, argv[0], strsignal(WTERMSIG(status)));
631: }
632:
633: send_listeners:
634: /* Send to our listeners */
635: status = 0;
1.1.1.8 roy 636: TAILQ_FOREACH(fd, &ctx->control_fds, next) {
1.1 roy 637: if (!(fd->flags & FD_LISTEN))
638: continue;
1.1.1.8 roy 639: if (control_queue(fd, ctx->script_buf, ctx->script_buflen, 1)
640: == -1)
1.1.1.2 roy 641: logerr("%s: control_queue", __func__);
1.1 roy 642: else
643: status = 1;
644: }
645:
646: return WEXITSTATUS(status);
647: }
CVSweb <webmaster@jp.NetBSD.org>