3 Support for executable statements. */
6 * Copyright (c) 2009,2013 by Internet Systems Consortium, Inc. ("ISC")
7 * Copyright (c) 2004-2007 by Internet Systems Consortium, Inc. ("ISC")
8 * Copyright (c) 1998-2003 by Internet Software Consortium
10 * Permission to use, copy, modify, and distribute this software for any
11 * purpose with or without fee is hereby granted, provided that the above
12 * copyright notice and this permission notice appear in all copies.
14 * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
15 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
16 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
17 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
19 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
20 * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * Internet Systems Consortium, Inc.
24 * Redwood City, CA 94063
26 * https://www.isc.org/
28 * This software has been written for Internet Systems Consortium
29 * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
30 * To learn more about Internet Systems Consortium, see
31 * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
32 * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
33 * ``http://www.nominum.com''.
37 #include <omapip/omapip_p.h>
38 #include <sys/types.h>
41 int execute_statements (result
, packet
, lease
, client_state
,
42 in_options
, out_options
, scope
, statements
)
43 struct binding_value
**result
;
44 struct packet
*packet
;
46 struct client_state
*client_state
;
47 struct option_state
*in_options
;
48 struct option_state
*out_options
;
49 struct binding_scope
**scope
;
50 struct executable_statement
*statements
;
52 struct executable_statement
*r
, *e
, *next
;
55 struct binding
*binding
;
56 struct data_string ds
;
57 struct binding_scope
*ns
;
62 r
= (struct executable_statement
*)0;
63 next
= (struct executable_statement
*)0;
64 e
= (struct executable_statement
*)0;
65 executable_statement_reference (&r
, statements
, MDL
);
66 while (r
&& !(result
&& *result
)) {
68 executable_statement_reference (&next
, r
-> next
, MDL
);
70 case statements_statement
:
71 #if defined (DEBUG_EXPRESSIONS)
72 log_debug ("exec: statements");
74 status
= execute_statements (result
, packet
, lease
,
75 client_state
, in_options
,
77 r
-> data
.statements
);
78 #if defined (DEBUG_EXPRESSIONS)
79 log_debug ("exec: statements returns %d", status
);
87 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
88 #if defined (DEBUG_EXPRESSIONS)
89 log_debug ("exec: on expiry");
91 if (lease
-> on_expiry
)
92 executable_statement_dereference
93 (&lease
-> on_expiry
, MDL
);
94 if (r
-> data
.on
.statements
)
95 executable_statement_reference
97 r
-> data
.on
.statements
, MDL
);
99 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
100 #if defined (DEBUG_EXPRESSIONS)
101 log_debug ("exec: on release");
103 if (lease
-> on_release
)
104 executable_statement_dereference
105 (&lease
-> on_release
, MDL
);
106 if (r
-> data
.on
.statements
)
107 executable_statement_reference
108 (&lease
-> on_release
,
109 r
-> data
.on
.statements
, MDL
);
111 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
112 #if defined (DEBUG_EXPRESSIONS)
113 log_debug ("exec: on commit");
115 if (lease
-> on_commit
)
116 executable_statement_dereference
117 (&lease
-> on_commit
, MDL
);
118 if (r
-> data
.on
.statements
)
119 executable_statement_reference
120 (&lease
-> on_commit
,
121 r
-> data
.on
.statements
, MDL
);
126 case switch_statement
:
127 #if defined (DEBUG_EXPRESSIONS)
128 log_debug ("exec: switch");
130 status
= (find_matching_case
131 (&e
, packet
, lease
, client_state
,
132 in_options
, out_options
, scope
,
133 r
-> data
.s_switch
.expr
,
134 r
-> data
.s_switch
.statements
));
135 #if defined (DEBUG_EXPRESSIONS)
136 log_debug ("exec: switch: case %lx", (unsigned long)e
);
139 if (!(execute_statements
140 (result
, packet
, lease
, client_state
,
141 in_options
, out_options
, scope
, e
))) {
142 executable_statement_dereference
146 executable_statement_dereference (&e
, MDL
);
150 /* These have no effect when executed. */
152 case default_statement
:
156 status
= (evaluate_boolean_expression
158 lease
, client_state
, in_options
,
159 out_options
, scope
, r
-> data
.ie
.expr
));
161 #if defined (DEBUG_EXPRESSIONS)
162 log_debug ("exec: if %s", (status
163 ? (rc
? "true" : "false")
166 /* XXX Treat NULL as false */
169 if (!execute_statements
170 (result
, packet
, lease
, client_state
,
171 in_options
, out_options
, scope
,
172 rc
? r
-> data
.ie
.tc
: r
-> data
.ie
.fc
))
177 status
= evaluate_expression
178 ((struct binding_value
**)0,
179 packet
, lease
, client_state
, in_options
,
180 out_options
, scope
, r
-> data
.eval
, MDL
);
181 #if defined (DEBUG_EXPRESSIONS)
182 log_debug ("exec: evaluate: %s",
183 (status
? "succeeded" : "failed"));
189 case execute_statement
: {
190 #ifdef ENABLE_EXECUTE
191 struct expression
*expr
;
193 int i
, argc
= r
->data
.execute
.argc
;
196 /* save room for the command and the NULL terminator */
197 argv
= dmalloc((argc
+ 2) * sizeof(*argv
), MDL
);
201 argv
[0] = dmalloc(strlen(r
->data
.execute
.command
) + 1,
204 strcpy(argv
[0], r
->data
.execute
.command
);
209 log_debug("execute_statement argv[0] = %s", argv
[0]);
211 for (i
= 1, expr
= r
->data
.execute
.arglist
; expr
;
212 expr
= expr
->data
.arg
.next
, i
++) {
213 memset (&ds
, 0, sizeof(ds
));
214 status
= (evaluate_data_expression
216 lease
, client_state
, in_options
,
218 expr
->data
.arg
.val
, MDL
));
220 argv
[i
] = dmalloc(ds
.len
+ 1, MDL
);
222 memcpy(argv
[i
], ds
.data
,
225 log_debug("execute_statement argv[%d] = %s", i
, argv
[i
]);
227 data_string_forget (&ds
, MDL
);
229 log_debug("execute_statement failed argv[%d]", i
);
233 log_debug("execute: bad arg %d", i
);
239 if ((p
= fork()) > 0) {
241 waitpid(p
, &status
, 0);
244 log_error("execute: %s exit status %d",
248 execvp(argv
[0], argv
);
249 log_error("Unable to execute %s: %m", argv
[0]);
252 log_error("execute: fork() failed");
256 for (i
= 0; i
<= argc
; i
++) {
262 #else /* !ENABLE_EXECUTE */
263 log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
264 "is not defined).", MDL
);
265 #endif /* ENABLE_EXECUTE */
269 case return_statement
:
270 status
= evaluate_expression
272 lease
, client_state
, in_options
,
273 out_options
, scope
, r
-> data
.retval
, MDL
);
274 #if defined (DEBUG_EXPRESSIONS)
275 log_debug ("exec: return: %s",
276 (status
? "succeeded" : "failed"));
283 #if defined (DEBUG_EXPRESSIONS)
284 log_debug ("exec: add %s", (r
-> data
.add
-> name
285 ? r
-> data
.add
-> name
286 : "<unnamed class>"));
288 classify (packet
, r
-> data
.add
);
291 case break_statement
:
292 #if defined (DEBUG_EXPRESSIONS)
293 log_debug ("exec: break");
297 case supersede_option_statement
:
298 case send_option_statement
:
299 #if defined (DEBUG_EXPRESSIONS)
300 log_debug ("exec: %s option %s.%s",
301 (r
-> op
== supersede_option_statement
302 ? "supersede" : "send"),
303 r
-> data
.option
-> option
-> universe
-> name
,
304 r
-> data
.option
-> option
-> name
);
305 goto option_statement
;
307 case default_option_statement
:
308 #if defined (DEBUG_EXPRESSIONS)
309 log_debug ("exec: default option %s.%s",
310 r
-> data
.option
-> option
-> universe
-> name
,
311 r
-> data
.option
-> option
-> name
);
312 goto option_statement
;
314 case append_option_statement
:
315 #if defined (DEBUG_EXPRESSIONS)
316 log_debug ("exec: append option %s.%s",
317 r
-> data
.option
-> option
-> universe
-> name
,
318 r
-> data
.option
-> option
-> name
);
319 goto option_statement
;
321 case prepend_option_statement
:
322 #if defined (DEBUG_EXPRESSIONS)
323 log_debug ("exec: prepend option %s.%s",
324 r
-> data
.option
-> option
-> universe
-> name
,
325 r
-> data
.option
-> option
-> name
);
328 set_option (r
-> data
.option
-> option
-> universe
,
329 out_options
, r
-> data
.option
, r
-> op
);
333 case define_statement
:
336 log_error("set %s: no scope",
341 if (!binding_scope_allocate(scope
, MDL
)) {
342 log_error("set %s: can't allocate scope",
347 binding
= find_binding(*scope
, r
->data
.set
.name
);
348 #if defined (DEBUG_EXPRESSIONS)
349 log_debug("exec: set %s", r
->data
.set
.name
);
353 if (binding
== NULL
) {
354 binding
= dmalloc(sizeof(*binding
), MDL
);
355 if (binding
!= NULL
) {
356 memset(binding
, 0, sizeof(*binding
));
359 (r
->data
.set
.name
) + 1,
361 if (binding
->name
!= NULL
) {
362 strcpy(binding
->name
, r
->data
.set
.name
);
363 binding
->next
= (*scope
)->bindings
;
364 (*scope
)->bindings
= binding
;
371 if (binding
!= NULL
) {
372 if (binding
->value
!= NULL
)
373 binding_value_dereference
374 (&binding
->value
, MDL
);
375 if (r
->op
== set_statement
) {
376 status
= (evaluate_expression
377 (&binding
->value
, packet
,
379 in_options
, out_options
,
380 scope
, r
->data
.set
.expr
,
383 if (!(binding_value_allocate
384 (&binding
->value
, MDL
))) {
388 if ((binding
!= NULL
) &&
389 (binding
->value
!= NULL
)) {
390 binding
->value
->type
=
393 (&binding
->value
->value
.fundef
,
394 r
->data
.set
.expr
->data
.func
,
399 #if defined (DEBUG_EXPRESSIONS)
400 log_debug ("exec: set %s%s", r
-> data
.set
.name
,
401 (binding
&& status
? "" : " (failed)"));
407 case unset_statement
:
408 if (!scope
|| !*scope
)
410 binding
= find_binding (*scope
, r
-> data
.unset
);
412 if (binding
-> value
)
413 binding_value_dereference
414 (&binding
-> value
, MDL
);
418 #if defined (DEBUG_EXPRESSIONS)
419 log_debug ("exec: unset %s: %s", r
-> data
.unset
,
420 (status
? "found" : "not found"));
427 #if defined (DEBUG_EXPRESSIONS)
428 log_debug("exec: let %s", r
->data
.let
.name
);
432 binding_scope_allocate (&ns
, MDL
);
437 binding
= dmalloc(sizeof(*binding
), MDL
);
438 memset(binding
, 0, sizeof(*binding
));
441 binding_scope_dereference(&ns
, MDL
);
445 (e
->data
.let
.name
+ 1),
448 strcpy(binding
->name
,
460 status
= (evaluate_expression
461 (&binding
->value
, packet
, lease
,
463 in_options
, out_options
,
464 scope
, e
->data
.set
.expr
, MDL
));
465 binding
->next
= ns
->bindings
;
466 ns
->bindings
= binding
;
469 #if defined (DEBUG_EXPRESSIONS)
470 log_debug("exec: let %s%s", e
->data
.let
.name
,
471 (binding
&& status
? "" : "failed"));
475 if (!e
->data
.let
.statements
) {
476 } else if (e
->data
.let
.statements
->op
==
478 e
= e
->data
.let
.statements
;
482 binding_scope_reference(&ns
->outer
,
485 (result
, packet
, lease
,
487 in_options
, out_options
,
488 &ns
, e
->data
.let
.statements
);
491 binding_scope_dereference(&ns
, MDL
);
495 memset (&ds
, 0, sizeof ds
);
496 status
= (evaluate_data_expression
498 lease
, client_state
, in_options
,
499 out_options
, scope
, r
-> data
.log
.expr
,
502 #if defined (DEBUG_EXPRESSIONS)
503 log_debug ("exec: log");
507 switch (r
-> data
.log
.priority
) {
508 case log_priority_fatal
:
509 log_fatal ("%.*s", (int)ds
.len
,
512 case log_priority_error
:
513 log_error ("%.*s", (int)ds
.len
,
516 case log_priority_debug
:
517 log_debug ("%.*s", (int)ds
.len
,
520 case log_priority_info
:
521 log_info ("%.*s", (int)ds
.len
,
525 data_string_forget (&ds
, MDL
);
531 log_error ("bogus statement type %d", r
-> op
);
534 executable_statement_dereference (&r
, MDL
);
536 executable_statement_reference (&r
, next
, MDL
);
537 executable_statement_dereference (&next
, MDL
);
544 /* Execute all the statements in a particular scope, and all statements in
545 scopes outer from that scope, but if a particular limiting scope is
546 reached, do not execute statements in that scope or in scopes outer
547 from it. More specific scopes need to take precedence over less
548 specific scopes, so we recursively traverse the scope list, executing
549 the most outer scope first. */
551 void execute_statements_in_scope (result
, packet
,
552 lease
, client_state
, in_options
, out_options
,
553 scope
, group
, limiting_group
)
554 struct binding_value
**result
;
555 struct packet
*packet
;
557 struct client_state
*client_state
;
558 struct option_state
*in_options
;
559 struct option_state
*out_options
;
560 struct binding_scope
**scope
;
562 struct group
*limiting_group
;
566 /* If we've recursed as far as we can, return. */
570 /* As soon as we get to a scope that is outer than the limiting
571 scope, we are done. This is so that if somebody does something
572 like this, it does the expected thing:
574 domain-name "fugue.com";
577 domain-name "othello.fugue.com";
578 fixed-address 10.20.30.40;
580 subnet 10.20.30.0 netmask 255.255.255.0 {
581 domain-name "manhattan.fugue.com";
585 The problem with the above arrangement is that the host's
586 group nesting will be host -> shared-network -> top-level,
587 and the limiting scope when we evaluate the host's scope
588 will be the subnet -> shared-network -> top-level, so we need
589 to know when we evaluate the host's scope to stop before we
590 evaluate the shared-networks scope, because it's outer than
591 the limiting scope, which means we've already evaluated it. */
593 for (limit
= limiting_group
; limit
; limit
= limit
-> next
) {
599 execute_statements_in_scope (result
, packet
,
601 in_options
, out_options
, scope
,
602 group
-> next
, limiting_group
);
603 execute_statements (result
, packet
, lease
, client_state
, in_options
,
604 out_options
, scope
, group
-> statements
);
607 /* Dereference or free any subexpressions of a statement being freed. */
609 int executable_statement_dereference (ptr
, file
, line
)
610 struct executable_statement
**ptr
;
615 log_error ("%s(%d): null pointer", file
, line
);
616 #if defined (POINTER_DEBUG)
624 rc_register (file
, line
, ptr
, *ptr
, (*ptr
) -> refcnt
, 1, RC_MISC
);
625 if ((*ptr
) -> refcnt
> 0) {
626 *ptr
= (struct executable_statement
*)0;
630 if ((*ptr
) -> refcnt
< 0) {
631 log_error ("%s(%d): negative refcnt!", file
, line
);
632 #if defined (DEBUG_RC_HISTORY)
633 dump_rc_history (*ptr
);
635 #if defined (POINTER_DEBUG)
643 executable_statement_dereference (&(*ptr
) -> next
, file
, line
);
645 switch ((*ptr
) -> op
) {
646 case statements_statement
:
647 if ((*ptr
) -> data
.statements
)
648 executable_statement_dereference
649 (&(*ptr
) -> data
.statements
, file
, line
);
653 if ((*ptr
) -> data
.on
.statements
)
654 executable_statement_dereference
655 (&(*ptr
) -> data
.on
.statements
, file
, line
);
658 case switch_statement
:
659 if ((*ptr
) -> data
.s_switch
.statements
)
660 executable_statement_dereference
661 (&(*ptr
) -> data
.on
.statements
, file
, line
);
662 if ((*ptr
) -> data
.s_switch
.expr
)
663 expression_dereference (&(*ptr
) -> data
.s_switch
.expr
,
668 if ((*ptr
) -> data
.s_switch
.expr
)
669 expression_dereference (&(*ptr
) -> data
.c_case
,
674 if ((*ptr
) -> data
.ie
.expr
)
675 expression_dereference (&(*ptr
) -> data
.ie
.expr
,
677 if ((*ptr
) -> data
.ie
.tc
)
678 executable_statement_dereference
679 (&(*ptr
) -> data
.ie
.tc
, file
, line
);
680 if ((*ptr
) -> data
.ie
.fc
)
681 executable_statement_dereference
682 (&(*ptr
) -> data
.ie
.fc
, file
, line
);
686 if ((*ptr
) -> data
.eval
)
687 expression_dereference (&(*ptr
) -> data
.eval
,
691 case return_statement
:
692 if ((*ptr
) -> data
.eval
)
693 expression_dereference (&(*ptr
) -> data
.eval
,
698 if ((*ptr
)->data
.set
.name
)
699 dfree ((*ptr
)->data
.set
.name
, file
, line
);
700 if ((*ptr
)->data
.set
.expr
)
701 expression_dereference (&(*ptr
) -> data
.set
.expr
,
705 case unset_statement
:
706 if ((*ptr
)->data
.unset
)
707 dfree ((*ptr
)->data
.unset
, file
, line
);
710 case execute_statement
:
711 if ((*ptr
)->data
.execute
.command
)
712 dfree ((*ptr
)->data
.execute
.command
, file
, line
);
713 if ((*ptr
)->data
.execute
.arglist
)
714 expression_dereference (&(*ptr
) -> data
.execute
.arglist
,
718 case supersede_option_statement
:
719 case send_option_statement
:
720 case default_option_statement
:
721 case append_option_statement
:
722 case prepend_option_statement
:
723 if ((*ptr
) -> data
.option
)
724 option_cache_dereference (&(*ptr
) -> data
.option
,
733 dfree ((*ptr
), file
, line
);
734 *ptr
= (struct executable_statement
*)0;
738 void write_statements (file
, statements
, indent
)
740 struct executable_statement
*statements
;
743 #if defined ENABLE_EXECUTE
744 struct expression
*expr
;
746 struct executable_statement
*r
, *x
;
747 const char *s
, *t
, *dot
;
753 for (r
= statements
; r
; r
= r
-> next
) {
755 case statements_statement
:
756 write_statements (file
, r
-> data
.statements
, indent
);
760 indent_spaces (file
, indent
);
761 fprintf (file
, "on ");
763 if (r
-> data
.on
.evtypes
& ON_EXPIRY
) {
764 fprintf (file
, "%sexpiry", s
);
767 if (r
-> data
.on
.evtypes
& ON_COMMIT
) {
768 fprintf (file
, "%scommit", s
);
771 if (r
-> data
.on
.evtypes
& ON_RELEASE
) {
772 fprintf (file
, "%srelease", s
);
775 if (r
-> data
.on
.statements
) {
776 fprintf (file
, " {");
777 write_statements (file
,
778 r
-> data
.on
.statements
,
780 indent_spaces (file
, indent
);
787 case switch_statement
:
788 indent_spaces (file
, indent
);
789 fprintf (file
, "switch (");
790 col
= write_expression (file
,
791 r
-> data
.s_switch
.expr
,
792 indent
+ 7, indent
+ 7, 1);
793 col
= token_print_indent (file
, col
, indent
+ 7,
795 token_print_indent (file
,
796 col
, indent
, " ", "", "{");
797 write_statements (file
, r
-> data
.s_switch
.statements
,
799 indent_spaces (file
, indent
);
804 indent_spaces (file
, indent
- 1);
805 fprintf (file
, "case ");
806 col
= write_expression (file
,
807 r
-> data
.s_switch
.expr
,
808 indent
+ 5, indent
+ 5, 1);
809 token_print_indent (file
, col
, indent
+ 5,
813 case default_statement
:
814 indent_spaces (file
, indent
- 1);
815 fprintf (file
, "default: ");
819 indent_spaces (file
, indent
);
820 fprintf (file
, "if ");
822 col
= write_expression (file
,
824 indent
+ 3, indent
+ 3, 1);
826 token_print_indent (file
, col
, indent
, " ", "", "{");
827 write_statements (file
, x
-> data
.ie
.tc
, indent
+ 2);
828 if (x
-> data
.ie
.fc
&&
829 x
-> data
.ie
.fc
-> op
== if_statement
&&
830 !x
-> data
.ie
.fc
-> next
) {
831 indent_spaces (file
, indent
);
832 fprintf (file
, "} elsif ");
834 col
= write_expression (file
,
840 if (x
-> data
.ie
.fc
) {
841 indent_spaces (file
, indent
);
842 fprintf (file
, "} else {");
843 write_statements (file
, x
-> data
.ie
.fc
,
846 indent_spaces (file
, indent
);
851 indent_spaces (file
, indent
);
852 fprintf (file
, "eval ");
853 (void) write_expression (file
, r
-> data
.eval
,
854 indent
+ 5, indent
+ 5, 1);
858 case return_statement
:
859 indent_spaces (file
, indent
);
860 fprintf (file
, "return;");
864 indent_spaces (file
, indent
);
865 fprintf (file
, "add \"%s\"", r
-> data
.add
-> name
);
868 case break_statement
:
869 indent_spaces (file
, indent
);
870 fprintf (file
, "break;");
873 case supersede_option_statement
:
874 case send_option_statement
:
876 goto option_statement
;
878 case default_option_statement
:
880 goto option_statement
;
882 case append_option_statement
:
884 goto option_statement
;
886 case prepend_option_statement
:
889 /* Note: the reason we don't try to pretty print
890 the option here is that the format of the option
891 may change in dhcpd.conf, and then when this
892 statement was read back, it would cause a syntax
894 if (r
-> data
.option
-> option
-> universe
==
899 t
= (r
-> data
.option
-> option
->
903 indent_spaces (file
, indent
);
904 fprintf (file
, "%s %s%s%s = ", s
, t
, dot
,
905 r
-> data
.option
-> option
-> name
);
906 col
= (indent
+ strlen (s
) + strlen (t
) +
907 strlen (dot
) + strlen (r
-> data
.option
->
908 option
-> name
) + 4);
909 if (r
-> data
.option
-> expression
)
912 r
-> data
.option
-> expression
,
915 token_indent_data_string
916 (file
, col
, indent
+ 8, "", "",
917 &r
-> data
.option
-> data
);
919 fprintf (file
, ";"); /* XXX */
923 indent_spaces (file
, indent
);
924 fprintf (file
, "set ");
925 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
926 "", "", r
-> data
.set
.name
);
927 (void) token_print_indent (file
, col
, indent
+ 4,
929 col
= write_expression (file
, r
-> data
.set
.expr
,
930 indent
+ 3, indent
+ 3, 0);
931 (void) token_print_indent (file
, col
, indent
+ 4,
935 case unset_statement
:
936 indent_spaces (file
, indent
);
937 fprintf (file
, "unset ");
938 col
= token_print_indent (file
, indent
+ 6, indent
+ 6,
939 "", "", r
-> data
.set
.name
);
940 (void) token_print_indent (file
, col
, indent
+ 6,
945 indent_spaces (file
, indent
);
946 fprintf (file
, "log ");
947 col
= token_print_indent (file
, indent
+ 4, indent
+ 4,
949 switch (r
-> data
.log
.priority
) {
950 case log_priority_fatal
:
951 (void) token_print_indent
952 (file
, col
, indent
+ 4, "",
955 case log_priority_error
:
956 (void) token_print_indent
957 (file
, col
, indent
+ 4, "",
960 case log_priority_debug
:
961 (void) token_print_indent
962 (file
, col
, indent
+ 4, "",
965 case log_priority_info
:
966 (void) token_print_indent
967 (file
, col
, indent
+ 4, "",
971 col
= write_expression (file
, r
-> data
.log
.expr
,
972 indent
+ 4, indent
+ 4, 0);
973 (void) token_print_indent (file
, col
, indent
+ 4,
978 case execute_statement
:
979 #ifdef ENABLE_EXECUTE
980 indent_spaces (file
, indent
);
981 col
= token_print_indent(file
, indent
+ 4, indent
+ 4,
983 col
= token_print_indent(file
, col
, indent
+ 4, " ", "",
985 col
= token_print_indent(file
, col
, indent
+ 4, "\"", "\"", r
->data
.execute
.command
);
986 for (expr
= r
->data
.execute
.arglist
; expr
; expr
= expr
->data
.arg
.next
) {
987 col
= token_print_indent(file
, col
, indent
+ 4, "", " ", ",");
988 col
= write_expression (file
, expr
->data
.arg
.val
, col
, indent
+ 4, 0);
990 (void) token_print_indent(file
, col
, indent
+ 4, "", "", ");");
991 #else /* !ENABLE_EXECUTE */
992 log_fatal("Impossible case at %s:%d (ENABLE_EXECUTE "
993 "is not defined).", MDL
);
994 #endif /* ENABLE_EXECUTE */
998 log_fatal ("bogus statement type %d\n", r
-> op
);
1003 /* Find a case statement in the sequence of executable statements that
1004 matches the expression, and if found, return the following statement.
1005 If no case statement matches, try to find a default statement and
1006 return that (the default statement can precede all the case statements).
1007 Otherwise, return the null statement. */
1009 int find_matching_case (struct executable_statement
**ep
,
1010 struct packet
*packet
, struct lease
*lease
,
1011 struct client_state
*client_state
,
1012 struct option_state
*in_options
,
1013 struct option_state
*out_options
,
1014 struct binding_scope
**scope
,
1015 struct expression
*expr
,
1016 struct executable_statement
*stmt
)
1019 struct executable_statement
*s
;
1021 if (is_data_expression (expr
)) {
1022 struct data_string cd
, ds
;
1023 memset (&ds
, 0, sizeof ds
);
1024 memset (&cd
, 0, sizeof cd
);
1026 status
= (evaluate_data_expression (&ds
, packet
, lease
,
1027 client_state
, in_options
,
1028 out_options
, scope
, expr
,
1031 for (s
= stmt
; s
; s
= s
-> next
) {
1032 if (s
-> op
== case_statement
) {
1033 sub
= (evaluate_data_expression
1034 (&cd
, packet
, lease
, client_state
,
1035 in_options
, out_options
,
1036 scope
, s
-> data
.c_case
, MDL
));
1037 if (sub
&& cd
.len
== ds
.len
&&
1038 !memcmp (cd
.data
, ds
.data
, cd
.len
))
1040 data_string_forget (&cd
, MDL
);
1041 data_string_forget (&ds
, MDL
);
1042 executable_statement_reference
1043 (ep
, s
-> next
, MDL
);
1046 data_string_forget (&cd
, MDL
);
1049 data_string_forget (&ds
, MDL
);
1053 status
= evaluate_numeric_expression (&n
, packet
, lease
,
1055 in_options
, out_options
,
1059 for (s
= stmt
; s
; s
= s
-> next
) {
1060 if (s
-> op
== case_statement
) {
1061 sub
= (evaluate_numeric_expression
1062 (&c
, packet
, lease
, client_state
,
1063 in_options
, out_options
,
1064 scope
, s
-> data
.c_case
));
1065 if (sub
&& n
== c
) {
1066 executable_statement_reference
1067 (ep
, s
-> next
, MDL
);
1075 /* If we didn't find a matching case statement, look for a default
1076 statement and return the statement following it. */
1077 for (s
= stmt
; s
; s
= s
-> next
)
1078 if (s
-> op
== default_statement
)
1081 executable_statement_reference (ep
, s
-> next
, MDL
);
1087 int executable_statement_foreach (struct executable_statement
*stmt
,
1088 int (*callback
) (struct
1089 executable_statement
*,
1091 void *vp
, int condp
)
1093 struct executable_statement
*foo
;
1096 for (foo
= stmt
; foo
; foo
= foo
-> next
) {
1097 if ((*callback
) (foo
, vp
, condp
) != 0)
1099 switch (foo
-> op
) {
1100 case null_statement
:
1103 if (executable_statement_foreach (foo
-> data
.ie
.tc
,
1106 if (executable_statement_foreach (foo
-> data
.ie
.fc
,
1112 case eval_statement
:
1114 case break_statement
:
1116 case default_option_statement
:
1118 case supersede_option_statement
:
1120 case append_option_statement
:
1122 case prepend_option_statement
:
1124 case send_option_statement
:
1126 case statements_statement
:
1127 if ((executable_statement_foreach
1128 (foo
-> data
.statements
, callback
, vp
, condp
)))
1132 if ((executable_statement_foreach
1133 (foo
-> data
.on
.statements
, callback
, vp
, 1)))
1136 case switch_statement
:
1137 if ((executable_statement_foreach
1138 (foo
-> data
.s_switch
.statements
, callback
, vp
, 1)))
1141 case case_statement
:
1143 case default_statement
:
1147 case unset_statement
:
1150 if ((executable_statement_foreach
1151 (foo
-> data
.let
.statements
, callback
, vp
, 0)))
1154 case define_statement
:
1157 case return_statement
:
1158 case execute_statement
: