3 Support for executable statements. */
6 * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 1998-2003 by Internet Software Consortium
9 * This Source Code Form is subject to the terms of the Mozilla Public
10 * License, v. 2.0. If a copy of the MPL was not distributed with this
11 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
13 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 * Internet Systems Consortium, Inc.
23 * Redwood City, CA 94063
25 * https://www.isc.org/
31 #include <omapip/omapip_p.h>
32 #include <sys/types.h>
35 int execute_statements (result
, packet
, lease
, client_state
,
36 in_options
, out_options
, scope
, statements
,
38 struct binding_value
**result
;
39 struct packet
*packet
;
41 struct client_state
*client_state
;
42 struct option_state
*in_options
;
43 struct option_state
*out_options
;
44 struct binding_scope
**scope
;
45 struct executable_statement
*statements
;
46 struct on_star
*on_star
;
48 struct executable_statement
*r
, *e
, *next
;
51 struct binding
*binding
;
52 struct data_string ds
;
53 struct binding_scope
*ns
;
61 executable_statement_reference (&r
, statements
, MDL
);
62 while (r
&& !(result
&& *result
)) {
64 executable_statement_reference (&next
, r
->next
, MDL
);
66 case statements_statement
:
67 #if defined (DEBUG_EXPRESSIONS)
68 log_debug ("exec: statements");
70 status
= execute_statements (result
, packet
, lease
,
71 client_state
, in_options
,
75 #if defined (DEBUG_EXPRESSIONS)
76 log_debug ("exec: statements returns %d", status
);
79 executable_statement_dereference (&r
, MDL
);
86 * if we haven't been passed an on_star block but
87 * do have a lease, use the one from the lease
88 * This handles the previous v4 calls.
90 if ((on_star
== NULL
) && (lease
!= NULL
))
91 on_star
= &lease
->on_star
;
93 if (on_star
!= NULL
) {
94 if (r
->data
.on
.evtypes
& ON_EXPIRY
) {
95 #if defined (DEBUG_EXPRESSIONS)
96 log_debug ("exec: on expiry");
98 if (on_star
->on_expiry
)
99 executable_statement_dereference
100 (&on_star
->on_expiry
, MDL
);
101 if (r
->data
.on
.statements
)
102 executable_statement_reference
103 (&on_star
->on_expiry
,
104 r
->data
.on
.statements
, MDL
);
106 if (r
->data
.on
.evtypes
& ON_RELEASE
) {
107 #if defined (DEBUG_EXPRESSIONS)
108 log_debug ("exec: on release");
110 if (on_star
->on_release
)
111 executable_statement_dereference
112 (&on_star
->on_release
, MDL
);
113 if (r
->data
.on
.statements
)
114 executable_statement_reference
115 (&on_star
->on_release
,
116 r
->data
.on
.statements
, MDL
);
118 if (r
->data
.on
.evtypes
& ON_COMMIT
) {
119 #if defined (DEBUG_EXPRESSIONS)
120 log_debug ("exec: on commit");
122 if (on_star
->on_commit
)
123 executable_statement_dereference
124 (&on_star
->on_commit
, MDL
);
125 if (r
->data
.on
.statements
)
126 executable_statement_reference
127 (&on_star
->on_commit
,
128 r
->data
.on
.statements
, MDL
);
133 case switch_statement
:
134 #if defined (DEBUG_EXPRESSIONS)
135 log_debug ("exec: switch");
137 status
= (find_matching_case
138 (&e
, packet
, lease
, client_state
,
139 in_options
, out_options
, scope
,
140 r
->data
.s_switch
.expr
,
141 r
->data
.s_switch
.statements
));
142 #if defined (DEBUG_EXPRESSIONS)
143 log_debug ("exec: switch: case %lx", (unsigned long)e
);
146 if (!(execute_statements
147 (result
, packet
, lease
, client_state
,
148 in_options
, out_options
, scope
, e
,
150 executable_statement_dereference
152 executable_statement_dereference
156 executable_statement_dereference (&e
, MDL
);
160 /* These have no effect when executed. */
162 case default_statement
:
166 status
= (evaluate_boolean_expression
168 lease
, client_state
, in_options
,
169 out_options
, scope
, r
->data
.ie
.expr
));
171 #if defined (DEBUG_EXPRESSIONS)
172 log_debug ("exec: if %s", (status
173 ? (rc
? "true" : "false")
176 /* XXX Treat NULL as false */
179 if (!execute_statements
180 (result
, packet
, lease
, client_state
,
181 in_options
, out_options
, scope
,
182 rc
? r
->data
.ie
.tc
: r
->data
.ie
.fc
,
184 executable_statement_dereference (&r
, MDL
);
190 status
= evaluate_expression
191 (NULL
, packet
, lease
, client_state
, in_options
,
192 out_options
, scope
, r
->data
.eval
, MDL
);
193 #if defined (DEBUG_EXPRESSIONS)
194 log_debug ("exec: evaluate: %s",
195 (status
? "succeeded" : "failed"));
201 case execute_statement
: {
202 #ifdef ENABLE_EXECUTE
203 struct expression
*expr
;
205 int i
, argc
= r
->data
.execute
.argc
;
208 /* save room for the command and the NULL terminator */
209 argv
= dmalloc((argc
+ 2) * sizeof(*argv
), MDL
);
213 argv
[0] = dmalloc(strlen(r
->data
.execute
.command
) + 1,
216 strcpy(argv
[0], r
->data
.execute
.command
);
221 log_debug("execute_statement argv[0] = %s", argv
[0]);
223 for (i
= 1, expr
= r
->data
.execute
.arglist
; expr
;
224 expr
= expr
->data
.arg
.next
, i
++) {
225 memset (&ds
, 0, sizeof(ds
));
226 status
= (evaluate_data_expression
228 lease
, client_state
, in_options
,
230 expr
->data
.arg
.val
, MDL
));
232 argv
[i
] = dmalloc(ds
.len
+ 1, MDL
);
234 memcpy(argv
[i
], ds
.data
,
237 log_debug("execute_statement argv[%d] = %s", i
, argv
[i
]);
239 data_string_forget (&ds
, MDL
);
241 log_debug("execute_statement failed argv[%d]", i
);
245 log_debug("execute: bad arg %d", i
);
251 if ((p
= fork()) > 0) {
253 waitpid(p
, &status
, 0);
256 log_error("execute: %s exit status %d",
260 execvp(argv
[0], argv
);
261 log_error("Unable to execute %s: %m", argv
[0]);
264 log_error("execute: fork() failed");
268 for (i
= 0; i
<= argc
; i
++) {
274 #else /* !ENABLE_EXECUTE */
275 log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
276 "is not defined).", MDL
);
277 #endif /* ENABLE_EXECUTE */
281 case return_statement
:
282 status
= evaluate_expression
284 lease
, client_state
, in_options
,
285 out_options
, scope
, r
-> data
.retval
, MDL
);
286 #if defined (DEBUG_EXPRESSIONS)
287 log_debug ("exec: return: %s",
288 (status
? "succeeded" : "failed"));
295 #if defined (DEBUG_EXPRESSIONS)
296 log_debug ("exec: add %s", (r
->data
.add
->name
298 : "<unnamed class>"));
300 classify (packet
, r
->data
.add
);
303 case break_statement
:
304 #if defined (DEBUG_EXPRESSIONS)
305 log_debug ("exec: break");
307 executable_statement_dereference (&r
, MDL
);
310 case supersede_option_statement
:
311 case send_option_statement
:
312 #if defined (DEBUG_EXPRESSIONS)
313 log_debug ("exec: %s option %s.%s",
314 (r
->op
== supersede_option_statement
315 ? "supersede" : "send"),
316 r
->data
.option
->option
->universe
->name
,
317 r
->data
.option
->option
->name
);
318 goto option_statement
;
320 case default_option_statement
:
321 #if defined (DEBUG_EXPRESSIONS)
322 log_debug ("exec: default option %s.%s",
323 r
->data
.option
->option
->universe
->name
,
324 r
->data
.option
->option
->name
);
325 goto option_statement
;
327 case append_option_statement
:
328 #if defined (DEBUG_EXPRESSIONS)
329 log_debug ("exec: append option %s.%s",
330 r
->data
.option
->option
->universe
->name
,
331 r
->data
.option
->option
->name
);
332 goto option_statement
;
334 case prepend_option_statement
:
335 #if defined (DEBUG_EXPRESSIONS)
336 log_debug ("exec: prepend option %s.%s",
337 r
->data
.option
->option
->universe
->name
,
338 r
->data
.option
->option
->name
);
341 set_option (r
->data
.option
->option
->universe
,
342 out_options
, r
->data
.option
, r
->op
);
346 case define_statement
:
349 log_error("set %s: no scope",
354 if (!binding_scope_allocate(scope
, MDL
)) {
355 log_error("set %s: can't allocate scope",
360 binding
= find_binding(*scope
, r
->data
.set
.name
);
361 #if defined (DEBUG_EXPRESSIONS)
362 log_debug("exec: set %s", r
->data
.set
.name
);
366 if (binding
== NULL
) {
367 binding
= dmalloc(sizeof(*binding
), MDL
);
368 if (binding
!= NULL
) {
369 memset(binding
, 0, sizeof(*binding
));
372 (r
->data
.set
.name
) + 1,
374 if (binding
->name
!= NULL
) {
375 strcpy(binding
->name
, r
->data
.set
.name
);
376 binding
->next
= (*scope
)->bindings
;
377 (*scope
)->bindings
= binding
;
384 if (binding
!= NULL
) {
385 if (binding
->value
!= NULL
)
386 binding_value_dereference
387 (&binding
->value
, MDL
);
388 if (r
->op
== set_statement
) {
389 status
= (evaluate_expression
390 (&binding
->value
, packet
,
392 in_options
, out_options
,
393 scope
, r
->data
.set
.expr
,
396 if (!(binding_value_allocate
397 (&binding
->value
, MDL
))) {
401 if ((binding
!= NULL
) &&
402 (binding
->value
!= NULL
)) {
403 binding
->value
->type
=
406 (&binding
->value
->value
.fundef
,
407 r
->data
.set
.expr
->data
.func
,
412 #if defined (DEBUG_EXPRESSIONS)
413 log_debug ("exec: set %s%s", r
-> data
.set
.name
,
414 (binding
&& status
? "" : " (failed)"));
420 case unset_statement
:
421 if (!scope
|| !*scope
)
423 binding
= find_binding (*scope
, r
->data
.unset
);
426 binding_value_dereference
427 (&binding
->value
, MDL
);
431 #if defined (DEBUG_EXPRESSIONS)
432 log_debug ("exec: unset %s: %s", r
->data
.unset
,
433 (status
? "found" : "not found"));
440 #if defined (DEBUG_EXPRESSIONS)
441 log_debug("exec: let %s", r
->data
.let
.name
);
445 binding_scope_allocate (&ns
, MDL
);
450 binding
= dmalloc(sizeof(*binding
), MDL
);
453 binding_scope_dereference(&ns
, MDL
);
455 memset(binding
, 0, sizeof(*binding
));
458 (e
->data
.let
.name
+ 1),
461 strcpy(binding
->name
,
473 status
= (evaluate_expression
474 (&binding
->value
, packet
, lease
,
476 in_options
, out_options
,
477 scope
, e
->data
.set
.expr
, MDL
));
478 binding
->next
= ns
->bindings
;
479 ns
->bindings
= binding
;
482 #if defined (DEBUG_EXPRESSIONS)
483 log_debug("exec: let %s%s", e
->data
.let
.name
,
484 (binding
&& status
? "" : "failed"));
488 if (!e
->data
.let
.statements
) {
489 } else if (e
->data
.let
.statements
->op
==
491 e
= e
->data
.let
.statements
;
495 binding_scope_reference(&ns
->outer
,
498 (result
, packet
, lease
, client_state
,
499 in_options
, out_options
,
500 &ns
, e
->data
.let
.statements
, on_star
);
503 binding_scope_dereference(&ns
, MDL
);
507 memset (&ds
, 0, sizeof ds
);
508 status
= (evaluate_data_expression
510 lease
, client_state
, in_options
,
511 out_options
, scope
, r
->data
.log
.expr
, MDL
));
513 #if defined (DEBUG_EXPRESSIONS)
514 log_debug ("exec: log");
518 switch (r
->data
.log
.priority
) {
519 case log_priority_fatal
:
520 log_fatal ("%.*s", (int)ds
.len
,
523 case log_priority_error
:
524 log_error ("%.*s", (int)ds
.len
,
527 case log_priority_debug
:
528 log_debug ("%.*s", (int)ds
.len
,
531 case log_priority_info
:
532 log_info ("%.*s", (int)ds
.len
,
536 data_string_forget (&ds
, MDL
);
541 case vendor_opt_statement
:
542 /* If possible parse any options in a vendor option
543 * encapsulation, this may add options to the in_options
545 parse_vendor_option(packet
, lease
, client_state
,
546 in_options
, out_options
, scope
);
550 log_error ("bogus statement type %d", r
-> op
);
553 executable_statement_dereference (&r
, MDL
);
555 executable_statement_reference (&r
, next
, MDL
);
556 executable_statement_dereference (&next
, MDL
);
563 /* Execute all the statements in a particular scope, and all statements in
564 scopes outer from that scope, but if a particular limiting scope is
565 reached, do not execute statements in that scope or in scopes outer
566 from it. More specific scopes need to take precedence over less
567 specific scopes, so we recursively traverse the scope list, executing
568 the most outer scope first. */
570 void execute_statements_in_scope (result
, packet
,
571 lease
, client_state
, in_options
, out_options
,
572 scope
, group
, limiting_group
, on_star
)
573 struct binding_value
**result
;
574 struct packet
*packet
;
576 struct client_state
*client_state
;
577 struct option_state
*in_options
;
578 struct option_state
*out_options
;
579 struct binding_scope
**scope
;
581 struct group
*limiting_group
;
582 struct on_star
*on_star
;
586 /* If we've recursed as far as we can, return. */
590 /* As soon as we get to a scope that is outer than the limiting
591 scope, we are done. This is so that if somebody does something
592 like this, it does the expected thing:
594 domain-name "example.com";
597 domain-name "othello.example.com";
598 fixed-address 10.20.30.40;
600 subnet 10.20.30.0 netmask 255.255.255.0 {
601 domain-name "manhattan.example.com";
605 The problem with the above arrangement is that the host's
606 group nesting will be host -> shared-network -> top-level,
607 and the limiting scope when we evaluate the host's scope
608 will be the subnet -> shared-network -> top-level, so we need
609 to know when we evaluate the host's scope to stop before we
610 evaluate the shared-networks scope, because it's outer than
611 the limiting scope, which means we've already evaluated it. */
613 for (limit
= limiting_group
; limit
; limit
= limit
-> next
) {
619 execute_statements_in_scope (result
, packet
,
621 in_options
, out_options
, scope
,
622 group
->next
, limiting_group
,
624 execute_statements (result
, packet
, lease
, client_state
, in_options
,
625 out_options
, scope
, group
->statements
, on_star
);
628 /* Dereference or free any subexpressions of a statement being freed. */
630 int executable_statement_dereference (ptr
, file
, line
)
631 struct executable_statement
**ptr
;
636 log_error ("%s(%d): null pointer", file
, line
);
637 #if defined (POINTER_DEBUG)
645 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
646 if ((*ptr
) -> refcnt
> 0) {
647 *ptr
= (struct executable_statement
*)0;
651 if ((*ptr
) -> refcnt
< 0) {
652 log_error ("%s(%d): negative refcnt!", file
, line
);
653 #if defined (DEBUG_RC_HISTORY)
654 dump_rc_history (*ptr
);
656 #if defined (POINTER_DEBUG)
664 executable_statement_dereference (&(*ptr
) -> next
, file
, line
);
666 switch ((*ptr
) -> op
) {
667 case statements_statement
:
668 if ((*ptr
) -> data
.statements
)
669 executable_statement_dereference
670 (&(*ptr
) -> data
.statements
, file
, line
);
674 if ((*ptr
) -> data
.on
.statements
)
675 executable_statement_dereference
676 (&(*ptr
) -> data
.on
.statements
, file
, line
);
679 case switch_statement
:
680 if ((*ptr
) -> data
.s_switch
.statements
)
681 executable_statement_dereference
682 (&(*ptr
) -> data
.on
.statements
, file
, line
);
683 if ((*ptr
) -> data
.s_switch
.expr
)
684 expression_dereference (&(*ptr
) -> data
.s_switch
.expr
,
689 if ((*ptr
) -> data
.s_switch
.expr
)
690 expression_dereference (&(*ptr
) -> data
.c_case
,
695 if ((*ptr
) -> data
.ie
.expr
)
696 expression_dereference (&(*ptr
) -> data
.ie
.expr
,
698 if ((*ptr
) -> data
.ie
.tc
)
699 executable_statement_dereference
700 (&(*ptr
) -> data
.ie
.tc
, file
, line
);
701 if ((*ptr
) -> data
.ie
.fc
)
702 executable_statement_dereference
703 (&(*ptr
) -> data
.ie
.fc
, file
, line
);
707 if ((*ptr
) -> data
.eval
)
708 expression_dereference (&(*ptr
) -> data
.eval
,
712 case return_statement
:
713 if ((*ptr
) -> data
.eval
)
714 expression_dereference (&(*ptr
) -> data
.eval
,
719 if ((*ptr
)->data
.set
.name
)
720 dfree ((*ptr
)->data
.set
.name
, file
, line
);
721 if ((*ptr
)->data
.set
.expr
)
722 expression_dereference (&(*ptr
) -> data
.set
.expr
,
726 case unset_statement
:
727 if ((*ptr
)->data
.unset
)
728 dfree ((*ptr
)->data
.unset
, file
, line
);
731 case execute_statement
:
732 if ((*ptr
)->data
.execute
.command
)
733 dfree ((*ptr
)->data
.execute
.command
, file
, line
);
734 if ((*ptr
)->data
.execute
.arglist
)
735 expression_dereference (&(*ptr
) -> data
.execute
.arglist
,
739 case supersede_option_statement
:
740 case send_option_statement
:
741 case default_option_statement
:
742 case append_option_statement
:
743 case prepend_option_statement
:
744 if ((*ptr
) -> data
.option
)
745 option_cache_dereference (&(*ptr
) -> data
.option
,
754 dfree ((*ptr
), file
, line
);
755 *ptr
= (struct executable_statement
*)0;
759 void write_statements (file
, statements
, indent
)
761 struct executable_statement
*statements
;
764 #if defined ENABLE_EXECUTE
765 struct expression
*expr
;
767 struct executable_statement
*r
, *x
;
768 const char *s
, *t
, *dot
;
774 for (r
= statements
; r
; r
= r
-> next
) {
776 case statements_statement
:
777 write_statements (file
, r
-> data
.statements
, indent
);
781 indent_spaces (file
, indent
);
782 fprintf (file
, "on ");
784 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
785 fprintf (file
, "%sexpiry", s
);
788 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
789 fprintf (file
, "%scommit", s
);
792 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
793 fprintf (file
, "%srelease", s
);
796 if (r
-> data
.on
.statements
) {
797 fprintf (file
, " {");
798 write_statements (file
,
799 r
-> data
.on
.statements
,
801 indent_spaces (file
, indent
);
808 case switch_statement
:
809 indent_spaces (file
, indent
);
810 fprintf (file
, "switch (");
811 col
= write_expression (file
,
812 r
-> data
.s_switch
.expr
,
813 indent
+ 7, indent
+ 7, 1);
814 col
= token_print_indent (file
, col
, indent
+ 7,
816 token_print_indent (file
,
817 col
, indent
, " ", "", "{");
818 write_statements (file
, r
-> data
.s_switch
.statements
,
820 indent_spaces (file
, indent
);
825 indent_spaces (file
, indent
- 1);
826 fprintf (file
, "case ");
827 col
= write_expression (file
,
828 r
-> data
.s_switch
.expr
,
829 indent
+ 5, indent
+ 5, 1);
830 token_print_indent (file
, col
, indent
+ 5,
834 case default_statement
:
835 indent_spaces (file
, indent
- 1);
836 fprintf (file
, "default: ");
840 indent_spaces (file
, indent
);
841 fprintf (file
, "if ");
843 col
= write_expression (file
,
845 indent
+ 3, indent
+ 3, 1);
847 token_print_indent (file
, col
, indent
, " ", "", "{");
848 write_statements (file
, x
-> data
.ie
.tc
, indent
+ 2);
849 if (x
-> data
.ie
.fc
&&
850 x
-> data
.ie
.fc
-> op
== if_statement
&&
851 !x
-> data
.ie
.fc
-> next
) {
852 indent_spaces (file
, indent
);
853 fprintf (file
, "} elsif ");
855 col
= write_expression (file
,
861 if (x
-> data
.ie
.fc
) {
862 indent_spaces (file
, indent
);
863 fprintf (file
, "} else {");
864 write_statements (file
, x
-> data
.ie
.fc
,
867 indent_spaces (file
, indent
);
872 indent_spaces (file
, indent
);
873 fprintf (file
, "eval ");
874 (void) write_expression (file
, r
-> data
.eval
,
875 indent
+ 5, indent
+ 5, 1);
879 case return_statement
:
880 indent_spaces (file
, indent
);
881 fprintf (file
, "return;");
885 indent_spaces (file
, indent
);
886 fprintf (file
, "add \"%s\"", r
-> data
.add
-> name
);
889 case break_statement
:
890 indent_spaces (file
, indent
);
891 fprintf (file
, "break;");
894 case supersede_option_statement
:
895 case send_option_statement
:
897 goto option_statement
;
899 case default_option_statement
:
901 goto option_statement
;
903 case append_option_statement
:
905 goto option_statement
;
907 case prepend_option_statement
:
910 /* Note: the reason we don't try to pretty print
911 the option here is that the format of the option
912 may change in dhcpd.conf, and then when this
913 statement was read back, it would cause a syntax
915 if (r
-> data
.option
-> option
-> universe
==
920 t
= (r
-> data
.option
-> option
->
924 indent_spaces (file
, indent
);
925 fprintf (file
, "%s %s%s%s = ", s
, t
, dot
,
926 r
-> data
.option
-> option
-> name
);
927 col
= (indent
+ strlen (s
) + strlen (t
) +
928 strlen (dot
) + strlen (r
-> data
.option
->
929 option
-> name
) + 4);
930 if (r
-> data
.option
-> expression
)
933 r
-> data
.option
-> expression
,
936 token_indent_data_string
937 (file
, col
, indent
+ 8, "", "",
938 &r
-> data
.option
-> data
);
940 fprintf (file
, ";"); /* XXX */
944 indent_spaces (file
, indent
);
945 fprintf (file
, "set ");
946 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
947 "", "", r
-> data
.set
.name
);
948 (void) token_print_indent (file
, col
, indent
+ 4,
950 col
= write_expression (file
, r
-> data
.set
.expr
,
951 indent
+ 3, indent
+ 3, 0);
952 (void) token_print_indent (file
, col
, indent
+ 4,
956 case unset_statement
:
957 indent_spaces (file
, indent
);
958 fprintf (file
, "unset ");
959 col
= token_print_indent (file
, indent
+ 6, indent
+ 6,
960 "", "", r
-> data
.set
.name
);
961 (void) token_print_indent (file
, col
, indent
+ 6,
966 indent_spaces (file
, indent
);
967 fprintf (file
, "log ");
968 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
970 switch (r
-> data
.log
.priority
) {
971 case log_priority_fatal
:
972 (void) token_print_indent
973 (file
, col
, indent
+ 4, "",
976 case log_priority_error
:
977 (void) token_print_indent
978 (file
, col
, indent
+ 4, "",
981 case log_priority_debug
:
982 (void) token_print_indent
983 (file
, col
, indent
+ 4, "",
986 case log_priority_info
:
987 (void) token_print_indent
988 (file
, col
, indent
+ 4, "",
992 col
= write_expression (file
, r
-> data
.log
.expr
,
993 indent
+ 4, indent
+ 4, 0);
994 (void) token_print_indent (file
, col
, indent
+ 4,
999 case execute_statement
:
1001 #ifdef ENABLE_EXECUTE
1002 indent_spaces(file
, indent
);
1003 col
= token_print_indent(file
, indent
+ 4, indent
+ 4,
1005 col
= token_print_indent(file
, col
, indent
+ 4, " ", "",
1007 col
= token_print_indent_concat(file
, col
, indent
+ 4,
1009 r
->data
.execute
.command
,
1011 for (expr
= r
->data
.execute
.arglist
; expr
; expr
= expr
->data
.arg
.next
) {
1012 col
= token_print_indent(file
, col
, indent
+ 4,
1014 col
= write_expression(file
, expr
->data
.arg
.val
,
1015 col
, indent
+ 4, 0);
1017 (void) token_print_indent(file
, col
, indent
+ 4,
1019 #else /* !ENABLE_EXECUTE */
1020 log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
1021 "is not defined).", MDL
);
1022 #endif /* ENABLE_EXECUTE */
1025 case vendor_opt_statement
:
1026 indent_spaces (file
, indent
);
1027 fprintf (file
, "parse-vendor-option;");
1031 log_fatal ("bogus statement type %d\n", r
-> op
);
1036 /* Find a case statement in the sequence of executable statements that
1037 matches the expression, and if found, return the following statement.
1038 If no case statement matches, try to find a default statement and
1039 return that (the default statement can precede all the case statements).
1040 Otherwise, return the null statement. */
1042 int find_matching_case (struct executable_statement
**ep
,
1043 struct packet
*packet
, struct lease
*lease
,
1044 struct client_state
*client_state
,
1045 struct option_state
*in_options
,
1046 struct option_state
*out_options
,
1047 struct binding_scope
**scope
,
1048 struct expression
*expr
,
1049 struct executable_statement
*stmt
)
1052 struct executable_statement
*s
;
1054 if (is_data_expression (expr
)) {
1055 struct data_string cd
, ds
;
1056 memset (&ds
, 0, sizeof ds
);
1057 memset (&cd
, 0, sizeof cd
);
1059 status
= (evaluate_data_expression (&ds
, packet
, lease
,
1060 client_state
, in_options
,
1061 out_options
, scope
, expr
,
1064 for (s
= stmt
; s
; s
= s
-> next
) {
1065 if (s
-> op
== case_statement
) {
1066 sub
= (evaluate_data_expression
1067 (&cd
, packet
, lease
, client_state
,
1068 in_options
, out_options
,
1069 scope
, s
->data
.c_case
, MDL
));
1070 if (sub
&& cd
.len
== ds
.len
&&
1071 !memcmp (cd
.data
, ds
.data
, cd
.len
))
1073 data_string_forget (&cd
, MDL
);
1074 data_string_forget (&ds
, MDL
);
1075 executable_statement_reference
1079 data_string_forget (&cd
, MDL
);
1082 data_string_forget (&ds
, MDL
);
1086 status
= evaluate_numeric_expression (&n
, packet
, lease
,
1088 in_options
, out_options
,
1092 for (s
= stmt
; s
; s
= s
->next
) {
1093 if (s
-> op
== case_statement
) {
1094 sub
= (evaluate_numeric_expression
1095 (&c
, packet
, lease
, client_state
,
1096 in_options
, out_options
,
1097 scope
, s
->data
.c_case
));
1098 if (sub
&& n
== c
) {
1099 executable_statement_reference
1108 /* If we didn't find a matching case statement, look for a default
1109 statement and return the statement following it. */
1110 for (s
= stmt
; s
; s
= s
->next
)
1111 if (s
->op
== default_statement
)
1114 executable_statement_reference (ep
, s
->next
, MDL
);
1120 int executable_statement_foreach (struct executable_statement
*stmt
,
1121 int (*callback
) (struct
1122 executable_statement
*,
1124 void *vp
, int condp
)
1126 struct executable_statement
*foo
;
1129 for (foo
= stmt
; foo
; foo
= foo
->next
) {
1130 if ((*callback
) (foo
, vp
, condp
) != 0)
1133 case null_statement
:
1136 if (executable_statement_foreach (foo
->data
.ie
.tc
,
1139 if (executable_statement_foreach (foo
->data
.ie
.fc
,
1145 case eval_statement
:
1147 case break_statement
:
1149 case default_option_statement
:
1151 case supersede_option_statement
:
1153 case append_option_statement
:
1155 case prepend_option_statement
:
1157 case send_option_statement
:
1159 case statements_statement
:
1160 if ((executable_statement_foreach
1161 (foo
->data
.statements
, callback
, vp
, condp
)))
1165 if ((executable_statement_foreach
1166 (foo
->data
.on
.statements
, callback
, vp
, 1)))
1169 case switch_statement
:
1170 if ((executable_statement_foreach
1171 (foo
->data
.s_switch
.statements
, callback
, vp
, 1)))
1174 case case_statement
:
1176 case default_statement
:
1180 case unset_statement
:
1183 if ((executable_statement_foreach
1184 (foo
->data
.let
.statements
, callback
, vp
, 0)))
1187 case define_statement
:
1190 case return_statement
:
1191 case execute_statement
:
1192 case vendor_opt_statement
: